Up

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