; asmloops.s 02/08/23 ; Copyright (c) 1991, 2002 Allegro Consultants, Inc. ; This source may be freely used only as part of the MIPSTEST program. ; For other uses, please contact info@allegro.com .SPACE $TEXT$ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY .SUBSPA $CODE$ .VERSION "asmloops.s 02/08/23" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; int32 asmloops_measure_blink (void); /* returns # of ticks */ asmloops_measure_blink .PROC .ENTRY .EXPORT asmloops_measure_blink, ENTRY ; wait until we see a BIG delta in ITMR values... LDI 1000, 31 ; value we want to see > than LDI 0, 29 MFCTL 16, 25 ; old_ITMR = itmr L$0 ADDI 1, 29, 29 MFCTL 16, 1 ; get new_ITMR SUB 1, 25, 28 ; subtract old_ITMR COMB,> 31, 28, L$0 ; if 1000 > delta, loop COPY 1, 25 ; old_ITMR = new_ITMR BV 0 (2) NOP .CALLINFO .EXIT .PROCEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; int32 asmloops_measure_burp (void); /* returns # of ticks */ asmloops_measure_burp .PROC .ENTRY .EXPORT asmloops_measure_burp, ENTRY ; wait until we see a BIG delta in ITMR values... LDI 1000, 31 ; value we want to see > than LDI 0, 29 MFCTL 16, 25 ; old_ITMR = itmr L$8 MFCTL 16, 1 ; get new_ITMR SUB 1, 25, 28 ; subtract old_ITMR COMB,> 31, 28, L$8 ; if 1000 > delta, loop COPY 1, 25 ; old_ITMR = new_ITMR ; ok, we're at start of a burp...loop until we hit ; a blink, then return delta between ITMR right now ; (end-of-blink/start-of-burp and the ITMR ; at the start of the blink) COPY 1, 24 ; save start-of-burp ITMR in r24 L$9 MFCTL 16, 1 ; get new_ITMR ADDI 1, 29, 29 SUB 1, 25, 28 ; subtract old_ITMR COMB,>,N 31, 28, L$9 ; if 1000 > delta, loop COPY 1, 25 ; old_ITMR = new_ITMR BV 0 (2) SUB 25, 24, 28 .CALLINFO .EXIT .PROCEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; double procedure asmloops (numloops); ; value numloops; ; double numloops; ; ; At entry, r26 = # instructions to execute (approx) ; exit, r28 = # instructions executed ; ; Goal: minimal loop, no consideraton of parallelism asmloops .PROC .ENTRY .EXPORT asmloops,ENTRY LDI 4, 28 ; initialize # instructions done ADDI -4, 26, 26 ; account for the extra instructions L$1 ADDIB,> -2, 26, L$1 ADDI 2, 28, 28 ; we've done 2 more instructions BV 0 (2) NOP .CALLINFO .EXIT .PROCEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; double procedure asmloops_nopar (numloops); ; value numloops; ; double numloops; ; ; At entry, r26 = # instructions to execute (approx) ; exit, r28 = # instructions executed ; ; Goal: do some instructions that can't be done in parallel ; ; Caller is expected to check ITMR before and after. ; ; This routine is structured in an manner designed to make the ; code be highly UN-parallelizable. The goal is to execute ; one instruction per clock tick. ; Note: some CPUs manage to get execute about 16 instructions ; in 15 clock ticks when doing the loop below multiple times. asmloops_nopar .PROC .ENTRY .EXPORT asmloops_nopar,ENTRY LDI 4, 28 ; initialize # instructions done ADDI -4, 26, 26 ; account for the extra instructions L$2 ; instruction count, approx ADDI,SV 1,28,28 ; 1 ADDI,SV 1,28,28 ; 2 ADDI,SV 1,28,28 ; 3 ADDI,SV 1,28,28 ; 4 ADDI,SV 1,28,28 ; 5 ADDI,SV 1,28,28 ; 6 ADDI,SV 1,28,28 ; 7 ADDI,SV 1,28,28 ; 8 ADDI,SV 1,28,28 ; 9 ADDI,SV 1,28,28 ; 10 ADDI,SV 1,28,28 ; 11 ADDI,SV 1,28,28 ; 12 ADDI,SV 1,28,28 ; 13 ADDI,SV 1,28,28 ; 14 ADDIB,> -16, 26, L$2 ; 15 ADDI,SV 2,28,28 ; 16 bundled with above ADDIB BV 0 (2) NOP .CALLINFO .EXIT .PROCEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; double procedure asmloops_nopar2 (numloops); ; value numloops; ; double numloops; ; ; At entry, r26 = # instructions to execute (approx) ; exit, r28 = # instructions executed ; ; Goal: do some instructions that can't be done in parallel asmloops_nopar2 .PROC .ENTRY .EXPORT asmloops_nopar2,ENTRY ADDI 4, 26, 28 ; initialize # instructions done ADDI -4, 26, 26 ; account for the extra instructions L$5 B .+4 ; 1 & 2 B .+4 ; 3 & 4 B .+4 ; 5 & 6 NOP ; 7 ADDIB,> -9, 26, L$5 ; 8 & 9 NOP BV 0 (2) NOP .CALLINFO .EXIT .PROCEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; double procedure asmloops_par (numloops); ; value numloops; ; double numloops; ; ; At entry, r26 = # instructions to execute (approx) ; exit, r28 = # instructions executed ; ; Goal: do some instructions that can be done in parallel asmloops_par .PROC .ENTRY .EXPORT asmloops_par,ENTRY LDI 4, 28 ; initialize # instructions done ADDI -4, 26, 26 ; account for the extra instructions L$3 ADD 1, 31, 1 ; 1 ADDI 1, 28, 25 ; 2 ADDI 2, 28, 24 ; 3 ADDI 3, 28, 23 ; 4 ADDI 1, 28, 25 ; 5 ADDI 2, 28, 24 ; 6 ADDI 3, 28, 23 ; 7 ADDI 1, 28, 25 ; 8 ADDIB,> -10, 26, L$3 ; 9 ADDI 10, 28, 28 ; 10; we've done 10 instructions BV 0 (2) NOP .CALLINFO .EXIT .PROCEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .END