1 /* exec.c: Glulxe code for program execution. The main interpreter loop.
2 Designed by Andrew Plotkin <erkyrath@eblong.com>
3 http://eblong.com/zarf/glulx/index.html
12 #endif /* FLOAT_SUPPORT */
15 The main interpreter loop. This repeats until the program is done.
19 int done_executing = FALSE;
22 operandlist_t *oplist;
23 oparg_t inst[MAX_OPERANDS];
24 glui32 value, addr, val0, val1;
29 gfloat32 valf, valf1, valf2;
30 #endif /* FLOAT_SUPPORT */
32 while (!done_executing) {
35 /* Do OS-specific processing, if appropriate. */
38 /* Fetch the opcode number. */
42 /* More than one-byte opcode. */
44 /* Four-byte opcode */
46 opcode = (opcode << 8) | Mem1(pc);
48 opcode = (opcode << 8) | Mem1(pc);
50 opcode = (opcode << 8) | Mem1(pc);
56 opcode = (opcode << 8) | Mem1(pc);
61 /* Now we have an opcode number. */
63 /* Fetch the structure that describes how the operands for this
64 opcode are arranged. This is a pointer to an immutable,
67 oplist = fast_operandlist[opcode];
69 oplist = lookup_operandlist(opcode);
72 fatal_error_i("Encountered unknown opcode.", opcode);
74 /* Based on the oplist structure, load the actual operand values
75 into inst. This moves the PC up to the end of the instruction. */
76 parse_operands(inst, oplist);
78 /* Perform the opcode. This switch statement is split in two, based
79 on some paranoid suspicions about the ability of compilers to
80 optimize large-range switches. Ignore that. */
90 value = inst[0].value + inst[1].value;
91 store_operand(inst[2].desttype, inst[2].value, value);
94 value = inst[0].value - inst[1].value;
95 store_operand(inst[2].desttype, inst[2].value, value);
98 value = inst[0].value * inst[1].value;
99 store_operand(inst[2].desttype, inst[2].value, value);
102 vals0 = inst[0].value;
103 vals1 = inst[1].value;
105 fatal_error("Division by zero.");
106 /* Since C doesn't guarantee the results of division of negative
107 numbers, we carefully convert everything to positive values
108 first. They have to be unsigned values, too, otherwise the
109 0x80000000 case goes wonky. */
118 value = -(val0 / val1);
125 value = -(val0 / val1);
132 store_operand(inst[2].desttype, inst[2].value, value);
135 vals0 = inst[0].value;
136 vals1 = inst[1].value;
138 fatal_error("Division by zero doing remainder.");
147 value = -(val0 % val1);
153 store_operand(inst[2].desttype, inst[2].value, value);
156 vals0 = inst[0].value;
158 store_operand(inst[1].desttype, inst[1].value, value);
162 value = (inst[0].value & inst[1].value);
163 store_operand(inst[2].desttype, inst[2].value, value);
166 value = (inst[0].value | inst[1].value);
167 store_operand(inst[2].desttype, inst[2].value, value);
170 value = (inst[0].value ^ inst[1].value);
171 store_operand(inst[2].desttype, inst[2].value, value);
174 value = ~(inst[0].value);
175 store_operand(inst[1].desttype, inst[1].value, value);
179 vals0 = inst[1].value;
180 if (vals0 < 0 || vals0 >= 32)
183 value = ((glui32)(inst[0].value) << (glui32)vals0);
184 store_operand(inst[2].desttype, inst[2].value, value);
187 vals0 = inst[1].value;
188 if (vals0 < 0 || vals0 >= 32)
191 value = ((glui32)(inst[0].value) >> (glui32)vals0);
192 store_operand(inst[2].desttype, inst[2].value, value);
195 vals0 = inst[1].value;
196 if (vals0 < 0 || vals0 >= 32) {
197 if (inst[0].value & 0x80000000)
203 /* This is somewhat foolhardy -- C doesn't guarantee that
204 right-shifting a signed value replicates the sign bit.
205 We'll assume it for now. */
206 value = ((glsi32)(inst[0].value) >> (glsi32)vals0);
208 store_operand(inst[2].desttype, inst[2].value, value);
212 value = inst[0].value;
213 /* fall through to PerformJump label. */
215 PerformJump: /* goto label for successful jumping... ironic, no? */
216 if (value == 0 || value == 1) {
217 /* Return from function. This is exactly what happens in
218 return_op, but it's only a few lines of code, so I won't
219 bother with a "goto". */
222 done_executing = TRUE;
225 pop_callstub(value); /* zero or one */
228 /* Branch to a new PC value. */
229 pc = (pc + value - 2);
234 if (inst[0].value == 0) {
235 value = inst[1].value;
240 if (inst[0].value != 0) {
241 value = inst[1].value;
246 if (inst[0].value == inst[1].value) {
247 value = inst[2].value;
252 if (inst[0].value != inst[1].value) {
253 value = inst[2].value;
258 vals0 = inst[0].value;
259 vals1 = inst[1].value;
261 value = inst[2].value;
266 vals0 = inst[0].value;
267 vals1 = inst[1].value;
269 value = inst[2].value;
274 vals0 = inst[0].value;
275 vals1 = inst[1].value;
276 if (vals0 <= vals1) {
277 value = inst[2].value;
282 vals0 = inst[0].value;
283 vals1 = inst[1].value;
284 if (vals0 >= vals1) {
285 value = inst[2].value;
290 val0 = inst[0].value;
291 val1 = inst[1].value;
293 value = inst[2].value;
298 val0 = inst[0].value;
299 val1 = inst[1].value;
301 value = inst[2].value;
306 val0 = inst[0].value;
307 val1 = inst[1].value;
309 value = inst[2].value;
314 val0 = inst[0].value;
315 val1 = inst[1].value;
317 value = inst[2].value;
323 value = inst[1].value;
324 arglist = pop_arguments(value, 0);
325 push_callstub(inst[2].desttype, inst[2].value);
326 enter_function(inst[0].value, value, arglist);
331 done_executing = TRUE;
334 pop_callstub(inst[0].value);
337 value = inst[1].value;
338 arglist = pop_arguments(value, 0);
340 enter_function(inst[0].value, value, arglist);
344 push_callstub(inst[0].desttype, inst[0].value);
345 value = inst[1].value;
347 store_operand(inst[0].desttype, inst[0].value, val0);
351 profile_fail("throw");
352 value = inst[0].value;
353 stackptr = inst[1].value;
358 value = inst[0].value;
359 store_operand(inst[1].desttype, inst[1].value, value);
362 value = inst[0].value;
363 store_operand_s(inst[1].desttype, inst[1].value, value);
366 value = inst[0].value;
367 store_operand_b(inst[1].desttype, inst[1].value, value);
371 val0 = inst[0].value;
376 store_operand(inst[1].desttype, inst[1].value, val0);
379 val0 = inst[0].value;
384 store_operand(inst[1].desttype, inst[1].value, val0);
388 value = inst[0].value;
389 value += 4 * inst[1].value;
391 store_operand(inst[2].desttype, inst[2].value, val0);
394 value = inst[0].value;
395 value += 2 * inst[1].value;
397 store_operand(inst[2].desttype, inst[2].value, val0);
400 value = inst[0].value;
401 value += inst[1].value;
403 store_operand(inst[2].desttype, inst[2].value, val0);
406 value = inst[0].value;
407 vals0 = inst[1].value;
410 value += (vals0 >> 3);
412 value -= (1 + ((-1 - vals0) >> 3));
413 if (Mem1(value) & (1 << val1))
417 store_operand(inst[2].desttype, inst[2].value, val0);
421 value = inst[0].value;
422 value += 4 * inst[1].value;
423 val0 = inst[2].value;
427 value = inst[0].value;
428 value += 2 * inst[1].value;
429 val0 = inst[2].value;
433 value = inst[0].value;
434 value += inst[1].value;
435 val0 = inst[2].value;
439 value = inst[0].value;
440 vals0 = inst[1].value;
443 value += (vals0 >> 3);
445 value -= (1 + ((-1 - vals0) >> 3));
450 val0 &= ~((glui32)(1 << val1));
455 value = (stackptr - valstackbase) / 4;
456 store_operand(inst[0].desttype, inst[0].value, value);
459 vals0 = inst[0].value * 4;
460 if (vals0 < 0 || vals0 >= (stackptr - valstackbase))
461 fatal_error("Stkpeek outside current stack range.");
462 value = Stk4(stackptr - (vals0+4));
463 store_operand(inst[1].desttype, inst[1].value, value);
466 if (stackptr < valstackbase+8) {
467 fatal_error("Stack underflow in stkswap.");
469 val0 = Stk4(stackptr-4);
470 val1 = Stk4(stackptr-8);
471 StkW4(stackptr-4, val1);
472 StkW4(stackptr-8, val0);
475 vals0 = inst[0].value;
477 fatal_error("Negative operand in stkcopy.");
480 if (stackptr < valstackbase+vals0*4)
481 fatal_error("Stack underflow in stkcopy.");
482 if (stackptr + vals0*4 > stacksize)
483 fatal_error("Stack overflow in stkcopy.");
484 addr = stackptr - vals0*4;
485 for (ix=0; ix<vals0; ix++) {
486 value = Stk4(addr + ix*4);
487 StkW4(stackptr + ix*4, value);
492 vals0 = inst[0].value;
493 vals1 = inst[1].value;
495 fatal_error("Negative operand in stkroll.");
496 if (stackptr < valstackbase+vals0*4)
497 fatal_error("Stack underflow in stkroll.");
500 /* The following is a bit ugly. We want to do vals1 = vals0-vals1,
501 because rolling down is sort of easier than rolling up. But
502 we also want to take the result mod vals0. The % operator is
503 annoying for negative numbers, so we need to do this in two
506 vals1 = vals1 % vals0;
507 vals1 = (vals0) - vals1;
510 vals1 = (-vals1) % vals0;
514 addr = stackptr - vals0*4;
515 for (ix=0; ix<vals1; ix++) {
516 value = Stk4(addr + ix*4);
517 StkW4(stackptr + ix*4, value);
519 for (ix=0; ix<vals0; ix++) {
520 value = Stk4(addr + (vals1+ix)*4);
521 StkW4(addr + ix*4, value);
526 profile_in(0xE0000001, stackptr, FALSE);
527 value = inst[0].value & 0xFF;
528 (*stream_char_handler)(value);
529 profile_out(stackptr);
531 case op_streamunichar:
532 profile_in(0xE0000002, stackptr, FALSE);
533 value = inst[0].value;
534 (*stream_unichar_handler)(value);
535 profile_out(stackptr);
538 profile_in(0xE0000003, stackptr, FALSE);
539 vals0 = inst[0].value;
540 stream_num(vals0, FALSE, 0);
541 profile_out(stackptr);
544 profile_in(0xE0000004, stackptr, FALSE);
545 stream_string(inst[0].value, 0, 0);
546 profile_out(stackptr);
550 fatal_error_i("Executed unknown opcode.", opcode);
558 value = do_gestalt(inst[0].value, inst[1].value);
559 store_operand(inst[2].desttype, inst[2].value, value);
563 fatal_error_i("user debugtrap encountered.", inst[0].value);
570 push_callstub(inst[1].desttype, inst[1].value);
571 enter_function(inst[0].value, 0, arglistfix);
574 arglistfix[0] = inst[1].value;
575 push_callstub(inst[2].desttype, inst[2].value);
576 enter_function(inst[0].value, 1, arglistfix);
579 arglistfix[0] = inst[1].value;
580 arglistfix[1] = inst[2].value;
581 push_callstub(inst[3].desttype, inst[3].value);
582 enter_function(inst[0].value, 2, arglistfix);
585 arglistfix[0] = inst[1].value;
586 arglistfix[1] = inst[2].value;
587 arglistfix[2] = inst[3].value;
588 push_callstub(inst[4].desttype, inst[4].value);
589 enter_function(inst[0].value, 3, arglistfix);
593 store_operand(inst[0].desttype, inst[0].value, endmem);
596 value = change_memsize(inst[0].value, FALSE);
597 store_operand(inst[1].desttype, inst[1].value, value);
600 case op_getstringtbl:
601 value = stream_get_table();
602 store_operand(inst[0].desttype, inst[0].value, value);
604 case op_setstringtbl:
605 stream_set_table(inst[0].value);
609 stream_get_iosys(&val0, &val1);
610 store_operand(inst[0].desttype, inst[0].value, val0);
611 store_operand(inst[1].desttype, inst[1].value, val1);
614 stream_set_iosys(inst[0].value, inst[1].value);
618 profile_in(0xF0000000+inst[0].value, stackptr, FALSE);
619 value = inst[1].value;
620 arglist = pop_arguments(value, 0);
621 val0 = perform_glk(inst[0].value, value, arglist);
622 store_operand(inst[2].desttype, inst[2].value, val0);
623 profile_out(stackptr);
627 vals0 = inst[0].value;
629 value = glulx_random();
631 value = glulx_random() % (glui32)(vals0);
633 value = -(glulx_random() % (glui32)(-vals0));
634 store_operand(inst[1].desttype, inst[1].value, value);
637 glulx_setrandom(inst[0].value);
641 value = perform_verify();
642 store_operand(inst[0].desttype, inst[0].value, value);
646 profile_fail("restart");
651 val0 = inst[0].value;
652 val1 = val0 + inst[1].value;
662 push_callstub(inst[1].desttype, inst[1].value);
663 value = perform_save(find_stream_by_id(inst[0].value));
668 profile_fail("restore");
669 value = perform_restore(find_stream_by_id(inst[0].value));
671 /* We've succeeded, and the stack now contains the callstub
672 saved during saveundo. Ignore this opcode's operand. */
677 /* We've failed, so we must store the failure in this opcode's
679 store_operand(inst[1].desttype, inst[1].value, value);
684 push_callstub(inst[0].desttype, inst[0].value);
685 value = perform_saveundo();
690 profile_fail("restoreundo");
691 value = perform_restoreundo();
693 /* We've succeeded, and the stack now contains the callstub
694 saved during saveundo. Ignore this opcode's operand. */
699 /* We've failed, so we must store the failure in this opcode's
701 store_operand(inst[0].desttype, inst[0].value, value);
706 done_executing = TRUE;
709 case op_linearsearch:
710 value = linear_search(inst[0].value, inst[1].value, inst[2].value,
711 inst[3].value, inst[4].value, inst[5].value, inst[6].value);
712 store_operand(inst[7].desttype, inst[7].value, value);
714 case op_binarysearch:
715 value = binary_search(inst[0].value, inst[1].value, inst[2].value,
716 inst[3].value, inst[4].value, inst[5].value, inst[6].value);
717 store_operand(inst[7].desttype, inst[7].value, value);
719 case op_linkedsearch:
720 value = linked_search(inst[0].value, inst[1].value, inst[2].value,
721 inst[3].value, inst[4].value, inst[5].value);
722 store_operand(inst[6].desttype, inst[6].value, value);
727 glui32 count = inst[0].value;
728 addr = inst[1].value;
729 for (lx=0; lx<count; lx++, addr++) {
736 glui32 count = inst[0].value;
737 glui32 addrsrc = inst[1].value;
738 glui32 addrdest = inst[2].value;
739 if (addrdest < addrsrc) {
740 for (lx=0; lx<count; lx++, addrsrc++, addrdest++) {
741 value = Mem1(addrsrc);
742 MemW1(addrdest, value);
746 addrsrc += (count-1);
747 addrdest += (count-1);
748 for (lx=0; lx<count; lx++, addrsrc--, addrdest--) {
749 value = Mem1(addrsrc);
750 MemW1(addrdest, value);
756 value = heap_alloc(inst[0].value);
757 store_operand(inst[1].desttype, inst[1].value, value);
760 heap_free(inst[0].value);
764 accel_set_func(inst[0].value, inst[1].value);
767 accel_set_param(inst[0].value, inst[1].value);
773 vals0 = inst[0].value;
774 value = encode_float((gfloat32)vals0);
775 store_operand(inst[1].desttype, inst[1].value, value);
778 valf = decode_float(inst[0].value);
779 if (!signbit(valf)) {
780 if (isnan(valf) || isinf(valf) || (valf > 2147483647.0))
783 vals0 = (glsi32)(truncf(valf));
786 if (isnan(valf) || isinf(valf) || (valf < -2147483647.0))
789 vals0 = (glsi32)(truncf(valf));
791 store_operand(inst[1].desttype, inst[1].value, vals0);
794 valf = decode_float(inst[0].value);
795 if (!signbit(valf)) {
796 if (isnan(valf) || isinf(valf) || (valf > 2147483647.0))
799 vals0 = (glsi32)(roundf(valf));
802 if (isnan(valf) || isinf(valf) || (valf < -2147483647.0))
805 vals0 = (glsi32)(roundf(valf));
807 store_operand(inst[1].desttype, inst[1].value, vals0);
811 valf1 = decode_float(inst[0].value);
812 valf2 = decode_float(inst[1].value);
813 value = encode_float(valf1 + valf2);
814 store_operand(inst[2].desttype, inst[2].value, value);
817 valf1 = decode_float(inst[0].value);
818 valf2 = decode_float(inst[1].value);
819 value = encode_float(valf1 - valf2);
820 store_operand(inst[2].desttype, inst[2].value, value);
823 valf1 = decode_float(inst[0].value);
824 valf2 = decode_float(inst[1].value);
825 value = encode_float(valf1 * valf2);
826 store_operand(inst[2].desttype, inst[2].value, value);
829 valf1 = decode_float(inst[0].value);
830 valf2 = decode_float(inst[1].value);
831 value = encode_float(valf1 / valf2);
832 store_operand(inst[2].desttype, inst[2].value, value);
836 valf1 = decode_float(inst[0].value);
837 valf2 = decode_float(inst[1].value);
838 valf = fmodf(valf1, valf2);
839 val0 = encode_float(valf);
840 val1 = encode_float((valf1-valf) / valf2);
841 if (val1 == 0x0 || val1 == 0x80000000) {
842 /* When the quotient is zero, the sign has been lost in the
843 shuffle. We'll set that by hand, based on the original
845 val1 = (inst[0].value ^ inst[1].value) & 0x80000000;
847 store_operand(inst[2].desttype, inst[2].value, val0);
848 store_operand(inst[3].desttype, inst[3].value, val1);
852 valf = decode_float(inst[0].value);
853 value = encode_float(floorf(valf));
854 store_operand(inst[1].desttype, inst[1].value, value);
857 valf = decode_float(inst[0].value);
858 value = encode_float(ceilf(valf));
859 if (value == 0x0 || value == 0x80000000) {
860 /* When the result is zero, the sign may have been lost in the
861 shuffle. (This is a bug in some C libraries.) We'll set the
862 sign by hand, based on the original argument. */
863 value = inst[0].value & 0x80000000;
865 store_operand(inst[1].desttype, inst[1].value, value);
869 valf = decode_float(inst[0].value);
870 value = encode_float(sqrtf(valf));
871 store_operand(inst[1].desttype, inst[1].value, value);
874 valf = decode_float(inst[0].value);
875 value = encode_float(logf(valf));
876 store_operand(inst[1].desttype, inst[1].value, value);
879 valf = decode_float(inst[0].value);
880 value = encode_float(expf(valf));
881 store_operand(inst[1].desttype, inst[1].value, value);
884 valf1 = decode_float(inst[0].value);
885 valf2 = decode_float(inst[1].value);
886 value = encode_float(glulx_powf(valf1, valf2));
887 store_operand(inst[2].desttype, inst[2].value, value);
891 valf = decode_float(inst[0].value);
892 value = encode_float(sinf(valf));
893 store_operand(inst[1].desttype, inst[1].value, value);
896 valf = decode_float(inst[0].value);
897 value = encode_float(cosf(valf));
898 store_operand(inst[1].desttype, inst[1].value, value);
901 valf = decode_float(inst[0].value);
902 value = encode_float(tanf(valf));
903 store_operand(inst[1].desttype, inst[1].value, value);
906 valf = decode_float(inst[0].value);
907 value = encode_float(asinf(valf));
908 store_operand(inst[1].desttype, inst[1].value, value);
911 valf = decode_float(inst[0].value);
912 value = encode_float(acosf(valf));
913 store_operand(inst[1].desttype, inst[1].value, value);
916 valf = decode_float(inst[0].value);
917 value = encode_float(atanf(valf));
918 store_operand(inst[1].desttype, inst[1].value, value);
921 valf1 = decode_float(inst[0].value);
922 valf2 = decode_float(inst[1].value);
923 value = encode_float(atan2f(valf1, valf2));
924 store_operand(inst[2].desttype, inst[2].value, value);
928 /* Infinity is well-defined, so we don't bother to convert to
930 val0 = inst[0].value;
931 if (val0 == 0x7F800000 || val0 == 0xFF800000) {
932 value = inst[1].value;
937 /* NaN is well-defined, so we don't bother to convert to
939 val0 = inst[0].value;
940 if ((val0 & 0x7F800000) == 0x7F800000 && (val0 & 0x007FFFFF) != 0) {
941 value = inst[1].value;
947 if ((inst[2].value & 0x7F800000) == 0x7F800000 && (inst[2].value & 0x007FFFFF) != 0) {
948 /* The delta is NaN, which can never match. */
951 else if ((inst[0].value == 0x7F800000 || inst[0].value == 0xFF800000)
952 && (inst[1].value == 0x7F800000 || inst[1].value == 0xFF800000)) {
953 /* Both are infinite. Opposite infinities are never equal,
954 even if the difference is infinite, so this is easy. */
955 val0 = (inst[0].value == inst[1].value);
958 valf1 = decode_float(inst[1].value) - decode_float(inst[0].value);
959 valf2 = fabs(decode_float(inst[2].value));
960 val0 = (valf1 <= valf2 && valf1 >= -valf2);
963 value = inst[3].value;
968 if ((inst[2].value & 0x7F800000) == 0x7F800000 && (inst[2].value & 0x007FFFFF) != 0) {
969 /* The delta is NaN, which can never match. */
972 else if ((inst[0].value == 0x7F800000 || inst[0].value == 0xFF800000)
973 && (inst[1].value == 0x7F800000 || inst[1].value == 0xFF800000)) {
974 /* Both are infinite. Opposite infinities are never equal,
975 even if the difference is infinite, so this is easy. */
976 val0 = (inst[0].value == inst[1].value);
979 valf1 = decode_float(inst[1].value) - decode_float(inst[0].value);
980 valf2 = fabs(decode_float(inst[2].value));
981 val0 = (valf1 <= valf2 && valf1 >= -valf2);
984 value = inst[3].value;
990 valf1 = decode_float(inst[0].value);
991 valf2 = decode_float(inst[1].value);
993 value = inst[2].value;
998 valf1 = decode_float(inst[0].value);
999 valf2 = decode_float(inst[1].value);
1000 if (valf1 > valf2) {
1001 value = inst[2].value;
1006 valf1 = decode_float(inst[0].value);
1007 valf2 = decode_float(inst[1].value);
1008 if (valf1 <= valf2) {
1009 value = inst[2].value;
1014 valf1 = decode_float(inst[0].value);
1015 valf2 = decode_float(inst[1].value);
1016 if (valf1 >= valf2) {
1017 value = inst[2].value;
1022 #endif /* FLOAT_SUPPORT */
1025 fatal_error_i("Executed unknown opcode.", opcode);