Finally, here is the complete map of the HP35 ROM 2 (256 instructions of 10 bits each).

ROM 2 contains the code for:
- Cordic routines for log (ln), ex and xy,
- prescaling routines,
- mutiplication and division,
- and result normalization.

 02000: err21: select rom 0 goto blinking display (0001) 02001: ln24: a exchange b[s] Computation of a new constant (2, 1.1, 1.01, 1.001 etc) 02002: a + 1 -> a[s] # SR ++ 02003: shift right c[ms] Make room for the next qj 02004: shift left a[wp] align left 02005: go to ln26 02006: xty22: stack -> a ax  is evaluated as ln(a) . x (see at 02074) 02007: jsb mpy21 02010: c -> a[w] Main entry point for ex and log 02011: if s8 = 0 If S8 = 0 -> ex 02012: then go to exp21 If S8 = 1 -> log (ln) 02013: 0 -> a[w] 02014: a - c -> a[m] Complement X for ln(X) 02015: if no carry go to err21 Goto error if ln(negative) 02016: shift right a[w] 02017: c - 1 -> c[s] 02020: if no carry go to err21 02021: ln25: c + 1 -> c[s] Prepare registers to compute pseudo quotients q0 q1  q5 02022: ln26: a -> b[w] 02023: jsb eca22 Call the "eca" routine to compute qj 02024: a - 1 -> a[p] complementation 02025: if no carry go to ln25 one more time for the same constant 02026: a exchange b[wp] 02027: a + b -> a[s] # of SR x 2 02030: if no carry go to ln24 test for 5 constants only 02031: 7 -> p Part 2 : pseudo multiplications to compute ∑ qj ln (1 + 10 j) 02032: jsb pqo23 02033: 8 -> p 02034: jsb pmu22 q5 ln(1.00001) 02035: 9 -> p 02036: jsb pmu21 q4 ln(1.0001) 02037: jsb lncd3 S2     S5     S9 02040: 10 -> p ln          1         0       1 02041: jsb pmu21 q3 ln(1.001) log        1        1        0 02042: jsb lncd2 ex         1         0        1 02043: 11 -> p xy             1        0        0 02044: jsb pmu21 q2 ln(1.01) 02045: jsb lncd1 02046: jsb pmu21 q1 ln(1.1) 02047: jsb lnc2 02050: jsb pmu21 q0 ln 2 02051: jsb lnc10 load ln 10 02052: a exchange c[w] 02053: a - c -> c[w] final sum, result in C 02054: if b[xs] = 0 Exponent processing 02055: then go to ln27 02056: a - c -> c[w] 02057: ln27: a exchange b[w] 02060: ln28: p - 1 -> p p=12 on entry (nrm27) 02061: shift left a[w] SL A (A = X) 02062: if p # 1 to prepare A and have A sign in 12th position 02063: then go to ln28 and A exp digits in 11 and 10th positions 02064: a exchange c[w] A -> C 02065: if c[s] = 0 test sign of exponent 02066: then go to ln29 02067: 0 - c - 1 -> c[m] invert if negative 02070: ln29: c + 1 -> c[x] go to normalize C (mantissa in A, exponent in C) 02071: 11 -> p (eg if ln(7.3 1043) C = [04300] 02072: jsb mpy27 02073: if s9 = 0 case xy 02074: then go to xty22 02075: if s5 = 0 log or ln 02076: then go to rtn21 02077: jsb lnc10 if log -> multiply by ln(10) 02100: jsb mpy22 return to normalize and loop. 02101: go to rtn21 02102: exp21: jsb lnc10 Load ln(10) 02103: jsb pre21 prescaling x between 0 and 1 02104: jsb lnc2 pseudo division by repeating subtraction to find the qj 02105: 11 -> p load ln(2) 02106: jsb pqo21 compute q0 by pseudo division 02107: jsb lncd1 load ln(1.1) 02110: 10 -> p 02111: jsb pqo21 compute q1 by pseudo division 02112: jsb lncd2 load ln(1.01) 02113: 9 -> p 02114: jsb pqo21 compute q2 by pseudo division 02115: jsb lncd3 load ln(1.001) 02116: 8 -> p 02117: jsb pqo21 compute q3 by pseudo division 02120: jsb pqo21 load ln(1.0001) compute q4 by pseudo division 02121: jsb pqo21 load ln(1.00001) compute q5 by pseudo division 02122: 6 -> p precision rectification to avoid algorithm flaw e ln(2.02) = 2 02123: 0 -> a[wp] 02124: 13 -> p Part 2 : Pseudo multiplication 02125: b exchange c[w] 02126: a exchange c[w] 02127: load constant 6 02130: go to exp23 ex = (1 + r) Π ( 1 + 10-j) qj 02131: pre23: if s2 = 0 Trigo prescaling 02132: then go to pre24 Θ - 2 π by repeated subtractions until remainder is between 0 and 2 π 02133: a + 1 -> a[x] 02134: pre29: if a[xs] >= 1 02135: then go to pre27 02136: pre24: a - b -> a[ms] Sub in loop 02137: if no carry go to pre23 02140: a + b -> a[ms] Restore one step too far 02141: shift left a[w] Save accuracy 02142: c - 1 -> c[x] # of decades in C 02143: if no carry go to pre29 02144: pre25: shift right a[w] 02145: 0 -> c[wp] 02146: a exchange c[x] 02147: pre26: if c[s] = 0 common part for prescaling trigo end ex 02150: then go to pre28 02151: a exchange b[w] if sign is negative 02152: a - b -> a[w] exchange A and C, A scaled argument B = ln(10) 02153: 0 - c - 1 -> c[w] invert sign 02154: pre28: shift right a[w] Align A then follow thru pqo to compute pseudo quotients. 02155: pqo23: b exchange c[w] Part of pseudo multiplication 02156: 0 -> c[w] This routine is use by ln, ex, direct and inverse trigov (s2=0) 02157: c - 1 -> c[m] 02160: if s2 = 0 02161: then go to pqo28 02162: load constant 4 The rest of the code use to forge constants with repeated patterns (see note) 02163: c + 1 -> c[m] 02164: if no carry go to pqo24 02165: pqo27: load constant 6 02166: pqo28: if p # 1 02167: then go to pqo27 02170: shift right c[w] 02171: pqo24: shift right c[w] 02172: nrm26: if s2 = 0 Use by ln or trigo 02173: then go to rtn21 trigo (S2=0) goto rtn21 02174: return and test S1 to do a "rtn12" or a "return" 02175: lncd2: 7 -> p Forge constant see note 02176: lnc6: load constant 3 load part of constant 02177: load constant 3 ln(1.001) = 0.999500330850 02200: load constant 0 02201: lnc7: load constant 8 02202: load constant 5 02203: load constant 0 02204: load constant 9 02205: go to lnc9 02206: exp29: jsb eca22 ex  processing by pseudo multiplication (called by exp21) after computation of pqj 02207: a + 1 -> a[p] 02210: exp22: a -> b[w] 02211: c - 1 -> c[s] 02212: if no carry go to exp29 loop for the next call to eca22 02213: shift right a[wp] A/10 02214: a exchange c[w] 02215: shift left a[ms] next qj 02216: exp23: a exchange c[w] entry point 02217: a - 1 -> a[s] dec # of SR for a constant 02220: if no carry go to exp22 test for a next cst 02221: a exchange b[w] No the end 02222: a + 1 -> a[p] Correct mantissa 02223: jsb nrm21 Goto normalize 02224: rtn21: select rom 1 relay to "rtn11" 02225: eca21: shift right a[wp] Exponent calculation in ( 1 + 10-j) qj 02226: eca22: a - 1 -> a[s] 02227: if no carry go to eca21 do the #of SR for a cst 02230: 0 -> a[s] 02231: a + b -> a[w] thA = A +B == B 1.01 if 2 SR 02232: return 02233: pqo21: select rom 1 relay to "pqo11" 02234: pmu21: shift right a[w] 02235: pmu22: b exchange c[w] Entry point for ln part 2 (pseudo multiplication) 02236: go to pmu24 02237: pmu23: a + b -> a[w] do the PM 02240: pmu24: c - 1 -> c[s] dec count 02241: if no carry go to pmu23 02242: a exchange c[w] keep accuracy 02243: shift left a[ms] 02244: a exchange c[w] 02245: go to pqo23 another cst ? 02246: mpy21: 3 -> p Came from 01245 "mpy11" (pqo) 02247: mpy22: a + c -> c[x] 02250: a - c -> c[s] 02251: if no carry go to div22 entry point for "div" 02252: 0 - c -> c[s] 02253: div22: a exchange b[m] 02254: 0 -> a[w] 02255: if p # 12 02256: then go to mpy27 02257: if c[m] >= 1 if FP of X > 0 then div23 02260: then go to div23 02261: if s1 = 0 else blinking display 02262: then go to err21 02263: b -> c[wp] separate FP and Y 02264: a - 1 -> a[m] and prepare A for repeated subtractions 02265: c + 1 -> c[xs] C holds the count 02266: div23: b exchange c[wp] 02267: a exchange c[m] 02270: select rom 1 go to  01271 02271: lnc2: 0 -> s8 load ln(2) 02272: load constant 6 0.6931471 02273: load constant 9 02274: load constant 3 02275: load constant 1 02276: load constant 4 02277: load constant 7 02300: load constant 1 02301: go to lnc8 +0.000000080553 02302: pre27: a + 1 -> a[m] Part of prescaling for ex 02303: if no carry go to pre25 02304: myp26: a + b -> a[w] Use by addition (place saving) 02305: mpy27: c - 1 -> c[p] 02306: if no carry go to myp26 02307: mpy28: shift right a[w] 02310: p + 1 -> p Normalization process 02311: if p # 13 02312: then go to mpy27 Right scaling loop 02313: c + 1 -> c[x] 02314: nrm21: 0 -> a[s] FP in A 02315: 12 -> p EXP in C 02316: 0 -> b[w] Left scaling 02317: nrm23: if a[p] >= 1 SLA and adjust EXP 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 Left scaling loop 02325: 0 -> c[w] 02326: nrm24: a -> b[x] 02327: a + b -> a[w] 02330: if a[s] >= 1 02331: then go to mpy28 Fractionoverflow ? 02332: a exchange c[m] If yes go to right scaling 02333: c -> a[w] result in C 02334: 0 -> b[w] zap B 02335: nrm27: 12 -> p point to 12 02336: go to nrm26 back to the farm via "rtn21" (S1=0) or "return" 02337: lncd1: 9 -> p load ln(1.1) 02340: load constant 3 =0.99531017980553 02341: load constant 1 02342: load constant 0 02343: load constant 1 02344: load constant 7 02345: load constant 9 02346: lnc8: load constant 8 02347: load constant 0 02350: load constant 5 02351: load constant 5 02352: lnc9: load constant 3 02353: go to nrm27 to to normalize 02354: pre21: a exchange c[w] Entry point for prescaling of ex 02355: a -> b[w] between 0 <= x < 1 02356: c -> a[m] 02357: c + c -> c[xs] repeated subtractions of ln(10) 02360: if no carry go to pre24 if positive "pre24" 02361: c + 1 -> c[xs] if negative 02362: pre22: shift right a[w] 02363: c + 1 -> c[x] 02364: if no carry go to pre22 02365: go to pre26 go to "prev26" to finish 02366: lnc10: 0 -> c[w] load ln(10) 02367: 12 -> p 2.3025 02370: load constant 2 02371: load constant 3 02372: load constant 0 02373: load constant 2 02374: load constant 5 02375: go to lnc7 + .00008509 02376: lncd3: 5 -> p 02377: go to lnc6 + .000000003

J. LAPORTE
12 November 2006

Note : How to forge constants when there is no room in Rom.

Only 3 constants

- π/4 = tan-1 = arc tan(1) = 0.7853981635
- ln (2) = 0.693147190553
- and ln(10) = 2.302585093

are loaded completely from rom.

The rest is forged (I used this term instead of calculated which makes no sense regarding a constant).
The pattern found in the ln(x) constants and in the angles in radians are singular: digits 6 and 9 are often used.

1) Inverse trigo

arc tan(0.1) = 0.099668652496
arc tan(0.01) = 0.0099996666866
arc tan(0.001) = 0.000999999666
arc tan(0.0001) = 0.000099999999666

2) ln and e^x

ln(1.00001) = 0.999995
ln(1.0001)   = 0.9995
ln(1.001)     = 0.999500330850
ln(1.01)       = 0.99503085093
ln(1.1)         = 0.09531017980553

The relevant code is at 02156

 02156: 0 -> c[w] 02157: c - 1 -> c[m] 02160: if s2 = 0 02161: then go to pqo28 02162: load constant 4 02163: c + 1 -> c[m] 02164: if no carry go to pqo24 02165: pqo27: load constant 6 02166: pqo28: if p # 1 02167: then go to pqo27 02170: shift right c[w] 02171: pqo24: shift right c[w]

The scheme is identical: register C is zapped and C=0
Then c  1 -> c[m] makes C=09999999999000
Pointer p is positioned load constant 4 makes C=09999499999000
And c + 1 -> c[m] finish the job C=09999500000000,
(this is the case of ln(1.00001).

Sometimes this scheme is completed with a few figures loaded from rom, eg. Ln(1.01) : C=00995033085093.

The case of const arc tan 0.001 and arc tan 0.0001 is simpler only digits 9 and 6!

That was surely a space saving strategy, but when memory was not so sparse : this code remain (in the Woodstock machines for example).