1 /* operand.c: Glulxe code for instruction operands, reading and writing.
2 Designed by Andrew Plotkin <erkyrath@eblong.com>
3 http://eblong.com/zarf/glulx/index.html
10 /* ### We could save a few cycles per operand by generating a function for
11 each operandlist type. */
13 /* fast_operandlist[]:
14 This is a handy array in which to look up operandlists quickly.
15 It stores the operandlists for the first 128 opcodes, which are
16 the ones used most frequently.
18 operandlist_t *fast_operandlist[0x80];
20 /* The actual immutable structures which lookup_operandlist()
22 static operandlist_t list_none = { 0, 4, NULL };
24 static int array_S[1] = { modeform_Store };
25 static operandlist_t list_S = { 1, 4, array_S };
26 static int array_LS[2] = { modeform_Load, modeform_Store };
27 static operandlist_t list_LS = { 2, 4, array_LS };
28 static int array_LLS[3] = { modeform_Load, modeform_Load, modeform_Store };
29 static operandlist_t list_LLS = { 3, 4, array_LLS };
30 static int array_LLLS[4] = { modeform_Load, modeform_Load, modeform_Load, modeform_Store };
31 static operandlist_t list_LLLS = { 4, 4, array_LLLS };
32 static int array_LLLLS[5] = { modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Store };
33 static operandlist_t list_LLLLS = { 5, 4, array_LLLLS };
34 static int array_LLLLLS[6] = { modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Store };
35 static operandlist_t list_LLLLLS = { 6, 4, array_LLLLLS };
36 static int array_LLLLLLS[7] = { modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Store };
37 static operandlist_t list_LLLLLLS = { 7, 4, array_LLLLLLS };
38 static int array_LLLLLLLS[8] = { modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Load, modeform_Store };
39 static operandlist_t list_LLLLLLLS = { 8, 4, array_LLLLLLLS };
41 static int array_L[1] = { modeform_Load };
42 static operandlist_t list_L = { 1, 4, array_L };
43 static int array_LL[2] = { modeform_Load, modeform_Load };
44 static operandlist_t list_LL = { 2, 4, array_LL };
45 static int array_LLL[3] = { modeform_Load, modeform_Load, modeform_Load };
46 static operandlist_t list_LLL = { 3, 4, array_LLL };
47 static operandlist_t list_2LS = { 2, 2, array_LS };
48 static operandlist_t list_1LS = { 2, 1, array_LS };
49 static int array_LLLL[4] = { modeform_Load, modeform_Load, modeform_Load, modeform_Load };
50 static operandlist_t list_LLLL = { 4, 4, array_LLLL };
51 static int array_SL[2] = { modeform_Store, modeform_Load };
52 static operandlist_t list_SL = { 2, 4, array_SL };
53 static int array_SS[2] = { modeform_Store, modeform_Store };
54 static operandlist_t list_SS = { 2, 4, array_SS };
55 static int array_LLSS[4] = { modeform_Load, modeform_Load, modeform_Store, modeform_Store };
56 static operandlist_t list_LLSS = { 4, 4, array_LLSS };
59 Set up the fast-lookup array of operandlists. This is called just
60 once, when the terp starts up.
65 for (ix=0; ix<0x80; ix++)
66 fast_operandlist[ix] = lookup_operandlist(ix);
69 /* lookup_operandlist():
70 Return the operandlist for a given opcode. For opcodes in the range
71 00..7F, it's faster to use the array fast_operandlist[].
73 operandlist_t *lookup_operandlist(glui32 opcode)
158 case op_streamunichar:
162 case op_getstringtbl:
164 case op_setstringtbl:
203 case op_linearsearch:
204 return &list_LLLLLLLS;
205 case op_binarysearch:
206 return &list_LLLLLLLS;
207 case op_linkedsearch:
208 return &list_LLLLLLS;
274 #endif /* FLOAT_SUPPORT */
282 Read the list of operands of an instruction, and put the values
283 in args. This assumes that the PC is at the beginning of the
284 operand mode list (right after an opcode number.) Upon return,
285 the PC will be at the beginning of the next instruction.
287 This also assumes that args points at an allocated array of
288 MAX_OPERANDS oparg_t structures.
290 void parse_operands(oparg_t *args, operandlist_t *oplist)
294 int numops = oplist->num_ops;
295 int argsize = oplist->arg_size;
296 glui32 modeaddr = pc;
299 pc += (numops+1) / 2;
301 for (ix=0, curarg=args; ix<numops; ix++, curarg++) {
306 curarg->desttype = 0;
309 modeval = Mem1(modeaddr);
310 mode = (modeval & 0x0F);
313 mode = ((modeval >> 4) & 0x0F);
317 if (oplist->formlist[ix] == modeform_Load) {
321 case 8: /* pop off stack */
322 if (stackptr < valstackbase+4) {
323 fatal_error("Stack underflow in operand.");
326 value = Stk4(stackptr);
329 case 0: /* constant zero */
333 case 1: /* one-byte constant */
334 /* Sign-extend from 8 bits to 32 */
335 value = (glsi32)(signed char)(Mem1(pc));
339 case 2: /* two-byte constant */
340 /* Sign-extend the first byte from 8 bits to 32; the subsequent
341 byte must not be sign-extended. */
342 value = (glsi32)(signed char)(Mem1(pc));
344 value = (value << 8) | (glui32)(Mem1(pc));
348 case 3: /* four-byte constant */
349 /* Bytes must not be sign-extended. */
354 case 15: /* main memory RAM, four-byte address */
360 case 14: /* main memory RAM, two-byte address */
361 addr = (glui32)Mem2(pc);
366 case 13: /* main memory RAM, one-byte address */
367 addr = (glui32)(Mem1(pc));
372 case 7: /* main memory, four-byte address */
377 case 6: /* main memory, two-byte address */
378 addr = (glui32)Mem2(pc);
382 case 5: /* main memory, one-byte address */
383 addr = (glui32)(Mem1(pc));
388 /* cases 5, 6, 7, 13, 14, 15 all wind up here. */
392 else if (argsize == 2) {
400 case 11: /* locals, four-byte address */
405 case 10: /* locals, two-byte address */
406 addr = (glui32)Mem2(pc);
410 case 9: /* locals, one-byte address */
411 addr = (glui32)(Mem1(pc));
416 /* cases 9, 10, 11 all wind up here. It's illegal for addr to not
417 be four-byte aligned, but we don't check this explicitly.
418 A "strict mode" interpreter probably should. It's also illegal
419 for addr to be less than zero or greater than the size of
420 the locals segment. */
425 else if (argsize == 2) {
434 fatal_error("Unknown addressing mode in load operand.");
437 curarg->value = value;
440 else { /* modeform_Store */
443 case 0: /* discard value */
444 curarg->desttype = 0;
448 case 8: /* push on stack */
449 curarg->desttype = 3;
453 case 15: /* main memory RAM, four-byte address */
459 case 14: /* main memory RAM, two-byte address */
460 addr = (glui32)Mem2(pc);
465 case 13: /* main memory RAM, one-byte address */
466 addr = (glui32)(Mem1(pc));
471 case 7: /* main memory, four-byte address */
476 case 6: /* main memory, two-byte address */
477 addr = (glui32)Mem2(pc);
481 case 5: /* main memory, one-byte address */
482 addr = (glui32)(Mem1(pc));
487 /* cases 5, 6, 7 all wind up here. */
488 curarg->desttype = 1;
489 curarg->value = addr;
492 case 11: /* locals, four-byte address */
497 case 10: /* locals, two-byte address */
498 addr = (glui32)Mem2(pc);
502 case 9: /* locals, one-byte address */
503 addr = (glui32)(Mem1(pc));
508 /* cases 9, 10, 11 all wind up here. It's illegal for addr to not
509 be four-byte aligned, but we don't check this explicitly.
510 A "strict mode" interpreter probably should. It's also illegal
511 for addr to be less than zero or greater than the size of
512 the locals segment. */
513 curarg->desttype = 2;
514 /* We don't add localsbase here; the store address for desttype 2
515 is relative to the current locals segment, not an absolute
517 curarg->value = addr;
523 fatal_error("Constant addressing mode in store operand.");
526 fatal_error("Unknown addressing mode in store operand.");
533 Store a result value, according to the desttype and destaddress given.
534 This is usually used to store the result of an opcode, but it's also
535 used by any code that pulls a call-stub off the stack.
537 void store_operand(glui32 desttype, glui32 destaddr, glui32 storeval)
541 case 0: /* do nothing; discard the value. */
544 case 1: /* main memory. */
545 MemW4(destaddr, storeval);
548 case 2: /* locals. */
549 destaddr += localsbase;
550 StkW4(destaddr, storeval);
553 case 3: /* push on stack. */
554 if (stackptr+4 > stacksize) {
555 fatal_error("Stack overflow in store operand.");
557 StkW4(stackptr, storeval);
562 fatal_error("Unknown destination type in store operand.");
567 void store_operand_s(glui32 desttype, glui32 destaddr, glui32 storeval)
573 case 0: /* do nothing; discard the value. */
576 case 1: /* main memory. */
577 MemW2(destaddr, storeval);
580 case 2: /* locals. */
581 destaddr += localsbase;
582 StkW2(destaddr, storeval);
585 case 3: /* push on stack. A four-byte value is actually pushed. */
586 if (stackptr+4 > stacksize) {
587 fatal_error("Stack overflow in store operand.");
589 StkW4(stackptr, storeval);
594 fatal_error("Unknown destination type in store operand.");
599 void store_operand_b(glui32 desttype, glui32 destaddr, glui32 storeval)
605 case 0: /* do nothing; discard the value. */
608 case 1: /* main memory. */
609 MemW1(destaddr, storeval);
612 case 2: /* locals. */
613 destaddr += localsbase;
614 StkW1(destaddr, storeval);
617 case 3: /* push on stack. A four-byte value is actually pushed. */
618 if (stackptr+4 > stacksize) {
619 fatal_error("Stack overflow in store operand.");
621 StkW4(stackptr, storeval);
626 fatal_error("Unknown destination type in store operand.");