OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [or32/] [or32.c] - Diff between revs 378 and 399

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 378 Rev 399
Line 3... Line 3...
   2005, 2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc
   2005, 2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc
   Copyright (C) 2010 Embecosm Limited
   Copyright (C) 2010 Embecosm Limited
 
 
   Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
   Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
   Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> in 2005.
   Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> in 2005.
   Updated for GCC 4.5 by Jeremy Bennett <jeremy.bennett@embecoms.com> in 2010
   Updated for GCC 4.5 by Jeremy Bennett <jeremy.bennett@embecoms.com>
 
   and Joern Rennecke <joern.rennecke@embecosm.com> in 2010.
 
 
   This file is part of GNU CC.
   This file is part of GNU CC.
 
 
   This program is free software; you can redistribute it and/or modify it
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   under the terms of the GNU General Public License as published by the Free
Line 99... Line 100...
 
 
 
 
/* ========================================================================== */
/* ========================================================================== */
/* Local (i.e. static) utility functions */
/* Local (i.e. static) utility functions */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Must the current function save a register?
/*!Must the current function save a register?
 
 
   @param[in] regno  The register to consider.
   @param[in] regno  The register to consider.
 
 
Line 121... Line 121...
  if (df_regs_ever_live_p(regno) && !call_used_regs[regno])
  if (df_regs_ever_live_p(regno) && !call_used_regs[regno])
    return true;
    return true;
 
 
  /* We need to save the old frame pointer before setting up a new
  /* We need to save the old frame pointer before setting up a new
     one.  */
     one.  */
  if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
  if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
    return true;
    return true;
 
 
  /* We need to save the incoming return address if it is ever clobbered
  /* We need to save the incoming return address if it is ever clobbered
     within the function.  */
     within the function.  */
  if (regno == LINK_REGNUM && df_regs_ever_live_p(regno))
  if (regno == LINK_REGNUM && df_regs_ever_live_p(regno))
Line 133... Line 133...
 
 
  return false;
  return false;
 
 
}       /* or32_save_reg_p () */
}       /* or32_save_reg_p () */
 
 
 
bool
 
or32_save_reg_p_cached (int regno)
 
{
 
  return (frame_info.mask & ((HOST_WIDE_INT) 1 << regno)) != 0;
 
}
 
 
 
/* N.B. contrary to the ISA documentation, the stack includes the outgoing
 
   arguments.  */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Compute full frame size and layout.
/*!Compute full frame size and layout.
 
 
   Store information in "frame_info".
   Store information in "frame_info".
 
 
Line 148... Line 156...
or32_compute_frame_size (HOST_WIDE_INT size)
or32_compute_frame_size (HOST_WIDE_INT size)
{
{
  HOST_WIDE_INT args_size;
  HOST_WIDE_INT args_size;
  HOST_WIDE_INT vars_size;
  HOST_WIDE_INT vars_size;
  HOST_WIDE_INT stack_offset;
  HOST_WIDE_INT stack_offset;
 
  bool interrupt_p = false;
 
 
  int regno;
  int regno;
 
 
  args_size = crtl->outgoing_args_size;
  args_size = crtl->outgoing_args_size;
  vars_size = OR32_ALIGN (size, 4);
  vars_size = OR32_ALIGN (size, 4);
Line 163... Line 172...
     allocating it anyway.  Otherwise reclaim it here.  */
     allocating it anyway.  Otherwise reclaim it here.  */
  /* FIXME: Verify this.  Got if from the MIPS port.  */
  /* FIXME: Verify this.  Got if from the MIPS port.  */
  if (vars_size == 0 && current_function_is_leaf)
  if (vars_size == 0 && current_function_is_leaf)
    args_size = 0;
    args_size = 0;
 
 
  stack_offset = args_size;
  stack_offset = 0;
 
 
  /* Save link register right after possible outgoing arguments.  */
  /* Save link register right at the bottom.  */
  if (or32_save_reg_p (LINK_REGNUM))
  if (or32_save_reg_p (LINK_REGNUM))
    {
    {
 
      stack_offset = stack_offset - UNITS_PER_WORD;
      frame_info.lr_save_offset = stack_offset;
      frame_info.lr_save_offset = stack_offset;
      frame_info.save_lr_p = true;
      frame_info.save_lr_p = true;
      stack_offset = stack_offset + UNITS_PER_WORD;
 
    }
    }
  else
  else
    frame_info.save_lr_p = false;
    frame_info.save_lr_p = false;
 
 
  /* Save frame pointer right after possible link register.  */
  /* Save frame pointer right after possible link register.  */
  if (or32_save_reg_p (FRAME_POINTER_REGNUM))
  if (frame_pointer_needed)
    {
    {
 
      stack_offset = stack_offset - UNITS_PER_WORD;
      frame_info.fp_save_offset = stack_offset;
      frame_info.fp_save_offset = stack_offset;
      frame_info.save_fp_p = true;
      frame_info.save_fp_p = true;
      stack_offset = stack_offset + UNITS_PER_WORD;
 
    }
    }
  else
  else
    frame_info.save_fp_p = false;
    frame_info.save_fp_p = false;
 
 
  frame_info.gpr_size = 0;
  frame_info.gpr_size = 0;
  frame_info.mask = 0;
  frame_info.mask = 0;
  frame_info.gpr_offset = stack_offset;
 
 
 
  for (regno = 0; regno <= OR32_LAST_INT_REG; regno++)
  for (regno = 0; regno <= OR32_LAST_ACTUAL_REG; regno++)
    {
    {
      if (regno == LINK_REGNUM || regno == FRAME_POINTER_REGNUM)
      if (regno == LINK_REGNUM
 
          || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM))
        /* These have already been saved if so needed.  */
        /* These have already been saved if so needed.  */
        continue;
        continue;
 
 
      if (or32_save_reg_p (regno))
      if (or32_save_reg_p (regno))
        {
        {
          frame_info.gpr_size += UNITS_PER_WORD;
          frame_info.gpr_size += UNITS_PER_WORD;
          frame_info.mask |= (1 << regno);
          frame_info.mask |= ((HOST_WIDE_INT) 1 << regno);
        }
        }
    }
    }
 
 
  frame_info.total_size = ((frame_info.save_fp_p ? UNITS_PER_WORD : 0)
  frame_info.total_size = ((frame_info.save_fp_p ? UNITS_PER_WORD : 0)
                           + (frame_info.save_lr_p ? UNITS_PER_WORD : 0)
                           + (frame_info.save_lr_p ? UNITS_PER_WORD : 0)
                           + args_size + frame_info.gpr_size + vars_size);
                           + args_size + frame_info.gpr_size + vars_size);
 
  gcc_assert (PROLOGUE_TMP != STATIC_CHAIN_REGNUM);
 
  if (frame_info.total_size > 32767 && interrupt_p)
 
    {
 
      int n_extra
 
        = (!!(~frame_info.mask && 1 << PROLOGUE_TMP)
 
           + !!(~frame_info.mask & 1 << EPILOGUE_TMP)) * UNITS_PER_WORD;
 
 
 
      frame_info.gpr_size += n_extra;
 
      frame_info.total_size += n_extra;
 
      frame_info.mask |= (1 << PROLOGUE_TMP) | (1 << EPILOGUE_TMP);
 
    }
 
 
 
  stack_offset -= frame_info.gpr_size;
 
  frame_info.gpr_offset = stack_offset;
 
 
  return frame_info.total_size;
  return frame_info.total_size;
 
 
}       /* or32_compute_frame_size () */
}       /* or32_compute_frame_size () */
 
 
Line 233... Line 256...
 
 
}       /* emit_frame_insn () */
}       /* emit_frame_insn () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Generate the RTX for an indexed memory access
/* Generate a RTX for the indexed memory address based on stack_pointer_rtx
 
   and a displacement
   Generate a RTX for the indexed memory address based on a base address and a
 
   displacement
 
 
 
   @param[in] base  The base address RTX
 
   @param[in] disp  The displacement
   @param[in] disp  The displacement
 
 
   @return  The RTX for the generated address.                                */
   @return  The RTX for the generated address.                                */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static rtx
static rtx
indexed_memory (rtx            base,
stack_disp_mem (HOST_WIDE_INT disp)
                HOST_WIDE_INT  disp)
 
{
{
  return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, GEN_INT (disp)));
  return gen_frame_mem (Pmode, plus_constant (stack_pointer_rtx, disp));
 
}
}       /* indexed_memory () */
 
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Generate insn patterns to do an integer compare of operands.
/*!Generate insn patterns to do an integer compare of operands.
 
 
Line 489... Line 507...
   @param[in] dest  Destination of the move.
   @param[in] dest  Destination of the move.
   @param[in] src   Source for the move.
   @param[in] src   Source for the move.
 
 
   @return  RTX for the move.                                                 */
   @return  RTX for the move.                                                 */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
rtx
static rtx
or32_emit_move (rtx dest, rtx src)
or32_emit_move (rtx dest, rtx src)
{
{
  return (can_create_pseudo_p ()
  return (can_create_pseudo_p ()
          ? emit_move_insn (dest, src)
          ? emit_move_insn (dest, src)
          : emit_move_insn_1 (dest, src));
          : emit_move_insn_1 (dest, src));
Line 594... Line 612...
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void
void
or32_expand_prologue (void)
or32_expand_prologue (void)
{
{
  int total_size = or32_compute_frame_size (get_frame_size ());
  int total_size = or32_compute_frame_size (get_frame_size ());
  rtx sp_rtx;
  rtx insn;
  rtx value_rtx;
 
 
 
  if (!total_size)
  if (!total_size)
    /* No frame needed.  */
    /* No frame needed.  */
    return;
    return;
 
 
  sp_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
 
 
 
  if (total_size > 32767)
 
    {
 
      value_rtx = gen_rtx_REG (Pmode, GP_ARG_RETURN);
 
      emit_frame_insn (gen_rtx_SET (Pmode, value_rtx, GEN_INT (total_size)));
 
    }
 
  else
 
    value_rtx = GEN_INT (total_size);
 
 
 
  /* Update the stack pointer to reflect frame size.  */
 
  emit_frame_insn
 
    (gen_rtx_SET (Pmode, stack_pointer_rtx,
 
                  gen_rtx_MINUS (Pmode, stack_pointer_rtx, value_rtx)));
 
 
 
  if (frame_info.save_fp_p)
  if (frame_info.save_fp_p)
    {
    {
      emit_frame_insn
      emit_frame_insn (gen_rtx_SET (Pmode,
        (gen_rtx_SET (Pmode,
                                    stack_disp_mem (frame_info.fp_save_offset),
                      indexed_memory (stack_pointer_rtx,
                                    hard_frame_pointer_rtx));
                                      frame_info.fp_save_offset),
 
                      frame_pointer_rtx));
 
 
 
      emit_frame_insn
      emit_frame_insn
        (gen_rtx_SET (Pmode, frame_pointer_rtx,
        (gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, const0_rtx));
                      gen_rtx_PLUS (Pmode, frame_pointer_rtx, value_rtx)));
 
    }
    }
  if (frame_info.save_lr_p)
  if (frame_info.save_lr_p)
    {
    {
 
 
      emit_frame_insn
      emit_frame_insn
        (gen_rtx_SET (Pmode,
        (gen_rtx_SET (Pmode, stack_disp_mem (frame_info.lr_save_offset),
                      indexed_memory (stack_pointer_rtx,
 
                                      frame_info.lr_save_offset),
 
                      gen_rtx_REG (Pmode, LINK_REGNUM)));
                      gen_rtx_REG (Pmode, LINK_REGNUM)));
    }
    }
  if (frame_info.gpr_size)
  if (frame_info.gpr_size)
    {
    {
      int offset = 0;
      int offset = 0;
      int regno;
      int regno;
 
 
      for (regno = 0; regno <= OR32_LAST_INT_REG; regno++)
      for (regno = 0; regno <= OR32_LAST_ACTUAL_REG; regno++)
        {
        {
          HOST_WIDE_INT disp = frame_info.gpr_offset + offset;
          if (!(frame_info.mask & ((HOST_WIDE_INT) 1 << regno)))
 
 
          if (!(frame_info.mask & (1 << regno)))
 
            continue;
            continue;
 
 
          emit_frame_insn
          emit_frame_insn
            (gen_rtx_SET (Pmode,
            (gen_rtx_SET (Pmode,
                          indexed_memory (stack_pointer_rtx, disp),
                          stack_disp_mem (frame_info.gpr_offset + offset),
                          gen_rtx_REG (Pmode, regno)));
                          gen_rtx_REG (Pmode, regno)));
          offset = offset + UNITS_PER_WORD;
          offset = offset + UNITS_PER_WORD;
        }
        }
    }
    }
 
 
 
  /* Update the stack pointer to reflect frame size.  */
 
  insn = gen_add2_insn (stack_pointer_rtx, GEN_INT (-total_size));
 
  if (total_size > 32767)
 
    {
 
      rtx note = insn;
 
      rtx value_rtx = gen_rtx_REG (Pmode, PROLOGUE_TMP);
 
 
 
      or32_emit_set_const32 (value_rtx, GEN_INT (-total_size));
 
      insn = emit_frame_insn (gen_add2_insn (stack_pointer_rtx, value_rtx));
 
      add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
 
    }
 
  else
 
    emit_frame_insn (insn);
 
 
}       /* or32_expand_prologue () */
}       /* or32_expand_prologue () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Expand an epilogue pattern.
/*!Expand an epilogue pattern.
Line 672... Line 682...
   first insn to prevent such scheduling.
   first insn to prevent such scheduling.
 
 
   For the OR32 this is currently controlled by the -mlogue option. It should
   For the OR32 this is currently controlled by the -mlogue option. It should
   be the default, once it is proved to work.
   be the default, once it is proved to work.
 
 
   @param[in] sibcall  Non-zero (TRUE) if this is a sibcall return, which can
   @param[in] sibcall  The sibcall epilogue insn if this is a sibcall return,
                       benefit from tail call optimization. Zero (FALSE)
                       NULL_RTX otherwise.                                             */
                       otherwise.                                             */
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void
void
or32_expand_epilogue (int sibcall)
or32_expand_epilogue (rtx sibcall)
{
{
  int total_size = or32_compute_frame_size (get_frame_size ());
  int total_size = or32_compute_frame_size (get_frame_size ());
 
  int sibcall_regno = FIRST_PSEUDO_REGISTER;
 
 
 
  if (sibcall)
 
    {
 
      sibcall = next_nonnote_insn (sibcall);
 
      gcc_assert (CALL_P (sibcall) && SIBLING_CALL_P (sibcall));
 
      sibcall = XVECEXP (PATTERN (sibcall), 0, 0);
 
      if (GET_CODE (sibcall) == SET)
 
        sibcall = SET_SRC (sibcall);
 
      gcc_assert (GET_CODE (sibcall) == CALL);
 
      sibcall = XEXP (sibcall, 0);
 
      gcc_assert (MEM_P (sibcall));
 
      sibcall = XEXP (sibcall, 0);
 
      if (REG_P (sibcall))
 
        sibcall_regno = REGNO (sibcall);
 
      else
 
        gcc_assert (CONSTANT_P (sibcall));
 
    }
 
  if (frame_info.save_fp_p)
 
    {
 
      emit_insn
 
        (gen_add3_insn (stack_pointer_rtx, hard_frame_pointer_rtx, const0_rtx));
 
      emit_insn
 
        (gen_rtx_SET (Pmode, hard_frame_pointer_rtx,
 
                      stack_disp_mem (frame_info.fp_save_offset)));
 
    }
 
  else
 
    {
  rtx value_rtx;
  rtx value_rtx;
 
 
  if (total_size > 32767)
  if (total_size > 32767)
    {
    {
      value_rtx = gen_rtx_REG (Pmode, 3);
          value_rtx = gen_rtx_REG (Pmode, EPILOGUE_TMP);
 
          or32_emit_set_const32 (value_rtx, GEN_INT (total_size));
      emit_insn (gen_rtx_SET (Pmode, value_rtx, GEN_INT (total_size)));
 
    }
    }
  else
  else
    value_rtx = GEN_INT (total_size);
    value_rtx = GEN_INT (total_size);
 
      if (total_size)
 
        emit_insn (gen_add2_insn (stack_pointer_rtx, value_rtx));
 
    }
 
 
  if (frame_info.save_lr_p)
  if (frame_info.save_lr_p)
    {
    {
      emit_insn
      emit_insn
        (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, LINK_REGNUM),
        (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, LINK_REGNUM),
                      indexed_memory (stack_pointer_rtx,
                      stack_disp_mem (frame_info.lr_save_offset)));
                                      frame_info.lr_save_offset)));
 
    }
 
  if (frame_info.save_fp_p)
 
    {
 
      emit_insn
 
        (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),
 
                      indexed_memory (stack_pointer_rtx,
 
                                      frame_info.fp_save_offset)));
 
    }
    }
 
 
  if (frame_info.gpr_size)
  if (frame_info.gpr_size)
    {
    {
      int offset = 0;
      int offset = 0;
      int regno;
      int regno;
 
 
      for (regno = 0; regno <= OR32_LAST_INT_REG; regno++)
      for (regno = 0; regno <= OR32_LAST_ACTUAL_REG; regno++)
        {
        {
          HOST_WIDE_INT disp = frame_info.gpr_offset + offset;
          if (!(frame_info.mask & ((HOST_WIDE_INT) 1 << regno)))
 
 
          if (!(frame_info.mask & (1 << regno)))
 
            continue;
            continue;
 
 
 
          if (regno != sibcall_regno)
          emit_insn
          emit_insn
            (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, regno),
            (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, regno),
                          indexed_memory (stack_pointer_rtx, disp)));
                            stack_disp_mem (frame_info.gpr_offset + offset)));
          offset = offset + UNITS_PER_WORD;
          offset = offset + UNITS_PER_WORD;
        }
        }
    }
    }
 
 
  if (total_size)
 
    {
 
      emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx,
 
                              gen_rtx_PLUS (Pmode,
 
                                            stack_pointer_rtx, value_rtx)));
 
    }
 
 
 
  if (!sibcall)
  if (!sibcall)
    emit_jump_insn (gen_return_internal (gen_rtx_REG( Pmode, 9)));
    emit_jump_insn (gen_return_internal (gen_rtx_REG( Pmode, 9)));
 
 
}       /* or32_expand_epilogue () */
}       /* or32_expand_epilogue () */
 
 
 
/* We are outputting a jump which needs JUMP_ADDRESS, which is the
 
   register it uses as jump destination, restored,
 
   e.g. a sibcall using a callee-saved register.
 
   Emit the register restore as delay slot insn.  */
 
void
 
or32_print_jump_restore (rtx jump_address)
 
{
 
  int regno, jump_regno;
 
  HOST_WIDE_INT offset = frame_info.gpr_offset;
 
 
 
  gcc_assert (REG_P (jump_address));
 
  jump_regno = REGNO (jump_address);
 
  for (regno = 0; regno != jump_regno; regno++)
 
    {
 
      gcc_assert (regno <= OR32_LAST_ACTUAL_REG);
 
      if (!(frame_info.mask & ((HOST_WIDE_INT) 1 << regno)))
 
        continue;
 
      offset = offset + UNITS_PER_WORD;
 
    }
 
  asm_fprintf (asm_out_file, "\n\tl.lwz\tr%d,"HOST_WIDE_INT_PRINT_DEC"(r1)\n",
 
               jump_regno, offset);
 
}
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Generate assembler code for a movdi/movdf pattern
/*!Generate assembler code for a movdi/movdf pattern
 
 
   @param[in] operands  Operands to the movdx pattern.
   @param[in] operands  Operands to the movdx pattern.
Line 981... Line 1027...
 
 
  code      = GET_CODE (operands[1]);
  code      = GET_CODE (operands[1]);
  mode_calc = SELECT_CC_MODE (code, or32_compare_op0, or32_compare_op1);
  mode_calc = SELECT_CC_MODE (code, or32_compare_op0, or32_compare_op1);
  mode_got  = GET_MODE (operands[2]);
  mode_got  = GET_MODE (operands[2]);
 
 
  if (!TARGET_MASK_ALIGNED_JUMPS)
 
    {
 
      if (mode_calc != mode_got)
      if (mode_calc != mode_got)
        return "l.bnf\t%l0%(";
        return "l.bnf\t%l0%(";
      else
      else
        return "l.bf\t%l0%(";
        return "l.bf\t%l0%(";
    }
 
  else
 
    {
 
      if (mode_calc != mode_got)
 
        return ".balignl\t0x8,0x15000015,0x4\n\tl.bnf\t%l0%(";
 
      else
 
        return ".balignl 0x8,0x15000015,0x4;\n\tl.bf\t%l0%(";
 
    }
 
}       /* or32_output_bf () */
}       /* or32_output_bf () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Output the assembler for a conditional move instruction.
/*!Output the assembler for a conditional move instruction.
Line 1174... Line 1210...
  /* If we are doing the prologue using the "prologue" pattern in the machine
  /* If we are doing the prologue using the "prologue" pattern in the machine
     description, do nothing more here.
     description, do nothing more here.
 
 
     JPB 30-Aug-10: Surely that is not correct. If this option is set, we
     JPB 30-Aug-10: Surely that is not correct. If this option is set, we
     should never even be called! */
     should never even be called! */
  if (TARGET_MASK_SCHED_LOGUE)
  if (TARGET_SCHED_LOGUE)
    return;
    return;
 
 
  if (size < 0)
  if (size < 0)
    abort ();
    abort ();
 
 
Line 1225... Line 1261...
    {
    {
      char *l     = dwarf2out_cfi_label (false);
      char *l     = dwarf2out_cfi_label (false);
      int  offset = OR32_ALIGN (crtl->outgoing_args_size, 4) + lr_save_area;
      int  offset = OR32_ALIGN (crtl->outgoing_args_size, 4) + lr_save_area;
 
 
      fprintf (file, "\tl.sw\t%d(r%d),r%d\n", offset,
      fprintf (file, "\tl.sw\t%d(r%d),r%d\n", offset,
               STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM);
               STACK_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM);
 
 
      if (stack_size >= 0x8000)
      if (stack_size >= 0x8000)
        fprintf (file, "\tl.add\tr%d,r%d,r%d\n", FRAME_POINTER_REGNUM,
        fprintf (file, "\tl.add\tr%d,r%d,r%d\n", HARD_FRAME_POINTER_REGNUM,
                 STACK_POINTER_REGNUM, GP_ARG_RETURN);
                 STACK_POINTER_REGNUM, GP_ARG_RETURN);
      else
      else
        fprintf (file, "\tl.addi\tr%d,r%d,%d\n", FRAME_POINTER_REGNUM,
        fprintf (file, "\tl.addi\tr%d,r%d,%d\n", HARD_FRAME_POINTER_REGNUM,
                 STACK_POINTER_REGNUM, stack_size);
                 STACK_POINTER_REGNUM, stack_size);
 
 
      /* The CFA is already pointing at the start of our frame (i.e. the new
      /* The CFA is already pointing at the start of our frame (i.e. the new
         FP). The old FP has been saved relative to the SP, so we need to use
         FP). The old FP has been saved relative to the SP, so we need to use
         stack_size to work out where. */
         stack_size to work out where. */
      dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, offset - stack_size);
      dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM, offset - stack_size);
    }
    }
 
 
  /* Save the return address if necessary */
  /* Save the return address if necessary */
  if (lr_save_area)
  if (lr_save_area)
    {
    {
Line 1252... Line 1288...
               LINK_REGNUM);
               LINK_REGNUM);
 
 
      /* The CFA is already pointing at the start of our frame (i.e. the new
      /* The CFA is already pointing at the start of our frame (i.e. the new
         FP). The LR has been saved relative to the SP, so we need to use
         FP). The LR has been saved relative to the SP, so we need to use
         stack_size to work out where. */
         stack_size to work out where. */
      dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, offset - stack_size);
      dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM, offset - stack_size);
    }
    }
 
 
  save_area = (OR32_ALIGN (crtl->outgoing_args_size, 4)
  save_area = (OR32_ALIGN (crtl->outgoing_args_size, 4)
               + lr_save_area + fp_save_area);
               + lr_save_area + fp_save_area);
 
 
Line 1271... Line 1307...
                   STACK_POINTER_REGNUM, regno);
                   STACK_POINTER_REGNUM, regno);
 
 
          /* The CFA is already pointing at the start of our frame (i.e. the
          /* The CFA is already pointing at the start of our frame (i.e. the
             new FP). The register has been saved relative to the SP, so we
             new FP). The register has been saved relative to the SP, so we
             need to use stack_size to work out where. */
             need to use stack_size to work out where. */
          dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, save_area - stack_size);
          dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM,
 
                              save_area - stack_size);
          save_area += 4;
          save_area += 4;
        }
        }
    }
    }
}       /* or32_output_function_prologue () */
}       /* or32_output_function_prologue () */
 
 
Line 1343... Line 1380...
  /* If we are doing the epilogue using the "epilogue" pattern in the machine
  /* If we are doing the epilogue using the "epilogue" pattern in the machine
     description, do nothing more here.
     description, do nothing more here.
 
 
     JPB 30-Aug-10: Surely that is not correct. If this option is set, we
     JPB 30-Aug-10: Surely that is not correct. If this option is set, we
     should never even be called! */
     should never even be called! */
  if (TARGET_MASK_SCHED_LOGUE)
  if (TARGET_SCHED_LOGUE)
    return;
    return;
 
 
  /* Work out the frame size */
  /* Work out the frame size */
  stack_size = calculate_stack_size (size, &lr_save_area, &fp_save_area,
  stack_size = calculate_stack_size (size, &lr_save_area, &fp_save_area,
                                     &gpr_save_area, &save_area);
                                     &gpr_save_area, &save_area);
Line 1361... Line 1398...
    }
    }
 
 
  /* Restore the frame pointer if necessary */
  /* Restore the frame pointer if necessary */
  if (fp_save_area)
  if (fp_save_area)
    {
    {
      fprintf (file, "\tl.lwz\tr%d,%d(r%d)\n", FRAME_POINTER_REGNUM,
      fprintf (file, "\tl.lwz\tr%d,%d(r%d)\n", HARD_FRAME_POINTER_REGNUM,
               OR32_ALIGN (crtl->outgoing_args_size, 4)
               OR32_ALIGN (crtl->outgoing_args_size, 4)
               + lr_save_area, STACK_POINTER_REGNUM);
               + lr_save_area, STACK_POINTER_REGNUM);
    }
    }
 
 
  save_area = (OR32_ALIGN (crtl->outgoing_args_size, 4)
  save_area = (OR32_ALIGN (crtl->outgoing_args_size, 4)
Line 1386... Line 1423...
  if (stack_size >= 0x8000)
  if (stack_size >= 0x8000)
    {
    {
      fprintf (file, "\tl.movhi\tr3,hi(%d)\n", stack_size);
      fprintf (file, "\tl.movhi\tr3,hi(%d)\n", stack_size);
      fprintf (file, "\tl.ori\tr3,r3,lo(%d)\n", stack_size);
      fprintf (file, "\tl.ori\tr3,r3,lo(%d)\n", stack_size);
 
 
      if (!TARGET_MASK_ALIGNED_JUMPS)
 
        fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
 
      else
 
        {
 
          fprintf (file, "\t.balignl\t0x8,0x15000015,0x4\n");
 
          fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
          fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
        }
 
 
 
      fprintf (file, "\tl.add\tr%d,r%d,r3\n", STACK_POINTER_REGNUM,
      fprintf (file, "\tl.add\tr%d,r%d,r3\n", STACK_POINTER_REGNUM,
               STACK_POINTER_REGNUM);
               STACK_POINTER_REGNUM);
    }
    }
  else if (stack_size > 0)
  else if (stack_size > 0)
    {
    {
      if (!TARGET_MASK_ALIGNED_JUMPS)
 
        fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
        fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
      else
 
        {
 
          fprintf (file, "\t.balignl 0x8,0x15000015,0x4\n");
 
          fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
 
        }
 
 
 
      fprintf (file, "\tl.addi\tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
      fprintf (file, "\tl.addi\tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
               STACK_POINTER_REGNUM, stack_size);
               STACK_POINTER_REGNUM, stack_size);
    }
    }
  else
  else
    {
    {
      if (!TARGET_MASK_ALIGNED_JUMPS)
 
        fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
        fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
      else
 
        {
 
          fprintf (file, "\t.balignl\t0x8,0x15000015,0x4\n");
 
          fprintf (file, "\tl.jr\tr%d\n", LINK_REGNUM);
 
        }
 
 
 
      fprintf (file, "\tl.nop\n");              /* Delay slot */
      fprintf (file, "\tl.nop\n");              /* Delay slot */
    }
    }
}       /* or32_output_function_epilogue () */
}       /* or32_output_function_epilogue () */
 
 
Line 1503... Line 1522...
   compilation. The hook is used to enforce these restrictions, as the sibcall
   compilation. The hook is used to enforce these restrictions, as the sibcall
   md pattern can not fail, or fall over to a “normal” call. The criteria for
   md pattern can not fail, or fall over to a “normal” call. The criteria for
   successful sibling call optimization may vary greatly between different
   successful sibling call optimization may vary greatly between different
   architectures.
   architectures.
 
 
   For the OR32, we currently allow sibcall optimization if the -msibcall
   For the OR32, we currently allow sibcall optimization whenever
   argument is passed.
   -foptimize-sibling-calls is enabled.
 
 
   JPB 30-Aug-10: Surely we should always allow this?
 
 
 
   @param[in] decl  The function for which we may optimize
   @param[in] decl  The function for which we may optimize
   @param[in] exp   The call expression which is candidate for optimization.
   @param[in] exp   The call expression which is candidate for optimization.
 
 
   @return  Non-zero (TRUE) if sibcall optimization is permitted, zero (FALSE)
   @return  Non-zero (TRUE) if sibcall optimization is permitted, zero (FALSE)
Line 1518... Line 1535...
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static bool
static bool
or32_function_ok_for_sibcall (tree  decl ATTRIBUTE_UNUSED,
or32_function_ok_for_sibcall (tree  decl ATTRIBUTE_UNUSED,
                              tree  exp ATTRIBUTE_UNUSED)
                              tree  exp ATTRIBUTE_UNUSED)
{
{
  return TARGET_MASK_SIBCALL;
  return true;
 
 
}       /* or32_function_ok_for_sibcall () */
}       /* or32_function_ok_for_sibcall () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Should an argument be passed by reference.
/*!Should an argument be passed by reference.
Line 1558... Line 1574...
  return (type && (AGGREGATE_TYPE_P (type) || int_size_in_bytes (type) > 8));
  return (type && (AGGREGATE_TYPE_P (type) || int_size_in_bytes (type) > 8));
 
 
}       /* or32_pass_by_reference () */
}       /* or32_pass_by_reference () */
 
 
 
 
 
#if 0
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Is a frame pointer required?
/*!Is a frame pointer required?
 
 
   This target hook should return TRUE if a function must have and use a frame
   This target hook should return TRUE if a function must have and use a frame
   pointer.  This target hook is called in the reload pass. If its return
   pointer.  This target hook is called in the reload pass. If its return
Line 1598... Line 1615...
or32_frame_pointer_required (void)
or32_frame_pointer_required (void)
{
{
        return 1;
        return 1;
 
 
}       /* or32_frame_pointer_required () */
}       /* or32_frame_pointer_required () */
 
#endif
 
 
 
int
 
or32_initial_elimination_offset(int from, int to)
 
{
 
  if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
 
    return 0;
 
  or32_compute_frame_size (get_frame_size ());
 
  return ((from == FRAME_POINTER_REGNUM ? frame_info.gpr_offset : 0)
 
          + (to == STACK_POINTER_REGNUM ? frame_info.total_size : 0));
 
}
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!How many bytes at the beginning of an argument must be put into registers.
/*!How many bytes at the beginning of an argument must be put into registers.
 
 
Line 1847... Line 1875...
   If the target requires any other actions, such as flushing caches or
   If the target requires any other actions, such as flushing caches or
   enabling stack execution, these actions should be performed after
   enabling stack execution, these actions should be performed after
   initializing the trampoline proper.
   initializing the trampoline proper.
 
 
   For the OR32, no static chain register is used. We choose to use the return
   For the OR32, no static chain register is used. We choose to use the return
   value (rv) register. The rvh register is used as a temporary. The code is
   value (rv) register. The code is based on that for MIPS.
   based on that for MIPS. The trampoline code is:
   The trampoline code is:
 
 
              l.movhi r12,hi(end_addr)
              l.movhi r11,hi(end_addr)
              l.ori   r12,lo(end_addr)
              l.ori   r11,lo(end_addr)
              l.lwz   r13,4(r12)
              l.lwz   r13,4(r11)
              l.jr    r13
              l.jr    r13
              l.lwz   r11,0(r12)
              l.lwz   r11,0(r11)
      end_addr:
      end_addr:
              .word   <static chain>
              .word   <static chain>
              .word   <nested_function>
              .word   <nested_function>
 
 
   @note For the OR32 we need to flush the instruction cache, which is a
   @note For the OR32 we need to flush the instruction cache, which is a
Line 1901... Line 1929...
  addr     = force_reg (Pmode, XEXP (m_tramp, 0));
  addr     = force_reg (Pmode, XEXP (m_tramp, 0));
  end_addr = or32_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset));
  end_addr = or32_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset));
 
 
  /* Build up the code in TRAMPOLINE.
  /* Build up the code in TRAMPOLINE.
 
 
              l.movhi r12,hi(end_addr)
              l.movhi r11,hi(end_addr)
              l.ori   r12,lo(end_addr)
              l.ori   r11,lo(end_addr)
              l.lwz   r13,4(r12)
              l.lwz   r13,4(r11)
              l.jr    r13
              l.jr    r13
              l.lwz   r11,0(r12)
              l.lwz   r11,0(r11)
       end_addr:
       end_addr:
  */
  */
 
 
  i = 0;
  i = 0;
 
 
Line 1918... Line 1946...
                              NULL, false, OPTAB_WIDEN);
                              NULL, false, OPTAB_WIDEN);
  low  = convert_to_mode (SImode, gen_lowpart (HImode, end_addr), true);
  low  = convert_to_mode (SImode, gen_lowpart (HImode, end_addr), true);
 
 
  /* Emit the l.movhi, adding an operation to OR in the high bits from the
  /* Emit the l.movhi, adding an operation to OR in the high bits from the
     RTX. */
     RTX. */
  opcode = gen_int_mode (OR32_MOVHI (12, 0), SImode);
  opcode = gen_int_mode (OR32_MOVHI (11, 0), SImode);
  trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, high, NULL,
  trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, high, NULL,
                                         false, OPTAB_WIDEN);
                                         false, OPTAB_WIDEN);
 
 
  /* Emit the l.ori, adding an operations to OR in the low bits from the
  /* Emit the l.ori, adding an operations to OR in the low bits from the
     RTX. */
     RTX. */
  opcode = gen_int_mode (OR32_ORI (12, 12, 0), SImode);
  opcode = gen_int_mode (OR32_ORI (11, 11, 0), SImode);
  trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, low, NULL,
  trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, low, NULL,
                                         false, OPTAB_WIDEN);
                                         false, OPTAB_WIDEN);
 
 
  /* Emit the l.lwz of the function address. No bits to OR in here, so we can
  /* Emit the l.lwz of the function address. No bits to OR in here, so we can
     do the opcode directly. */
     do the opcode directly. */
  trampoline[i++] =
  trampoline[i++] =
    gen_int_mode (OR32_LWZ (13, 12, target_function_offset - end_addr_offset),
    gen_int_mode (OR32_LWZ (13, 11, target_function_offset - end_addr_offset),
                  SImode);
                  SImode);
 
 
  /* Emit the l.jr of the function. No bits to OR in here, so we can do the
  /* Emit the l.jr of the function. No bits to OR in here, so we can do the
     opcode directly. */
     opcode directly. */
  trampoline[i++] = gen_int_mode (OR32_JR (13), SImode);
  trampoline[i++] = gen_int_mode (OR32_JR (13), SImode);
 
 
  /* Emit the l.lwz of the static chain. No bits to OR in here, so we can
  /* Emit the l.lwz of the static chain. No bits to OR in here, so we can
     do the opcode directly. */
     do the opcode directly. */
  trampoline[i++] =
  trampoline[i++] =
    gen_int_mode (OR32_LWZ (STATIC_CHAIN_REGNUM, 12,
    gen_int_mode (OR32_LWZ (STATIC_CHAIN_REGNUM, 11,
                            static_chain_offset - end_addr_offset), SImode);
                            static_chain_offset - end_addr_offset), SImode);
 
 
  /* Copy the trampoline code.  Leave any padding uninitialized.  */
  /* Copy the trampoline code.  Leave any padding uninitialized.  */
  for (j = 0; j < i; j++)
  for (j = 0; j < i; j++)
    {
    {
Line 1991... Line 2019...
{
{
  return  DW_CC_normal;
  return  DW_CC_normal;
 
 
}       /* or32_dwarf_calling_convention () */
}       /* or32_dwarf_calling_convention () */
 
 
 
/* If DELTA doesn't fit into a 16 bit signed number, emit instructions to
 
   add the highpart to DST; return the signed-16-bit lowpart of DELTA.
 
   TMP_REGNO is a register that may be used to load a constant.  */
 
static HOST_WIDE_INT
 
or32_output_highadd (FILE *file,
 
                     const char *dst, int tmp_regno, HOST_WIDE_INT delta)
 
{
 
  if (delta < -32768 || delta > 32767)
 
    {
 
      if (delta >= -65536 && delta < 65534)
 
        {
 
          asm_fprintf (file, "\tl.addi\t%s,%s,%d\n",
 
                       dst, dst, (int) (delta + 1) >> 1);
 
          delta >>= 1;
 
        }
 
      else
 
        {
 
          const char *tmp = reg_names[tmp_regno];
 
          HOST_WIDE_INT high = (delta + 0x8000) >> 16;
 
 
 
          gcc_assert (call_used_regs[tmp_regno]);
 
          asm_fprintf (file, "\tl.movhi\t%s,%d\n" "\tl.add\t%s,%s,%s\n",
 
                 tmp, (int) high,
 
                 dst, dst, tmp);
 
          delta -= high << 16;
 
        }
 
    }
 
  return delta;
 
}
 
 
 
/* Output a tailcall to FUNCTION.  The caller will fill in the delay slot.  */
 
void
 
or32_output_tailcall (FILE *file, tree function)
 
{
 
  /* We'll need to add more code if we want to fully support PIC.  */
 
  gcc_assert (!flag_pic || (*targetm.binds_local_p) (function));
 
 
 
  fputs ("\tl.j\t", file);
 
  assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
 
  fputc ('\n', file);
 
}
 
 
 
static void
 
or32_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
 
                      HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
 
                      tree function)
 
{
 
  int this_regno
 
    = aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 4 : 3;
 
  const char *this_name = reg_names[this_regno];
 
 
 
 
 
  delta = or32_output_highadd (file, this_name, PROLOGUE_TMP, delta);
 
  if (!vcall_offset)
 
    or32_output_tailcall (file, function);
 
  if (delta || !vcall_offset)
 
    asm_fprintf (file, "\tl.addi\t%s,%s,%d\n",
 
                 this_name, this_name, (int) delta);
 
 
 
  /* If needed, add *(*THIS + VCALL_OFFSET) to THIS.  */
 
  if (vcall_offset != 0)
 
    {
 
      const char *tmp_name = reg_names[PROLOGUE_TMP];
 
 
 
      /* l.lwz tmp,0(this)           --> tmp = *this
 
         l.lwz tmp,vcall_offset(tmp) --> tmp = *(*this + vcall_offset)
 
         add this,this,tmp           --> this += *(*this + vcall_offset) */
 
 
 
      asm_fprintf (file, "\tl.lwz\t%s,0(%s)\n",
 
                   tmp_name, this_name);
 
      vcall_offset = or32_output_highadd (file, tmp_name,
 
                                          STATIC_CHAIN_REGNUM, vcall_offset);
 
      asm_fprintf (file, "\tl.lwz\t%s,%d(%s)\n",
 
                   tmp_name, (int) vcall_offset, tmp_name);
 
      or32_output_tailcall (file, function);
 
      asm_fprintf (file, "\tl.add\t%s,%s,%s\n", this_name, this_name, tmp_name);
 
    }
 
}
 
 
 
 
/* ========================================================================== */
/* ========================================================================== */
/* Target hook initialization.
/* Target hook initialization.
 
 
   In most cases these use the static functions declared above. They have
   In most cases these use the static functions declared above. They have
Line 2007... Line 2114...
   The final declaration is of the global "targetm" structure. */
   The final declaration is of the global "targetm" structure. */
 
 
 
 
/* Default target_flags if no switches specified. */
/* Default target_flags if no switches specified. */
#undef  TARGET_DEFAULT_TARGET_FLAGS
#undef  TARGET_DEFAULT_TARGET_FLAGS
#define TARGET_DEFAULT_TARGET_FLAGS (MASK_HARD_MUL)
#define TARGET_DEFAULT_TARGET_FLAGS (MASK_HARD_MUL | MASK_SCHED_LOGUE)
 
 
/* Output assembly directives to switch to section name. The section should
/* Output assembly directives to switch to section name. The section should
   have attributes as specified by flags, which is a bit mask of the SECTION_*
   have attributes as specified by flags, which is a bit mask of the SECTION_*
   flags defined in ‘output.h’. If decl is non-NULL, it is the VAR_DECL or
   flags defined in ‘output.h’. If decl is non-NULL, it is the VAR_DECL or
   FUNCTION_DECL with which this section is associated.
   FUNCTION_DECL with which this section is associated.
Line 2033... Line 2140...
#define TARGET_FUNCTION_OK_FOR_SIBCALL or32_function_ok_for_sibcall
#define TARGET_FUNCTION_OK_FOR_SIBCALL or32_function_ok_for_sibcall
 
 
#undef  TARGET_PASS_BY_REFERENCE
#undef  TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE or32_pass_by_reference
#define TARGET_PASS_BY_REFERENCE or32_pass_by_reference
 
 
#undef  TARGET_FRAME_POINTER_REQUIRED
 
#define TARGET_FRAME_POINTER_REQUIRED or32_frame_pointer_required
 
 
 
#undef  TARGET_ARG_PARTIAL_BYTES
#undef  TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES or32_arg_partial_bytes
#define TARGET_ARG_PARTIAL_BYTES or32_arg_partial_bytes
 
 
/* This target hook returns TRUE if an argument declared in a prototype as an
/* This target hook returns TRUE if an argument declared in a prototype as an
   integral type smaller than int should actually be passed as an int. In
   integral type smaller than int should actually be passed as an int. In
Line 2063... Line 2167...
#define TARGET_TRAMPOLINE_INIT  or32_trampoline_init
#define TARGET_TRAMPOLINE_INIT  or32_trampoline_init
 
 
#undef TARGET_DWARF_CALLING_CONVENTION
#undef TARGET_DWARF_CALLING_CONVENTION
#define TARGET_DWARF_CALLING_CONVENTION  or32_dwarf_calling_convention
#define TARGET_DWARF_CALLING_CONVENTION  or32_dwarf_calling_convention
 
 
 
#undef TARGET_ASM_OUTPUT_MI_THUNK
 
#define TARGET_ASM_OUTPUT_MI_THUNK or32_output_mi_thunk
 
 
 
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
 
 
/* Trampoline stubs are yet to be written. */
/* Trampoline stubs are yet to be written. */
/* #define TARGET_ASM_TRAMPOLINE_TEMPLATE */
/* #define TARGET_ASM_TRAMPOLINE_TEMPLATE */
/* #define TARGET_TRAMPOLINE_INIT */
/* #define TARGET_TRAMPOLINE_INIT */
 
 
/* Initialize the GCC target structure.  */
/* Initialize the GCC target structure.  */
struct gcc_target targetm = TARGET_INITIALIZER;
struct gcc_target targetm = TARGET_INITIALIZER;
 
 
 No newline at end of file
 No newline at end of file
 
/* Lay out structs with increased alignment so that they can be accessed
 
   more efficiently.  But don't increase the size of one or two byte
 
   structs.  */
 
int
 
or32_struct_alignment (tree t)
 
{
 
  unsigned HOST_WIDE_INT total = 0;
 
  tree field;
 
  unsigned max_align
 
    = maximum_field_alignment ? maximum_field_alignment : BIGGEST_ALIGNMENT;
 
  bool struct_p;
 
 
 
  switch (TREE_CODE (t))
 
    {
 
    case RECORD_TYPE:
 
      struct_p = true; break;
 
    case UNION_TYPE: case QUAL_UNION_TYPE:
 
      struct_p = false; break;
 
    default: gcc_unreachable ();
 
    }
 
  /* Skip all non field decls */
 
  for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
 
    {
 
      unsigned HOST_WIDE_INT field_size;
 
 
 
      if (TREE_CODE (field) != FIELD_DECL)
 
        continue;
 
      if (!host_integerp (DECL_SIZE (field), 1))
 
        return max_align;
 
      field_size = tree_low_cst (DECL_SIZE (field), 1);
 
      if (field_size >= BIGGEST_ALIGNMENT)
 
        return max_align;
 
      if (struct_p)
 
        total += field_size;
 
      else
 
        total = MAX (total, field_size);
 
    }
 
 
 
  return total < max_align ? (1U << ceil_log2 (total)) : max_align;
 
}
 
 
 
/* Increase the alignment of objects so that they are easier to copy.
 
   Note that this can cause more struct copies to be inlined, so code
 
   size might increase, but so should perfromance.  */
 
int
 
or32_data_alignment (tree t, int align)
 
{
 
  if (align < FASTEST_ALIGNMENT && TREE_CODE (t) == ARRAY_TYPE)
 
    {
 
      int size = int_size_in_bytes (t);
 
 
 
      return (size > 0 && size < FASTEST_ALIGNMENT / BITS_PER_UNIT
 
              ? (1 << floor_log2 (size)) * BITS_PER_UNIT
 
              : FASTEST_ALIGNMENT);
 
    }
 
  return align;
 
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.