+sttrimmed64:
+ ld r5,SAVprev(r7) ; Get the next one (for new head of free list)
+ lwz r4,SVfreecnt(0) ; Get the free count
+ std r5,SVfree(0) ; Set new head
+ sub r4,r4,r8 ; Calculate the new free count
+ li r31,0 ; Show we have no free pool blocks yet
+ crclr cr1_eq ; dont exit loop before 1st iteration
+ stw r4,SVfreecnt(0) ; Set new free count
+ lis r30,hi16(sac_empty) ; Get what empty looks like
+
+
+ ; Loop over each savearea we are trimming.
+ ; r6 = next savearea to trim
+ ; r7 = last savearea to trim
+ ; r8 = #pages to trim (>0)
+ ; r9 = return address
+ ; r10 = per-proc ptr
+ ; r11 = MSR at entry
+ ; r30 = what SACalloc looks like when all saveareas are free
+ ; r31 = free pool block list
+ ; cr1 = beq set if we just trimmed the last, ie if we are done
+ ;
+ ; WARNING: as in the 32-bit path, this code is doing a divide by 640 (SAVsize).
+
+sttoss64:
+ beq++ cr1,stdone ; All done now...
+
+ cmpld cr1,r6,r7 ; Have we finished the loop?
+
+ lis r0,0x0044 ; Get top of table
+ rldicr r2,r6,0,51 ; r2 <- phys addr of savearea block (with control area)
+ ori r0,r0,0x2200 ; Finish shift table
+ rlwinm r4,r6,25,27,30 ; Get (addr >> 7) & 0x1E (same as twice high nybble)
+ lwz r5,SACalloc(r2) ; Get the allocation bits
+ addi r4,r4,1 ; Shift 1 extra
+ rlwinm r3,r6,25,31,31 ; Get (addr >> 7) & 1
+ rlwnm r0,r0,r4,29,31 ; Get partial index
+ lis r4,lo16(0x8000) ; Get the bit mask
+ add r0,r0,r3 ; Make the real index
+ srw r4,r4,r0 ; Get the allocation mask
+ or r5,r5,r4 ; Free this entry
+ cmplw r5,r4 ; Is this the only free entry?
+ ld r6,SAVprev(r6) ; Chain to the next trimmed savearea
+ cmplw cr7,r30,r5 ; Does this look empty?
+ stw r5,SACalloc(r2) ; Save back the allocation bits
+ beq-- stputpool64 ; First free entry, go put it into the pool...
+ bne++ cr7,sttoss64 ; Not an empty block
+
+; We have an empty block. Remove it from the pool list.
+
+ lwz r29,SACflags(r2) ; Get the flags
+ cmpldi cr5,r31,0 ; Is this guy on the release list?
+ ld r28,SACnext(r2) ; Get the forward chain
+
+ rlwinm. r0,r29,0,sac_permb,sac_permb ; Is this a permanently allocated area? (also sets 0 needed below)
+ bne-- sttoss64 ; This is permanent entry, do not try to release...
+
+ ld r29,SACprev(r2) ; and the previous
+ beq-- cr5,stnot1st64 ; Not first
+ ld r0,SACvrswap(r31) ; Load the previous pool page vr conversion
+
+stnot1st64:
+ std r28,SACnext(r29) ; Previous guy points to my next
+ xor r0,r0,r31 ; Make the last guy virtual
+ std r29,SACprev(r28) ; Next guy points back to my previous
+ std r0,SAVprev(r2) ; Store the old top virtual as my back chain
+ mr r31,r2 ; My physical is now the head of the chain
+ b sttoss64 ; Get the next one...
+
+; A pool block that had no free entries now has one. Stick it on the pool list.