lbn68020.c
上传用户:zbbssh
上传日期:2007-01-08
资源大小:196k
文件大小:8k
源码类别:

CA认证

开发平台:

C/C++

  1. /*
  2.  * lbn68020.c - 32-bit bignum primitives for the 68020+ (0r 683xx) processors.
  3.  *
  4.  * Copyright (c) 1995  Colin Plumb.  All rights reserved.
  5.  * For licensing and other legal details, see the file legal.c.
  6.  *
  7.  * This was written for Metrowerks C, and while it should be reasonably
  8.  * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2.
  9.  * Some 680x0 compilers make d2 callee-save, so instructions to save it
  10.  * will have to be added.
  11.  * 
  12.  * This code supports 16 or 32-bit ints, based on UINT_MAX.
  13.  * Regardless of UINT_MAX, only bignums up to 64K words (2 million bits)
  14.  * are supported.  (68k hackers will recognize this as a consequence of
  15.  * using dbra.)
  16.  *
  17.  * These primitives use little-endian word order.
  18.  * (The order of bytes within words is irrelevant to this issue.)
  19.  *
  20.  * TODO: Schedule this for the 68040's pipeline.  (When I get a 68040 manual.)
  21.  */
  22. #include <limits.h>
  23. #include "lbn.h"        /* Should include lbn68020.h */
  24. /*
  25.  * The Metrowerks C compiler (1.2.2) produces bad 68k code for the
  26.  * following input, which happens to be the inner loop of lbnSub1,
  27.  * so a few less than critical routines have been recoded in assembly
  28.  * to avoid the bug.  (Optimizer on or off does not matter.)
  29.  * 
  30.  * unsigned
  31.  * decrement(unsigned *num, unsigned len)
  32.  * {
  33.  *      do {
  34.  *              if ((*num++)-- != 0)
  35.  *                      return 0;
  36.  *      } while (--len);
  37.  *      return 1;
  38.  * }
  39.  */
  40. asm BNWORD32
  41. lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow)
  42. {
  43.         movea.l 4(sp),a0        /* num */
  44. #if UINT_MAX == 0xffff
  45.         move.l  10(sp),d0       /* borrow */
  46. #else
  47.         move.l  12(sp),d0       /* borrow */
  48. #endif
  49.         sub.l   d0,(a0)+
  50.         bcc             done
  51. #if UINT_MAX == 0xffff
  52.         move.w  8(sp),d0        /* len */
  53. #else
  54.         move.w  10(sp),d0       /* len */
  55. #endif
  56.         subq.w  #2,d0
  57.         bcs             done
  58. loop:
  59.         subq.l  #1,(a0)+
  60.         dbcc    d0,loop
  61. done:
  62.         moveq.l #0,d0
  63.         addx.w  d0,d0
  64.         rts
  65. }
  66. asm BNWORD32
  67. lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry)
  68. {
  69.         movea.l 4(sp),a0        /* num */
  70. #if UINT_MAX == 0xffff
  71.         move.l  10(sp),d0       /* carry */
  72. #else
  73.         move.l  12(sp),d0       /* carry */
  74. #endif
  75.         add.l   d0,(a0)+
  76.         bcc             done
  77. #if UINT_MAX == 0xffff
  78.         move.w  8(sp),d0        /* len */
  79. #else
  80.         move.w  10(sp),d0       /* len */
  81. #endif
  82.         subq.w  #2,d0
  83.         bcs             done
  84. loop:
  85.         addq.l  #1,(a0)+
  86.         dbcc    d0,loop
  87. done:
  88.         moveq.l #0,d0
  89.         addx.w  d0,d0
  90.         rts
  91. }
  92. asm void
  93. lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
  94. {
  95.         machine 68020
  96.         
  97.         movem.l d3-d5,-(sp)     /* 12 bytes of extra data */
  98.         moveq.l #0,d4
  99.         move.l  16(sp),a1       /* out */
  100.         move.l  20(sp),a0       /* in */
  101. #if UINT_MAX == 0xffff
  102.         move.w  24(sp),d5       /* len */
  103.         move.l  26(sp),d2       /* k */
  104. #else
  105.         move.w  26(sp),d5       /* len */
  106.         move.l  28(sp),d2       /* k */
  107. #endif
  108.         move.l  (a0)+,d3        /* First multiply */
  109.         mulu.l  d2,d1:d3        /* dc.w    0x4c02, 0x3401 */
  110.         move.l  d3,(a1)+
  111.         subq.w  #1,d5           /* Setup for loop unrolling */
  112.         lsr.w   #1,d5
  113.         bcs.s   m32_even
  114.         beq.s   m32_short
  115.         
  116.         subq.w  #1,d5           /* Set up software pipeline properly */
  117.         move.l  d1,d0
  118.         
  119. m32_loop:
  120.         move.l  (a0)+,d3
  121.         mulu.l  d2,d1:d3        /* dc.w    0x4c02, 0x3401 */
  122.         add.l   d0,d3
  123.         addx.l  d4,d1
  124.         move.l  d3,(a1)+
  125. m32_even:
  126.         move.l  (a0)+,d3
  127.         mulu.l  d2,d0:d3        /* dc.w    0x4c02, 0x3400 */
  128.         add.l   d1,d3
  129.         addx.l  d4,d0
  130.         move.l  d3,(a1)+
  131.         dbra    d5,m32_loop
  132.         
  133.         move.l  d0,(a1)
  134.         movem.l (sp)+,d3-d5
  135.         rts
  136. m32_short:
  137.         move.l  d1,(a1)
  138.         movem.l (sp)+,d3-d5
  139.         rts
  140. }
  141. asm BNWORD32
  142. lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
  143. {
  144.         machine 68020
  145.         movem.l d3-d5,-(sp)     /* 12 bytes of extra data */
  146.         moveq.l #0,d4
  147.         move.l  16(sp),a1       /* out */
  148.         move.l  20(sp),a0       /* in */
  149. #if UINT_MAX == 0xffff
  150.         move.w  24(sp),d5       /* len */
  151.         move.l  26(sp),d2       /* k */
  152. #else
  153.         move.w  26(sp),d5       /* len */
  154.         move.l  28(sp),d2       /* k */
  155. #endif
  156.         move.l  (a0)+,d3        /* First multiply */
  157.         mulu.l  d2,d1:d3        /* dc.w    0x4c02, 0x3401 */
  158.         add.l   d3,(a1)+
  159.         addx.l  d4,d1
  160.         subq.w  #1,d5           /* Setup for loop unrolling */
  161.         lsr.w   #1,d5
  162.         bcs.s   ma32_even
  163.         beq.s   ma32_short
  164.         
  165.         subq.w  #1,d5           /* Set up software pipeline properly */
  166.         move.l  d1,d0
  167.         
  168. ma32_loop:
  169.         move.l  (a0)+,d3
  170.         mulu.l  d2,d1:d3        /* dc.w    0x4c02, 0x3401 */
  171.         add.l   d0,d3
  172.         addx.l  d4,d1
  173.         add.l   d3,(a1)+
  174.         addx.l  d4,d1
  175. ma32_even:
  176.         move.l  (a0)+,d3
  177.         mulu.l  d2,d0:d3        /* dc.w    0x4c02, 0x3400 */
  178.         add.l   d1,d3
  179.         addx.l  d4,d0
  180.         add.l   d3,(a1)+
  181.         addx.l  d4,d0
  182.         dbra    d5,ma32_loop
  183.         
  184.         movem.l (sp)+,d3-d5
  185.         rts
  186. ma32_short:
  187.         move.l  d1,d0   
  188.         movem.l (sp)+,d3-d5
  189.         rts
  190. }
  191. asm BNWORD32
  192. lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
  193. {
  194.         machine 68020
  195.         movem.l d3-d5,-(sp)     /* 12 bytes of extra data */
  196.         moveq.l #0,d4
  197.         move.l  16(sp),a1       /* out */
  198.         move.l  20(sp),a0       /* in */
  199. #if UINT_MAX == 0xffff
  200.         move.w  24(sp),d5       /* len */
  201.         move.l  26(sp),d2       /* k */
  202. #else
  203.         move.w  26(sp),d5       /* len */
  204.         move.l  28(sp),d2       /* k */
  205. #endif
  206.         move.l  (a0)+,d3        /* First multiply */
  207.         mulu.l  d2,d1:d3        /* dc.w    0x4c02, 0x3401 */
  208.         sub.l   d3,(a1)+
  209.         addx.l  d4,d1
  210.         subq.w  #1,d5           /* Setup for loop unrolling */
  211.         lsr.w   #1,d5
  212.         bcs.s   ms32_even
  213.         beq.s   ms32_short
  214.         
  215.         subq.w  #1,d5           /* Set up software pipeline properly */
  216.         move.l  d1,d0
  217.         
  218. ms32_loop:
  219.         move.l  (a0)+,d3
  220.         mulu.l  d2,d1:d3        /* dc.w    0x4c02, 0x3401 */
  221.         add.l   d0,d3
  222.         addx.l  d4,d1
  223.         sub.l   d3,(a1)+
  224.         addx.l  d4,d1
  225. ms32_even:
  226.         move.l  (a0)+,d3
  227.         mulu.l  d2,d0:d3        /* dc.w    0x4c02, 0x3400 */
  228.         add.l   d1,d3
  229.         addx.l  d4,d0
  230.         sub.l   d3,(a1)+
  231.         addx.l  d4,d0
  232.         dbra    d5,ms32_loop
  233.         
  234.         movem.l (sp)+,d3-d5
  235.         rts
  236.         
  237. ms32_short:
  238.         move.l  d1,d0
  239.         movem.l (sp)+,d3-d5
  240.         rts
  241. }
  242. asm BNWORD32
  243. lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
  244. {
  245.         machine 68020
  246.         move.l  8(sp),d0
  247.         move.l  12(sp),d1
  248.         move.l  4(sp),a0
  249.         divu.l  16(sp),d0:d1    /*  dc.w    0x4c6f, 0x1400, 16 */
  250.         move.l  d1,(a0)
  251.         rts
  252. }
  253. asm unsigned
  254. lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
  255. {
  256.         machine 68020
  257.         move.l  4(sp),a0        /* n */
  258.         move.l  d3,a1
  259. #if UINT_MAX == 0xffff
  260.         moveq.l #0,d2
  261.         move.w  8(sp),d1        /* len */
  262.         move.w  10(sp),d2       /* d */
  263. #else
  264.         move.w  10(sp),d1       /* len */
  265.         move.l  12(sp),d2       /* d */
  266. #endif
  267.         dc.w    0x41f0, 0x1cfc  /* lea  -4(a0,d1.L*4),a0 */
  268. /* First time, divide 32/32 - may be faster than 64/32 */
  269.         move.l  (a0),d3
  270.         divul.l d2,d0:d3        /* dc.w    0x4c02, 0x3000 */
  271.         subq.w  #2,d1
  272.         bmi mq32_done
  273. mq32_loop:
  274.         move.l  -(a0),d3
  275.         divu.l  d2,d0:d3        /* dc.w    0x4c02,0x3400 */
  276.         dbra    d1,mq32_loop    
  277.                         
  278. mq32_done:
  279.         move.l  a1,d3
  280.         rts
  281. }
  282. /* 45678901234567890123456789012345678901234567890123456789012345678901234567 */