-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement division and modulo for RV32I #134
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code generator for division and modulo has only 2 instructions in difference.
--- codegen-div.c
+++ codegen-mod.c
@@ -7,7 +7,7 @@
emit(__srai(__t1, __t3, 31));
emit(__add(__t3, __t3, __t1));
emit(__xor(__t3, __t3, __t1));
- emit(__xor(__t5, __t0, __t1));
+ emit(__addi(__t5, __t0, 0));
/* Unsigned integer division */
emit(__addi(__t0, __zero, 0));
emit(__addi(__t1, __zero, 1));
@@ -23,7 +23,7 @@
emit(__srli(__t1, __t1, 1));
emit(__srli(__t3, __t3, 1));
emit(__bne(__t1, __zero, -20));
- emit(__addi(rd, __t0, 0));
- /* Handle the correct sign for the quotient */
+ emit(__addi(rd, __t2, 0));
+ /* Handle the correct sign for the remainder */
emit(__beq(__t5, __zero, 8));
emit(__sub(rd, __zero, rd));
Thus, we can introduce a helper function to generate div/mod emulation instructions, enhancing code reusability.
A similar case for div/mod emulation instruction generation exists in the Arm backend. Let's refine the RISC-V backend in this pull request and address the Arm backend in another. |
Yes, the proposed changes can be improved to enhance code reusability. I will refine the RISC-V backend first and submit another pull request for refining the Arm backend. |
Rather than adding a helper function, I thought of another approach that adds two local variables in |
src/riscv-codegen.c
Outdated
/* Prepare the variables to reuse the same code for | ||
* the instruction sequence of division and modulo. | ||
*/ | ||
rv_reg soft_div_rd = __t0, soft_div_rs2_sign_reg = __t1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
soft_div_rs2_sign_reg
looks weird. Can you shorten it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about renaming it as divisor_mask_reg
?
At the beginning of the emulation, it obtains the absolute values of the dividend and divisor using the following approach.
int32_t abs(int32_t x)
{
int32_t mask = x >> 31; /* arithmetic right shift */
return (x + mask) ^ mask
}
Therefore, the register __t1
will store 0
or 0xFFFFFFFF
initially, indicating that it serves as the mask for the divisor.
(Similarly, __t0
will be the mask for the dividend.)
If the requested operation is division, divisor_mask_reg
will be __t1
and helps to determine the result's sign. Otherwise, for the modulo operation, because it only needs the dividend's mask to determine the result's sign, divisor_mask_reg
becomes unnecessary and is assigned to __zero
so that it doesn't affect the result's sign.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simply name it divisor_mask
as it is intended to behave as its name suggests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Execute git rebase -i
to squash the commits.
This commit allows shecc to generate a sequence of instructions to perform division or modulo for RISC-V targets with RV32I only. Close sysprog21#46
Thank @DrXiao for contributing! |
This commit allows shecc to generate a sequence of instructions to perform division or modulo for RISC-V targets with RV32I only.
Close #46