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 parseL (git_uint32* pc, Label op)
51 parseModeNibbles (pc, 1, modes);
53 parseLoad (pc, reg_L1, modes [0], size32, NULL);
56 static void parseLL (git_uint32* pc, Label op)
59 parseModeNibbles (pc, 2, modes);
61 parseLoad (pc, reg_L1, modes [0], size32, NULL);
62 parseLoad (pc, reg_L2, modes [1], size32, NULL);
65 static void parse_finish_branch (git_uint32* pc, Label op, LoadReg reg, int mode)
68 if (parseLoad (pc, reg, mode, size32, &val))
70 // The branch offset is a constant, so we can
71 // check for the special values 0 and 1 right here.
75 emitCode (op - label_jeq_var + label_jeq_return0);
79 emitCode (op - label_jeq_var + label_jeq_return1);
83 // Calculate the destination address and
84 // emit a constant branch opcode.
85 emitConstBranch (op - label_jeq_var + label_jeq_const, *pc + val - 2);
90 // The branch offset isn't a constant, so just
91 // emit the normal opcode plus the current PC.
97 static void parseLLL_branch (git_uint32* pc, Label op)
100 parseModeNibbles (pc, 3, modes);
102 parseLoad (pc, reg_L1, modes [0], size32, NULL);
103 parseLoad (pc, reg_L2, modes [1], size32, NULL);
104 parse_finish_branch (pc, op, reg_L3, modes [2]);
106 static void parseLL_branch (git_uint32* pc, Label op)
109 parseModeNibbles (pc, 2, modes);
111 parseLoad (pc, reg_L1, modes [0], size32, NULL);
112 parse_finish_branch (pc, op, reg_L2, modes [1]);
114 static void parseL_branch (git_uint32* pc, Label op)
117 parseModeNibbles (pc, 1, modes);
119 parse_finish_branch (pc, op, reg_L1, modes [0]);
121 static void parseLLL (git_uint32* pc, Label op)
124 parseModeNibbles (pc, 3, modes);
126 parseLoad (pc, reg_L1, modes [0], size32, NULL);
127 parseLoad (pc, reg_L2, modes [1], size32, NULL);
128 parseLoad (pc, reg_L3, modes [2], size32, NULL);
131 static void parseS (git_uint32* pc, Label op)
134 parseModeNibbles (pc, 1, modes);
137 parseStore (pc, reg_S1, modes [0], size32);
139 static void parseSS (git_uint32* pc, Label op)
142 parseModeNibbles (pc, 2, modes);
145 parseStore (pc, reg_S1, modes [0], size32);
146 parseStore (pc, reg_S2, modes [1], size32);
148 static void parseCatch (git_uint32 * pc)
152 parseModeNibbles (pc, 2, modes);
154 parseCatchStub (pc, modes[0]);
156 // This is a little nasty. The last thing emitted by
157 // parseCatchStub() is the current value of the PC,
158 // which is where execution will resume when and if
159 // the stub is used; but execution should resume
160 // after the branch we're about to do, so we'll need
161 // to fix up that emitted value.
163 stubCode = peekAtEmittedStuff (1);
165 parseLoad (pc, reg_L1, modes[1], size32, NULL);
166 emitCode (label_jump_var);
169 // Fix up the end of the stub, as described above.
172 void parseInstruction (git_uint32* pc, int * done)
174 git_uint32 pcStart = *pc;
182 opcode = memRead8((*pc)++);
184 // Check for multi-byte opcode.
191 opcode = (opcode << 8) | memRead8((*pc)++);
192 opcode = (opcode << 8) | memRead8((*pc)++);
193 opcode = (opcode << 8) | memRead8((*pc)++);
199 opcode = (opcode << 8) | memRead8((*pc)++);
205 emitCode (label_debug_step);
210 // printf (" opcode=0x%x", opcode);
212 // Now we have an opcode number,
213 // parse the operands and emit code.
217 case op_nop: emitCode (label_nop); break;
219 // Arithmetic and logic
221 case op_add: parseLLS (pc, label_add_discard); break;
222 case op_sub: parseLLS (pc, label_sub_discard); break;
223 case op_mul: parseLLS (pc, label_mul_discard); break;
224 case op_div: parseLLS (pc, label_div_discard); break;
225 case op_mod: parseLLS (pc, label_mod_discard); break;
227 case op_bitand: parseLLS (pc, label_bitand_discard); break;
228 case op_bitor: parseLLS (pc, label_bitor_discard); break;
229 case op_bitxor: parseLLS (pc, label_bitxor_discard); break;
231 case op_neg: parseLS (pc, label_neg_discard); break;
232 case op_bitnot: parseLS (pc, label_bitnot_discard); break;
234 case op_shiftl: parseLLS (pc, label_shiftl_discard); break;
235 case op_ushiftr: parseLLS (pc, label_ushiftr_discard); break;
236 case op_sshiftr: parseLLS (pc, label_sshiftr_discard); break;
240 case op_jump: parseL_branch (pc, label_jump_var); *done = 1; break;
241 case op_jz: parseLL_branch (pc, label_jz_var); break;
242 case op_jnz: parseLL_branch (pc, label_jnz_var); break;
243 case op_jeq: parseLLL_branch (pc, label_jeq_var); break;
244 case op_jne: parseLLL_branch (pc, label_jne_var); break;
245 case op_jlt: parseLLL_branch (pc, label_jlt_var); break;
246 case op_jgt: parseLLL_branch (pc, label_jgt_var); break;
247 case op_jle: parseLLL_branch (pc, label_jle_var); break;
248 case op_jge: parseLLL_branch (pc, label_jge_var); break;
249 case op_jltu: parseLLL_branch (pc, label_jltu_var); break;
250 case op_jgtu: parseLLL_branch (pc, label_jgtu_var); break;
251 case op_jleu: parseLLL_branch (pc, label_jleu_var); break;
252 case op_jgeu: parseLLL_branch (pc, label_jgeu_var); break;
254 case op_jumpabs: parseL (pc, label_jumpabs); *done = 1; break;
259 parseModeNibbles (pc, 2, modes);
260 parseLoad (pc, reg_L1, modes [0], size32, NULL);
261 parseStore (pc, reg_S1, modes [1], size32);
265 parseModeNibbles (pc, 2, modes);
266 parseLoad (pc, reg_L1, modes [0], size16, NULL);
267 emitCode (label_copys_discard);
268 parseStore (pc, reg_S1, modes [1], size16);
272 parseModeNibbles (pc, 2, modes);
273 parseLoad (pc, reg_L1, modes [0], size8, NULL);
274 emitCode (label_copyb_discard);
275 parseStore (pc, reg_S1, modes [1], size8);
278 case op_sexs: parseLS (pc, label_sexs_discard); break;
279 case op_sexb: parseLS (pc, label_sexb_discard); break;
283 case op_aload: parseLLS (pc, label_aload_discard); break;
284 case op_aloads: parseLLS (pc, label_aloads_discard); break;
285 case op_aloadb: parseLLS (pc, label_aloadb_discard); break;
286 case op_aloadbit: parseLLS (pc, label_aloadbit_discard); break;
288 case op_astore: parseLLL (pc, label_astore); break;
289 case op_astores: parseLLL (pc, label_astores); break;
290 case op_astoreb: parseLLL (pc, label_astoreb); break;
291 case op_astorebit: parseLLL (pc, label_astorebit); break;
295 case op_stkcount: parseS (pc, label_stkcount); break;
296 case op_stkpeek: parseLS (pc, label_stkpeek); break;
297 case op_stkswap: emitCode (label_stkswap); break;
298 case op_stkcopy: parseL (pc, label_stkcopy); break;
299 case op_stkroll: parseLL (pc, label_stkroll); break;
304 parseModeNibbles (pc, 3, modes);
305 parseLoad (pc, reg_L1, modes [0], size32, NULL);
306 parseLoad (pc, reg_L2, modes [1], size32, NULL);
307 emitCode (label_args_stack);
308 parseCallStub (pc, modes [2]);
312 parseModeNibbles (pc, 2, modes);
313 parseLoad (pc, reg_L1, modes [0], size32, NULL);
314 emitCode (label_args_0);
315 parseCallStub (pc, modes [1]);
319 parseModeNibbles (pc, 3, modes);
320 parseLoad (pc, reg_L1, modes [0], size32, NULL);
321 parseLoad (pc, reg_L2, modes [1], size32, NULL);
322 emitCode (label_args_1);
323 parseCallStub (pc, modes [2]);
327 parseModeNibbles (pc, 4, modes);
328 parseLoad (pc, reg_L1, modes [0], size32, NULL);
329 parseLoad (pc, reg_L2, modes [1], size32, NULL);
330 parseLoad (pc, reg_L3, modes [2], size32, NULL);
331 emitCode (label_args_2);
332 parseCallStub (pc, modes [3]);
336 parseModeNibbles (pc, 5, modes);
337 parseLoad (pc, reg_L1, modes [0], size32, NULL);
338 parseLoad (pc, reg_L2, modes [1], size32, NULL);
339 parseLoad (pc, reg_L3, modes [2], size32, NULL);
340 parseLoad (pc, reg_L4, modes [3], size32, NULL);
341 emitCode (label_args_3);
342 parseCallStub (pc, modes [4]);
346 parseL (pc, label_return);
351 parseModeNibbles (pc, 2, modes);
352 parseLoad (pc, reg_L1, modes [0], size32, NULL);
353 parseLoad (pc, reg_L2, modes [1], size32, NULL);
354 emitCode (label_args_stack);
355 emitCode (label_tailcall);
361 case op_catch: parseCatch (pc); break;
363 parseLL (pc, label_throw);
367 case op_random: parseLS (pc, label_random); break;
368 case op_setrandom: parseL (pc, label_setrandom); break;
370 case op_getmemsize: parseS (pc, label_getmemsize); break;
371 case op_setmemsize: parseLS (pc, label_setmemsize); break;
374 emitCode (label_quit);
379 emitCode (label_restart);
383 case op_restore: parseLS (pc, label_restore); break;
384 case op_restoreundo: parseS (pc, label_restoreundo); break;
385 case op_protect: parseLL (pc, label_protect); break;
386 case op_verify: parseS (pc, label_verify); break;
389 parseModeNibbles (pc, 2, modes);
390 parseLoad (pc, reg_L1, modes [0], size32, NULL);
391 parseSaveStub (pc, modes [1]);
395 parseModeNibbles (pc, 1, modes);
396 parseUndoStub (pc, modes [0]);
399 case op_getiosys: parseSS (pc, label_getiosys); break;
400 case op_setiosys: parseLL (pc, label_setiosys); break;
402 case op_getstringtbl: parseS (pc, label_getstringtbl); break;
403 case op_setstringtbl: parseL (pc, label_setstringtbl); break;
405 case op_streamchar: parseL (pc, label_streamchar); emitData(*pc); break;
406 case op_streamnum: parseL (pc, label_streamnum); emitData(*pc); break;
407 case op_streamstr: parseL (pc, label_streamstr); emitData(*pc); break;
408 case op_streamunichar: parseL (pc, label_streamunichar); emitData(*pc); break;
410 case op_glk: parseLLS (pc, label_glk); break;
411 case op_gestalt: parseLLS (pc, label_gestalt); break;
413 case op_binarysearch:
414 case op_linearsearch:
415 parseModeNibbles (pc, 8, modes);
416 parseLoad (pc, reg_L1, modes [0], size32, NULL);
417 parseLoad (pc, reg_L2, modes [1], size32, NULL);
418 parseLoad (pc, reg_L3, modes [2], size32, NULL);
419 parseLoad (pc, reg_L4, modes [3], size32, NULL);
420 parseLoad (pc, reg_L5, modes [4], size32, NULL);
421 parseLoad (pc, reg_L6, modes [5], size32, NULL);
422 parseLoad (pc, reg_L7, modes [6], size32, NULL);
423 emitCode (opcode == op_linearsearch ? label_linearsearch : label_binarysearch);
424 parseStore (pc, reg_S1, modes [7], size32);
427 case op_linkedsearch:
428 parseModeNibbles (pc, 7, modes);
429 parseLoad (pc, reg_L1, modes [0], size32, NULL);
430 parseLoad (pc, reg_L2, modes [1], size32, NULL);
431 parseLoad (pc, reg_L3, modes [2], size32, NULL);
432 parseLoad (pc, reg_L4, modes [3], size32, NULL);
433 parseLoad (pc, reg_L5, modes [4], size32, NULL);
434 parseLoad (pc, reg_L6, modes [5], size32, NULL);
435 emitCode (label_linkedsearch);
436 parseStore (pc, reg_S1, modes [6], size32);
440 parseL (pc, label_debugtrap);
445 case op_mzero: parseLL (pc, label_mzero); break;
446 case op_mcopy: parseLLL (pc, label_mcopy); break;
448 case op_malloc: parseLS (pc, label_malloc); break;
449 case op_mfree: parseL (pc, label_mfree); break;
451 // Function acceleration
453 case op_accelfunc: parseLL (pc, label_accelfunc); break;
454 case op_accelparam: parseLL (pc, label_accelparam); break;
456 // Special Git opcodes
458 case op_git_setcacheram: parseL (pc, label_git_setcacheram); break;
459 case op_git_prunecache: parseLL (pc, label_git_prunecache); break;