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

Subversion Repositories openrisc_2011-10-31

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/gnu-src/gcc-4.5.1/gcc/config/or32
    from Rev 282 to Rev 332
    Reverse comparison

Rev 282 → Rev 332

/or32-protos.h
3,8 → 3,10
#ifndef GCC_OR32_PROTOS_H
#define GCC_OR32_PROTOS_H
 
/* The following are for general support. */
extern int or32_trampoline_code_size (void);
 
/* The following are only needed when handling the machine definition. */
 
#ifdef RTX_CODE
extern void or32_expand_prologue (void);
extern void or32_expand_epilogue (int sibcall);
/or32.c
54,7 → 54,25
#include "dwarf2.h"
 
 
/* ========================================================================== */
/* Local macros */
 
/* Construct a l.movhi instruction for the given reg and value */
#define OR32_MOVHI(rd, k) \
((0x6 << 26) | ((rd) << 21) | (k))
 
/* Construct a l.ori instruction for the given two regs and value */
#define OR32_ORI(rd, ra, k) \
((0x2a << 26) | ((rd) << 21) | ((ra) << 16) | (k))
 
/* Construct a l.lwz instruction for the given two registers and offset */
#define OR32_LWZ(rd, ra, i) \
((0x21 << 26) | ((rd) << 21) | ((ra) << 16) | (i))
 
/* Construct a l.jr instruction for the given register */
#define OR32_JR(rb) \
((0x11 << 26) | ((rb) << 11))
 
/* ========================================================================== */
/* Static variables (i.e. global to this file only. */
 
461,7 → 479,104
} /* or32_regnum_ok_for_base_p () */
 
 
/* -------------------------------------------------------------------------- */
/*!Emit a move from SRC to DEST.
 
Assume that the move expanders can handle all moves if !can_create_pseudo_p
(). The distinction is important because, unlike emit_move_insn, the move
expanders know how to force Pmode objects into the constant pool even when
the constant pool address is not itself legitimate.
 
@param[in] dest Destination of the move.
@param[in] src Source for the move.
 
@return RTX for the move. */
/* -------------------------------------------------------------------------- */
rtx
or32_emit_move (rtx dest, rtx src)
{
return (can_create_pseudo_p ()
? emit_move_insn (dest, src)
: emit_move_insn_1 (dest, src));
 
} /* or32_emit_move () */
 
 
/* -------------------------------------------------------------------------- */
/*!Emit an instruction of the form (set TARGET (CODE OP0 OP1)).
 
@param[in] code The code for the operation.
@param[in] target Destination for the set operation.
@param[in] op0 First operand.
@param[in] op1 Second operand. */
/* -------------------------------------------------------------------------- */
static void
or32_emit_binary (enum rtx_code code,
rtx target,
rtx op0,
rtx op1)
{
emit_insn (gen_rtx_SET (VOIDmode, target,
gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1)));
 
} /* or32_emit_binary () */
 
 
/* -------------------------------------------------------------------------- */
/*!Compute the result of an operation into a new register.
 
Compute ("code" "op0" "op1") and store the result in a new register of mode
"mode".
 
@param[in] mode Mode of the result
@parma[in] code RTX for the operation to perform
@param[in] op0 RTX for the first operand
@param[in] op1 RTX for the second operand
@return The RTX for the new register. */
/* -------------------------------------------------------------------------- */
static rtx
or32_force_binary (enum machine_mode mode,
enum rtx_code code,
rtx op0,
rtx op1)
{
rtx reg;
 
reg = gen_reg_rtx (mode);
or32_emit_binary (code, reg, op0, op1);
 
return reg;
 
} /* or32_force_binary () */
 
 
/* ========================================================================== */
/* Global support functions */
 
/* -------------------------------------------------------------------------- */
/* Return the size in bytes of the trampoline code.
 
Padded to TRAMPOLINE_ALIGNMENT bits. The code sequence is documented in
or32_trampoline_init ().
 
This is just the code size. the static chain pointer and target function
address immediately follow.
 
@return The size of the trampoline code in bytes. */
/* -------------------------------------------------------------------------- */
int
or32_trampoline_code_size (void)
{
const int TRAMP_BYTE_ALIGN = TRAMPOLINE_ALIGNMENT / 8;
 
/* Five 32-bit code words are needed */
return (5 * 4 + TRAMP_BYTE_ALIGN - 1) / TRAMP_BYTE_ALIGN * TRAMP_BYTE_ALIGN;
 
} /* or32_trampoline_code_size () */
 
 
/* ========================================================================== */
/* Functions to support the Machine Description */
 
 
872,16 → 987,16
if (!TARGET_MASK_ALIGNED_JUMPS)
{
if (mode_calc != mode_got)
return "\tl.bnf\t%l0%(";
return "l.bnf\t%l0%(";
else
return "\tl.bf\t%l0%(";
return "l.bf\t%l0%(";
}
else
{
if (mode_calc != mode_got)
return "\t.balignl\t0x8,0x15000015,0x4\n\tl.bnf\t%l0%(";
return ".balignl\t0x8,0x15000015,0x4\n\tl.bnf\t%l0%(";
else
return "\t.balignl 0x8,0x15000015,0x4;\n\tl.bf\t%l0%(";
return ".balignl 0x8,0x15000015,0x4;\n\tl.bf\t%l0%(";
}
} /* or32_output_bf () */
 
1690,6 → 1805,172
 
 
/* -------------------------------------------------------------------------- */
/*!Initialize a trampoline for nested functions.
 
A nested function is defined by *two* pieces of information, the address of
the function (like any other function) and a pointer to the frame of the
enclosing function. The latter is required to allow the nested function to
access local variables in the enclosing function's frame.
 
This represents a problem, since a function in C is represented as an
address that can be held in a single variable as a pointer. Requiring two
pointers will not fit.
 
The solution is documented in "Lexical Closures for C++" by Thomas
M. Breuel (USENIX C++ Conference Proceedings, October 17-21, 1988). The
nested function is represented by a small block of code and data on the
enclosing function's stack frame, which sets up a pointer to the enclosing
function's stack frame (the static chain pointer) in a register defined by
the ABI, and then jumps to the code of the function proper.
 
The function can be represented as a single pointer to this block of code,
known as a trampoline, which when called generates both pointers
needed. The nested function (which knows it is a nested function at compile
time) can then generate code to access the enclosing frame via the static
chain register.
 
There is a catch that the trampoline is set up as data, but executed as
instructions. The former will be via the data cache, the latter via the
instruction cache. There is a risk that a later trampoline will not be seen
by the instruction cache, so the wrong code will be executed. So the
instruction cache should be flushed for the trampoline address range.
 
This hook is called to initialize a trampoline. "m_tramp" is an RTX for the
memory block for the trampoline; "fndecl" is the FUNCTION_DECL for the
nested function; "static_chain" is an RTX for the static chain value that
should be passed to the function when it is called.
 
If the target defines TARGET_ASM_TRAMPOLINE_TEMPLATE, then the first thing
this hook should do is emit a block move into "m_tramp" from the memory
block returned by assemble_trampoline_template. Note that the block move
need only cover the constant parts of the trampoline. If the target
isolates the variable parts of the trampoline to the end, not all
TRAMPOLINE_SIZE bytes need be copied.
 
If the target requires any other actions, such as flushing caches or
enabling stack execution, these actions should be performed after
initializing the trampoline proper.
 
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
based on that for MIPS. The trampoline code is:
 
l.movhi r12,hi(end_addr)
l.ori r12,lo(end_addr)
l.lwz r13,4(r12)
l.jr r13
l.lwz r11,0(r12)
end_addr:
.word <static chain>
.word <nested_function>
 
@note For the OR32 we need to flush the instruction cache, which is a
privileged operation. Needs fixing.
 
@param[in] m_tramp The lowest address of the trampoline on the stack.
@param[in] fndecl Declaration of the enclosing function.
@param[in] chain_value Static chain pointer to pass to the nested
function. */
/* -------------------------------------------------------------------------- */
static void
or32_trampoline_init (rtx m_tramp,
tree fndecl,
rtx chain_value)
{
rtx addr; /* Start address of the trampoline */
rtx end_addr; /* End address of the code block */
 
rtx high; /* RTX for the high part of end_addr */
rtx low; /* RTX for the low part of end_addr */
rtx opcode; /* RTX for generated opcodes */
rtx mem; /* RTX for trampoline memory */
 
rtx trampoline[5]; /* The trampoline code */
 
unsigned int i; /* Index into trampoline */
unsigned int j; /* General counter */
 
HOST_WIDE_INT end_addr_offset; /* Offset to end of code */
HOST_WIDE_INT static_chain_offset; /* Offset to stack chain word */
HOST_WIDE_INT target_function_offset; /* Offset to func address word */
 
/* Work out the offsets of the pointers from the start of the trampoline
code. */
end_addr_offset = or32_trampoline_code_size ();
static_chain_offset = end_addr_offset;
target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode);
 
/* Get pointers in registers to the beginning and end of the code block. */
addr = force_reg (Pmode, XEXP (m_tramp, 0));
end_addr = or32_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset));
 
/* Build up the code in TRAMPOLINE.
 
l.movhi r12,hi(end_addr)
l.ori r12,lo(end_addr)
l.lwz r13,4(r12)
l.jr r13
l.lwz r11,0(r12)
end_addr:
*/
 
i = 0;
 
/* Break out the high and low parts of the end_addr */
high = expand_simple_binop (SImode, LSHIFTRT, end_addr, GEN_INT (16),
NULL, false, OPTAB_WIDEN);
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
RTX. */
opcode = gen_int_mode (OR32_MOVHI (12, 0), SImode);
trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, high, NULL,
false, OPTAB_WIDEN);
/* Emit the l.ori, adding an operations to OR in the low bits from the
RTX. */
opcode = gen_int_mode (OR32_ORI (12, 12, 0), SImode);
trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, low, NULL,
false, OPTAB_WIDEN);
 
/* Emit the l.lwz of the function address. No bits to OR in here, so we can
do the opcode directly. */
trampoline[i++] =
gen_int_mode (OR32_LWZ (13, 12, target_function_offset - end_addr_offset),
SImode);
 
/* Emit the l.jr of the function. No bits to OR in here, so we can do the
opcode directly. */
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
do the opcode directly. */
trampoline[i++] =
gen_int_mode (OR32_LWZ (STATIC_CHAIN_REGNUM, 12,
static_chain_offset - end_addr_offset), SImode);
 
/* Copy the trampoline code. Leave any padding uninitialized. */
for (j = 0; j < i; j++)
{
mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode));
or32_emit_move (mem, trampoline[j]);
}
 
/* Set up the static chain pointer field. */
mem = adjust_address (m_tramp, ptr_mode, static_chain_offset);
or32_emit_move (mem, chain_value);
 
/* Set up the target function field. */
mem = adjust_address (m_tramp, ptr_mode, target_function_offset);
or32_emit_move (mem, XEXP (DECL_RTL (fndecl), 0));
 
/* Flushing the trampoline from the instruction cache needs to be done
here. */
 
} /* or32_trampoline_init () */
 
 
/* -------------------------------------------------------------------------- */
/*!Provide support for DW_AT_calling_convention
 
Define this to enable the dwarf attribute DW_AT_calling_convention to be
1735,28 → 2016,28
FUNCTION_DECL with which this section is associated.
 
For OR32, we use the default ELF sectioning. */
#undef TARGET_ASM_NAMED_SECTION
#undef TARGET_ASM_NAMED_SECTION
#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
 
#undef TARGET_ASM_FUNCTION_PROLOGUE
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE or32_output_function_prologue
 
#undef TARGET_ASM_FUNCTION_EPILOGUE
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE or32_output_function_epilogue
 
#undef TARGET_FUNCTION_VALUE
#undef TARGET_FUNCTION_VALUE
#define TARGET_FUNCTION_VALUE or32_function_value
 
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#undef TARGET_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
 
#undef TARGET_FRAME_POINTER_REQUIRED
#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
 
/* This target hook returns TRUE if an argument declared in a prototype as an
1768,15 → 2049,18
 
For the OR32 we do require this, so use a utility hook, which always
returns TRUE. */
#undef TARGET_PROMOTE_PROTOTYPES
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
#undef TARGET_PROMOTE_FUNCTION_MODE
#undef TARGET_PROMOTE_FUNCTION_MODE
#define TARGET_PROMOTE_FUNCTION_MODE or32_promote_function_mode
 
#undef TARGET_LEGITIMATE_ADDRESS_P
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P or32_legitimate_address_p
 
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT or32_trampoline_init
 
#undef TARGET_DWARF_CALLING_CONVENTION
#define TARGET_DWARF_CALLING_CONVENTION or32_dwarf_calling_convention
 
/or32.h
367,9 → 367,13
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
 
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 0
/* Register in which static-chain is passed to a function.
 
JPB 4-Sep-10: r0 was the wrong thing to use here. I'll take a punt at
using r11 (return value reg). This is a change to the
ABI, which needs documenting. */
#define STATIC_CHAIN_REGNUM 11
 
/* Register in which address to store a structure value
is passed to a function. */
/*#define STRUCT_VALUE_REGNUM 0*/
1336,10 → 1340,16
} \
}
 
/* Trampoline stuff are stubs yet to be written */
#define TRAMPOLINE_SIZE 26
/* The size of the trampoline in bytes. This is a block of code followed by
two words specifying the function address and static chain pointer. */
#define TRAMPOLINE_SIZE \
(or32_trampoline_code_size + GET_MODE_SIZE (ptr_mode) * 2)
 
/* Alignment required for trampolines, in bits.
 
For the OR32, there is no need for anything other than word alignment. */
#define TRAMPOLINE_ALIGNMENT 32
 
/* Mark functions for garbage collection. */
extern GTY(()) rtx or32_compare_op0;
extern GTY(()) rtx or32_compare_op1;

powered by: WebSVN 2.1.0

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