windows-nt/Source/XPSP1/NT/base/crts/crtw32/startup/ia64/chkstk.s
2020-09-26 16:20:57 +08:00

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)