|
@@ -155,105 +155,6 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-{$push}
|
|
|
-{$r-}
|
|
|
-{$q-}
|
|
|
-{ helper function which calculate "magic" values for replacement of unsigned
|
|
|
- division by constant operation by multiplication. See the PowerPC compiler
|
|
|
- developer manual for more information }
|
|
|
-procedure getmagic_unsignedN(const N : byte; const d : aWord;
|
|
|
- out magic_m : aWord; out magic_add : boolean; out magic_shift : byte);
|
|
|
-var
|
|
|
- p : aInt;
|
|
|
- nc, delta, q1, r1, q2, r2, two_N_minus_1 : aWord;
|
|
|
-begin
|
|
|
- assert(d > 0);
|
|
|
-
|
|
|
- two_N_minus_1 := aWord(1) shl (N-1);
|
|
|
-
|
|
|
- magic_add := false;
|
|
|
-{$push}
|
|
|
-{$warnings off }
|
|
|
- nc := aWord(-1) - (-d) mod d;
|
|
|
-{$pop}
|
|
|
- p := N-1; { initialize p }
|
|
|
- q1 := two_N_minus_1 div nc; { initialize q1 = 2p/nc }
|
|
|
- r1 := two_N_minus_1 - q1*nc; { initialize r1 = rem(2p,nc) }
|
|
|
- q2 := (two_N_minus_1-1) div d; { initialize q2 = (2p-1)/d }
|
|
|
- r2 := (two_N_minus_1-1) - q2*d; { initialize r2 = rem((2p-1),d) }
|
|
|
- repeat
|
|
|
- inc(p);
|
|
|
- if (r1 >= (nc - r1)) then begin
|
|
|
- q1 := 2 * q1 + 1; { update q1 }
|
|
|
- r1 := 2*r1 - nc; { update r1 }
|
|
|
- end else begin
|
|
|
- q1 := 2*q1; { update q1 }
|
|
|
- r1 := 2*r1; { update r1 }
|
|
|
- end;
|
|
|
- if ((r2 + 1) >= (d - r2)) then begin
|
|
|
- if (q2 >= (two_N_minus_1-1)) then
|
|
|
- magic_add := true;
|
|
|
- q2 := 2*q2 + 1; { update q2 }
|
|
|
- r2 := 2*r2 + 1 - d; { update r2 }
|
|
|
- end else begin
|
|
|
- if (q2 >= two_N_minus_1) then
|
|
|
- magic_add := true;
|
|
|
- q2 := 2*q2; { update q2 }
|
|
|
- r2 := 2*r2 + 1; { update r2 }
|
|
|
- end;
|
|
|
- delta := d - 1 - r2;
|
|
|
- until not ((p < (2*N)) and ((q1 < delta) or ((q1 = delta) and (r1 = 0))));
|
|
|
- magic_m := q2 + 1; { resulting magic number }
|
|
|
- magic_shift := p - N; { resulting shift }
|
|
|
-end;
|
|
|
-
|
|
|
-{ helper function which calculate "magic" values for replacement of signed
|
|
|
- division by constant operation by multiplication. See the PowerPC compiler
|
|
|
- developer manual for more information }
|
|
|
-procedure getmagic_signedN(const N : byte; const d : aInt;
|
|
|
- out magic_m : aInt; out magic_s : aInt);
|
|
|
-var
|
|
|
- p : aInt;
|
|
|
- ad, anc, delta, q1, r1, q2, r2, t : aWord;
|
|
|
- two_N_minus_1 : aWord;
|
|
|
-
|
|
|
-begin
|
|
|
- assert((d < -1) or (d > 1));
|
|
|
-
|
|
|
- two_N_minus_1 := aWord(1) shl (N-1);
|
|
|
-
|
|
|
- ad := abs(d);
|
|
|
- t := two_N_minus_1 + (aWord(d) shr (N-1));
|
|
|
- anc := t - 1 - t mod ad; { absolute value of nc }
|
|
|
- p := (N-1); { initialize p }
|
|
|
- q1 := two_N_minus_1 div anc; { initialize q1 = 2p/abs(nc) }
|
|
|
- r1 := two_N_minus_1 - q1*anc; { initialize r1 = rem(2p,abs(nc)) }
|
|
|
- q2 := two_N_minus_1 div ad; { initialize q2 = 2p/abs(d) }
|
|
|
- r2 := two_N_minus_1 - q2*ad; { initialize r2 = rem(2p,abs(d)) }
|
|
|
- repeat
|
|
|
- inc(p);
|
|
|
- q1 := 2*q1; { update q1 = 2p/abs(nc) }
|
|
|
- r1 := 2*r1; { update r1 = rem(2p/abs(nc)) }
|
|
|
- if (r1 >= anc) then begin { must be unsigned comparison }
|
|
|
- inc(q1);
|
|
|
- dec(r1, anc);
|
|
|
- end;
|
|
|
- q2 := 2*q2; { update q2 = 2p/abs(d) }
|
|
|
- r2 := 2*r2; { update r2 = rem(2p/abs(d)) }
|
|
|
- if (r2 >= ad) then begin { must be unsigned comparison }
|
|
|
- inc(q2);
|
|
|
- dec(r2, ad);
|
|
|
- end;
|
|
|
- delta := ad - r2;
|
|
|
- until not ((q1 < delta) or ((q1 = delta) and (r1 = 0)));
|
|
|
- magic_m := q2 + 1;
|
|
|
- if (d < 0) then begin
|
|
|
- magic_m := -magic_m; { resulting magic number }
|
|
|
- end;
|
|
|
- magic_s := p - N; { resulting shift }
|
|
|
-end;
|
|
|
-{$pop}
|
|
|
-
|
|
|
{ finds positive and negative powers of two of the given value, returning the
|
|
|
power and whether it's a negative power or not in addition to the actual result
|
|
|
of the function }
|
|
@@ -710,7 +611,7 @@ var
|
|
|
const
|
|
|
negops : array[boolean] of tasmop = (A_NEG, A_NEGO);
|
|
|
var
|
|
|
- magic, shift : int64;
|
|
|
+ magic : int64;
|
|
|
u_magic : qword;
|
|
|
u_shift : byte;
|
|
|
u_add : boolean;
|
|
@@ -742,7 +643,7 @@ var
|
|
|
{ from "The PowerPC Compiler Writer's Guide" pg. 53ff }
|
|
|
divreg := getintregister(list, OS_INT);
|
|
|
if (signed) then begin
|
|
|
- getmagic_signedN(sizeof(aInt)*8, a, magic, shift);
|
|
|
+ calc_divconst_magic_signed(sizeof(aInt)*8, a, magic, u_shift);
|
|
|
{ load magic value }
|
|
|
a_load_const_reg(list, OS_INT, magic, divreg);
|
|
|
{ multiply }
|
|
@@ -754,7 +655,7 @@ var
|
|
|
a_op_reg_reg_reg(list, OP_SUB, OS_INT, src, dst, dst);
|
|
|
end;
|
|
|
{ shift shift places to the right (arithmetic) }
|
|
|
- a_op_const_reg_reg(list, OP_SAR, OS_INT, shift, dst, dst);
|
|
|
+ a_op_const_reg_reg(list, OP_SAR, OS_INT, u_shift, dst, dst);
|
|
|
{ extract and add sign bit }
|
|
|
if (a >= 0) then begin
|
|
|
a_op_const_reg_reg(list, OP_SHR, OS_INT, 63, src, divreg);
|
|
@@ -763,7 +664,7 @@ var
|
|
|
end;
|
|
|
a_op_reg_reg_reg(list, OP_ADD, OS_INT, dst, divreg, dst);
|
|
|
end else begin
|
|
|
- getmagic_unsignedN(sizeof(aWord)*8, a, u_magic, u_add, u_shift);
|
|
|
+ calc_divconst_magic_unsigned(sizeof(aWord)*8, a, u_magic, u_add, u_shift);
|
|
|
{ load magic in divreg }
|
|
|
a_load_const_reg(list, OS_INT, aint(u_magic), divreg);
|
|
|
list.concat(taicpu.op_reg_reg_reg(A_MULHDU, dst, src, divreg));
|