@@ -85,18 +85,16 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
8585 elf_offset += 4 ;
8686 return ;
8787 case OP_div :
88- if (hard_mul_div ) {
89- elf_offset += 4 ;
90- } else {
91- elf_offset += 104 ;
92- }
93- return ;
9488 case OP_mod :
9589 if (hard_mul_div ) {
96- elf_offset += 12 ;
97- } else {
98- elf_offset += 104 ;
90+ if (ph2_ir -> op == OP_div )
91+ elf_offset += 4 ;
92+ else
93+ elf_offset += 12 ;
94+ return ;
9995 }
96+ /* div/mod emulation's offset */
97+ elf_offset += 116 ;
10098 return ;
10199 case OP_load_data_address :
102100 elf_offset += 8 ;
@@ -193,6 +191,11 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
193191 int rm = ph2_ir -> src1 ;
194192 int ofs ;
195193
194+ /* Prepare this variable to reuse the same code for
195+ * the instruction sequence of division and modulo.
196+ */
197+ arm_reg soft_div_rd = __r8 ;
198+
196199 switch (ph2_ir -> op ) {
197200 case OP_define :
198201 emit (__sw (__AL , __lr , __sp , -4 ));
@@ -335,76 +338,69 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
335338 emit (__mul (__AL , rd , rn , rm ));
336339 return ;
337340 case OP_div :
338- if (hard_mul_div ) {
339- emit (__div (__AL , rd , rm , rn ));
340- } else {
341- /* Obtain absolute values of dividend and divisor */
342- emit (__srl_amt (__AL , 0 , arith_rs , __r8 , rn , 31 ));
343- emit (__add_r (__AL , rn , rn , __r8 ));
344- emit (__eor_r (__AL , rn , rn , __r8 ));
345- emit (__srl_amt (__AL , 0 , arith_rs , __r9 , rm , 31 ));
346- emit (__add_r (__AL , rm , rm , __r9 ));
347- emit (__eor_r (__AL , rm , rm , __r9 ));
348- emit (__eor_r (__AL , __r10 , __r8 , __r9 ));
349- /* Unsigned integer division */
350- emit (__zero (__r9 ));
351- emit (__mov_i (__AL , __r8 , 1 ));
352- emit (__cmp_i (__AL , rm , 0 ));
353- emit (__b (__EQ , 52 ));
354- emit (__cmp_i (__AL , rn , 0 ));
355- emit (__b (__EQ , 44 ));
356- emit (__cmp_r (__AL , rm , rn ));
357- emit (__sll_amt (__CC , 0 , logic_ls , rm , rm , 1 ));
358- emit (__sll_amt (__CC , 0 , logic_ls , __r8 , __r8 , 1 ));
359- emit (__b (__CC , -12 ));
360- emit (__cmp_r (__AL , rn , rm ));
361- emit (__sub_r (__CS , rn , rn , rm ));
362- emit (__add_r (__CS , __r9 , __r9 , __r8 ));
363- emit (__srl_amt (__AL , 1 , logic_rs , __r8 , __r8 , 1 ));
364- emit (__srl_amt (__CC , 0 , logic_rs , rm , rm , 1 ));
365- emit (__b (__CC , -20 ));
366- emit (__mov_r (__AL , rd , __r9 ));
367- /* Handle the correct sign for quotient */
368- emit (__cmp_i (__AL , __r10 , 0 ));
369- emit (__rsb_i (__NE , rd , 0 , rd ));
370- }
371- return ;
372341 case OP_mod :
373342 if (hard_mul_div ) {
374- emit (__div (__AL , __r8 , rm , rn ));
375- emit (__mul (__AL , __r8 , rm , __r8 ));
376- emit (__sub_r (__AL , rd , rn , __r8 ));
377- } else {
378- /* Obtain absolute values of dividend and divisor */
379- emit (__srl_amt (__AL , 0 , arith_rs , __r8 , rn , 31 ));
380- emit (__add_r (__AL , rn , rn , __r8 ));
381- emit (__eor_r (__AL , rn , rn , __r8 ));
382- emit (__srl_amt (__AL , 0 , arith_rs , __r9 , rm , 31 ));
383- emit (__add_r (__AL , rm , rm , __r9 ));
384- emit (__eor_r (__AL , rm , rm , __r9 ));
343+ if (ph2_ir -> op == OP_div )
344+ emit (__div (__AL , rd , rm , rn ));
345+ else {
346+ emit (__div (__AL , __r8 , rm , rn ));
347+ emit (__mul (__AL , __r8 , rm , __r8 ));
348+ emit (__sub_r (__AL , rd , rn , __r8 ));
349+ }
350+ return ;
351+ }
352+ /* div/mod emulation */
353+ /* Preserve the values of the dividend and divisor */
354+ emit (__stmdb (__AL , 1 , __sp , (1 << rn ) | (1 << rm )));
355+ /* Obtain absolute values of the dividend and divisor */
356+ emit (__srl_amt (__AL , 0 , arith_rs , __r8 , rn , 31 ));
357+ emit (__add_r (__AL , rn , rn , __r8 ));
358+ emit (__eor_r (__AL , rn , rn , __r8 ));
359+ emit (__srl_amt (__AL , 0 , arith_rs , __r9 , rm , 31 ));
360+ emit (__add_r (__AL , rm , rm , __r9 ));
361+ emit (__eor_r (__AL , rm , rm , __r9 ));
362+ if (ph2_ir -> op == OP_div )
363+ emit (__eor_r (__AL , __r10 , __r8 , __r9 ));
364+ else {
365+ /* If the requested operation is modulo, the result will be stored
366+ * in __r9. The sign of the divisor is irrelevant for determining
367+ * the result's sign.
368+ */
369+ soft_div_rd = __r9 ;
385370 emit (__mov_r (__AL , __r10 , __r8 ));
386- /* Unsigned integer division */
387- emit (__zero (__r9 ));
388- emit (__mov_i (__AL , __r8 , 1 ));
389- emit (__cmp_i (__AL , rm , 0 ));
390- emit (__b (__EQ , 52 ));
391- emit (__cmp_i (__AL , rn , 0 ));
392- emit (__b (__EQ , 44 ));
393- emit (__cmp_r (__AL , rm , rn ));
394- emit (__sll_amt (__CC , 0 , logic_ls , rm , rm , 1 ));
395- emit (__sll_amt (__CC , 0 , logic_ls , __r8 , __r8 , 1 ));
396- emit (__b (__CC , -12 ));
397- emit (__cmp_r (__AL , rn , rm ));
398- emit (__sub_r (__CS , rn , rn , rm ));
399- emit (__add_r (__CS , __r9 , __r9 , __r8 ));
400- emit (__srl_amt (__AL , 1 , logic_rs , __r8 , __r8 , 1 ));
401- emit (__srl_amt (__CC , 0 , logic_rs , rm , rm , 1 ));
402- emit (__b (__CC , -20 ));
403- emit (__mov_r (__AL , rd , rn ));
404- /* Handle the correct sign for remainder */
405- emit (__cmp_i (__AL , __r10 , 0 ));
406- emit (__rsb_i (__NE , rd , 0 , rd ));
407371 }
372+ /* Unsigned integer division */
373+ emit (__zero (__r8 ));
374+ emit (__mov_i (__AL , __r9 , 1 ));
375+ emit (__cmp_i (__AL , rm , 0 ));
376+ emit (__b (__EQ , 52 ));
377+ emit (__cmp_i (__AL , rn , 0 ));
378+ emit (__b (__EQ , 44 ));
379+ emit (__cmp_r (__AL , rm , rn ));
380+ emit (__sll_amt (__CC , 0 , logic_ls , rm , rm , 1 ));
381+ emit (__sll_amt (__CC , 0 , logic_ls , __r9 , __r9 , 1 ));
382+ emit (__b (__CC , -12 ));
383+ emit (__cmp_r (__AL , rn , rm ));
384+ emit (__sub_r (__CS , rn , rn , rm ));
385+ emit (__add_r (__CS , __r8 , __r8 , __r9 ));
386+ emit (__srl_amt (__AL , 1 , logic_rs , __r9 , __r9 , 1 ));
387+ emit (__srl_amt (__CC , 0 , logic_rs , rm , rm , 1 ));
388+ emit (__b (__CC , -20 ));
389+ /* After completing the emulation, the quotient and remainder
390+ * will be stored in __r8 and __r9, respectively.
391+ *
392+ * The original values of the dividend and divisor will be
393+ * restored in rn and rm.
394+ *
395+ * Finally, the result (quotient or remainder) will be stored
396+ * in rd.
397+ */
398+ emit (__mov_r (__AL , __r9 , rn ));
399+ emit (__ldm (__AL , 1 , __sp , (1 << rn ) | (1 << rm )));
400+ emit (__mov_r (__AL , rd , soft_div_rd ));
401+ /* Handle the correct sign for the quotient or remainder */
402+ emit (__cmp_i (__AL , __r10 , 0 ));
403+ emit (__rsb_i (__NE , rd , 0 , rd ));
408404 return ;
409405 case OP_lshift :
410406 emit (__sll (__AL , rd , rn , rm ));
0 commit comments