text: // -*- c -*-
  //
  // %CopyrightBegin%
  //
  // Copyright Ericsson AB 2017. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  //
  // %CopyrightEnd%
  //
  
  return_trace() {
      ErtsCodeMFA* mfa = (ErtsCodeMFA *)(E[1]);
  
      SWAPOUT;		/* Needed for shared heap */
      ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
      erts_trace_return(c_p, mfa, r(0), ERTS_TRACER_FROM_ETERM(E+2)/* tracer */);
      ERTS_REQ_PROC_MAIN_LOCK(c_p);
      SWAPIN;
      E += 3;
      $RETURN();
      Goto(*I);
      //| -no_next
  }
  
  i_generic_breakpoint() {
      BeamInstr real_I;
      HEAVY_SWAPOUT;
      real_I = erts_generic_breakpoint(c_p, erts_code_to_codeinfo(I), reg);
      HEAVY_SWAPIN;
      ASSERT(VALID_INSTR(real_I));
      Goto(real_I);
      //| -no_next
  }
  
  i_return_time_trace() {
      BeamInstr *pc = (BeamInstr *) (UWord) E[1];
      SWAPOUT;
      erts_trace_time_return(c_p, erts_code_to_codeinfo(pc));
      SWAPIN;
      E += 2;
      $RETURN();
      Goto(*I);
      //| -no_next
  }
  
  i_return_to_trace() {
      if (IS_TRACED_FL(c_p, F_TRACE_RETURN_TO)) {
          Uint *cpp = (Uint*) E;
          while (is_not_CP(*cpp)) {
              cpp++;
          }
          for(;;) {
              if (IsOpCode(*cp_val(*cpp), return_trace)) {
                  do
                      ++cpp;
                  while (is_not_CP(*cpp));
                  cpp += 2;
              } else if (IsOpCode(*cp_val(*cpp), i_return_to_trace)) {
                  do
                      ++cpp;
                  while (is_not_CP(*cpp));
              } else {
                  break;
              }
          }
          SWAPOUT;		/* Needed for shared heap */
          ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
          erts_trace_return_to(c_p, cp_val(*cpp));
          ERTS_REQ_PROC_MAIN_LOCK(c_p);
          SWAPIN;
      }
      E += 1;
      $RETURN();
      Goto(*I);
      //| -no_next
  }
  
  i_yield() {
      /* This is safe as long as REDS_IN(c_p) is never stored
       * in c_p->arg_reg[0]. It is currently stored in c_p->def_arg_reg[5].
       */
      c_p->arg_reg[0] = am_true;
      c_p->arity = 1; /* One living register (the 'true' return value) */
      SWAPOUT;
      $SET_CP_I_ABS($NEXT_INSTRUCTION);
      c_p->current = NULL;
      goto do_schedule;
      //| -no_next
  }
  
  i_hibernate() {
      HEAVY_SWAPOUT;
      if (erts_hibernate(c_p, reg)) {
          FCALLS = c_p->fcalls;
          c_p->flags &= ~F_HIBERNATE_SCHED;
          goto do_schedule;
      } else {
          HEAVY_SWAPIN;
          I = handle_error(c_p, I, reg, &bif_trap_export[BIF_hibernate_3].info.mfa);
          goto post_error_handling;
      }
      //| -no_next
  }
  
  // This is optimised as an instruction because
  // it has to be very very fast.
  
  i_perf_counter() {
      ErtsSysPerfCounter ts;
  
      ts = erts_sys_perf_counter();
      if (IS_SSMALL(ts)) {
          r(0) = make_small((Sint)ts);
      } else {
          $GC_TEST(0, ERTS_SINT64_HEAP_SIZE(ts), 0);
          r(0) = make_big(HTOP);
  #if defined(ARCH_32)
          if (ts >= (((Uint64) 1) << 32)) {
              *HTOP = make_pos_bignum_header(2);
              BIG_DIGIT(HTOP, 0) = (Uint) (ts & ((Uint) 0xffffffff));
              BIG_DIGIT(HTOP, 1) = (Uint) ((ts >> 32) & ((Uint) 0xffffffff));
              HTOP += 3;
          }
          else
  #endif
              {
                  *HTOP = make_pos_bignum_header(1);
                  BIG_DIGIT(HTOP, 0) = (Uint) ts;
                  HTOP += 2;
              }
      }
  }
  
  i_debug_breakpoint() {
      HEAVY_SWAPOUT;
      I = call_error_handler(c_p, erts_code_to_codemfa(I), reg, am_breakpoint);
      HEAVY_SWAPIN;
      if (I) {
          Goto(*I);
      }
      goto handle_error;
      //| -no_next
  }
  
  
  
  //
  // Special jump instruction used for tracing. Takes an absolute
  // failure address.
  //
  
  trace_jump(Fail) {
      //| -no_next
      SET_I((BeamInstr *) $Fail);
      Goto(*I);
  }
  