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

372 lines
9.9 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//++
//
// Module Name:
//
// longjmp.s
//
// Abstract:
//
// This module implements the IA64 specific routine to perform a long
// jump operation.
//
// N.B. This routine conditionally provides SAFE & UNSAFE handling of longjmp
// which is NOT integrated with structured exception handling. The
// determination is made based on whether the Type field
// has been set to a nonzero value.
//
// N.B. Currently, this routine assumes the setjmp site is EM.
// Support for iA setjmp site is to be finished.
//
// Author:
//
// William K. Cheung (wcheung) 30-Jan-1996
//
// Environment:
//
// Any mode.
//
// Revision History:
//
// Updated to EAS2.1.
//
//--
#include "ksia64.h"
//++
//
// int
// longjmp (
// IN jmp_buf JumpBuffer,
// IN int ReturnValue
// )
//
// Routine Description:
//
// This function performs a long jump to the context specified by the
// jump buffer.
//
// Arguments:
//
// JumpBuffer (a0) - Supplies the address of a jump buffer that contains
// jump information.
//
// ReturnValue (a1) - Supplies the value that is to be returned to the
// caller of set jump.
//
// Return Value:
//
// None.
//
//--
.global RtlUnwind2
.type RtlUnwind2, @function
NESTED_ENTRY(longjmp)
NESTED_SETUP(2, 2, 6, 0)
.fframe ExceptionRecordLength+ContextFrameLength
add sp = -ExceptionRecordLength-ContextFrameLength, sp
ARGPTR(a0)
PROLOGUE_END
mov t4 = ar.rsc
cmp.eq pt1, pt0 = zero, a1
add t6 = JbUnwindData, a0
;;
ld8 out0 = [t6], 8 // get the UnwindData
mov t2 = ar.bsp
add t0 = JbIntNats, a0
;;
//
// If address of registration record is not equal to zero,
// a safe longjmp is to be performed.
//
cmp.ne pt2, pt3 = zero, out0
add t1 = JbBrS0, a0
add t22 = JbIntS0, a0
;;
(pt1) add a1 = 1, r0
shr.u t22 = t22, 3
;;
mov v0 = a1
//
// before restoring integer registers, restore their NaT bits so that
// the load fills will recover them correctly.
//
(pt3) ld8 t7 = [t0], JbStIIP - JbIntNats
(pt3) and t22 = 0x3f, t22
(pt2) br.spnt Lj30
mov ar.rsc = zero // put RSE in lazy mode
;;
mov t3 = ar.bspstore
cmp4.ge pt1, pt0 = 4, t22
;;
//
// at the same time, compute and shift the loaded preserved integer
// registers' NaTs to the proper location.
//
ld8.nt1 t15 = [t0], JbBrS1 - JbStIIP
ld8.nt1 t16 = [t1], JbBrS2 - JbBrS0
(pt0) add t21 = -4, t22
;;
ld8.nt1 t17 = [t0], JbBrS3 - JbBrS1
ld8.nt1 t18 = [t1], JbBrS4 - JbBrS2
(pt0) add t6 = 68, t22
;;
ld8.nt1 t19 = [t0], JbRsBSP - JbBrS3
ld8.nt1 t20 = [t1], JbRsPFS - JbBrS4
(pt1) sub t21 = 4, t22
;;
ld8.nt1 t10 = [t0], JbApUNAT - JbRsBSP
ld8.nt1 t11 = [t1], JbApLC - JbRsPFS
(pt0) shl t5 = t7, t21
;;
ld8.nt1 t12 = [t0]
ld8.nt1 t13 = [t1], JbPreds - JbApLC
(pt0) shr.u t8 = t7, t6
;;
ld8.nt1 t14 = [t1]
(pt1) shr t9 = t7, t21
(pt0) or t9 = t8, t5
;;
extr.u t5 = t11, 7, 7 // local frame size
extr.u t6 = t10, 3, 6 // rnat index
;;
sub t8 = 63, t6
mov t1 = t5
;;
cmp.le pt2, pt1 = t8, t5
;;
(pt2) add t1 = 1, t1
(pt2) sub t5 = t5, t8
(pt1) br.sptk Lj50
;;
Lj40:
cmp.le pt2, pt3 = 63, t5
;;
(pt2) add t5 = -63, t5
(pt2) add t1 = 1, t1
(pt2) br.cond.dpnt Lj40
;;
Lj50:
shladd t10 = t1, 3, t10
//
// t2 = current bsp
// t3 = current bspstore
// t4 = saved rsc
// t9 = NaTs of sp, s0 - s3
// t10 = setjmp's bsp
// t11 = setjmp's pfs
// t12 = setjmp's unat
// t13 = setjmp's loop counter
// t14 = setjmp's predicates
// t15 = setjmp's brp (StIIP)
// t16 = setjmp's bs0
// t17 = setjmp's bs1
// t18 = setjmp's bs2
// t19 = setjmp's bs3
// t20 = setjmp's bs4
//
// Now UNAT contains the NaTs of the preserved integer registers
// at bit positions corresponding to the locations from which the
// integer registers can be restored (with load fill operations)
//
// Restore predicates and loop counter.
//
mov ar.unat = t9
mov pr = t14, -1
mov ar.lc = t13
add t0 = JbFltS0, a0
add t1 = JbFltS1, a0
mov ar.pfs = t11
;;
//
// scratch registers t5 - t9, t11, t13, t14 are available for use.
//
// load preserved floating point states from jump buffer
// move the loaded branch register states to the corresponding br registers
//
ldf.fill.nt1 fs0 = [t0], JbFltS2 - JbFltS0
ldf.fill.nt1 fs1 = [t1], JbFltS3 - JbFltS1
nop.i 0
;;
ldf.fill.nt1 fs2 = [t0], JbFltS4 - JbFltS2
ldf.fill.nt1 fs3 = [t1], JbFltS5 - JbFltS3
mov brp = t15
;;
ldf.fill.nt1 fs4 = [t0], JbFltS6 - JbFltS4
ldf.fill.nt1 fs5 = [t1], JbFltS7 - JbFltS5
mov bs0 = t16
;;
ldf.fill.nt1 fs6 = [t0], JbFltS8 - JbFltS6
ldf.fill.nt1 fs7 = [t1], JbFltS9 - JbFltS7
mov bs1 = t17
;;
ldf.fill.nt1 fs8 = [t0], JbFltS10 - JbFltS8
ldf.fill.nt1 fs9 = [t1], JbFltS11 - JbFltS9
mov bs2 = t18
;;
ldf.fill.nt1 fs10 = [t0], JbFltS12 - JbFltS10
ldf.fill.nt1 fs11 = [t1], JbFltS13 - JbFltS11
mov bs3 = t19
;;
ldf.fill.nt1 fs12 = [t0], JbFltS14 - JbFltS12
ldf.fill.nt1 fs13 = [t1], JbFltS15 - JbFltS13
mov bs4 = t20
;;
ldf.fill.nt1 fs14 = [t0], JbFltS16 - JbFltS14
ldf.fill.nt1 fs15 = [t1], JbFltS17 - JbFltS15
brp.ret.sptk brp, Lj20
;;
//
// scratch registers t6 - t9, t11, t13 - t20 are available for use
//
// t2 is current bsp
// t3 is current bspstore
// t4 is saved rsc
// t5 is the setjmp's fpsr
// t10 is the setjmp's bsp
// t12 is the setjmp's unat
//
ldf.fill.nt1 fs16 = [t0], JbFltS18 - JbFltS16
ldf.fill.nt1 fs17 = [t1], JbFltS19 - JbFltS17
cmp.lt p0, pt1 = t3, t10 // current bspstore < setjmp's bsp
;;
ldf.fill.nt1 fs18 = [t0], JbFPSR - JbFltS18
ldf.fill.nt1 fs19 = [t1], JbIntS1 - JbFltS19
dep t9 = 1, t10, 3, 6 // OR 1s to get desired RNAT location
;; // t9 = OR(0x1f8, t10)
mov t11 = ar.rnat // save rnat for later use
ld8.nt1 t5 = [t0], JbIntS0 - JbFPSR
(pt1) br.cond.spnt Lj10
;;
flushrs // Flush the RSE and move up
nop.m 0
mov t3 = t2 // the current bspstore
;;
Lj10:
//
// t3 is top of backing store in memory
// t9 is desired RNAT collection location
//
ld8.fill.nt1 s0 = [t0], JbIntS2 - JbIntS0
ld8.fill.nt1 s1 = [t1], JbIntS3 - JbIntS1
cmp.lt pt1, pt2 = t3, t9 // current top of backing store
;; // is smaller than desired RNAT
// collection location?
// pt1: use RNAT app. register
// pt2: load RNAT from bstore
ld8.fill.nt1 s2 = [t0], JbIntSp - JbIntS2
ld8.fill.nt1 s3 = [t1]
nop.i 0
;;
ld8.fill.nt1 t17 = [t0] // load setjmp's sp
(pt2) ld8.nt1 t15 = [t9] // load desired RNAT
nop.i 0
;;
loadrs // invalidates dirty registers
;;
mov ar.bspstore = t10 // set bspstore register
;;
invala
mov ar.unat = t12 // set unat
mov sp = t17 // set stack pointer
(pt2) mov ar.rnat = t15 // set rnat to loaded value
(pt1) mov ar.rnat = t11 // reuse rnat content
nop.i 0
Lj20:
mov ar.rsc = t4 // restore RSC
;;
mov ar.fpsr = t5 // restore FPSR
br.ret.sptk.clr brp // return to setjmp site
Lj30:
//
// t6 -> UnwindData+8
// out0 - target psp
// out1 - target bsp
// out2 - target ip (setjmp's StIIP)
// out3 - exception record address
// out4 - return value
// out5 - context record address
//
add t5 = JbStIIP, a0
add t0 = ErExceptionCode+STACK_SCRATCH_AREA, sp
add t1 = ErExceptionFlags+STACK_SCRATCH_AREA, sp
;;
ld8 out1 = [t6] // target bsp
movl v0 = STATUS_LONGJUMP // get long jump status code
ld8 out2 = [t5] // target ip
st4 [t1] = zero, ErExceptionAddress - ErExceptionFlags
add out3 = STACK_SCRATCH_AREA, sp
;;
st4 [t0] = v0, ErExceptionInformation - ErExceptionCode
STPTRINC(t1, zero, ErExceptionRecord - ErExceptionAddress)
mov out4 = a1
;;
STPTR(t0, a0)
STPTRINC(t1, zero, ErNumberParameters - ErExceptionRecord)
mov t4 = 1 // set to 1 argument
;;
st4 [t1] = t4
add out5 = STACK_SCRATCH_AREA+ExceptionRecordLength, sp
br.call.sptk.many brp = RtlUnwind2 // call RtlUnwind2
NESTED_EXIT(longjmp)