3 ms·
This is interesting to hear, and surprising. What are the provisions for efficient handling of integer overflows & underflows? I took a quick look at the ISA
by kannanvijayan 8y ago
This is interesting to hear, and surprising. What are the provisions for efficient handling of integer overflows & underflows? I took a quick look at the ISA spec and am trying to track down how this is handled, as a curiosity.
- jabl 8y agoAFAIU, none. It's designed for C, essentially, where signed integer overflows are undefined. In practice, the easiest and fastest design is to have it wrap around, just like unsigned. I'm not sure I agree with that particular design decision, considering newer languages such as Rust that want to detect overflows. Then again, if/when such languages become more important, I guess RISC-V could add an extension featuring some kind of trapping overflow (or whatever mechanism is deemed best).
- zozbot123 8y agoThe RISC-V spec does claim that "many overflow checks can be cheaply implemented using branches" and then provides recommended instruction sequences. One could definitely imagine a RV implementation where e.g. macro-op fusion is used to systematically turn some of these recommended sequences into hardware-assisted branches. (Ref: search for the "Integer Computational Instructions" section in the RISC-V "user mode" reference. It should be section 2.4)
- nickik 8y agoThis. Also the J extention should add some more stuff in that direction.
- brucehoult 8y agoNot mentioned there: you can if you want replace the BLTU (for carry) with a SLTU to set a register to 0 if no carry and 1 if there is a carry, effectively getting you a condition code register in a normal register, at the cost of one instruction (or three for signed overflow). If you're going to be doing a lot of signed overflow checking (e.g. JavaScript) it may be better to store your numbers as N+0x8000000 (for 32 bit). Then each addition needs to subtract the offset afterwards, and each subtraction needs to add it (which works out to the same thing). The overflow check is then a single branch after the add and the adjust, for a total of three instructions instead of a total of four. This seems bad, but if you're loading the values from memory and putting them back afterwards then it's pretty minor. A later extension (such as J) could add instructions such as BADC/BADV/BSUC/BSUV a,b,label -- "Branch if ADd generates Carry" etc. These would fit into the existing instruction encoding and execution pipelines no problem. Or, if this is a rare thing (as it should be in JavaScript) then making them "Trap if ADd generates oVerflow" would take a tiny amount of opcode space and allow the trap handler (which can be delegated to User space) to perhaps transparently fix up the result.
- kannanvijayan 8y agoI can appreciate the implementation benefits in not having a single mutating global state register. One option I just thought of is simply to have multi-output variants of the instruction which would take an extra flags register as an output operand. Anyway that's really interesting to find out. It would complicate the optimized implementation of JS engines, which need it to promote int32 arithmetic to doubles where needed, which is what I was thinking of when I asked the question.