|  | ; QuickThreads -- Threads-building toolkit. | 
|  | ; Copyright (c) 1993 by David Keppel | 
|  |  | 
|  | ; Permission to use, copy, modify and distribute this software and | 
|  | ; its documentation for any purpose and without fee is hereby | 
|  | ; granted, provided that the above copyright notice and this notice | 
|  | ; appear in all copies.  This software is provided as a | 
|  | ; proof-of-concept and for demonstration purposes; there is no | 
|  | ; representation about the suitability of this software for any | 
|  | ; purpose. | 
|  |  | 
|  | ; This file (pa-risc_b.s) is part of the port of QuickThreads for | 
|  | ; PA-RISC 1.1 architecture.  It contains assembly-level support for | 
|  | ; raw processor performance measurement.  It was written in 1994 by | 
|  | ; Uwe Reder (`uereder@cip.informatik.uni-erlangen.de') | 
|  | ; for the Operating Systems Department (IMMD4) at the | 
|  | ; University of Erlangen/Nuernberg Germany. | 
|  |  | 
|  |  | 
|  | ; Note that the number of instructions in the measurement-loops, differ | 
|  | ; from implementation to implementation. I took eight instructions in a loop | 
|  | ; for every test (execute eight instructions and loop to the start). | 
|  |  | 
|  | .CODE | 
|  |  | 
|  | .IMPORT $global$,DATA | 
|  | .IMPORT $$dyncall,MILLICODE | 
|  | .EXPORT b_call_reg | 
|  | .EXPORT b_call_imm | 
|  | .EXPORT b_add | 
|  | .EXPORT b_load | 
|  |  | 
|  | ; Just do nothing, only return to caller. This procedure is called by | 
|  | ; `b_call_reg' and `b_call_imm'. | 
|  |  | 
|  | b_null | 
|  | .PROC | 
|  | .CALLINFO   NO_CALLS, FRAME=0 | 
|  | .ENTRY | 
|  |  | 
|  | bv,n        %r0(%rp)        ; just return | 
|  |  | 
|  | .EXIT | 
|  | .PROCEND | 
|  |  | 
|  | ; Call the procedure `b_null' with function pointer in a register. | 
|  |  | 
|  | b_call_reg | 
|  | .PROC | 
|  | .CALLINFO   CALLER, FRAME=0 | 
|  | .ENTRY | 
|  |  | 
|  | stwm        %r3,64(%sp)     ; store r3 (may be used by caller) | 
|  | stw         %rp,-20(%sp)    ; save return-pointer to frame-marker | 
|  |  | 
|  | addil       LR'to_call-$global$,%r27 | 
|  | ldw         RR'to_call-$global$(%r1),%r3 | 
|  |  | 
|  | _loop0 | 
|  | copy        %r3,%r22        ; copy the procedure label to r22, ... | 
|  | .CALL                       ; ...this is the input to $$dyncall | 
|  | bl          $$dyncall,%mrp  ; call $$dyncall (millicode function) | 
|  | copy        %mrp,%rp        ; remember the return-pointer | 
|  |  | 
|  | copy        %r3,%r22 | 
|  | .CALL | 
|  | bl          $$dyncall,%mrp | 
|  | copy        %mrp,%rp | 
|  |  | 
|  | copy        %r3,%r22 | 
|  | .CALL | 
|  | bl          $$dyncall,%mrp | 
|  | copy        %mrp,%rp | 
|  |  | 
|  | copy        %r3,%r22 | 
|  | .CALL | 
|  | bl          $$dyncall,%mrp | 
|  | copy        %mrp,%rp | 
|  |  | 
|  | copy        %r3,%r22 | 
|  | .CALL | 
|  | bl          $$dyncall,%mrp | 
|  | copy        %mrp,%rp | 
|  |  | 
|  | copy        %r3,%r22 | 
|  | .CALL | 
|  | bl          $$dyncall,%mrp | 
|  | copy        %mrp,%rp | 
|  |  | 
|  | copy        %r3,%r22 | 
|  | .CALL | 
|  | bl          $$dyncall,%mrp | 
|  | copy        %mrp,%rp | 
|  |  | 
|  | copy        %r3,%r22 | 
|  | .CALL | 
|  | bl          $$dyncall,%mrp | 
|  | copy        %mrp,%rp | 
|  |  | 
|  | addibf,<=   -8,%arg0,_loop0 ; decrement counter by 8 and loop | 
|  | nop | 
|  |  | 
|  | ldw         -20(%sp),%rp    ; restore return-pointer | 
|  | bv          %r0(%rp)        ; return to caller | 
|  | ldwm        -64(%sp),%r3    ; resore r3 and remove stack frame | 
|  |  | 
|  | .EXIT | 
|  | .PROCEND | 
|  |  | 
|  | ; Call the procedure `b_null' immediate. | 
|  |  | 
|  | b_call_imm | 
|  | .PROC | 
|  | .CALLINFO   CALLER, FRAME=0, SAVE_RP | 
|  | .ENTRY | 
|  |  | 
|  | ldo         64(%sp),%sp     ; caller needs a stack-frame | 
|  | stw         %rp,-20(%sp)    ; save return-pointer to frame-marker | 
|  |  | 
|  | _loop1 | 
|  | bl          b_null,%rp      ; call `b_null' immediate (8 times) | 
|  | nop | 
|  | bl          b_null,%rp | 
|  | nop | 
|  | bl          b_null,%rp | 
|  | nop | 
|  | bl          b_null,%rp | 
|  | nop | 
|  | bl          b_null,%rp | 
|  | nop | 
|  | bl          b_null,%rp | 
|  | nop | 
|  | bl          b_null,%rp | 
|  | nop | 
|  | bl          b_null,%rp | 
|  | nop | 
|  |  | 
|  | addibf,<=   -8,%arg0,_loop1 ; decrement counter by 8 and loop | 
|  | nop | 
|  |  | 
|  | ldw         -20(%sp),%rp    ; restore return-pointer | 
|  | bv          %r0(%rp)        ; return to caller | 
|  | ldo         -64(%sp),%sp    ; remove stack-frame | 
|  |  | 
|  | .EXIT | 
|  | .PROCEND | 
|  |  | 
|  | ; Copy register-to-register. | 
|  | ; On PA-RISC this is implemented with an `or'. | 
|  | ; The `or' is hidden by a pseudo-operation called `copy'. | 
|  |  | 
|  | b_add | 
|  | .PROC | 
|  | .CALLINFO   NO_CALLS, FRAME=0 | 
|  | .ENTRY | 
|  |  | 
|  | _loop2 | 
|  | copy        %r19,%r20       ; copy register-to-register | 
|  | copy        %r20,%r21       ; use caller-saves registers | 
|  | copy        %r21,%r22 | 
|  | copy        %r22,%r21 | 
|  | copy        %r21,%r20 | 
|  | copy        %r20,%r19 | 
|  | copy        %r19,%r20 | 
|  | copy        %r20,%r21 | 
|  |  | 
|  | addibf,<=   -8,%arg0,_loop2 ; decrement counter by 8 and loop | 
|  | nop | 
|  |  | 
|  | bv,n        %r0(%rp) | 
|  |  | 
|  | .EXIT | 
|  | .PROCEND | 
|  |  | 
|  | ; Load memory to a register. | 
|  |  | 
|  | b_load | 
|  | .PROC | 
|  | .CALLINFO   NO_CALLS, FRAME=0 | 
|  | .ENTRY | 
|  |  | 
|  | _loop3 | 
|  | ldw         -4(%sp),%r22    ; load data from frame-marker | 
|  | ldw         -8(%sp),%r22    ; use a caller-saves register | 
|  | ldw         -12(%sp),%r22 | 
|  | ldw         -16(%sp),%r22 | 
|  | ldw         -20(%sp),%r22 | 
|  | ldw         -24(%sp),%r22 | 
|  | ldw         -28(%sp),%r22 | 
|  | ldw         -32(%sp),%r22 | 
|  |  | 
|  | addibf,<=   -8,%arg0,_loop3 ; decrement counter by 8 and loop | 
|  | nop | 
|  |  | 
|  | bv,n        %r0(%rp) | 
|  |  | 
|  | .EXIT | 
|  | .PROCEND | 
|  |  | 
|  |  | 
|  | .ALIGN 8 | 
|  | to_call | 
|  | .WORD       b_null |