Quetzal - Why is the stack return PC 3 byes?

In the Quertzal save standard, the stack return PC is stored as 3 bytes.

4.3

Each frame has the format:

4.3.1

        3 bytes         ...             return PC (byte address)

Yet, the Z-Machine standards guide Section 1.2 states all addresses can be stored in two byes:

1.2

There are three kinds of address in the Z-machine, all of which can be stored in a 2-byte number: byte addresses, word addresses and packed addresses. 

Section 2.1 of the guide states:

2.1

In the Z-machine, numbers are usually stored in 2 bytes (in the form most-significant-byte first, then least-significant) and hold any value in the range $0000 to $ffff (0 to 65535 decimal). 

I don’t think it clarifies what “usually” means. Is it, “usually two bytes, but sometimes one” like the version number in byte 0 of the header?

Given this, should the Quetzal file stack return PC address most significant byte always be 0? Or is it to be able to store the “unpacked” representation of a packed address?

All function addresses can be stored in two bytes. This is because function addresses are all divisible by 4 (in v5 games), and are stored divided by 4.

That is, in v5, functions can start at any address from 0 to 262140 – anywhere in the game files 256kb address space. But the value stored in N/4, which is a value from 0 to 65535, so it fits in two bytes.

The program counter is not always divisible by 4. It can be anywhere inside a function. The PC could be from 0 to 262143, so it takes three bytes.

(For v3, the divisor is 2; for v8, the divisor is 8. Same idea though.)

3 Likes

Thanks @zarf.

So, it’s to store the literal PC value. It isn’t expected that it would be stored in Quetzal as a packed address?

The PC can’t be stored as a packed address, because it will not in general be divisible by 4. (Or 2, 8, whatever.) Only the start of the function can be referred to with a packed address.

3 Likes

With you, thanks @zarf.