//++ // // 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)