0339bfe7f3a82a7c298c26de495bd0e923994e14
[openssl.git] / crypto / bn / asm / sparcv9-mont.pl
1 #!/usr/bin/env perl
2
3 # ====================================================================
4 # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
5 # project. Rights for redistribution and usage in source and binary
6 # forms are granted according to the OpenSSL license.
7 # ====================================================================
8
9 # December 2005
10 #
11 # Pure SPARCv9/8+ and IALU-only bn_mul_mont implementation. The reasons
12 # for undertaken effort are multiple. First of all, UltraSPARC is not
13 # the whole SPARCv9 universe and other VIS-free implementations deserve
14 # optimized code as much. Secondly, newly introduced UltraSPARC T1,
15 # a.k.a. Niagara, has shared FPU and concurrent FPU-intensive pathes,
16 # such as sparcv9a-mont, will simply sink it. Yes, T1 is equipped with
17 # several integrated RSA/DSA accelerator circuits accessible through
18 # kernel driver [only(*)], but having decent user-land software
19 # implementation is important too. Finally, reasons like desire to
20 # experiment with dedicated squaring procedure. Yes, this module
21 # implements one, because it was easiest to draft it in SPARCv9
22 # instructions...
23
24 # (*)   Engine accessing the driver in question is on my TODO list.
25 #       For reference, acceleator is estimated to give 6 to 10 times
26 #       improvement on single-threaded RSA sign. It should be noted
27 #       that 6-10x improvement coefficient does not actually mean
28 #       something extraordinary in terms of absolute [single-threaded]
29 #       performance, as SPARCv9 instruction set is by all means least
30 #       suitable for high performance crypto among other 64 bit
31 #       platforms. 6-10x factor simply places T1 in same performance
32 #       domain as say AMD64 and IA-64. Improvement of RSA verify don't
33 #       appear impressive at all, but it's the sign operation which is
34 #       far more critical/interesting.
35
36 # You might notice that inner loops are modulo-scheduled:-) This has
37 # essentially negligible impact on UltraSPARC performance, it's
38 # Fujitsu SPARC64 V users who should notice and hopefully appreciate
39 # the advantage... Currently this module surpasses sparcv9a-mont.pl
40 # by ~20% on UltraSPARC-III and later cores, but recall that sparcv9a
41 # module still have hidden potential [see TODO list there], which is
42 # estimated to be larger than 20%...
43
44 # int bn_mul_mont(
45 $rp="%i0";      # BN_ULONG *rp,
46 $ap="%i1";      # const BN_ULONG *ap,
47 $bp="%i2";      # const BN_ULONG *bp,
48 $np="%i3";      # const BN_ULONG *np,
49 $n0="%i4";      # const BN_ULONG *n0,
50 $num="%i5";     # int num);
51
52 $bits=32;
53 for (@ARGV)     { $bits=64 if (/\-m64/ || /\-xarch\=v9/); }
54 if ($bits==64)  { $bias=2047; $frame=192; }
55 else            { $bias=0;    $frame=128; }
56
57 $car0="%o0";
58 $car1="%o1";
59 $car2="%o2";    # 1 bit
60 $acc0="%o3";
61 $acc1="%o4";
62 $mask="%g1";    # 32 bits, what a waste...
63 $tmp0="%g4";
64 $tmp1="%g5";
65
66 $i="%l0";
67 $j="%l1";
68 $mul0="%l2";
69 $mul1="%l3";
70 $tp="%l4";
71 $apj="%l5";
72 $npj="%l6";
73 $tpj="%l7";
74
75 $fname="bn_mul_mont";
76
77 $code=<<___;
78 .section        ".text",#alloc,#execinstr
79
80 .global $fname
81 .align  32
82 $fname:
83         cmp     %o5,4                   ! 128 bits minimum
84         bge,pt  %icc,.Lenter
85         sethi   %hi(0xffffffff),$mask
86         retl
87         clr     %o0
88 .align  32
89 .Lenter:
90         save    %sp,-$frame,%sp
91         sll     $num,2,$num             ! num*=4
92         or      $mask,%lo(0xffffffff),$mask
93         ld      [$n0],$n0
94         cmp     $ap,$bp
95         and     $num,$mask,$num
96         ld      [$bp],$mul0             ! bp[0]
97         be,pt   `$bits==32?"%icc":"%xcc"`,.Lbn_sqr_mont
98         nop
99
100         add     %sp,$bias,%o7           ! real top of stack
101         ld      [$ap],$car0             ! ap[0]
102         sub     %o7,$num,%o7
103         ld      [$ap+4],$apj            ! ap[1]
104         and     %o7,-1024,%o7
105         ld      [$np],$car1             ! np[0]
106         sub     %o7,$bias,%sp           ! alloca
107         ld      [$np+4],$npj            ! np[1]
108         mov     12,$j
109
110         mulx    $car0,$mul0,$car0       ! ap[0]*bp[0]
111         mulx    $apj,$mul0,$tmp0        !prologue! ap[1]*bp[0]
112         and     $car0,$mask,$acc0
113         add     %sp,$bias+$frame,$tp
114         ld      [$ap+8],$apj            !prologue!
115
116         mulx    $n0,$acc0,$mul1         ! "t[0]"*n0
117         and     $mul1,$mask,$mul1
118
119         mulx    $car1,$mul1,$car1       ! np[0]*"t[0]"*n0
120         mulx    $npj,$mul1,$acc1        !prologue! np[1]*"t[0]"*n0
121         srlx    $car0,32,$car0
122         add     $acc0,$car1,$car1
123         ld      [$np+8],$npj            !prologue!
124         srlx    $car1,32,$car1
125         mov     $tmp0,$acc0             !prologue!
126
127 .L1st:
128         mulx    $apj,$mul0,$tmp0
129         mulx    $npj,$mul1,$tmp1
130         add     $acc0,$car0,$car0
131         ld      [$ap+$j],$apj           ! ap[j]
132         and     $car0,$mask,$acc0
133         add     $acc1,$car1,$car1
134         ld      [$np+$j],$npj           ! np[j]
135         srlx    $car0,32,$car0
136         add     $acc0,$car1,$car1
137         add     $j,4,$j                 ! j++
138         mov     $tmp0,$acc0
139         st      $car1,[$tp]
140         cmp     $j,$num
141         mov     $tmp1,$acc1
142         srlx    $car1,32,$car1
143         bl      %icc,.L1st
144         add     $tp,4,$tp               ! tp++
145 !.L1st
146
147         mulx    $apj,$mul0,$tmp0        !epilogue!
148         mulx    $npj,$mul1,$tmp1
149         add     $acc0,$car0,$car0
150         and     $car0,$mask,$acc0
151         add     $acc1,$car1,$car1
152         srlx    $car0,32,$car0
153         add     $acc0,$car1,$car1
154         st      $car1,[$tp]
155         srlx    $car1,32,$car1
156
157         add     $tmp0,$car0,$car0
158         and     $car0,$mask,$acc0
159         add     $tmp1,$car1,$car1
160         srlx    $car0,32,$car0
161         add     $acc0,$car1,$car1
162         st      $car1,[$tp+4]
163         srlx    $car1,32,$car1
164
165         add     $car0,$car1,$car1
166         st      $car1,[$tp+8]
167         srlx    $car1,32,$car2
168 \f
169         mov     4,$i                    ! i++
170         ld      [$bp+4],$mul0           ! bp[1]
171 .Louter:
172         add     %sp,$bias+$frame,$tp
173         ld      [$ap],$car0             ! ap[0]
174         ld      [$ap+4],$apj            ! ap[1]
175         ld      [$np],$car1             ! np[0]
176         ld      [$np+4],$npj            ! np[1]
177         ld      [$tp],$tmp1             ! tp[0]
178         ld      [$tp+4],$tpj            ! tp[1]
179         mov     12,$j
180
181         mulx    $car0,$mul0,$car0
182         mulx    $apj,$mul0,$tmp0        !prologue!
183         add     $tmp1,$car0,$car0
184         ld      [$ap+8],$apj            !prologue!
185         and     $car0,$mask,$acc0
186
187         mulx    $n0,$acc0,$mul1
188         and     $mul1,$mask,$mul1
189
190         mulx    $car1,$mul1,$car1
191         mulx    $npj,$mul1,$acc1        !prologue!
192         srlx    $car0,32,$car0
193         add     $acc0,$car1,$car1
194         ld      [$np+8],$npj            !prologue!
195         srlx    $car1,32,$car1
196         mov     $tmp0,$acc0             !prologue!
197
198 .Linner:
199         mulx    $apj,$mul0,$tmp0
200         mulx    $npj,$mul1,$tmp1
201         add     $tpj,$car0,$car0
202         ld      [$ap+$j],$apj           ! ap[j]
203         add     $acc0,$car0,$car0
204         add     $acc1,$car1,$car1
205         ld      [$np+$j],$npj           ! np[j]
206         and     $car0,$mask,$acc0
207         ld      [$tp+8],$tpj            ! tp[j]
208         srlx    $car0,32,$car0
209         add     $acc0,$car1,$car1
210         add     $j,4,$j                 ! j++
211         mov     $tmp0,$acc0
212         st      $car1,[$tp]             ! tp[j-1]
213         srlx    $car1,32,$car1
214         mov     $tmp1,$acc1
215         cmp     $j,$num
216         bl      %icc,.Linner
217         add     $tp,4,$tp               ! tp++
218 !.Linner
219
220         mulx    $apj,$mul0,$tmp0        !epilogue!
221         mulx    $npj,$mul1,$tmp1
222         add     $tpj,$car0,$car0
223         add     $acc0,$car0,$car0
224         ld      [$tp+8],$tpj            ! tp[j]
225         and     $car0,$mask,$acc0
226         add     $acc1,$car1,$car1
227         srlx    $car0,32,$car0
228         add     $acc0,$car1,$car1
229         st      $car1,[$tp]             ! tp[j-1]
230         srlx    $car1,32,$car1
231
232         add     $tpj,$car0,$car0
233         add     $tmp0,$car0,$car0
234         and     $car0,$mask,$acc0
235         add     $tmp1,$car1,$car1
236         add     $acc0,$car1,$car1
237         st      $car1,[$tp+4]           ! tp[j-1]
238         srlx    $car0,32,$car0
239         add     $i,4,$i                 ! i++
240         srlx    $car1,32,$car1
241
242         add     $car0,$car1,$car1
243         cmp     $i,$num
244         add     $car2,$car1,$car1
245         st      $car1,[$tp+8]
246
247         srlx    $car1,32,$car2
248         bl,a    %icc,.Louter
249         ld      [$bp+$i],$mul0          ! bp[i]
250 !.Louter
251
252         add     $tp,12,$tp
253 \f
254 .Ltail:
255         add     $np,$num,$np
256         add     $rp,$num,$rp
257
258         cmp     $car2,0                 ! clears %icc.c
259         bne,pn  %icc,.Lsub
260         sub     %g0,$num,%o7            ! k=-num
261
262         cmp     $car1,$npj              ! compare top-most $tp and $np words
263         bcs,pt  %icc,.Lcopy             ! %icc.c is clean if not taken
264         nop
265
266 .align  16,0x1000000
267 .Lsub:
268         ld      [$tp+%o7],%o0
269         ld      [$np+%o7],%o1
270         subccc  %o0,%o1,%o1
271         st      %o1,[$rp+%o7]
272         add     %o7,4,%o7
273         brnz    %o7,.Lsub
274         nop
275         subccc  $car2,0,$car2
276         bcc     %icc,.Lzap
277         sub     %g0,$num,%o7
278
279 .align  16,0x1000000
280 .Lcopy:
281         ld      [$tp+%o7],%o0
282         st      %o0,[$rp+%o7]
283         add     %o7,4,%o7
284         brnz    %o7,.Lcopy
285         nop
286         ba      .Lzap
287         sub     %g0,$num,%o7
288
289 .align  32
290 .Lzap:
291         st      %g0,[$tp+%o7]
292         add     %o7,4,%o7
293         brnz    %o7,.Lzap
294         nop
295         mov     1,%i0
296         ret
297         restore
298 ___
299 \f
300 ########
301 ######## bn_sqr_mont gives up to 20% improvement over above code
302 ########
303 $sbit="%i2";            # re-use $bp!
304
305 $code.=<<___;
306 .align  32
307 .Lbn_sqr_mont:
308         add     %sp,$bias,%o7                   ! real top of stack
309         ld      [$ap+4],$apj                    ! ap[1]
310         sub     %o7,$num,%o7
311         ld      [$np],$car1                     ! np[0]
312         and     %o7,-1024,%o7
313         ld      [$np+4],$npj                    ! np[1]
314         sub     %o7,$bias,%sp                   ! alloca
315         mov     12,$j
316
317         mulx    $mul0,$mul0,$car0               ! ap[0]*ap[0]
318         mulx    $apj,$mul0,$tmp0                !prologue!
319         and     $car0,$mask,$acc0
320         add     %sp,$bias+$frame,$tp
321         ld      [$ap+8],$apj                    !prologue!
322
323         mulx    $n0,$acc0,$mul1                 ! "t[0]"*n0
324         srlx    $car0,32,$car0
325         and     $mul1,$mask,$mul1
326
327         mulx    $car1,$mul1,$car1               ! np[0]*"t[0]"*n0
328         mulx    $npj,$mul1,$acc1                !prologue!
329         and     $car0,1,$sbit
330         ld      [$np+8],$npj                    !prologue!
331         srlx    $car0,1,$car0
332         add     $acc0,$car1,$car1
333         srlx    $car1,32,$car1
334         mov     $tmp0,$acc0                     !prologue!
335
336 .Lsqr_1st:
337         mulx    $apj,$mul0,$tmp0
338         mulx    $npj,$mul1,$tmp1
339         add     $acc0,$car0,$car0               ! ap[j]*a0+c0
340         add     $acc1,$car1,$car1
341         ld      [$ap+$j],$apj                   ! ap[j]
342         and     $car0,$mask,$acc0
343         ld      [$np+$j],$npj                   ! np[j]
344         srlx    $car0,32,$car0
345         add     $acc0,$acc0,$acc0
346         or      $sbit,$acc0,$acc0
347         mov     $tmp1,$acc1
348         srlx    $acc0,32,$sbit
349         add     $j,4,$j                         ! j++
350         and     $acc0,$mask,$acc0
351         cmp     $j,$num
352         add     $acc0,$car1,$car1
353         st      $car1,[$tp]
354         mov     $tmp0,$acc0
355         srlx    $car1,32,$car1
356         bl      %icc,.Lsqr_1st
357         add     $tp,4,$tp                       ! tp++
358 !.Lsqr_1st
359
360         mulx    $apj,$mul0,$tmp0                ! epilogue
361         mulx    $npj,$mul1,$tmp1
362         add     $acc0,$car0,$car0               ! ap[j]*a0+c0
363         add     $acc1,$car1,$car1
364         and     $car0,$mask,$acc0
365         srlx    $car0,32,$car0
366         add     $acc0,$acc0,$acc0
367         or      $sbit,$acc0,$acc0
368         srlx    $acc0,32,$sbit
369         and     $acc0,$mask,$acc0
370         add     $acc0,$car1,$car1
371         st      $car1,[$tp]
372         srlx    $car1,32,$car1
373
374         add     $tmp0,$car0,$car0               ! ap[j]*a0+c0
375         add     $tmp1,$car1,$car1
376         and     $car0,$mask,$acc0
377         srlx    $car0,32,$car0
378         add     $acc0,$acc0,$acc0
379         or      $sbit,$acc0,$acc0
380         srlx    $acc0,32,$sbit
381         and     $acc0,$mask,$acc0
382         add     $acc0,$car1,$car1
383         st      $car1,[$tp+4]
384         srlx    $car1,32,$car1
385
386         add     $car0,$car0,$car0
387         or      $sbit,$car0,$car0
388         add     $car0,$car1,$car1
389         st      $car1,[$tp+8]
390         srlx    $car1,32,$car2
391 \f
392         ld      [%sp+$bias+$frame],$tmp0        ! tp[0]
393         ld      [%sp+$bias+$frame+4],$tmp1      ! tp[1]
394         ld      [%sp+$bias+$frame+8],$tpj       ! tp[2]
395         ld      [$ap+4],$mul0                   ! ap[1]
396         ld      [$ap+8],$apj                    ! ap[2]
397         ld      [$np],$car1                     ! np[0]
398         ld      [$np+4],$npj                    ! np[1]
399         mulx    $n0,$tmp0,$mul1
400
401         mulx    $mul0,$mul0,$car0
402         and     $mul1,$mask,$mul1
403
404         mulx    $car1,$mul1,$car1
405         mulx    $npj,$mul1,$acc1
406         add     $tmp0,$car1,$car1
407         and     $car0,$mask,$acc0
408         ld      [$np+8],$npj                    ! np[2]
409         srlx    $car1,32,$car1
410         add     $tmp1,$car1,$car1
411         srlx    $car0,32,$car0
412         add     $acc0,$car1,$car1
413         and     $car0,1,$sbit
414         add     $acc1,$car1,$car1
415         srlx    $car0,1,$car0
416         mov     12,$j
417         st      $car1,[%sp+$bias+$frame]        ! tp[0]=
418         srlx    $car1,32,$car1
419         add     %sp,$bias+$frame+4,$tp
420
421 .Lsqr_2nd:
422         mulx    $apj,$mul0,$acc0
423         mulx    $npj,$mul1,$acc1
424         add     $acc0,$car0,$car0
425         add     $tpj,$car1,$car1
426         ld      [$ap+$j],$apj                   ! ap[j]
427         and     $car0,$mask,$acc0
428         ld      [$np+$j],$npj                   ! np[j]
429         srlx    $car0,32,$car0
430         add     $acc1,$car1,$car1
431         ld      [$tp+8],$tpj                    ! tp[j]
432         add     $acc0,$acc0,$acc0
433         add     $j,4,$j                         ! j++
434         or      $sbit,$acc0,$acc0
435         srlx    $acc0,32,$sbit
436         and     $acc0,$mask,$acc0
437         cmp     $j,$num
438         add     $acc0,$car1,$car1
439         st      $car1,[$tp]                     ! tp[j-1]
440         srlx    $car1,32,$car1
441         bl      %icc,.Lsqr_2nd
442         add     $tp,4,$tp                       ! tp++
443 !.Lsqr_2nd
444
445         mulx    $apj,$mul0,$acc0
446         mulx    $npj,$mul1,$acc1
447         add     $acc0,$car0,$car0
448         add     $tpj,$car1,$car1
449         and     $car0,$mask,$acc0
450         srlx    $car0,32,$car0
451         add     $acc1,$car1,$car1
452         add     $acc0,$acc0,$acc0
453         or      $sbit,$acc0,$acc0
454         srlx    $acc0,32,$sbit
455         and     $acc0,$mask,$acc0
456         add     $acc0,$car1,$car1
457         st      $car1,[$tp]                     ! tp[j-1]
458         srlx    $car1,32,$car1
459
460         add     $car0,$car0,$car0
461         or      $sbit,$car0,$car0
462         add     $car0,$car1,$car1
463         add     $car2,$car1,$car1
464         st      $car1,[$tp+4]
465         srlx    $car1,32,$car2
466 \f
467         ld      [%sp+$bias+$frame],$tmp1        ! tp[0]
468         ld      [%sp+$bias+$frame+4],$tpj       ! tp[1]
469         ld      [$ap+8],$mul0                   ! ap[2]
470         ld      [$np],$car1                     ! np[0]
471         ld      [$np+4],$npj                    ! np[1]
472         mulx    $n0,$tmp1,$mul1
473         and     $mul1,$mask,$mul1
474         mov     8,$i
475
476         mulx    $mul0,$mul0,$car0
477         mulx    $car1,$mul1,$car1
478         and     $car0,$mask,$acc0
479         add     $tmp1,$car1,$car1
480         srlx    $car0,32,$car0
481         add     %sp,$bias+$frame,$tp
482         srlx    $car1,32,$car1
483         and     $car0,1,$sbit
484         srlx    $car0,1,$car0
485         mov     4,$j
486
487 .Lsqr_outer:
488 .Lsqr_inner1:
489         mulx    $npj,$mul1,$acc1
490         add     $tpj,$car1,$car1
491         add     $j,4,$j
492         ld      [$tp+8],$tpj
493         cmp     $j,$i
494         add     $acc1,$car1,$car1
495         ld      [$np+$j],$npj
496         st      $car1,[$tp]
497         srlx    $car1,32,$car1
498         bl      %icc,.Lsqr_inner1
499         add     $tp,4,$tp
500 !.Lsqr_inner1
501
502         add     $j,4,$j
503         ld      [$ap+$j],$apj                   ! ap[j]
504         mulx    $npj,$mul1,$acc1
505         add     $tpj,$car1,$car1
506         ld      [$np+$j],$npj                   ! np[j]
507         add     $acc0,$car1,$car1
508         ld      [$tp+8],$tpj                    ! tp[j]
509         add     $acc1,$car1,$car1
510         st      $car1,[$tp]
511         srlx    $car1,32,$car1
512
513         add     $j,4,$j
514         cmp     $j,$num
515         be,pn   %icc,.Lsqr_no_inner2
516         add     $tp,4,$tp
517
518 .Lsqr_inner2:
519         mulx    $apj,$mul0,$acc0
520         mulx    $npj,$mul1,$acc1
521         add     $tpj,$car1,$car1
522         add     $acc0,$car0,$car0
523         ld      [$ap+$j],$apj                   ! ap[j]
524         and     $car0,$mask,$acc0
525         ld      [$np+$j],$npj                   ! np[j]
526         srlx    $car0,32,$car0
527         add     $acc0,$acc0,$acc0
528         ld      [$tp+8],$tpj                    ! tp[j]
529         or      $sbit,$acc0,$acc0
530         add     $j,4,$j                         ! j++
531         srlx    $acc0,32,$sbit
532         and     $acc0,$mask,$acc0
533         cmp     $j,$num
534         add     $acc0,$car1,$car1
535         add     $acc1,$car1,$car1
536         st      $car1,[$tp]                     ! tp[j-1]
537         srlx    $car1,32,$car1
538         bl      %icc,.Lsqr_inner2
539         add     $tp,4,$tp                       ! tp++
540
541 .Lsqr_no_inner2:
542         mulx    $apj,$mul0,$acc0
543         mulx    $npj,$mul1,$acc1
544         add     $tpj,$car1,$car1
545         add     $acc0,$car0,$car0
546         and     $car0,$mask,$acc0
547         srlx    $car0,32,$car0
548         add     $acc0,$acc0,$acc0
549         or      $sbit,$acc0,$acc0
550         srlx    $acc0,32,$sbit
551         and     $acc0,$mask,$acc0
552         add     $acc0,$car1,$car1
553         add     $acc1,$car1,$car1
554         st      $car1,[$tp]                     ! tp[j-1]
555         srlx    $car1,32,$car1
556
557         add     $car0,$car0,$car0
558         or      $sbit,$car0,$car0
559         add     $car0,$car1,$car1
560         add     $car2,$car1,$car1
561         st      $car1,[$tp+4]
562         srlx    $car1,32,$car2
563 \f
564         add     $i,4,$i                         ! i++
565         ld      [%sp+$bias+$frame],$tmp1        ! tp[0]
566         ld      [%sp+$bias+$frame+4],$tpj       ! tp[1]
567         ld      [$ap+$i],$mul0                  ! ap[j]
568         ld      [$np],$car1                     ! np[0]
569         ld      [$np+4],$npj                    ! np[1]
570         mulx    $n0,$tmp1,$mul1
571         and     $mul1,$mask,$mul1
572         add     $i,4,$tmp0
573
574         mulx    $mul0,$mul0,$car0
575         mulx    $car1,$mul1,$car1
576         and     $car0,$mask,$acc0
577         add     $tmp1,$car1,$car1
578         srlx    $car0,32,$car0
579         add     %sp,$bias+$frame,$tp
580         srlx    $car1,32,$car1
581         and     $car0,1,$sbit
582         srlx    $car0,1,$car0
583
584         cmp     $tmp0,$num                      ! i<num-1
585         bl      %icc,.Lsqr_outer
586         mov     4,$j
587 \f
588 .Lsqr_last:
589         mulx    $npj,$mul1,$acc1
590         add     $tpj,$car1,$car1
591         add     $j,4,$j
592         ld      [$tp+8],$tpj
593         cmp     $j,$i
594         add     $acc1,$car1,$car1
595         ld      [$np+$j],$npj
596         st      $car1,[$tp]
597         srlx    $car1,32,$car1
598         bl      %icc,.Lsqr_last
599         add     $tp,4,$tp
600 !.Lsqr_last
601
602         mulx    $npj,$mul1,$acc1
603         add     $tpj,$car1,$car1
604         add     $acc0,$car1,$car1
605         add     $acc1,$car1,$car1
606         st      $car1,[$tp]
607         srlx    $car1,32,$car1
608
609         add     $car0,$car0,$car0               ! recover $car0
610         or      $sbit,$car0,$car0
611         add     $car0,$car1,$car1
612         add     $car2,$car1,$car1
613         st      $car1,[$tp+4]
614         srlx    $car1,32,$car2
615
616         ba      .Ltail
617         add     $tp,8,$tp
618 .type   $fname,#function
619 .size   $fname,(.-$fname)
620 ___
621 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
622 print $code;
623 close STDOUT;