@@ -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