I’ve got Glulxe running and passing the tests on Windows, and I’m some of the way through producing a patch for Git. (On Git some tests pass, and some blow up the interpreter - damned preprocessor macro cleverness/madness). A few thoughts:
The math functions used mean that the compiler must pretty much support C99. This isn’t entirely unreasonable, but might be worth mentioning in the README, at least.
The code in exec.c presumes that the C99 math functions get all the special cases right. Unfortunately the pow() function in the GCC build I’m using doesn’t get a few special cases right, resulting in me having to do preprocessor macro nastiness to call my own pow() function first. Looking around online, I can see that this won’t be uncommon on other platforms. Is there a case for a glulx_pow() function in osdepend.c?
Which functions are C99? signbit() and any others? I’d be willing to rewrite them out, if it’s easy, and for signbit() it should be.
(I already got rid of isless() and friends for that reason – they weren’t on my Ubuntu machine. I didn’t realize there were intermediate classes of availability.)
Yeah, glulx_pow() makes sense. Send me what you have when you get it working.
Errm, well, all of them, really: signbit(), isnan(), isinf(), truncf(), roundf(), ceilf(), floorf(), sqrtf(), expf() and so on … ceil(double) and friends are C89, but the float forms like ceilf(float) are C99.
For some reason, trying to call out from op_pow to glulx_powf(valf1, valf2) resulted in those values getting scrambled. Could be a quirk of GCC 4.5, but I could not get the correct values to come through.
I ended up having to add your conditions directly to the op_pow code:
case op_pow:
valf1 = decode_float(inst[0].value);
valf2 = decode_float(inst[1].value);
if (valf1 == 1.0f)
value = encode_float(1.0f);
else if ((valf2 == 0.0f) || (valf2 == -0.0f))
value = encode_float(1.0f);
else if ((valf1 == -1.0f) && isinf(valf2))
value = encode_float(1.0f);
else
value = encode_float(powf(valf1, valf2));
store_operand(inst[2].desttype, inst[2].value, value);
break;
The same glulx_powf() code works fine if it’s defined in exec.c instead of osdepend.c.
I’ve tried to get around this a number of ways and I’ve basically given up. GCC 4.5 / MinGW seems to have trouble passing float values correctly between functions in different source files. No idea why this should be so, but there you go.
I’ve checked in David’s glulx_powf change (to the master branch).
I rearranged it a little bit – the VM now always calls glulx_powf(), and osdepend.c compiles that function differently if the FLOAT_COMPILE_SAFER_POWF symbol is defined. (This is closer to the way glulx_random() works. It shouldn’t act any differently from what David had.)
I don’t understand the Windows build problem. But then, I wouldn’t.
My only idea is this: the header is compiling the line “typedef float gfloat32;” without including math.h. Maybe float is defined to a different type when you’ve got math.h included? You could test this by throwing an #include math.h line at the top of glulxe.h.