home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / utilities / cli / pgp2 / src / s / arm next >
Encoding:
Text File  |  1995-06-08  |  5.3 KB  |  216 lines

  1. ; multiple-precision arithmetic routines
  2. ; the ARM is a 32-bit little-endian RISC processor
  3.  
  4. r0 RN 0
  5. r1 RN 1
  6. r2 RN 2
  7. r3 RN 3
  8. r4 RN 4
  9. r5 RN 5
  10. r6 RN 6
  11. r7 RN 7
  12. r8 RN 8
  13. r9 RN 9
  14. r10 RN 10
  15. r11 RN 11
  16. r12 RN 12
  17. r14 RN 14
  18. sp RN 13
  19. lr RN 14
  20. pc RN 15
  21.  
  22.     AREA |A$$Code|, CODE, READONLY
  23.  
  24.     IMPORT global_precision
  25.  
  26. gp_    DCD global_precision
  27.  
  28.     EXPORT _p_addc
  29. ; _p_addc
  30. ; r0,r1 point to the numbers, r2 is carry (0 or 1)
  31. ; return with number at r0 increased, new carry in r0
  32. _p_addc    STMFD sp!,{r4,r5,lr}
  33.     LDR r3,gp_            ; addr of gp variable
  34.     LDR r3,[r3]            ; value of gp variable
  35.     MOVS r3,r3,LSL#16        ; <<16 [it's a short]
  36.     MOVEQ r0,r2            ; precision = 0 ??!
  37.     LDMEQFD sp!,{r4,r5,pc}^
  38.     MOVS r2,r2,LSR#1        ; carry into C flag
  39. pa1    LDR r4,[r0]
  40.     LDR r5,[r1],#4
  41.     ADCS r4,r4,r5
  42.     STR r4,[r0],#4
  43.     SUB r3,r3,#1<<16
  44.     TEQ r3,#0
  45.     BNE pa1
  46.     ADC r0,r3,#0            ; r3==0 here, so r0 = carry
  47.     LDMFD sp!,{r4,r5,pc}^
  48.  
  49.     EXPORT _p_subb
  50. ; _p_subb
  51. ; r0,r1 point to the numbers, r2 is borrow (0 or 1)
  52. ; return with number at r1 decreased, new borrow in r0
  53. _p_subb    STMFD sp!,{r4,r5,lr}
  54.     LDR r3,gp_            ; addr of gp variable
  55.     LDR r3,[r3]            ; value of gp variable
  56.     MOVS r3,r3,LSL#16        ; <<16 [it's a short]
  57.     MOVEQ r0,r2            ; precision = 0 ??!
  58.     LDMEQFD sp!,{r4,r5,pc}^
  59.     EOR r2,r2,#1            ; carry = 1-borrow
  60.     MOVS r2,r2,LSR#1        ; carry into C flag
  61. ps1    LDR r4,[r0]
  62.     LDR r5,[r1],#4
  63.     SBCS r4,r4,r5
  64.     STR r4,[r0],#4
  65.     SUB r3,r3,#1<<16
  66.     TEQ r3,#0
  67.     BNE ps1
  68.     ADC r0,r3,#0            ; r3==0 here, so r0 = carry
  69.     EOR r0,r0,#1            ; borrow = 1-carry
  70.     LDMFD sp!,{r4,r5,pc}^
  71.  
  72.     EXPORT _p_rol
  73. ; _p_rol
  74. ; r0 points to a number, r1 is carry.
  75. ; rotate left 1 bit, return new carry
  76. _p_rol    LDR r3,gp_
  77.     LDR r3,[r3]
  78.     MOVS r3,r3,LSL#16
  79.     MOVEQ r0,r1
  80.     MOVEQS pc,lr
  81.     MOVS r1,r1,LSR#1        ; carry into C flag
  82. pr1    LDR r2,[r0]
  83.     ADCS r2,r2,r2            ; left shift 1b with carry -> b0
  84.     STR r2,[r0],#4
  85.     SUB r3,r3,#1<<16
  86.     TEQ r3,#0
  87.     BNE pr1
  88.     ADC r0,r3,#0
  89.     MOVS pc,lr
  90.  
  91.     EXPORT _p_smul
  92. ; _p_smul
  93. ; r0:prod r1:multiplicand r2=multiplier
  94. ; accumulate into prod
  95. _p_smul    STMFD sp!,{r5-r9,lr}
  96.     LDR r3,gp_
  97.     LDR r3,[r3]
  98.     MOVS r3,r3,LSL#16
  99.     LDMEQFD sp!,{r5-r9,pc}^
  100.     MOV r14,#0        ; carried-over high word
  101.     MOV r7,r2,LSR#16    ; high1    in r7
  102. pm1    LDR r5,[r1],#4        ; get a digit
  103.     ; now a 32x32->64 multiply...
  104. ;NBNBNB factor out splitting of r2, since it doesn't change
  105.     MOV r6,r5,LSR#16    ; high0 in r6
  106.     SUB r5,r5,r6,LSL#16    ; low0    in r5
  107.     SUB r8,r2,r7,LSL#16    ; low1  in r8
  108.     MUL r9,r5,r8        ; ll in r9
  109.     MUL r8,r6,r8        ; hl in r8
  110.     MUL r5,r7,r5        ; lh in r5
  111.     MUL r6,r7,r6        ; hh in r6
  112.     ADDS r8,r5,r8        ; sum of cross terms in r8
  113.     ADDCS r6,r6,#&10000    ; bit 16 of hh
  114.     ADDS r5,r9,r8,LSL#16    ; ll + low(cross)
  115.     ADC r8,r6,r8,LSR#16    ; hh + high(cross) + carry
  116.     ; now low in r5, high in r8
  117.     ADDS r5,r5,r14        ; add in carry
  118.     ADC r8,r8,#0
  119.     LDR r14,[r0]        ; digit from PROD
  120.     ADDS r5,r5,r14        ; add it in. There will be at most 1
  121.     ADC r14,r8,#0        ;  carry between prev add and this.
  122.     STR r5,[r0],#4        ; store a digit
  123.     LDR r5,[r0]
  124.     SUBS r3,r3,#1<<16
  125.     BNE pm1
  126.     ADD r5,r5,r14
  127.     STR r5,[r0]        ; add final carry back in
  128.     LDMFD sp!,{r5-r9,pc}^
  129.  
  130. ; I really ought to implement mp_dmul in assembler too.
  131. ; It's pretty speed-critical.
  132. ; Actually if I do this my effort on mp_smul will have been
  133. ; wasted :-)
  134. ; Well, here goes...
  135.  
  136.     EXPORT _p_dmul
  137. ; _p_dmul
  138. ; r0 points to double-length space. r1,r2 point to bignums.
  139. _p_dmul    STMFD sp!,{r4-r11,lr}
  140.     ; next few instructions are nasty hack so I can just drop in
  141.     ; my existing code...
  142.     MOV r4,r0
  143.     MOV r0,r2
  144.     LDR r3,gp_
  145.     LDR r3,[r3]
  146.     MOV r3,r3,LSL#16
  147.     MOV r3,r3,LSR#16
  148.     MOV r2,r3
  149.     ; now for the code itself
  150. mul9999    MOV r6,#0
  151.     MOV r7,r4        ; save start of answer
  152.     ANDS r5,r3,#3
  153.     BEQ m99l1        ; multiple of 4 words
  154.     CMP r5,#2
  155.     STR r6,[r4],#4
  156.     STRGE r6,[r4],#4
  157.     STRGT r6,[r4],#4
  158. m99l1    BICS r5,r3,#3
  159.     BEQ m99l3
  160.     MOV r8,#0
  161.     MOV r9,#0
  162.     MOV r10,#0
  163. m99l2    STMIA r4!,{r6,r8,r9,r10}
  164.     SUBS r5,r5,#4
  165.     BGT m99l2
  166.     ; destination now has lots of 0s
  167.     ; it's worth setting out the register allocation here:
  168.     ; r0,r1 are digit pointers. r0 points to a[i], r1 to b[0]
  169.     ; r2,r3 are lengths. r2 decrements, r3 doesn't
  170.     ; r4 points to c[i]
  171.     ; r5 is the digit (of a) we're multiplying by
  172.     ; r6 is the carry
  173.     ; r7 is the inner loop counter ("j")
  174.     ; r8,9,10,11,12 are used by the 32x32 multiply
  175.     ; r13 is SP
  176.     ; r14 is the (unmodified) length of the first number
  177. m99l3    ;STMFD sp!,{r14}
  178.     MOV r4,r7        ; restore c
  179.     MOV r14,r2        ; save la
  180. m99l4    LDR r5,[r0],#4        ; f=a[i++]    START OF OUTER LOOP
  181.     MOV r6,#0        ; ca=0
  182.     MOV r7,#0        ; j=0
  183. m99l5    LDR r8,[r1,r7,LSL#2]    ; b[j]        START OF INNER LOOP
  184.     ; start of multiply routine -- mul3232 with all regs +8
  185.     MOV r10,r8,LSR#16    ; high halfwords in r10,r11
  186.     MOV r11,r5,LSR#16
  187.     SUB r8,r8,r10,LSL#16    ; low halfwords in r8,r9
  188.     SUB r9,r5,r11,LSL#16
  189.     MUL r12,r8,r9        ; ll in r12
  190.     MUL r9,r10,r9        ; hl in r9
  191.     MUL r8,r11,r8        ; lh in r8
  192.     MUL r10,r11,r10        ; hh in r10
  193.     ADDS r9,r8,r9        ; sum of cross terms in r9; now r8 spare
  194.     ADDCS r10,r10,#&10000    ; insert carry
  195.     ADDS r8,r12,r9,LSL#16    ; low bits in r8
  196.     ADC r9,r10,r9,LSR#16    ; high bits in r9
  197.     ; end of multiply routine. H in r9, L in r8
  198.     LDR r10,[r4,r7,LSL#2]    ; c[i+j]
  199.     ADDS r8,r8,r10        ; f*b[j] + c[i+j]
  200.     ADC r9,r9,#0        ; including high bits
  201.     ADDS r8,r8,r6        ; ... + ca
  202.     ADC r6,r9,#0        ; high bits are new carry
  203.     STR r8,[r4,r7,LSL#2]    ; low bits are new value for c[i+j]
  204.     ADD r7,r7,#1        ; ++j
  205.     CMP r7,r3        ; if (j<lb)
  206.     BLT m99l5        ; then continue with inner loop
  207.     ; END OF INNER LOOP
  208.     STR r6,[r4,r7,LSL#2]    ; c[i+j]=ca
  209.     ADD r4,r4,#4        ; advance &c[i]
  210.     SUBS r2,r2,#1        ; finished outer loop?
  211.     BGT m99l4        ; nope
  212.     ; END OF OUTER LOOP
  213.     LDMFD sp!,{r4-r11,pc}^
  214.  
  215.     END
  216.