5 ms·
TL;DR Instead of call [32-bit-start-address-of-function] use call [8-bit-index-into-table-of-start-addresses-of-functions] plus a mechanism to build such a tabl
by danbruc 13y ago
TL;DR Instead of call [32-bit-start-address-of-function] use call [8-bit-index-into-table-of-start-addresses-of-functions] plus a mechanism to build such a table and make the look-up depended on the current value of the program counter because otherwise you could only ever call 256 different methods.
IMHO needlessly complex just to make call instructions smaller. And on its own it provides not any more security - messing with a call instruction will no longer let you jump into the middle of nowhere but only to the beginning of a basic block, but you can still just mess with the table of addresses unless protected by other measures.
- danbruc 13y agoOn a second thought it is actually hard to save any memory at all. The proposed look-up is table[PC >> 4 + index] so the table will have code-size/16 + 255 entries of 32 bit each, making it code-size/4 + 1020 byte large. Given the normal code size s with n call instructions you can reduce the code size to s - 3n because you save three byte per call but you have an additional table of size s/4 + 1020. This yields n = s/12 + 340 and that means there has to be more than one call instruction every 12 byte on average to save any memory at all.
- skew 13y agoThat sounds like a pretty reasonable density to see savings in threaded forth code like the second post talks about (it also mentions adjusting the shift for other densities). Second, you don't need to reserve excess state at the end like that if the linker/compiler takes a little care allocating offsets so the last instructions use small indices. It definitely seems like a bit of a specialized trick, but the articles do a decent job describing conditions where it might make sense.
- danbruc 13y agoAssuming 32 bit instructions at least every third instruction would have to be a call or jump - this seams no reasonable assumption. And if you have code with such a high density of jumps you will run into a lot of other problems, too, for example branch mispredictions and cache inefficiency due to non-locality. Maybe there is really a niche where this design has advantages but I don't think it is good for general purpose code.
- prutschman 13y ago> Assuming 32 bit instructions You don't have to assume, the article itself says the author is contemplating 9-bit instructions.
- danbruc 13y agoI did not read it like that. 9 bit is not really enough for an interesting instruction set for a register machine. It is however enough for a stack machine or something similar with implicit operands, but then again you need more instructions for the same task than with a register machine.
- prutschman 13y agoIf you search for the phrase "To add more 'regular' instructions" in part 1, you'll see where he references 8 or 9 bit instructions. The author goes on, in subsequent sections, to expand the idea of tokenized jump references to tokenized instructions. Each instruction token may only be 8 or 9 bits, but the secondary memory which contains jump targets is expanded to also contain full-width instructions. The operating hypothesis is that just it's desirable to be able to "reach" any 32-bit destination address despite any given code segment not needing that flexibility, it's likewise desirable to be able to execute any, say, 36-bit instruction even though any given code segment only needs a subset of them. It's really worth a read.
- mamcx 13y agoFor what I get from this, that is not the only advantage. Also the ability to expand the registers, the easy interpreter and the scalability of it.
- danbruc 13y agoI have to admit I did not read all the parts. I looked at the function call related thing first and it was not convincing enough to me to bother reading the remaining parts.