Normalization routine
We have already studied the normalization routine ("nrm2x") in the floating point article. In this routine the number is set up in normalized form (mantissa and exponent).
There are 2 normalization processes :
- left scaling (shift to the left and decrease exponent), in the case of non significant zeros (nrm23),
shift left a[w]
c - 1 -> c[x]
On exit, we go to nrm24, address 02317 ; in the case of A register = 0 control may fall through nrm24, putting a zero in register C.
- right scaling (shift to the right and increase exponent) in the case of “fraction overflow” (nrm24)
Routine nrm24’s task is right scaling. We have a fraction overflow when an addition exceeds the 10 bits length of the mantissa, and we have to a shifting right and a rounding to register A fraction part.
In this case, the least significant digit of the number in register A occupies the digit reserved for the exponent sign. So if we double the A exponent, we will have an overflow in fraction part sign.
This is the task of the 3 first lines of nrm24 and of the label "mpy28" in the floating point multiplication code:
nrm24: a -> b[x]
a + b -> a[w]
if a[s] >= 1 then go to mpy28
1) Floating
point 4 operations.
Let’s take the example of the subtraction of 10 - .0000000004
On entry in routine “nrm24” the registers are:
02326:
.1..1.1.1. nrm24: a -> b[x]
A=09999999999600 B=00000000000600 C=00000000000000
D=00000000000000 M=00000000000000 P=c S=0.....678..b
Then, we double register A exponent and the A fraction part sign byte becomes
“1” signalling thus the “fraction overflow”.
02327: 111...111. a + b -> a[w]
A=10000000000200
B=00000000000600 C=00000000000000
D=00000000000000 M=00000000000000 P=c S=0.....678..b
In this case, we branch to “mpy28” and after one shift right of A and one exponent increment of C, we exit thru nrm21, etc.
02334: ....1.111. 0 -> b[w]
A=01000000000001
B=00000000000000 C=01000000000001
D=00000000000000 M=00000000000000 P=c S=0.....678..b
The end of normalization is quite simple (see flow chart):
The whole result
(fraction part and exponent) is placed in C ( a exchange c[m] ) then in A
( c -> a[w] ) and B finally is zeroed ( 0 -> b[w] ).
nrm26: if s2 = 0 then go to rtn21
return
rtn21: select rom 1 ; goto rtn11
rtn11: if s1 = 0
then go to rtn12
return
rtn12: select rom 0 ; goto 00333
00333: jsb of13
....
The process will call next the output format routine (jsb of13) whose task is to create mask and display registers (see the "output format" article) and to end in the display and waiting loop.
2) Other math routines.
The same scheme is
used in the other math routines (see the relevant article for details).
Let’s have a look at the trace of the logarithm algorithm:
ln() 02311: if p # 13 02312: then go to mpy27 02313: c + 1 -> c[x] 02314: nrm21: 0 -> a[s] 02315: 12 -> p 02316: 0 -> b[w] 02317: nrm23: if a[p] >= 1 02320: then go to nrm24 02321: shift left a[w] 02322: c - 1 -> c[x] 02323: if a[w] >= 1 02324: then go to nrm23 02317: nrm23: if a[p] >= 1 02320: then go to nrm24 02321: shift left a[w] 02322: c - 1 -> c[x] 02323: if a[w] >= 1 02324: then go to nrm23 02317: nrm23: if a[p] >= 1 02320: then go to nrm24 02321: shift left a[w] 02322: c - 1 -> c[x] 02323: if a[w] >= 1 02324: then go to nrm23 02317: nrm23: if a[p] >= 1 02320: then go to nrm24 02326: nrm24: a -> b[x] 02327: a + b -> a[w] 02330: if a[s] >= 1 02331: then go to mpy28 02332: a exchange c[m] 02333: c -> a[w] 02334: 0 -> b[w] 02335: nrm27: 12 -> p 02336: go to nrm26 02172: nrm26: if s2 = 0 02173: then go to rtn21 02174: return 02073: if s9 = 0 02074: then go to xty22 02075: if s5 = 0 02076: then go to rtn21 02224: rtn21: select rom 1 01225: rtn11: if s1 = 0 01226: then go to rtn12 01332: rtn12: select rom 0 00333: l00333: jsb of13 |
After the ln computation, control goes to “nrm21” to normalized the result, before bailing out to rtn21 (the “2” mean Rom 2) and then to “rtn12” and finally to address 333 where a call is issued to format the output context before ending at address 367 “fst2zx” to call “dsp1”.
Let’s take now the example of the square root routine, where the same path is followed, but via the relay “tnm12”.
sqt(x) 01256: sqt17: shift right c[wp] 01257: if p # 0 01260: then go to sqt16 01261: go to tnm12 01055: tnm12: c -> a[w] 01056: b -> c[x] 01057: go to add15 01313: add15: select rom 2 02314: nrm21: 0 -> a[s] 02315: 12 -> p 02316: 0 -> b[w] 02317: nrm23: if a[p] >= 1 02320: then go to nrm24 02326: nrm24: a -> b[x] 02327: a + b -> a[w] 02330: if a[s] >= 1 02331: then go to mpy28 02332: a exchange c[m] 02333: c -> a[w] 02334: 0 -> b[w] 02335: nrm27: 12 -> p 02336: go to nrm26 02172: nrm26: if s2 = 0 02173: then go to rtn21 02224: rtn21: select rom 1 01225: rtn11: if s1 = 0 01226: then go to rtn12 01332: rtn12: select rom 0 00333: l00333: jsb of13 |
Finally, in the exponential routine ex same process, exception made of the inter ROMs relays used.
02220: if no carry go to exp22 02221: a exchange b[w] 02222: a + 1 -> a[p] 02223: jsb nrm21 02314: nrm21: 0 -> a[s] 02315: 12 -> p 02316: 0 -> b[w] 02317: nrm23: if a[p] >= 1 02320: then go to nrm24 02326: nrm24: a -> b[x] 02327: a + b -> a[w] 02330: if a[s] >= 1 02331: then go to mpy28 02332: a exchange c[m] 02333: c -> a[w] 02334: 0 -> b[w] 02335: nrm27: 12 -> p 02336: go to nrm26 02172: nrm26: if s2 = 0 02173: then go to rtn21 02174: return 02224: rtn21: select rom 1 01225: rtn11: if s1 = 0 01226: then go to rtn12 01332: rtn12: select rom 0 00333: l00333: jsb of13 |
J. Laporte
Monday, 27 February 2006