[Vm-dev] VM Maker: VMMaker.oscog-nice.1744.mcz
commits at source.squeak.org
commits at source.squeak.org
Sun Mar 27 22:37:18 UTC 2016
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1744.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1744
Author: nice
Time: 28 March 2016, 12:30:43.777 am
UUID: f0299599-4f32-422e-b4de-edbd3f35c594
Ancestors: VMMaker.oscog-nice.1743
Correct the LargeInteger division bug I've just introduced by declaring some variable unsigned.
Note: the easiest correction would be to restore the signed declaration of hi/lo.
Indeed, signed variable are going to work because we don't fear that (unsigned char)*(unsigned char) would overflow MAX_INT (it uses at most 16 bits, and we have 31).
I keep those variable unsigned though because it ain't gonna scale with 32 bit limbs...
(unsigned int)*(unsigned int) might overflow (signed long long).
=============== Diff against VMMaker.oscog-nice.1743 ===============
Item was changed:
----- Method: LargeIntegersPlugin>>cDigitDiv:len:rem:len:quo:len: (in category 'C core') -----
cDigitDiv: pDiv len: divLen rem: pRem len: remLen quo: pQuo len: quoLen
| dl ql dh dnh j t hi lo r3 l a cond q r1r2 mul b |
<var: #pDiv type: #'unsigned char *'>
<var: #pRem type: #'unsigned char *'>
<var: #pQuo type: #'unsigned char *'>
<var: #dh type: #'unsigned int'>
<var: #dnh type: #'unsigned int'>
<var: #r3 type: #'unsigned int'>
<var: #q type: #'unsigned int'>
<var: #a type: #'unsigned int'>
<var: #b type: #'unsigned int'>
<var: #t type: #'unsigned int'>
<var: #mul type: #'unsigned int'>
<var: #hi type: #'unsigned int'>
<var: #lo type: #'unsigned int'>
<var: #r1r2 type: #'unsigned int'>
dl := divLen - 1.
"Last actual byte of data (ST ix)"
ql := quoLen.
dh := pDiv at: dl - 1.
dl = 1
ifTrue: [dnh := 0]
ifFalse: [dnh := pDiv at: dl - 2].
1 to: ql do:
[:k |
"maintain quo*arg+rem=self"
"Estimate rem/div by dividing the leading two digits of rem by dh."
"The estimate is q = qhi*16r100+qlo, where qhi and qlo are unsigned char."
j := remLen + 1 - k.
"r1 := rem digitAt: j."
(pRem at: j - 1)
= dh
ifTrue: [q := 16rFF]
ifFalse:
["Compute q = (r1,r2)//dh, t = (r1,r2)\\dh."
"r2 := (rem digitAt: j - 2)."
r1r2 := pRem at: j - 1.
r1r2 := (r1r2 << 8) + (pRem at: j - 2).
t := r1r2 \\ dh.
q := r1r2 // dh.
"Next compute (hi,lo) := q*dnh"
mul := q * dnh.
hi := mul >> 8.
lo := mul bitAnd: 16rFF.
"Correct overestimate of q.
Max of 2 iterations through loop -- see Knuth vol. 2"
j < 3
ifTrue: [r3 := 0]
ifFalse: [r3 := pRem at: j - 3].
[(t < hi
or: [t = hi and: [r3 < lo]])
ifTrue:
["i.e. (t,r3) < (hi,lo)"
q := q - 1.
+ hi = 0 "since hi is unsigned we must have this guard"
+ ifTrue: [cond := false]
- lo < dnh
- ifTrue:
- [hi := hi - 1.
- lo := lo + 16r100 - dnh]
ifFalse:
+ [lo < dnh
+ ifTrue:
+ [hi := hi - 1.
+ lo := lo + 16r100 - dnh]
+ ifFalse:
+ [lo := lo - dnh].
+ cond := hi >= dh]]
- [lo := lo - dnh].
- cond := hi >= dh]
ifFalse: [cond := false].
cond]
whileTrue: [hi := hi - dh]].
"Subtract q*div from rem"
l := j - dl.
a := 0.
1 to: divLen do:
[:i |
hi := (pDiv at: i - 1) * (q >> 8).
lo := (pDiv at: i - 1) * (q bitAnd: 16rFF).
b := (pRem at: l - 1) - a - (lo bitAnd: 16rFF).
pRem at: l - 1 put: (b bitAnd: 16rFF).
"BEWARE: signed shift is implementation defined in C..."
b := b signedBitShift: -8.
"This is a possible replacement to simulate arithmetic shift (preserving sign of b)"
"b := b >> 8 bitOr: (0 - (b >> ((interpreterProxy sizeof: b)*8""CHAR_BIT""-1)) << 8)."
a := hi + (lo >> 8) - b.
l := l + 1].
a > 0
ifTrue:
["Add div back into rem, decrease q by 1"
q := q - 1.
l := j - dl.
a := 0.
1 to: divLen do:
[:i |
a := (a >> 8)
+ (pRem at: l - 1) + (pDiv at: i - 1).
pRem at: l - 1 put: (a bitAnd: 16rFF).
l := l + 1]].
pQuo at: quoLen - k put: q].
^0!
More information about the Vm-dev
mailing list