home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol123 / mathlib.src < prev    next >
Encoding:
Text File  |  1984-04-29  |  10.5 KB  |  488 lines

  1. ;
  2. ; MATHLIB: a 16 Bit Arithmetic Package for 8048
  3. ; Sourced Nov-Dec '80 by Trevor Marshall
  4. ;            SYSOP, Thousand Oaks Tech RBBS
  5. ;
  6. ; This package may be freely distributed but not for profit
  7. ; (C) 1980 Trevor Marshall
  8. ;-----------------------------------------------
  9. ;
  10. ; This S/R shifts the register pair whose LSB
  11. ;   is being pointed at by R0 right one position
  12. ; All registers are preserved
  13. ROTATERIGHTR0: CLR C
  14. SHIFTRIGHTR0: INC R0    ;R0 points to the LSB
  15.     MOV    A,@R0    ;get MSB
  16.     RRC    A
  17.     MOV    @R0,A    ;Result MSB
  18.     DEC    R0    ;point at LSB
  19.     MOV    A,@R0    ;get it
  20.     RRC    A
  21.     MOV    @R0,A    ;Store result LSB
  22.     RET
  23. ;
  24. ;----------------------------------------------
  25. ;
  26. ; This S/R shifts the register pair whose LSB
  27. ;   is being pointed at by R1 right one position
  28. ; All registers are preserved
  29. ROTATERIGHTR1: CLR C
  30. SHIFTRIGHTR1: INC R1    ;R1 points to the LSB
  31.     MOV    A,@R1    ;get MSB
  32.     RRC    A
  33.     MOV    @R1,A    ;Result MSB
  34.     DEC    R1    ;point at LSB
  35.     MOV    A,@R1    ;get it
  36.     RRC    A
  37.     MOV    @R1,A    ;Store result LSB
  38.     RET
  39. ;
  40. ;-----------------------------------------------
  41. ;
  42. ; This S/R shifts the register pair whose LSB is
  43. ;  being indicated by R0 left one position
  44. ; All registers are preserved
  45. ROTATELEFTR0: CLR C
  46. SHIFTLEFTR0: MOV A,@R0 ;get LSB
  47.     RLC    A
  48.     MOV    @R0,A    ;Result LSB
  49.     INC    R0    ;Point at MSB
  50.     MOV    A,@R0
  51.     RLC    A
  52.     MOV    @R0,A    ;store MSB
  53.     DEC    R0    ;restore R0
  54.     RET
  55. ;
  56. ;------------------------------------------------
  57. ;
  58. ; This S/R shifts the register pair whose LSB is
  59. ;  being indicated by R1 left one position
  60. ; All registers are preserved
  61. ROTATELEFTR1: CLR C
  62. SHIFTLEFTR1: MOV A,@R1 ;get LSB
  63.     RLC    A
  64.     MOV    @R1,A    ;Result LSB
  65.     INC    R1    ;Point at MSB
  66.     MOV    A,@R1
  67.     RLC    A
  68.     MOV    @R1,A    ;store MSB
  69.     DEC    R1    ;restore R1
  70.     RET
  71. ;
  72. ;---------------------------------------------------
  73. ;
  74. ; This S/R, ADD, adds a 16 Bit number pointed at by R1
  75. ;  to a sum indicated by R0. The sum (@R0) is updated
  76. ;  @R1 is not changed
  77. ; All registers preserved
  78. ADD:    CLR    C    ;Add without carry, or with it:
  79. ADDC:    MOV    A,@R0    ;LSB of sum
  80.     ADDC    A,@R1    ; + LSB of number
  81.     MOV    @R0,A    ;New sum LSB to @R0
  82.     INC    R0
  83.     INC    R1    ;point at MSBs
  84.     MOV    A,@R0    ;MSB of sum
  85.     ADDC    A,@R1    ; + MSB of number
  86.     MOV    @R0,A    ;New sum MSB to @R0
  87.     DEC    R0    ;Restore R0, R1
  88.     DEC    R1
  89.     RET
  90. ;
  91. ;----------------------------------------------------
  92. ;
  93. ; A S/R to complement a 16 Bit number indicated by R0
  94. ; All registers preserved
  95. COMPLEMENTR0: INC R0
  96.     MOV    A,@R0    ;get MSB
  97.     CPL    A
  98.     MOV    @R0,A    ;store its compl
  99.     DEC    R0
  100.     MOV    A,@R0    ;get LSB
  101.     CPL    A    ;Have 1s complemented it, add 1
  102.     CLR    C
  103.     ADD    A,#1
  104.     MOV    @R0,A    ;Store LSB
  105.     INC    R0
  106.     MOV    A,@R0    ;get MSB
  107.     ADDC    A,#0    ;use carry
  108.     MOV    @R0,A    ;store MSB
  109.     DEC    R0    ;restore R0
  110.     RET
  111. ;
  112. ;------------------------------------------------------
  113. ;
  114. ;MULTIPLY:  16 x 16 Bit multiplication
  115. ;
  116. ;result (@R0) = multiplicand (@R1) x multiplier (@R0)
  117. ;
  118. ; It overflows safely, but without indication
  119. ; Registers R4,R5,R6,R7 are destroyed
  120. ;
  121. ;    Example: 5 x 3
  122. ;        101
  123. ;         x  011
  124. ;    ----------------
  125. ;        101    (Shifted LSBit=1)
  126. ;           101    (Shifted LSBit=1)
  127. ;          000    (Shifted LSBit=0,no add)
  128. ;    ----------------
  129. ;          01111    (Result)
  130. ;
  131. MULTIPLY: MOV    R7,#16    ;Loop count in R7
  132.     CLR    A    ;Clear result 
  133.     MOV    R6,A    ;R6 is result MSB
  134.     MOV    R5,A    ;R5 is LSB
  135. ; shift and test if multiplier LSBit = 1 
  136. ZZMULT:    CALL    ROTATERIGHTR0 ;0-> MSBit,LSBit-> C
  137.     JNC    ZZNOADD ;LSBit not 1, Don't add
  138. ;
  139.     MOV    A,R0    ;Save R0 in
  140.     MOV    R4,A    ; R4
  141.     MOV    R0,#5    ;Point at the result R5,R6
  142.     CALL    ADD    ;Add result, multiplicand @R1
  143.     MOV    A,R4    ;Restore
  144.     MOV    R0,A    ;R0
  145. ; (Could test for overflow here:)
  146. ;
  147. ;Now we shift left the multiplicand
  148. ZZNOADD: CALL    ROTATELEFTR1 ;0->LSBit, MSBit->Carry
  149. ;
  150.     DJNZ    R7,ZZMULT    ;Loop for 16 Bits
  151. ; Now shift the result to @R0
  152.     MOV    A,R1    ;Save R1
  153.     MOV    R4,A    ;in R4
  154.     MOV    R1,#5    ;Point to R5,R6
  155.     MOV    A,@R1    ;Get LSB
  156.     MOV    @R0,A    ;Put LSB
  157.     INC    R0
  158.     INC    R1
  159.     MOV    A,@R1    ;Get MSB
  160.     MOV    @R0,A    ;Put MSB
  161.     DEC    R0    ;Restore R0
  162.     MOV    A,R4    ;Restore R1
  163.     MOV    R1,A
  164. ;
  165.     RET    ; ***** DONE *****
  166. ;
  167. ;-------------------------------------------------------
  168. ; MPY8X8, 8 x 8 multiply, 16 Bit product
  169. ;
  170. ; On Entry
  171. ;    R6    contains multiplicand
  172. ;    R7       "    multiplier
  173. ; On Exit
  174. ;    A    contains the result LSB
  175. ;    R2       "            MSB
  176. ;
  177. ; DESTROYS R5, USES A,R5,R6,R7
  178. ;
  179. MPY8X8:    CLR    A    ;Clear Result LSB
  180.     MOV    R2,A    ;  "     "    MSB
  181.     MOV    R5,#8    ;Bit cntr
  182. ;
  183. SHIFT:    CLR    C    ;Shift multiplicand 16 Bits
  184.     RLC    A
  185.     XCH    A,R2    ;Prepare to
  186.     RLC    A    ;RLC R2
  187.     XCH    A,R2
  188. ; Shift left multiplicand
  189.     XCH    A,R6
  190.     RLC    A
  191.     XCH    A,R6
  192. ;Test carry
  193.     JNC    DECR
  194. ;Else add multiplier
  195.     ADD    A,R7
  196.     XCH    A,R6
  197.     ADDC    A,#0
  198.     XCH    A,R6
  199. DECR:    DJNZ    R5,SHIFT
  200.     RET    
  201. ;
  202. ;-------------------------------------------------------
  203. ; DIVIDE  Low byte count 15 / 15 divide
  204. ;         the MSBs must not be 1
  205. ;
  206. ;            divisor(@R1)
  207. ;    result(R6,R7) = ---------------
  208. ;            dividend(@R0)
  209. ;
  210. ;Operands are in reverse order to improve efficiency
  211. ;DESTROYS divisor(@R0),dividend(@R1),R0,R1,R6,R7
  212. ;The dividend is successively subtracted fromthe divisor
  213. ;First check if dividend is 0
  214. DIVIDE: MOV    A,@R0    ;Is LSByte=0 ?
  215.     JNZ    OK    ;Skip if OK
  216.     INC    R0    ;Otherwise test MSByte
  217.     ORL    A,@R0    ;A was 0
  218.     JZ    DIVIDEBYZERO
  219.     DEC    R0
  220. ;First form the complement of @R0 IN @R0
  221. OK:    CALL    COMPLEMENT    ;@R0
  222. ;Now clear result area
  223.     CLR    A
  224.     MOV    R7,A
  225.     MOV    R6,A
  226. ;ADD destroys @R0, so swap R1,R0
  227.     MOV    A,R0
  228.     XCH    A,R1
  229.     MOV    R0,A
  230. ;
  231. DIVLOOP: CALL    ADD ;Add (subtract) once
  232.     INC    R0
  233.     MOV    A,@R0    ;if MSBit is 1, negative, done
  234.     DEC    R0
  235.     JB7    DONEDIVIDE   ;Done if -ve result
  236. ;Else increment R6,R7
  237. ; (Trick courtesy of SIGNETICS 2650)
  238.     INC    R6    ;Increment LSB, but dont
  239.     MOV    A,R6
  240.     JNZ    NXT9
  241.     INC    R7    ;incr MSB unless new LSB is 0
  242. ;
  243. NXT9:    JMP    DIVLOOP    ;And try to subtract again
  244. ;
  245. DIVIDEBYZERO: MOV    R6,#0FCH ;nearly infinite
  246.     MOV    R7,#0FFH
  247. DONEDIVIDE:    RET
  248. ;
  249. ;------------------------------------------------
  250. ;
  251. ; BINTOBCD: Converts an 8 Bit Binary value to BCD
  252. ;
  253. ;------------------------------------------------
  254. ;
  255. ; The Binary value is in A
  256. ; R0 is pointer to the packed BCD string storage
  257. ; DESTROYS R1, R5, R6, R7
  258. BINTOBCD: XCH    A,R0    ;Get R0 to R1
  259.     MOV    R1,A    ;without changing A
  260.     XCH    A,R0
  261. ;
  262.     MOV    R7,#2    ;2 is digit byte count
  263. ;            ;  extension register
  264. ;
  265. BINLP1: MOV    @R1,#0    ;Clear the BCD area
  266.     INC    R1
  267.     DJNZ    R7,BINLP1
  268. ;
  269.     MOV    R6,#8    ;Bit count
  270. ; now do A = A*2
  271. ; to get the MSBit into the carry
  272. BINLP2:    CLR    C
  273.     RLC    A
  274. ; now do  BCD = BCD*2 + Carry
  275.     XCH    A,R0    ;Get R0
  276.     MOV    R1,A    ;to R1
  277.     XCH    A,R0
  278.     MOV    R7,#2    ;2 is digit byte count
  279.     MOV    R5,A    ;save A in R5
  280. BINLP3:    MOV    A,@R1    ;fetch LSByte of BCD
  281.     ADDC    A,@R1    ;double it + carry
  282.     DA    A
  283.     MOV    @R1,A    ;store it back
  284.     INC    R1    ;point at next BCD byte
  285.     DJNZ    R7,BINLP3 ;process it too
  286.     MOV    A,R5    ;Retrieve A
  287. ; If carry from BCDacc could GOTO error exit
  288.     JC    BINERROR
  289. ; Count=count-1, until count=0 :
  290.     DJNZ    R6,BINLP2
  291.     CLR    C ;Reset Indicates normal termination
  292. BINERROR: RET      ; C set if error termination
  293. ;
  294. ;-------------------------------------------------------
  295. ;
  296. ; BCDTOBIN: Converts a 3 digit BCD value to 8 Bit Binary
  297. ;
  298. ;-------------------------------------------------------
  299. ;
  300. ;at entry R0 points to the LSByte of a packed BCD string
  301. ;
  302. ;at exit A has the result
  303. ;     Carry is set if overflow has occurred
  304. ; DESTROYS R4,R5,R6,R7
  305. ;
  306. ; Point at most significant digitpair
  307. ; R0 = R0 + #digitpairs - 1
  308.     MOV    A,R0
  309.     ADD    A,#1    ; 2 packed bytes - 1
  310.     MOV    R0,A
  311. ; count = #digitpairs
  312.     MOV    R7,#2
  313. ; BIN = 0
  314.     CLR    A
  315.     MOV    R4,A
  316. ; BIN = BIN*10
  317. BCDLP1:    CALL    MUL10
  318.     JC    CONVERSIONERROR
  319. ; BIN = BIN + MSNibble(@R0)
  320.     MOV    R5,A    ;save BIN*10
  321.     MOV    A,@R0    ;get MSDigitpair
  322.     SWAP    A    ;mask except
  323.     ANL    A,#0FH    ;the MSNibble
  324. ; Now have the most significant BCD nibble in A
  325.     ADD    A,R5    ;Add BIN*10
  326.     XCH    A,R4    ;to A in
  327.     ADDC    A,#0    ;double
  328.     XCH    A,R4    ;precision
  329.     JC    CONVERSIONERROR
  330. ; BIN = BIN * 10
  331.     CALL    MUL10
  332.     JC    CONVERSIONERROR
  333. ; bin = bin + LSNibble(@R0)
  334.     MOV    R5,A    ;save R5
  335.     MOV    A,@R0
  336.     ANL    A,#0FH ;get LSNibble of MSDigit
  337.     ADD    A,R5    ;add it to BIN
  338.     XCH    A,R4    ;in
  339.     ADDC    A,#0    ;double
  340.     XCH    A,R4    ;precision
  341.     JC    CONVERSIONERROR
  342. ; point now to the next lower digitpair
  343.     DEC    R0
  344. ; count = count-1 until 0 repeat proceedure
  345.     DJNZ    R7,BCDLP1
  346. CONVERSIONERROR: RET    ; C cleared normal return
  347. ;            ;   set if error return
  348. ;
  349. ; Utility to multiply BIN by 10
  350. MUL10:    MOV    R5,A    ;save A
  351.     XCH    A,R4    ;save R4
  352.     MOV    R6,A
  353.     XCH    A,R4
  354. ; BIN = BIN * 2
  355.     CLR    C
  356.     RLC    A
  357.     XCH    A,R4
  358.     RLC    A
  359.     XCH    A,R4
  360.     JC    MUL10ERROR
  361. ; BIN = BIN * 4
  362.     RLC    A
  363.     XCH    A,R4
  364.     RLC    A
  365.     XCH    A,R4
  366.     JC    MUL10ERROR
  367. ; BIN = BIN * 5
  368.     ADD    A,R5
  369.     XCH    A,R4
  370.     ADDC    A,R6
  371.     XCH    A,R4
  372.     JC    MUL10ERROR
  373. ; BIN = BIN * 10
  374.     RLC    A
  375.     XCH    A,R4
  376.     RLC    A
  377.     XCH    A,R4
  378. ;
  379. MUL10ERROR: RET    ; C set if error on return
  380. ;
  381. ;--------------------------------------------
  382. ;
  383. ;*************THIS ROUTINE DID NOT WORK*****************
  384. ;
  385. ;DIVIDE: 16 Bit by 16 Bit Integer Division
  386. ;
  387. ;          dividend (@R0)
  388. ;  result (@R0) = --------------  + remainder (@R6)
  389. ;          divisor (@R1)
  390. ;
  391. ; DESTROYS ALL REGISTERS except R0,R1, in MB0
  392. ;    and DESTROYS  R7' (R31) in MB1
  393. ; DO NOT CALL THIS ROUTINE WHILST IN MB1
  394. ;
  395. ; The divisor is successively subtracted from the high 
  396. ;   order bits of the dividend. After each subtraction 
  397. ;   the result is used instead of the initial dividend
  398. ; The result is increased by 1 each time.
  399. ; When the result of the subtraction is negative the 
  400. ;   partial result is restored by adding the divisor 
  401. ;   back to it.
  402. ; The result is simulataneously decremented by 1
  403. ;
  404. ;First check if divisor is 0
  405. ;
  406. ;*************THIS ROUTINE DID NOT WORK*****************
  407. ;
  408. DIVIDE:    MOV    A,@R1    ;Is LSByte=0 ?
  409.     JNZ    OK    ;Skip if OK
  410.     INC    R1    ;Otherwise test MSByte
  411.     ORL    A,@R1    ;A was 0
  412.     JZ    DIVIDEBYZEROERROR
  413.     DEC    R1
  414. ; Dividend is @R0
  415. ;clear result register pair
  416. OK:    CLR    A
  417.     MOV    R7,A ;Use R6, R7 as result pair
  418.     MOV    R6,A
  419. ;loop counter,R5
  420.     MOV    R5,#16
  421. ;
  422.     CLR    C
  423. ;Rotate Dividend left 
  424. ZZDIV1:    CALL    SHIFTLEFTR0 ; C  -> LSBit
  425. ;                MSBit -> Carry
  426. ;Rotate Remainder left
  427.     MOV    A,R0    ;Save R0 in 
  428.     MOV    R4,A    ; R4
  429.     MOV    R0,#6    ;Point at R6,R7
  430.     CALL    SHIFTLEFTR0 ;C -> LSBit, MSBit-> C
  431. ;Trial subtraction of divisor from result
  432. ; Problems here, as need to complement (& change)
  433. ;  divisor before we can subtract it.
  434. ; So have to use R2,R3 as scratch
  435.     MOV    A,@R1 ;get divisor in R2,R3
  436.     MOV    R2,A
  437.     INC    R1
  438.     MOV    A,@R1
  439.     MOV    R3,A
  440.     DEC    R1  ;still points at divisor
  441. ; Now we could do:
  442. ;    MOV    R0,#2    ;Point at R2,R3
  443. ;    MOV    R1,#6    ;Point at R6,R7
  444. ; !!!! CLANG !!!! have destroyed pointer R1
  445. ; So we must destroy R7' (R31)
  446.     MOV    R0,#31
  447.     MOV    A,R1    ;Save R1
  448.     MOV    @R0,A    ; in R31
  449.     MOV    R0,#2
  450.     MOV    R1,#6
  451.     CALL    COMPLEMENTR0
  452.     CALL    ADD    ;Result in scratch R2,R3
  453.     MOV    A,R2    ;Copy result to R6,7
  454.     MOV    R6,A
  455.     MOV    A,R3
  456.     MOV    R7,A
  457. ;
  458.     MOV    R0,#31
  459.     MOV    A,@R0    ;Get divisor pointer
  460.     MOV    R1,A    ;to R1 again
  461. ; Carry must be 1 if borrow occurred (@R0 >= @R1)
  462.     JNC    ZZPOS
  463. ;otherwise negative, restore dividend
  464.     MOV    R0,#6    ;remainder regs
  465.     CALL    ADD
  466. ;    
  467. ZZPOS:    CPL    C ;Calc result bit
  468. ;Restore R0
  469.     MOV    A,R4
  470.     MOV    R0,A
  471. ;
  472.     DJNZ    R5,ZZDIV1 ;Loop for 16 bits
  473. ;
  474. ; Shift in last result bit
  475.     CALL    SHIFTLEFTR0
  476. ; On exit the result is in @R0, the remainder in R6,R7
  477. ;
  478.     RET    ; ***** DONE ****
  479. ;
  480. DIVIDEBYZEROERROR: MOV A,#0FFH ;Move #infinity to
  481.     MOV    @R0,A    ;@R0
  482.     INC    R0
  483.     MOV    @R0,A
  484.     DEC    R0
  485. ; Output a diagnostic message if desired
  486.     RET
  487. ;
  488.