CA_Pr and bad function calls

I’m making good progress with my new Z-Machine interpreter ( but have found a bug I can’t diagnose.

If you run the test page tests/praxix.html and enter something the interpreter will crash after finding an unimplemented opcode, usually 0. It is finding these opcodes because a call is being made to address 28, which is in the header and most definitely not the correct function. The error occurs in CA_Pr, but I think the cause might be before it. It is calling the number of the object, rather than the address of it’s property.

I’m not sure about this however, as the actually code which is in CA_Pr does not seem identical to what should have been compiled from veneer.c. Would the compiler optimise the veneer functions? The bad function call is from indirect().

Any ideas?

Veneer functions end up being treated exactly as if they were appended to the source file, so they’re handled by the compiler exactly as it would any other code. Not sure that that helps, though…

I found the source of the bug: bad branch addresses. The code that processed branches is given a branch address, but at that stage it can’t tell if it was originally, for example, 0x40 or 0x0040, which are two very different addresses (remember that 0x40 in the first byte indicates a single byte address, so it would be 0/rfalse, while the second would be +38.) So I shifted some code around and now it processes the branch address while it still knows whether it was a byte or a word.

ZVM is now passing a substantial amount of Praxix, so I think it will soon be ready for some serious testing. :slight_smile: I’ll be adding it to Parchment soon too, but Gnusto will remain the default for the time being.

Glad to hear you fixed the bug. I took a look at your site and saw the file praxix.z5 you use for testing. Is this something you created? I’ve never seen it anywhere else and had some questions about it. My terp passes most of the tests, but fails on a few. One of the failures is on bit shifting operations with shift values beyond +15 or -15 which I thought the 1.1 standard decalared to be undefined. There are a couple other failures that I don’t understand yet as well.


Praxix is a bunch of tests that I started putting together a couple of years ago. Then Dannii expanded it, and I’ve also merged in some tests from other Z-machine test suites.

It lives in the gnusto distribution: … ster/tests

It’s not complete (obviously) but I’m not surprised that it also goes beyond the formal Z-spec. I threw in a lot of everything-I-could-think-of tests. If there are tests that we should label “This is undefined according to the spec, failing this is not a disaster”, then we can do that.

(But I don’t want to drop such tests, because it’s good to know what interpreters behave like what other interpreters.)

Thanks, I’ll check that out. I’ve run various test files but am never sure if I have the latest and greatest. :slight_smile:
I think marking certain tests being above and beyond the spec is a good idea.

In my terp if the shift amount is out of the range + or - 15, then I signal an error. If the user opts to continue, then the result is simply the unchanged initial value. This is probably very different behavior from most and I will likely change it to bring it in line with the expected results.

I also had some trouble with two of the streamtrip tests and one other set of tests but I can’t recall the details at the moment.

[Edit: I was able to fix the other failed tests. I was allowing null characters to the output stream causing failures in the streamtrip tests. I was also allowing loadw, loadb, storew, and storeb to go beyond 16-bit addresses causing 8 failures in the array tests.]

I’ve updated Praxix to note when a test is checking something unspecified. Get the new version from

You should use the other unit tests there too. Czech covers a lot of the same material as Praxix, but it also tests the object opcodes and has some print tests. TerpEtude covers a lot of IO stuff. Maybe some day I’ll combine all the static (ie, non-input dependant) tests into Praxix, but it’s no priority. Maybe even that initial choose-a-test should be removed, and then we could work on another test suite covering everything input.

(Zarf, I’ve made my if repo the new home for Praxix, so if you ever want to add more tests then clone it instead.)