357fdcb2d905f31492ad961d94578bc73d1f83dd
[nmutil.git] / src / nmutil / divmod.py
1 from copy import copy
2 # this is a POWER ISA 3.0B compatible *signed* div function
3 # however it is also the c, c++, rust, java *and* x86 way of doing things
4
5
6 def trunc_divs(n, d):
7 abs_n = abs(n.to_signed_int())
8 abs_d = abs(d.to_signed_int())
9 print("trunc_div n", abs_n, n.to_signed_int())
10 print("trunc_div d", abs_d, d.to_signed_int())
11 abs_q = abs_n // abs_d
12 sign_n = n.value & (1 << (n.bits - 1)) != 0
13 sign_d = d.value & (1 << (d.bits - 1)) != 0
14 print("trunc_div", hex(n.value), hex(d.value),
15 hex(abs_n), hex(abs_d), hex(abs_q),
16 sign_n, sign_d)
17 res = copy(n)
18 if (sign_n == sign_d):
19 res.value = abs_q
20 if res.value & (1 << (res.bits - 1)) != 0:
21 # result should be positive but is negative
22 raise OverflowError()
23 return res
24 mask = (1 << res.bits) - 1
25 res.value = (-abs_q) & mask
26
27 return res
28
29
30 # this is a POWER ISA 3.0B compatible *signed* mod / remainder function
31 # however it is also the c, c++, rust, java *and* x86 way of doing things
32 def trunc_rems(n, d):
33 m = d * trunc_divs(n, d)
34
35 # cheat - really shouldn't do this. mul returns full length
36 m.bits = n.bits
37 return n - m