Back to index

glibc  2.9
Defines | Functions
__longjmp.c File Reference
#include <setjmp.h>

Go to the source code of this file.

Defines

#define REI   02 /* Vax `rei' opcode. */

Functions

__NORETURN void __longjmp (__jmp_buf env, int val) const

Define Documentation

#define REI   02 /* Vax `rei' opcode. */

Definition at line 55 of file __longjmp.c.


Function Documentation

__NORETURN void __longjmp ( __jmp_buf  env,
int  val 
) const

Definition at line 61 of file __longjmp.c.

{
  register long int *fp asm("fp");
  long int *regsave;
  unsigned long int flags;

  if (env.__fp == NULL)
    __libc_fatal("longjmp: Invalid ENV argument.\n");

  if (val == 0)
    val = 1;

  asm volatile("loop:");

  flags = *(long int *) (6 + (char *) fp);
  regsave = (long int *) (20 + (char *) fp);
  if (flags & 1)
    /* R0 was saved by the caller.
       Store VAL where it will be restored from.  */
    *regsave++ = val;
  if (flags & 2)
    /* R1 was saved by the caller.
       Store ENV where it will be restored from.  */
    *regsave = env;

  /* Was the FP saved in the last call the same one in ENV?  */
  asm volatile("cmpl %0, 12(fp);"
              /* Yes, return to it.  */
              "beql done;"
              /* The FP in ENV is less than the one saved in the last call.
                This means we have already returned from the function that
                called `setjmp' with ENV!  */
              "blssu latejump;" : /* No outputs.  */ : "g" (env.__fp));

  /* We are more than one level below the state in ENV.
     Return to where we will pop another stack frame.  */
  asm volatile("movl $loop, 16(fp);"
              "ret");

  asm volatile("done:");
  {
    char return_insn asm("*16(fp)");
    if (return_insn == REI)
      /* We're returning with an `rei' instruction.
        Do a return with PSL-PC pop.  */
      asm volatile("movab 0f, 16(fp)");
    else
      /* Do a standard return.  */
      asm volatile("movab 1f, 16(fp)");

    /* Return.  */
    asm volatile("ret");
  }

  asm volatile("0:"  /* `rei' return.  */
              /* Compensate for PSL-PC push.  */
              "addl2 %0, sp;"
              "1:"   /* Standard return.  */
              /* Return to saved PC.  */
              "jmp %1" : /* No outputs.  */ :
              "g" (8), "g" (env.__pc));

  /* Jump here when the FP saved in ENV points
     to a function that has already returned.  */
  asm volatile("latejump:");
  __libc_fatal("longjmp: Attempt to jump to a function that has returned.\n");
}

Here is the call graph for this function: