Skip to content

Commit 6cdd7e2

Browse files
authored
Merge pull request #134 from DrXiao/master
Implement division and modulo for RV32I
2 parents 1faf508 + 17fe9fd commit 6cdd7e2

File tree

1 file changed

+57
-5
lines changed

1 file changed

+57
-5
lines changed

src/riscv-codegen.c

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
5050
case OP_indirect:
5151
case OP_add:
5252
case OP_sub:
53-
case OP_div:
54-
case OP_mod:
5553
case OP_lshift:
5654
case OP_rshift:
5755
case OP_gt:
@@ -70,6 +68,13 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
7068
else
7169
elf_offset += 52;
7270
return;
71+
case OP_div:
72+
case OP_mod:
73+
if (hard_mul_div)
74+
elf_offset += 4;
75+
else
76+
elf_offset += 104;
77+
return;
7378
case OP_load_data_address:
7479
case OP_neq:
7580
case OP_geq:
@@ -152,6 +157,11 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
152157
int rs2 = ph2_ir->src1 + 10;
153158
int ofs;
154159

160+
/* Prepare the variables to reuse the same code for
161+
* the instruction sequence of division and modulo.
162+
*/
163+
rv_reg soft_div_rd = __t0, divisor_mask = __t1;
164+
155165
switch (ph2_ir->op) {
156166
case OP_define:
157167
emit(__lui(__t0, rv_hi(ph2_ir->src0 + 4)));
@@ -307,10 +317,52 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
307317
}
308318
return;
309319
case OP_div:
310-
emit(__div(rd, rs1, rs2));
311-
return;
312320
case OP_mod:
313-
emit(__mod(rd, rs1, rs2));
321+
if (hard_mul_div) {
322+
if (ph2_ir->op == OP_div)
323+
emit(__div(rd, rs1, rs2));
324+
else
325+
emit(__mod(rd, rs1, rs2));
326+
return;
327+
}
328+
/* div/mod emulation */
329+
if (ph2_ir->op == OP_mod) {
330+
/* If the requested operation is modulo, the result will be stored
331+
* in __t2. The sign of the divisor is irrelevant for determining
332+
* the result's sign.
333+
*/
334+
soft_div_rd = __t2;
335+
divisor_mask = __zero;
336+
}
337+
/* Obtain absolute values of the dividend and divisor */
338+
emit(__addi(__t2, rs1, 0));
339+
emit(__addi(__t3, rs2, 0));
340+
emit(__srai(__t0, __t2, 31));
341+
emit(__add(__t2, __t2, __t0));
342+
emit(__xor(__t2, __t2, __t0));
343+
emit(__srai(__t1, __t3, 31));
344+
emit(__add(__t3, __t3, __t1));
345+
emit(__xor(__t3, __t3, __t1));
346+
emit(__xor(__t5, __t0, divisor_mask));
347+
/* Unsigned integer division */
348+
emit(__addi(__t0, __zero, 0));
349+
emit(__addi(__t1, __zero, 1));
350+
emit(__beq(__t3, __zero, 48));
351+
emit(__beq(__t2, __zero, 44));
352+
emit(__bltu(__t2, __t3, 16));
353+
emit(__slli(__t3, __t3, 1));
354+
emit(__slli(__t1, __t1, 1));
355+
emit(__jal(__zero, -12));
356+
emit(__bltu(__t2, __t3, 12));
357+
emit(__sub(__t2, __t2, __t3));
358+
emit(__add(__t0, __t0, __t1));
359+
emit(__srli(__t1, __t1, 1));
360+
emit(__srli(__t3, __t3, 1));
361+
emit(__bne(__t1, __zero, -20));
362+
emit(__addi(rd, soft_div_rd, 0));
363+
/* Handle the correct sign for the quotient or remainder */
364+
emit(__beq(__t5, __zero, 8));
365+
emit(__sub(rd, __zero, rd));
314366
return;
315367
case OP_lshift:
316368
emit(__sll(rd, rs1, rs2));

0 commit comments

Comments
 (0)