107 lines
2.9 KiB
ArmAsm
107 lines
2.9 KiB
ArmAsm
|
.file "chkstk.s"
|
||
|
|
||
|
/* _chkstk - check stack upon procedure entry
|
||
|
|
||
|
;Purpose:
|
||
|
; Provide stack checking on procedure entry. Method is to simply probe
|
||
|
; each page of memory required for the stack in descending order. This
|
||
|
; causes the necessary pages of memory to be allocated via the guard
|
||
|
; page scheme, if possible. In the event of failure, the OS raises the
|
||
|
; _XCPT_UNABLE_TO_GROW_STACK exception.
|
||
|
;
|
||
|
; The link register is b7 to avoid conflicts with linker thunks.
|
||
|
;
|
||
|
;
|
||
|
;Entry:
|
||
|
; r26: Size of the storage to allocate
|
||
|
; (This is rounded up to the next multiple of 16)
|
||
|
;
|
||
|
;Exit:
|
||
|
;
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
*/
|
||
|
#include "ksia64.h"
|
||
|
|
||
|
.section .text
|
||
|
.align 32
|
||
|
|
||
|
LEAF_ENTRY(__chkstk)
|
||
|
ALTERNATE_ENTRY(__alloca_probe)
|
||
|
|
||
|
.prologue
|
||
|
|
||
|
cond_reg1 = p6
|
||
|
cond_discard = p0
|
||
|
|
||
|
return_branch_register = b7
|
||
|
|
||
|
argument_reg = r26
|
||
|
discard_reg = r27
|
||
|
new_stack_pointer = r28
|
||
|
page_size_reg = r29
|
||
|
alloc_size_reg = r30
|
||
|
|
||
|
.altrp return_branch_register
|
||
|
|
||
|
mov discard_reg = 15
|
||
|
|
||
|
mov page_size_reg = PAGE_SIZE
|
||
|
// load page size into a register, we'll need to use it again.
|
||
|
|
||
|
add alloc_size_reg=15,argument_reg
|
||
|
// Make sure the requested size is = 0 mod 16: round up
|
||
|
;;
|
||
|
|
||
|
.body
|
||
|
|
||
|
mov new_stack_pointer = sp
|
||
|
// Save the stack pointer to a different register for manipulation
|
||
|
// new_stack_pointer is scratch
|
||
|
|
||
|
|
||
|
andcm alloc_size_reg=alloc_size_reg,discard_reg
|
||
|
// setting the lower four bits to zero
|
||
|
|
||
|
;;
|
||
|
|
||
|
cmp.le cond_reg1,p0 = alloc_size_reg, page_size_reg
|
||
|
// assume greater than 1 page most of the time.
|
||
|
|
||
|
(cond_reg1) br.cond.dpnt ._last_page
|
||
|
// if size is <= 1 page, branch to
|
||
|
|
||
|
._probepages:
|
||
|
sub alloc_size_reg = alloc_size_reg,page_size_reg
|
||
|
|
||
|
// The size is more than 1 page, subtract a page from sp
|
||
|
sub new_stack_pointer = new_stack_pointer,page_size_reg
|
||
|
;;
|
||
|
|
||
|
// Do we still have more than 1 page?
|
||
|
cmp.gt cond_reg1,cond_discard = alloc_size_reg, page_size_reg
|
||
|
|
||
|
;;
|
||
|
|
||
|
// Use non-temporal locality hint so the cache is not polluted
|
||
|
ld8.nta discard_reg = [new_stack_pointer] // probe it
|
||
|
(cond_reg1) br.cond.dpnt ._probepages
|
||
|
;;
|
||
|
|
||
|
// .mmi
|
||
|
._last_page:
|
||
|
sub new_stack_pointer = new_stack_pointer, alloc_size_reg
|
||
|
;;
|
||
|
|
||
|
// subtract the last piecemill, which is in alloc_size_reg.
|
||
|
// the new stack pointer.
|
||
|
|
||
|
ld8.nta discard_reg = [new_stack_pointer] // probe it.
|
||
|
|
||
|
// If we are here, everything is ok.
|
||
|
|
||
|
br.ret.dpnt return_branch_register
|
||
|
|
||
|
LEAF_EXIT(__chkstk)
|