home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / CLISP / CLISPSRC.TAR / clisp-1995-01-01 / src / arihppa.d < prev    next >
Encoding:
Text File  |  1993-08-20  |  11.7 KB  |  263 lines

  1. # Externe Routinen zu ARILEV1.D
  2. # Prozessor: HPPA, wegen XMPYU nur auf HPPA 1.1 (etwa HP9000/720)
  3. # Compiler: GNU-C oder HP-C
  4. # Parameter-▄bergabe: in Registern %arg0,%arg1,%arg2, Rⁿckgabewert in %ret0.
  5. # Einstellungen: intCsize=32, intDsize=32.
  6.  
  7. #ifdef INCLUDED_FROM_C
  8.  
  9. #else
  10.  
  11. # Gro▀enteils abgeschrieben von hppa.s aus der PARI/GP-Distribution.
  12.  
  13.                 .SHORTDATA
  14.                 .IMPORT $global$,DATA
  15.  
  16.  
  17. #if 0 # brauchen wir nicht
  18.                 .CODE
  19.                 .EXPORT bfffo
  20. # Liefert die Anzahl der fⁿhrenden Nullbits von x.
  21. bfffo           .PROC
  22.                 .CALLINFO
  23.                 .ENTER
  24.                 # if (x==0) goto L$0;
  25.                 COMB,=,N        %r0,%arg0,L$0
  26.                 # y = 31;
  27.                 LDI             31,%ret0
  28.                 # if (x & (bit(31-15)*(bit(16)-1)) == 0)
  29.                 EXTRU,<>        %arg0,15,16,%r0
  30.                 SHD,TR          %arg0,%r0,16,%arg0      # x = x<<(32-16); else
  31.                 ADDI            -16,%ret0,%ret0         # y = y-16;
  32.                 # if (x & (bit(31-7)*(bit(8)-1)) == 0)
  33.                 EXTRU,<>        %arg0,7,8,%r0
  34.                 SHD,TR          %arg0,%r0,24,%arg0      # x = x<<(32-24); else
  35.                 ADDI            -8,%ret0,%ret0          # y = y-8;
  36.                 # if (x & (bit(31-3)*(bit(4)-1)) == 0)
  37.                 EXTRU,<>        %arg0,3,4,%r0
  38.                 SHD,TR          %arg0,%r0,28,%arg0      # x = x<<(32-28); else
  39.                 ADDI            -4,%ret0,%ret0          # y = y-4;
  40.                 # if (x & (bit(31-1)*(bit(2)-1)) == 0)
  41.                 EXTRU,<>        %arg0,1,2,%r0
  42.                 SHD,TR          %arg0,%r0,30,%arg0      # x = x<<(32-30); else
  43.                 ADDI            -2,%ret0,%ret0          # y = y-2;
  44.                 # if (x & (bit(31-0)*(bit(1)-1)) != 0)
  45.                 EXTRU,=         %arg0,0,1,%r0
  46.                 ADDI            -1,%ret0,%ret0          # y = y-1;
  47.                 # goto L$1;
  48.                 B,N             L$1
  49. L$0             LDI             32,%ret0
  50. L$1             .LEAVE
  51.                 .PROCEND
  52. #endif
  53.  
  54.                 .CODE
  55.                 .EXPORT length32
  56. # Liefert integer-size (>=1, <=32) des Arguments /=0.
  57. length32        .PROC
  58.                 .CALLINFO
  59.                 .ENTER          # Input in %arg0, Output in %ret0
  60.                 # y = 1;
  61.                 LDI             1,%ret0
  62.                 # if (x & (bit(31-15)*(bit(16)-1)) == 0)
  63.                 EXTRU,<>        %arg0,15,16,%r0
  64.                 SHD,TR          %arg0,%r0,16,%arg0      # x = x<<(32-16); else
  65.                 ADDI            16,%ret0,%ret0          # y = y+16;
  66.                 # if (x & (bit(31-7)*(bit(8)-1)) == 0)
  67.                 EXTRU,<>        %arg0,7,8,%r0
  68.                 SHD,TR          %arg0,%r0,24,%arg0      # x = x<<(32-24); else
  69.                 ADDI            8,%ret0,%ret0           # y = y+8;
  70.                 # if (x & (bit(31-3)*(bit(4)-1)) == 0)
  71.                 EXTRU,<>        %arg0,3,4,%r0
  72.                 SHD,TR          %arg0,%r0,28,%arg0      # x = x<<(32-28); else
  73.                 ADDI            4,%ret0,%ret0           # y = y+4;
  74.                 # if (x & (bit(31-1)*(bit(2)-1)) == 0)
  75.                 EXTRU,<>        %arg0,1,2,%r0
  76.                 SHD,TR          %arg0,%r0,30,%arg0      # x = x<<(32-30); else
  77.                 ADDI            2,%ret0,%ret0           # y = y+2;
  78.                 # if (x & (bit(31-0)*(bit(1)-1)) != 0)
  79.                 EXTRU,=         %arg0,0,1,%r0
  80.                 ADDI            1,%ret0,%ret0           # y = y+1;
  81.                 .LEAVE
  82.                 .PROCEND
  83.  
  84.  
  85. #ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */
  86.  
  87.                 .SHORTDATA
  88.                 .EXPORT mulu32_high
  89.                 .ALIGN 8
  90. mulu32_high     .WORD           # 8 Byte Platz
  91.                 .WORD
  92.  
  93.                 .CODE
  94.                 .EXPORT mulu32_
  95. # extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
  96. # 2^32*hi+lo := arg1*arg2.
  97. mulu32_         .PROC
  98.                 .CALLINFO
  99.                 .ENTER  # Input in %arg0,%arg1, Output in %ret0,mulu32_high
  100.                 LDIL    L'mulu32_high-$global$,%r1
  101.                 LDO     R'mulu32_high-$global$(%r1),%r1
  102.                                                 # %r1 = &x
  103.                 STW     %arg0,0(%r1)            # x abspeichern
  104.                 FLDWS   0(%r1),%fr4             # und in den Coprozessor laden
  105.                 STW     %arg1,0(%r1)            # y abspeichern
  106.                 FLDWS   0(%r1),%fr5             # und in den Coprozessor laden
  107.                 XMPYU   %fr4,%fr5,%fr6          # beides multiplizieren
  108.                 FSTDS   %fr6,0(%r1)             # Ergebnis (64 Bit) abspeichern
  109.                 LDWS    4(%r1),%ret0            # low 32 Bit als Ergebnis
  110.                 .LEAVE
  111.                 .PROCEND
  112.  
  113. #endif
  114.  
  115.  
  116. #if 0 # Das funktioniert noch nicht.
  117.       # Wenn das mal geht (insbes. UDS_to_DIGITS testen!), dann
  118.       # in arilev0.d HPPA_DIV_WORKS -> HPPA Σndern.
  119.  
  120.                 .CODE
  121.                 .EXPORT divu_6432_3232_
  122.                 .IMPORT divu_32_rest,DATA
  123. # extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
  124. # x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, da▀ 0 <= x < 2^32*y .
  125. divu_6432_3232_ .PROC
  126.                 .CALLINFO
  127.                 .ENTER  # Input in %arg0,%arg1,%arg2, Output in %ret0,divu_32_rest
  128. # Registerbezeichnungen:
  129. hirem           .REG    %arg0   # xhi
  130. lorem           .REG    %arg1   # xlo
  131. div             .REG    %arg2   # y bzw. y'
  132. origdiv         .REG    %arg3
  133. quo             .REG    %ret0   # q
  134. temp1           .REG    %r20
  135. temp2           .REG    %r21
  136. temp3           .REG    %r22
  137.  
  138. # Divisions-Einzelschritt:
  139. #               DS      hirem,div,hirem
  140. # div sollte >0 und <2^31 sein.
  141. #if 0 # so steht's dokumentiert
  142. # Schiebt hirem um 1 Bit nach links, wobei der Carry rechts hineingeschoben
  143. # wird. Dann wird div addiert bzw. - falls V gesetzt - (-div) addiert.
  144. # Der ▄bertrag dieser Addition kommt sowohl in den Carry als auch ins V-Bit
  145. # (ins V-Bit invertiert, falls div >= 2^31).
  146. #else # so scheint's aber zu stimmen
  147. # Schiebt hirem um 1 Bit nach links, wobei der Carry rechts hineingeschoben
  148. # wird. Dann wird div subtrahiert bzw. - falls V gel÷scht - (-div) subtrahiert.
  149. # Der ▄bertrag dieser Subtraktion kommt sowohl in den Carry als auch
  150. # invertiert ins V-Bit (nicht invertiert, falls div >= 2^31).
  151. #endif
  152.  
  153. # Der Algorithmus ist wie der von meinem arisparc.s:_divu_3216_1616_ :
  154. # Wenn man y zu Unrecht subtrahiert hat, so gleicht man dies dadurch aus,
  155. # da▀ man nach dem nΣchsten 1-Bit-Shift - statt y zu subtrahieren -
  156. # 2*y addiert und y subtrahiert, d.h. y addiert.
  157.  
  158. # 1 Divisions-Einzelschritt:
  159. # hirem|lorem um 1 Bit nach links schieben und (falls V gesetzt)
  160. # div = y subtrahieren bzw. (falls V gel÷scht) div = y addieren.
  161. DS1             .MACRO
  162.                 ADDC    lorem,lorem,lorem
  163.                 DS      hirem,div,hirem
  164.                 .ENDM
  165.  
  166. # 4 Divisions-Einzelschritte:
  167. DS4             .MACRO
  168.                 DS1
  169.                 DS1
  170.                 DS1
  171.                 DS1
  172.                 .ENDM
  173.  
  174. # 32 Divisions-Einzelschritte:
  175. DS32            .MACRO
  176.                 DS4
  177.                 DS4
  178.                 DS4
  179.                 DS4
  180.                 DS4
  181.                 DS4
  182.                 DS4
  183.                 DS4
  184.                 .ENDM
  185.  
  186.                 COMB,<          div,0,L$50              # y>=0(signed), d.h. y < 2^31 ?
  187.                 # ja -> "kleine" Division
  188.                 SUB             0,div,temp1             # temp1 = -y > 2^31
  189.                 DS              0,temp1,0               # V-Bit setzen (erfolgreiche Subtraktion vortΣuschen)
  190.                 DS32                                    # 32 mal hirem|lorem shiften,
  191.                                                         # jeweils den Carry in lorem hineinshiften
  192.                 ADDC            lorem,lorem,lorem       # letzten Carry in lorem hineinshiften
  193.                 # Nun enthΣlt hirem den Rest r oder r-y, lorem den Quotienten q.
  194.                 ADD,>=          0,hirem,0               # hirem < 0 (signed) ?
  195.                 ADD             hirem,div,hirem         # ja -> mu▀ noch y addieren
  196.                 ADDIL           L'divu_32_rest-$global$,%dp
  197.                 STW             hirem,R'divu_32_rest-$global$(%r1)
  198.                                                         # Rest r abspeichern
  199.                 COPY            lorem,quo               # Quotient q
  200.                 .LEAVE
  201.  
  202. L$50            # y >= 2^31. Reduktion durch Halbieren von x und y.
  203.                 COPY            div,origdiv             # y in origdiv retten
  204.                 EXTRU,<>        div,31,1,temp2          # temp2 := Bit 0 von y
  205.                 B               L$51
  206.                 # Division durch ungerade Zahl:
  207.                 # Schreibe y = 2*y'-1.
  208.                 # floor(x / (2*y'-1)) = floor(floor(x/2) / y') + (0 oder 1 oder 2)
  209.                 # da  0 <= x/(2*y'-1) - x/(2*y') = x/(2*y'-1) / (2*y') = x/y / (2*y')
  210.                 #       < 2^32 / (2*y') < 2^32/y <= 2 .
  211.                 EXTRU           div,30,31,div           # div := floor(y/2) = Bits 31..1 von div
  212.                 ADDB,NSV        temp2,div,L$52          # div := div+1 = y'
  213.                 EXTRU           lorem,31,1,temp3        # s.u. (delay slot)
  214.                 # Spezialfall: signed-▄berlauf bei der Addition, d.h. y' = 2^31.
  215.                 # Division durch 2*y' ist hier besonders einfach:
  216.                 COPY            hirem,quo               # Quotient := hirem
  217.                 B               L$53
  218.                 COPY            lorem,hirem             # Rest := lorem
  219.  
  220. L$51            # Division durch gerades y.
  221.                 # x/2 durch y/2 dividieren, Quotient OK, Rest mit 2 multiplizieren, evtl. + 1.
  222.                 EXTRU           lorem,31,1,temp3        # temp3 := Bit 0 von xlo
  223. L$52            SHD             hirem,lorem,1,lorem     # hirem|lorem um 1 Bit ...
  224.                 EXTRU           hirem,30,31,hirem       # ... nach rechts schieben
  225.                 # kleine Division (wie oben):
  226.                 SUB             0,div,temp1
  227.                 DS              0,temp1,0
  228.                 DS32
  229.                 ADDC            lorem,lorem,lorem
  230.                 ADD,>=          0,hirem,0
  231.                 ADD             hirem,div,hirem
  232.                 # Quotient in lorem fertig.
  233.                 COPY            lorem,quo               # Quotient q
  234.                 COMB,=          0,temp2,L$55            # war temp2=0, d.h. y gerade?
  235.                 SH1ADD          hirem,temp3,hirem         # ja -> nur noch hirem:=2*hirem+temp3 und fertig
  236. L$53            # Es war y gerade, nun ist quo = floor(x / 2*y').
  237.                 # Quotient und Rest umrechnen:
  238.                 # x = quo * 2*y' + hirem = quo * (2*y'-1) + (quo+hirem)
  239.                 # Also Quotient = quo, Rest = quo+hirem.
  240.                 # Noch maximal 2 mal: Quotient += 1, Rest -= y.
  241.                 ADDB,NUV,N      quo,hirem,L$54          # Additions-▄berlauf -> Quotient erh÷hen
  242.                                                         # kein delay-slot wegen ,N !
  243.                 SUB             hirem,origdiv,hirem     # Rest -= y
  244.                 ADDI            1,quo,quo               # Quotient += 1
  245. L$54            # Wegen y>=2^31 mu▀ der Quotient noch h÷chstens 1 mal erh÷ht werden:
  246.                 COMB,<<,N       hirem,origdiv,L$55      # hirem < y -> Quotient erh÷hen
  247.                                                         # kein delay-slot wegen ,N !
  248.                 SUB             hirem,origdiv,hirem     # Rest -= y
  249.                 ADDI            1,quo,quo               # Quotient += 1
  250.  
  251. L$55            ADDIL           L'divu_32_rest-$global$,%dp
  252.                 STW             hirem,R'divu_32_rest-$global$(%r1)
  253.                                                         # Rest r abspeichern
  254.                 .LEAVE
  255.                 .PROCEND
  256.  
  257. #endif
  258.  
  259.  
  260.                 .END
  261.  
  262. #endif
  263.