Skip to content

Commit

Permalink
Implement division and modulo for RV32I
Browse files Browse the repository at this point in the history
This commit allows shecc to generate a sequence of
instructions to perform division or modulo for RISC-V
targets with RV32I only.

Close #46
  • Loading branch information
DrXiao committed Jun 20, 2024
1 parent 1faf508 commit c399550
Showing 1 changed file with 73 additions and 4 deletions.
77 changes: 73 additions & 4 deletions src/riscv-codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
case OP_indirect:
case OP_add:
case OP_sub:
case OP_div:
case OP_mod:
case OP_lshift:
case OP_rshift:
case OP_gt:
Expand All @@ -70,6 +68,13 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
else
elf_offset += 52;
return;
case OP_div:
case OP_mod:
if (hard_mul_div)
elf_offset += 4;
else
elf_offset += 104;
return;
case OP_load_data_address:
case OP_neq:
case OP_geq:
Expand Down Expand Up @@ -307,10 +312,74 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
}
return;
case OP_div:
emit(__div(rd, rs1, rs2));
if (hard_mul_div)
emit(__div(rd, rs1, rs2));
else {
/* Obtain absolute values of the dividend and divisor */
emit(__addi(__t2, rs1, 0));
emit(__addi(__t3, rs2, 0));
emit(__srai(__t0, __t2, 31));
emit(__add(__t2, __t2, __t0));
emit(__xor(__t2, __t2, __t0));
emit(__srai(__t1, __t3, 31));
emit(__add(__t3, __t3, __t1));
emit(__xor(__t3, __t3, __t1));
emit(__xor(__t5, __t0, __t1));
/* Unsigned integer division */
emit(__addi(__t0, __zero, 0));
emit(__addi(__t1, __zero, 1));
emit(__beq(__t3, __zero, 48));
emit(__beq(__t2, __zero, 44));
emit(__bltu(__t2, __t3, 16));
emit(__slli(__t3, __t3, 1));
emit(__slli(__t1, __t1, 1));
emit(__jal(__zero, -12));
emit(__bltu(__t2, __t3, 12));
emit(__sub(__t2, __t2, __t3));
emit(__add(__t0, __t0, __t1));
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(__beq(__t5, __zero, 8));
emit(__sub(rd, __zero, rd));
}
return;
case OP_mod:
emit(__mod(rd, rs1, rs2));
if (hard_mul_div)
emit(__mod(rd, rs1, rs2));
else {
/* Obtain absolute values of the dividend and divisor */
emit(__addi(__t2, rs1, 0));
emit(__addi(__t3, rs2, 0));
emit(__srai(__t0, __t2, 31));
emit(__add(__t2, __t2, __t0));
emit(__xor(__t2, __t2, __t0));
emit(__srai(__t1, __t3, 31));
emit(__add(__t3, __t3, __t1));
emit(__xor(__t3, __t3, __t1));
emit(__addi(__t5, __t0, 0));
/* Unsigned integer division */
emit(__addi(__t0, __zero, 0));
emit(__addi(__t1, __zero, 1));
emit(__beq(__t3, __zero, 48));
emit(__beq(__t2, __zero, 44));
emit(__bltu(__t2, __t3, 16));
emit(__slli(__t3, __t3, 1));
emit(__slli(__t1, __t1, 1));
emit(__jal(__zero, -12));
emit(__bltu(__t2, __t3, 12));
emit(__sub(__t2, __t2, __t3));
emit(__add(__t0, __t0, __t1));
emit(__srli(__t1, __t1, 1));
emit(__srli(__t3, __t3, 1));
emit(__bne(__t1, __zero, -20));
emit(__addi(rd, __t2, 0));
/* Handle the correct sign for the remainder */
emit(__beq(__t5, __zero, 8));
emit(__sub(rd, __zero, rd));
}
return;
case OP_lshift:
emit(__sll(rd, rs1, rs2));
Expand Down

0 comments on commit c399550

Please sign in to comment.