I’m writing my own 64-bit integer math routines for RV32. Call me crazy. Actually, it’s for the RISC-V target of my Forth cross-compiler project, muforth.
Having never written assembler code for an architecture that lacks condition codes, I was at first at a loss about how to approach the problem. After some thinking, I realized that I could use the SLTU instruction to calculate the carry (for add) and borrow (for subtract). I tested that code, and it seems to work correctly.
But doing 64-bit signed and unsigned compares - especially doing it without any branch instructions - mystified me even more. I initially tried to modify my 64-bit subtraction code, but I kept getting wrong answers.
After yet more thinking, I realized a way to get the correct answer, but it requires the use of a conditional branch.
Here is my method:
-
Compare the high-order words. If they are equal, return as the result the unsigned comparison of the low-order words.
-
Otherwise, ignore the low-order words and:
- For unsigned values, return the unsigned comparison of the high-order words
- For signed values, return the signed comparison of the high-order words
I tested this code and it seems to work, but it requires a BEQ or BNE instruction and two separate code paths. What I am wondering is, am I missing something? Is there a better way?
Sorry about the re-invention of the wheel here.