home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 6 / FreshFish_September1994.bin / bbs / gnu / gcc-2.6.0-src.lha / GNU / src / amiga / gcc-2.6.0 / config / h8300 / lib1funcs.asm < prev    next >
Encoding:
Assembly Source File  |  1994-07-12  |  10.2 KB  |  672 lines

  1. ;; libgcc1 routines for the Hitachi h8/300 cpu.
  2. ;; Contributed by Steve Chamberlain.
  3. ;; sac@cygnus.com
  4. ;; This file is in the public domain.
  5.  
  6. /* Assembler register definitions.  */
  7.  
  8. #define A0 r0
  9. #define A0L r0l
  10. #define A0H r0h
  11.  
  12. #define A1 r1
  13. #define A1L r1l
  14. #define A1H r1h
  15.  
  16. #define A2 r2
  17. #define A2L r2l
  18. #define A2H r2h
  19.  
  20. #define A3 r3
  21. #define A3L r3l
  22. #define A3H r3h
  23.  
  24. #define S0 r4
  25. #define S0L r4l
  26. #define S0H r4h
  27.  
  28. #define S1 r5
  29. #define S1L r5l
  30. #define S1H r5h
  31.  
  32. #define S2 r6
  33. #define S2L r6l
  34. #define S2H r6h
  35.  
  36. #ifdef __H8300__
  37. #define MOVP    mov.w    /* pointers are 16 bits */
  38. #define ADDP    add.w
  39. #define CMPP    cmp.w
  40. #define PUSHP    push
  41. #define POPP    pop
  42.  
  43. #define A0P    r0
  44. #define A1P    r1
  45. #define A2P    r2
  46. #define A3P    r3
  47. #define S0P    r4
  48. #define S1P    r5
  49. #define S2P    r6
  50. #endif
  51.  
  52. #ifdef __H8300H__
  53. #define MOVP    mov.l    /* pointers are 32 bits */
  54. #define ADDP    add.l
  55. #define CMPP    cmp.l
  56. #define PUSHP    push.l
  57. #define POPP    pop.l
  58.  
  59. #define A0P    er0
  60. #define A1P    er1
  61. #define A2P    er2
  62. #define A3P    er3
  63. #define S0P    er4
  64. #define S1P    er5
  65. #define S2P    er6
  66.  
  67. #define A0E    e0
  68. #define A1E    e1
  69. #define A2E    e2
  70. #define A3E    e3
  71. #endif
  72.  
  73. #ifdef L_cmpsi2
  74. #ifdef __H8300__
  75.     .section .text
  76.     .align 2
  77.     .global ___cmpsi2
  78. ___cmpsi2:
  79.     cmp.w    A2,A0
  80.     bne    .L2
  81.     cmp.w    A3,A1
  82.     bne    .L2
  83.     mov.w    #1,A0
  84.     rts
  85. .L2:
  86.     cmp.w    A0,A2
  87.     bgt    .L4
  88.     bne    .L3
  89.     cmp.w    A1,A3
  90.     bls    .L3
  91. .L4:
  92.     sub.w    A0,A0
  93.     rts
  94. .L3:
  95.     mov.w    #2,A0
  96. .L5:
  97.     rts
  98.     .end
  99. #endif
  100. #endif /* L_cmpsi2 */
  101.  
  102. #ifdef L_ucmpsi2
  103. #ifdef __H8300__
  104.     .section .text
  105.     .align 2
  106.     .global ___ucmpsi2
  107. ___ucmpsi2:
  108.     cmp.w    A2,A0
  109.     bne    .L2
  110.     cmp.w    A3,A1
  111.     bne    .L2
  112.     mov.w    #1,A0
  113.     rts
  114. .L2:
  115.     cmp.w    A0,A2
  116.     bhi    .L4
  117.     bne    .L3
  118.     cmp.w    A1,A3
  119.     bls    .L3
  120. .L4:
  121.     sub.w    A0,A0
  122.     rts
  123. .L3:
  124.     mov.w    #2,A0
  125. .L5:
  126.     rts
  127.     .end
  128. #endif
  129. #endif /* L_ucmpsi2 */
  130.  
  131. #ifdef L_divhi3
  132.  
  133. ;; HImode divides for the H8/300.
  134. ;; We bunch all of this into one object file since there are several
  135. ;; "supporting routines".
  136.  
  137. ; general purpose normalize routine
  138. ; divisor in A0
  139. ; dividend in A1
  140. ; turns both into +ve numbers, and leaves what the answer sign
  141. ; should be in A2L
  142.  
  143. #ifdef __H8300__
  144.     .section .text
  145.     .align 2
  146. divnorm:
  147.     mov.b    #0x0,A2L
  148.     or    A0H,A0H        ; is divisor > 0
  149.     bge    _lab1            
  150.     not    A0H        ; no - then make it +ve
  151.     not    A0L
  152.     adds    #1,A0            
  153.     xor    #0x1,A2L    ; and remember that in A2L
  154. _lab1:    or    A1H,A1H    ; look at dividend
  155.     bge    _lab2        
  156.     not    A1H        ; it is -ve, make it positive
  157.     not    A1L
  158.     adds    #1,A1
  159.     xor    #0x1,A2L; and toggle sign of result
  160. _lab2:    rts
  161.  
  162. ; A0=A0/A1 signed
  163.  
  164.     .global    ___divhi3
  165. ___divhi3:
  166.     bsr    divnorm
  167.     bsr    ___udivhi3
  168. negans:    or    A2L,A2L    ; should answer be negative ?
  169.     beq    _lab4
  170.     not    A0H    ; yes, so make it so
  171.     not    A0L
  172.     adds    #1,A0
  173. _lab4:    rts    
  174.  
  175. ; A0=A0%A1 signed
  176.  
  177.     .global    ___modhi3
  178. ___modhi3:
  179.     bsr    divnorm
  180.     bsr    ___udivhi3
  181.     mov    A3,A0
  182.     bra    negans
  183.  
  184. ; A0=A0%A1 unsigned
  185.  
  186.     .global    ___umodhi3
  187. ___umodhi3:
  188.     bsr    ___udivhi3
  189.     mov    A3,A0
  190.     rts
  191.  
  192. ; A0=A0/A1 unsigned
  193. ; A3=A0%A1 unsigned
  194. ; A2H trashed
  195. ; D high 8 bits of denom
  196. ; d low 8 bits of denom
  197. ; N high 8 bits of num
  198. ; n low 8 bits of num
  199. ; M high 8 bits of mod
  200. ; m low 8 bits of mod
  201. ; Q high 8 bits of quot
  202. ; q low 8 bits of quot
  203. ; P preserve
  204.  
  205. ; The h8 only has a 16/8 bit divide, so we look at the incoming and
  206. ; see how to partition up the expression.
  207.  
  208.     .global    ___udivhi3
  209. ___udivhi3:
  210.                 ; A0 A1 A2 A3 
  211.                 ; Nn Dd       P
  212.     sub.w    A3,A3        ; Nn Dd xP 00 
  213.     or    A1H,A1H         
  214.     bne    divlongway
  215.     or    A0H,A0H        
  216.     beq    _lab6        
  217.  
  218. ; we know that D == 0 and N is != 0
  219.     mov.b    A0H,A3L        ; Nn Dd xP 0N
  220.     divxu    A1L,A3        ;          MQ
  221.     mov.b    A3L,A0H         ; Q
  222. ; dealt with N, do n
  223. _lab6:    mov.b    A0L,A3L        ;           n
  224.     divxu    A1L,A3        ;          mq
  225.     mov.b    A3L,A0L        ; Qq
  226.     mov.b    A3H,A3L         ;           m
  227.     mov.b    #0x0,A3H    ; Qq       0m
  228.     rts    
  229.  
  230. ; D != 0 - which means the denominator is
  231. ;          loop around to get the result.
  232.  
  233. divlongway:
  234.     mov.b    A0H,A3L        ; Nn Dd xP 0N
  235.     mov.b    #0x0,A0H    ; high byte of answer has to be zero
  236.     mov.b    #0x8,A2H    ;       8
  237. div8:    add.b    A0L,A0L        ; n*=2
  238.     rotxl    A3L        ; Make remainder bigger
  239.     rotxl    A3H        
  240.     sub.w    A1,A3        ; Q-=N
  241.     bhs    setbit        ; set a bit ?
  242.     add.w    A1,A3        ;  no : too far , Q+=N
  243.  
  244.     dec    A2H        
  245.     bne    div8        ; next bit    
  246.     rts    
  247.  
  248. setbit:    inc    A0L        ; do insert bit
  249.     dec    A2H        
  250.     bne    div8        ; next bit    
  251.     rts    
  252.  
  253. #endif /* __H8300__ */
  254. #endif /* L_divhi3 */
  255.  
  256. #ifdef L_divsi3
  257.  
  258. ;; 4 byte integer divides for the H8/300.
  259. ;;
  260. ;; We have one routine which does all the work and lots of 
  261. ;; little ones which prepare the args and massage the sign.
  262. ;; We bunch all of this into one object file since there are several
  263. ;; "supporting routines".
  264.  
  265. #ifdef __H8300H__
  266.     .h8300h
  267. #endif
  268.  
  269.     .section .text
  270.     .align 2
  271.  
  272. ; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest.
  273. ; This function is here to keep branch displacements small.
  274.  
  275. #ifdef __H8300__
  276.  
  277. divnorm:
  278.     mov.b    #0,S2L        ; keep the sign in S2
  279.     mov.b    A0H,A0H        ; is the numerator -ve
  280.     bge    postive
  281.  
  282.     ; negate arg
  283.     not    A0H
  284.     not    A1H
  285.     not    A0L
  286.     not    A1L
  287.  
  288.     add    #1,A1L
  289.     addx    #0,A1H
  290.     addx    #0,A0H
  291.     addx    #0,A0L
  292.  
  293.     mov.b    #1,S2L        ; the sign will be -ve
  294. postive:
  295.     mov.b    A2H,A2H        ; is the denominator -ve
  296.     bge    postive2
  297.     not    A2L        
  298.     not    A2H
  299.     not    A3L
  300.     not    A3H
  301.     add.b    #1,A3L    
  302.     addx    #0,A3H
  303.     addx    #0,A2L
  304.     addx    #0,A2H
  305.     xor    #1,S2L        ; toggle result sign
  306. postive2:
  307.     rts
  308.  
  309. #else /* __H8300H__ */
  310.  
  311. divnorm:
  312.     mov.b    #0,S2L        ; keep the sign in S2
  313.     mov.l    A0P,A0P        ; is the numerator -ve
  314.     bge    postive
  315.  
  316.     neg.l    A0P        ; negate arg
  317.     mov.b    #1,S2L        ; the sign will be -ve
  318.  
  319. postive:
  320.     mov.l    A1P,A1P        ; is the denominator -ve
  321.     bge    postive2
  322.  
  323.     neg.l    A1P        ; negate arg
  324.     xor.b    #1,S2L        ; toggle result sign
  325.  
  326. postive2:
  327.     rts
  328.  
  329. #endif
  330.  
  331. ; numerator in A0/A1
  332. ; denominator in A2/A3
  333.     .global    ___modsi3
  334. ___modsi3:
  335.     PUSHP    S2P        
  336.     PUSHP    S0P
  337.     PUSHP    S1P
  338.  
  339.     bsr    divnorm
  340.     bsr    divmodsi4
  341. #ifdef __H8300__
  342.     mov    S0,A0
  343.     mov    S1,A1
  344. #else
  345.     mov.l    S0P,A0P
  346. #endif
  347.     bra    exitdiv
  348.  
  349.     .global    ___udivsi3
  350. ___udivsi3:
  351.     PUSHP    S2P
  352.     PUSHP    S0P
  353.     PUSHP    S1P
  354.     mov.b    #0,S2L    ; keep sign low
  355.     bsr    divmodsi4
  356.     bra    exitdiv
  357.  
  358.     .global    ___umodsi3
  359. ___umodsi3:
  360.     PUSHP    S2P
  361.     PUSHP    S0P
  362.     PUSHP    S1P
  363.     mov.b    #0,S2L    ; keep sign low
  364.     bsr    divmodsi4
  365. #ifdef __H8300__
  366.     mov    S0,A0
  367.     mov    S1,A1
  368. #else
  369.     mov.l    S0P,A0P
  370. #endif
  371.     bra    exitdiv
  372.     
  373.     .global    ___divsi3
  374. ___divsi3:
  375.     PUSHP    S2P
  376.     PUSHP    S0P
  377.     PUSHP    S1P
  378.     jsr    divnorm
  379.     jsr    divmodsi4
  380.  
  381.     ; examine what the sign should be
  382. exitdiv:
  383.     POPP    S1P
  384.     POPP    S0P
  385.  
  386.     or    S2L,S2L
  387.     beq    reti
  388.     
  389.     ; should be -ve
  390. #ifdef __H8300__
  391.     not    A0H
  392.     not    A1H
  393.     not    A0L
  394.     not    A1L
  395.  
  396.     add    #1,A1L
  397.     addx    #0,A1H
  398.     addx    #0,A0H
  399.     addx    #0,A0L
  400. #else /* __H8300H__ */
  401.     neg.l    A0P
  402. #endif
  403.  
  404. reti:
  405.     POPP    S2P
  406.     rts    
  407.  
  408.     ; takes A0/A1 numerator (A0P for 300h)
  409.     ; A2/A3 denominator (A1P for 300h)
  410.     ; returns A0/A1 quotient (A0P for 300h)
  411.     ; S0/S1 remainder (S0P for 300h)
  412.     ; trashes S2
  413.  
  414. #ifdef __H8300__
  415.  
  416. divmodsi4:
  417.         sub.w    S0,S0        ; zero play area
  418.         mov.w    S0,S1
  419.         mov.b    A2H,S2H
  420.         or    A2L,S2H
  421.         or    A3H,S2H
  422.         bne    DenHighZero
  423.         mov.b    A0H,A0H
  424.         bne    NumByte0Zero
  425.         mov.b    A0L,A0L
  426.         bne    NumByte1Zero
  427.         mov.b    A1H,A1H
  428.         bne    NumByte2Zero
  429.         bra    NumByte3Zero
  430. NumByte0Zero:
  431.     mov.b    A0H,S1L
  432.         divxu    A3L,S1
  433.         mov.b    S1L,A0H
  434. NumByte1Zero:
  435.     mov.b    A0L,S1L
  436.         divxu    A3L,S1
  437.         mov.b    S1L,A0L
  438. NumByte2Zero:
  439.     mov.b    A1H,S1L
  440.         divxu    A3L,S1
  441.         mov.b    S1L,A1H
  442. NumByte3Zero:
  443.     mov.b    A1L,S1L
  444.         divxu    A3L,S1
  445.         mov.b    S1L,A1L
  446.  
  447.         mov.b    S1H,S1L
  448.         mov.b    #0x0,S1H
  449.         rts    
  450.  
  451. ; have to do the divide by shift and test
  452. DenHighZero:
  453.     mov.b    A0H,S1L
  454.         mov.b    A0L,A0H
  455.         mov.b    A1H,A0L
  456.         mov.b    A1L,A1H
  457.  
  458.         mov.b    #0,A1L
  459.         mov.b    #24,S2H    ; only do 24 iterations
  460.  
  461. nextbit:
  462.     add.w    A1,A1    ; double the answer guess
  463.         rotxl    A0L
  464.         rotxl    A0H
  465.  
  466.         rotxl    S1L    ; double remainder
  467.         rotxl    S1H
  468.         rotxl    S0L
  469.         rotxl    S0H
  470.         sub.w    A3,S1    ; does it all fit
  471.         subx    A2L,S0L
  472.         subx    A2H,S0H
  473.         bhs    setone     
  474.  
  475.         add.w    A3,S1    ; no, restore mistake
  476.         addx    A2L,S0L
  477.         addx    A2H,S0H
  478.  
  479.         dec    S2H
  480.         bne    nextbit
  481.         rts    
  482.     
  483. setone:
  484.     inc    A1L
  485.         dec    S2H
  486.         bne    nextbit
  487.         rts    
  488.  
  489. #else /* __H8300H__ */
  490.  
  491. divmodsi4:
  492.     sub.l    S0P,S0P        ; zero play area
  493.     mov.w    A1E,A1E        ; denominator top word 0?
  494.     bne    DenHighZero
  495.  
  496.     ; do it the easy way, see page 107 in manual
  497.     mov.w    A0E,A2
  498.     extu.l    A2P
  499.     divxu.w    A1,A2P
  500.     mov.w    A2E,A0E
  501.     divxu.w    A1,A0P
  502.     mov.w    A0E,S0
  503.     mov.w    A2,A0E
  504.     extu.l    S0P
  505.     rts
  506.  
  507. DenHighZero:
  508.     mov.w    A0E,A2
  509.     mov.b    A2H,S0L
  510.     mov.b    A2L,A2H
  511.     mov.b    A0H,A2L
  512.     mov.w    A2,A0E
  513.     mov.b    A0L,A0H
  514.     mov.b    #0,A0L
  515.     mov.b    #24,S2H        ; only do 24 iterations
  516.  
  517. nextbit:
  518.     shll.l    A0P        ; double the answer guess
  519.     rotxl.l    S0P        ; double remainder
  520.     sub.l    A1P,S0P        ; does it all fit?
  521.     bhs    setone
  522.  
  523.     add.l    A1P,S0P        ; no, restore mistake
  524.     dec    S2H
  525.     bne    nextbit
  526.     rts
  527.  
  528. setone:
  529.     inc    A0L
  530.     dec    S2H
  531.     bne    nextbit
  532.     rts
  533.  
  534. #endif
  535. #endif /* L_divsi3 */
  536.  
  537. #ifdef L_mulhi3
  538.  
  539. ;; HImode multiply.
  540. ; The h8 only has an 8*8->16 multiply.
  541. ; The answer is the same as:
  542. ; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256
  543. ; (we can ignore A1.h * A0.h cause that will all off the top)
  544. ; A0 in
  545. ; A1 in 
  546. ; A0 answer
  547.  
  548. #ifdef __H8300__
  549.     .section .text
  550.     .align 2
  551.     .global    ___mulhi3
  552. ___mulhi3:
  553.     mov.b    A1L,A2L        ; A2l gets srcb.l
  554.     mulxu    A0L,A2        ; A2 gets first sub product 
  555.  
  556.     mov.b    A0H,A3L        ; prepare for
  557.     mulxu    A1L,A3        ; second sub product
  558.  
  559.     add.b    A3L,A2H        ; sum first two terms
  560.  
  561.     mov.b    A1H,A3L        ; third sub product
  562.     mulxu    A0L,A3        
  563.  
  564.     add.b    A3L,A2H        ; almost there
  565.     mov.w    A2,A0        ; that is
  566.     rts
  567.  
  568. #endif
  569. #endif /* L_mulhi3 */
  570.  
  571. #ifdef L_mulsi3
  572.  
  573. ;; SImode multiply.
  574. ;; 
  575. ;; I think that shift and add may be sufficient for this.  Using the
  576. ;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead.  This way
  577. ;; the inner loop uses maybe 20 cycles + overhead, but terminates
  578. ;; quickly on small args.
  579. ;;
  580. ;; A0/A1 src_a
  581. ;; A2/A3 src_b
  582. ;;
  583. ;;  while (a) 
  584. ;;    {
  585. ;;      if (a & 1)
  586. ;;        r += b;
  587. ;;      a >>= 1;
  588. ;;      b <<= 1;
  589. ;;    }
  590.  
  591.     .section .text
  592.     .align 2
  593.  
  594. #ifdef __H8300__
  595.  
  596.     .global    ___mulsi3
  597. ___mulsi3:
  598.     PUSHP    S0P
  599.     PUSHP    S1P
  600.     PUSHP    S2P
  601.     
  602.     sub.w    S0,S0
  603.     sub.w    S1,S1
  604.     
  605.     ; while (a)
  606. _top:    mov.w    A0,A0
  607.     bne    _more
  608.     mov.w    A1,A1
  609.     beq    _done
  610. _more:    ; if (a & 1)
  611.     bld    #0,A1L
  612.     bcc    _nobit
  613.     ; r += b
  614.     add.w    A3,S1
  615.     addx    A2L,S0L
  616.     addx    A2H,S0H
  617. _nobit:
  618.     ; a >>= 1
  619.     shlr    A0H
  620.     rotxr    A0L
  621.     rotxr    A1H
  622.     rotxr    A1L
  623.     
  624.     ; b <<= 1
  625.     add.w    A3,A3
  626.     addx    A2L,A2L
  627.     addx    A2H,A2H
  628.     bra     _top
  629.  
  630. _done:
  631.     mov.w    S0,A0    
  632.     mov.w    S1,A1
  633.     POPP    S2P
  634.     POPP    S1P
  635.     POPP    S0P
  636.     rts
  637.  
  638. #else /* __H8300H__ */
  639.  
  640.     .h8300h
  641.  
  642.     .global    ___mulsi3
  643. ___mulsi3:
  644.     sub.l    A2P,A2P
  645.  
  646.     ; while (a)
  647. _top:    mov.l    A0P,A0P
  648.     beq    _done
  649.  
  650.     ; if (a & 1)
  651.     bld    #0,A0L
  652.     bcc    _nobit
  653.  
  654.     ; r += b
  655.     add.l    A1P,A2P
  656.  
  657. _nobit:
  658.     ; a >>= 1
  659.     shlr.l    A0P
  660.  
  661.     ; b <<= 1
  662.     shll.l    A1P
  663.     bra    _top
  664.  
  665. _done:
  666.     mov.l    A2P,A0P
  667.     rts
  668.  
  669. #endif
  670. #endif /* L_mulsi3 */