#include "git.h"
#include <assert.h>
+#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define CHECK_FREE(n) if ((top - sp) < (n)) goto stack_overflow
#define CHECK_USED(n) if ((sp - values) < (n)) goto stack_underflow
+// -------------------------------------------------------------
+// Floating point support
+
+#define ENCODE_FLOAT(f) (* (git_uint32*) &f)
+#define DECODE_FLOAT(n) (* (git_float*) &n)
+
+int floatCompare(git_sint32 L1, git_sint32 L2, git_sint32 L3)
+{
+ git_float F1, F2;\r
+\r
+ if (((L3 & 0x7F800000) == 0x7F800000) && ((L3 & 0x007FFFFF) != 0))\r
+ return 0;\r
+ if ((L1 == 0x7F800000 || L1 == 0xFF800000) && (L2 == 0x7F800000 || L2 == 0xFF800000))\r
+ return (L1 == L2);\r
+\r
+ F1 = DECODE_FLOAT(L2) - DECODE_FLOAT(L1);\r
+ F2 = fabs(DECODE_FLOAT(L3));\r
+ return ((F1 <= F2) && (F1 >= -F2));\r
+}
+
+#ifdef USE_OWN_POWF\r
+float git_powf(float x, float y)\r
+{\r
+ if (x == 1.0f)\r
+ return 1.0f;\r
+ else if ((y == 0.0f) || (y == -0.0f))\r
+ return 1.0f;\r
+ else if ((x == -1.0f) && isinf(y))\r
+ return 1.0f;\r
+ return powf(x,y);\r
+}\r
+#endif
+
// -------------------------------------------------------------
// Functions
git_sint32 L1=0, L2=0, L3=0, L4=0, L5=0, L6=0, L7=0;
#define S1 L1
#define S2 L2
+ git_float F1=0.0f, F2=0.0f, F3=0.0f, F4=0.0f;
git_sint32* base; // Bottom of the stack.
git_sint32* frame; // Bottom of the current stack frame.
PEEPHOLE_STORE(bitor, S1 = L1 | L2);
PEEPHOLE_STORE(bitxor, S1 = L1 ^ L2);
- PEEPHOLE_STORE(shiftl, if (L2 > 31) S1 = 0; else S1 = L1 << ((git_uint32) L2));
- PEEPHOLE_STORE(sshiftr, if (L2 > 31) L2 = 31; S1 = ((git_sint32) L1) >> ((git_uint32) L2));
- PEEPHOLE_STORE(ushiftr, if (L2 > 31) S1 = 0; else S1 = ((git_uint32) L1) >> ((git_uint32) L2));
+ PEEPHOLE_STORE(shiftl, if (L2 > 31 || L2 < 0) S1 = 0; else S1 = L1 << ((git_uint32) L2));
+ PEEPHOLE_STORE(sshiftr, if (L2 > 31 || L2 < 0) L2 = 31; S1 = ((git_sint32) L1) >> ((git_uint32) L2));
+ PEEPHOLE_STORE(ushiftr, if (L2 > 31 || L2 < 0) S1 = 0; else S1 = ((git_uint32) L1) >> ((git_uint32) L2));
PEEPHOLE_STORE(aload, S1 = memRead32 (L1 + (L2<<2)));
PEEPHOLE_STORE(aloads, S1 = memRead16 (L1 + (L2<<1)));
PEEPHOLE_STORE(sexs, S1 = (git_sint32)((signed short)(L1 & 0xFFFF)));
PEEPHOLE_STORE(sexb, S1 = (git_sint32)((signed char)(L1 & 0x00FF)));
+ PEEPHOLE_STORE(fadd, F1 = DECODE_FLOAT(L1) + DECODE_FLOAT(L2); S1 = ENCODE_FLOAT(F1));
+ PEEPHOLE_STORE(fsub, F1 = DECODE_FLOAT(L1) - DECODE_FLOAT(L2); S1 = ENCODE_FLOAT(F1));
+ PEEPHOLE_STORE(fmul, F1 = DECODE_FLOAT(L1) * DECODE_FLOAT(L2); S1 = ENCODE_FLOAT(F1));
+ PEEPHOLE_STORE(fdiv, F1 = DECODE_FLOAT(L1) / DECODE_FLOAT(L2); S1 = ENCODE_FLOAT(F1));\r
+
#define PEEPHOLE_LOAD(tag,reg) \
do_ ## tag ## _ ## reg ## _const: reg = READ_PC; goto do_ ## tag; \
do_ ## tag ## _ ## reg ## _stack: CHECK_USED(1); reg = POP; goto do_ ## tag; \
do_ ## tag ## _return0: if (cond) { L1 = 0; goto do_return; } NEXT; \
do_ ## tag ## _return1: if (cond) { L1 = 1; goto do_return; } NEXT
- DO_JUMP(jump, L1, 1 == 1);
- DO_JUMP(jz, L2, L1 == 0);
- DO_JUMP(jnz, L2, L1 != 0);
- DO_JUMP(jeq, L3, L1 == L2);
- DO_JUMP(jne, L3, L1 != L2);
- DO_JUMP(jlt, L3, L1 < L2);
- DO_JUMP(jge, L3, L1 >= L2);
- DO_JUMP(jgt, L3, L1 > L2);
- DO_JUMP(jle, L3, L1 <= L2);
- DO_JUMP(jltu, L3, ((git_uint32)L1 < (git_uint32)L2));
- DO_JUMP(jgeu, L3, ((git_uint32)L1 >= (git_uint32)L2));
- DO_JUMP(jgtu, L3, ((git_uint32)L1 > (git_uint32)L2));
- DO_JUMP(jleu, L3, ((git_uint32)L1 <= (git_uint32)L2));
+ DO_JUMP(jump, L1, 1 == 1);
+ DO_JUMP(jz, L2, L1 == 0);
+ DO_JUMP(jnz, L2, L1 != 0);
+ DO_JUMP(jeq, L3, L1 == L2);
+ DO_JUMP(jne, L3, L1 != L2);
+ DO_JUMP(jlt, L3, L1 < L2);
+ DO_JUMP(jge, L3, L1 >= L2);
+ DO_JUMP(jgt, L3, L1 > L2);
+ DO_JUMP(jle, L3, L1 <= L2);
+ DO_JUMP(jltu, L3, ((git_uint32)L1 < (git_uint32)L2));
+ DO_JUMP(jgeu, L3, ((git_uint32)L1 >= (git_uint32)L2));
+ DO_JUMP(jgtu, L3, ((git_uint32)L1 > (git_uint32)L2));
+ DO_JUMP(jleu, L3, ((git_uint32)L1 <= (git_uint32)L2));
+ DO_JUMP(jisnan, L2, (((L1 & 0x7F800000) == 0x7F800000) && ((L1 & 0x007FFFFF) != 0)));
+ DO_JUMP(jisinf, L2, ((L1 == 0x7F800000) || (L1 == 0xFF800000)));
+ DO_JUMP(jflt, L3, DECODE_FLOAT(L1) < DECODE_FLOAT(L2));
+ DO_JUMP(jfge, L3, DECODE_FLOAT(L1) >= DECODE_FLOAT(L2));
+ DO_JUMP(jfgt, L3, DECODE_FLOAT(L1) > DECODE_FLOAT(L2));
+ DO_JUMP(jfle, L3, DECODE_FLOAT(L1) <= DECODE_FLOAT(L2));
+ DO_JUMP(jfeq, L4, floatCompare(L1, L2, L3) != 0);
+ DO_JUMP(jfne, L4, floatCompare(L1, L2, L3) == 0);
#undef DO_JUMP
do_jumpabs: L7 = L1; goto do_jump_abs_L7; NEXT;
+ do_goto_L4_from_L7: L1 = L4; goto do_goto_L1_from_L7;
do_goto_L3_from_L7: L1 = L3; goto do_goto_L1_from_L7;
do_goto_L2_from_L7: L1 = L2; goto do_goto_L1_from_L7;
do_goto_L1_from_L7:
do_catch_stub_local:
CHECK_FREE(4);
L7 = READ_PC;
- memWrite32(L7, (sp-base+4)*4);
+ LOCAL(L7 / 4) = (sp-base+4)*4;
PUSH (2); // DestType
goto finish_catch_stub_addr_L7;
case 0xC0: case 0xC1: // Function.
// Retrieve arguments.
- for (L1 += 8, L4 = 0; L4 < L2 ; ++L4, L1+=4)
- args[L4] = memRead32(L1);
+ for (L1 += 8, L4 = L2; L4 > 0 ; --L4, L1+=4)
+ args[L4-1] = memRead32(L1);
// Enter function.
L1 = L3;
goto do_enter_function_L1;
do_restart:
// Reset game memory to its initial state.
resetMemory(protectPos, protectSize);
- resetUndo();
// Reset all the stack pointers.
frame = locals = values = sp = base;
// The parameter is zero, so we should generate a
// random number in "the full 32-bit range". The rand()
// function might not cover the entire range, so we'll
- // generate the high 16 bits and low 16 bits separately.
+ // generate the number with several calls.
+#if (RAND_MAX < 0xffff)
+ S1 = rand() ^ (rand() << 12) ^ (rand() << 24);
+#else
S1 = (rand() & 0xffff) | (rand() << 16);
+#endif
}
NEXT;
fatalError ("Negative number of elements to rotate in stkroll");
if (L1 > (sp - values))
fatalError ("Tried to rotate too many elements in stkroll");
+ if (L1 == 0)
+ NEXT;
// Now, let's normalise L2 into the range [0..L1).
if (L2 >= 0)
L2 = L2 % L1;
else
L2 = L1 - (-L2 % L1);
// Avoid trivial cases.
- if (L1 == 0 || L2 == 0 || L2 == L1)
+ if (L2 == 0 || L2 == L1)
NEXT;
L2 = L1 - L2;
// The problem is reduced to swapping elements [0..L2) with
accel_set_param(L1, L2);
NEXT;
+ // Floating point (new with glulx spec 3.1.2)
+
+ do_numtof:\r
+ F1 = (git_float) L1;\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_ftonumz:\r
+ F1 = DECODE_FLOAT(L1);\r
+ if (!signbit(F1)) {\r
+ if (isnan(F1) || isinf(F1) || (F1 > 2147483647.0))\r
+ S1 = 0x7FFFFFFF;\r
+ else\r
+ S1 = (git_sint32) truncf(F1);\r
+ } else {\r
+ if (isnan(F1) || isinf(F1) || (F1 < -2147483647.0))\r
+ S1 = 0x80000000;\r
+ else\r
+ S1 = (git_sint32) truncf(F1);\r
+ }\r
+ NEXT;\r
+\r
+ do_ftonumn:\r
+ F1 = DECODE_FLOAT(L1);\r
+ if (!signbit(F1)) {\r
+ if (isnan(F1) || isinf(F1) || (F1 > 2147483647.0))\r
+ S1 = 0x7FFFFFFF;\r
+ else\r
+ S1 = (git_sint32) roundf(F1);\r
+ } else {\r
+ if (isnan(F1) || isinf(F1) || (F1 < -2147483647.0))\r
+ S1 = 0x80000000;\r
+ else\r
+ S1 = (git_sint32) roundf(F1);\r
+ }\r
+ NEXT;\r
+\r
+ do_ceil:\r
+ F1 = ceilf(DECODE_FLOAT(L1));\r
+ L2 = ENCODE_FLOAT(F1);\r
+ if ((L2 == 0x0) || (L2 == 0x80000000))\r
+ L2 = L1 & 0x80000000;\r
+ S1 = L2;\r
+ NEXT;\r
+\r
+ do_floor:\r
+ F1 = floorf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_sqrt:\r
+ F1 = sqrtf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_exp:\r
+ F1 = expf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_log:\r
+ F1 = logf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_pow:\r
+#ifdef USE_OWN_POWF\r
+ F1 = git_powf(DECODE_FLOAT(L1), DECODE_FLOAT(L2));\r
+#else\r
+ F1 = powf(DECODE_FLOAT(L1), DECODE_FLOAT(L2));\r
+#endif\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_atan2:\r
+ F1 = atan2f(DECODE_FLOAT(L1), DECODE_FLOAT(L2));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_fmod:\r
+ F1 = DECODE_FLOAT(L1);\r
+ F2 = DECODE_FLOAT(L2);\r
+ F3 = fmodf(F1, F2);\r
+ F4 = (F1 - F3) / F2;\r
+ L4 = ENCODE_FLOAT(F4);\r
+ if ((L4 == 0) || (L4 == 0x80000000))\r
+ L4 = (L1 ^ L2) & 0x80000000;\r
+ S1 = ENCODE_FLOAT(F3);\r
+ S2 = L4;\r
+ NEXT;\r
+\r
+ do_sin:\r
+ F1 = sinf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_cos:\r
+ F1 = cosf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_tan:\r
+ F1 = tanf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_asin:\r
+ F1 = asinf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_acos:\r
+ F1 = acosf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+\r
+ do_atan:\r
+ F1 = atanf(DECODE_FLOAT(L1));\r
+ S1 = ENCODE_FLOAT(F1);\r
+ NEXT;\r
+
// Special Git opcodes
do_git_setcacheram: