newlib/libgloss/or1k/include/or1k-asm.h

84 lines
3.1 KiB
C

/* or1k-asm.h -- OR1K assembly helper macros
Copyright (c) 2014 OpenRISC Project Maintainers
Copyright (C) 2012-2014 Peter Gavin <pgavin@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following condition
is met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OR1K_ASM_H
#define OR1K_ASM_H
/* The purpose of the OR1K_INST macro is simply to protect the commas
embedded within an instruction from the C preprocessor. An entire
instruction can be safely embedded within its arguments, including
an arbitrary number of commas, and it will be reproduced
exactly. */
#define OR1K_INST(...) __VA_ARGS__
/* OR1K_DELAYED takes two arguments which must be instructions. They
should be wrapped in OR1K_INST if the instructions require commas.
The second argument should be a jump or branch instruction. If we
are assembling the code in delay-slot mode (e.g., for the standard
OR1K) the first instruction will be emitted in the delay slot of
the second instruction. In no-delay-slot mode they will be emitted
in order. If we are using compat-delay mode, they will be emitted
in order, but an l.nop instruction will be emitted immediately
after. */
/* OR1K_DELAYED_NOP takes a single argument, which should be a
branch/jump instruction. In delay-slot or compat-delay modes, the
instruction will be emitted with an l.nop in its delay slot. In
no-delay mode, the instruction will be emitted by itself. */
#if defined(__OR1K_NODELAY__)
#define OR1K_DELAYED(a, b) a; b
#define OR1K_DELAYED_NOP(a) a
/* Go ahead and emit the .nodelay directive when in no-delay mode, so
that the flags are appropriately set in the binary. */
.nodelay
#elif defined(__OR1K_DELAY__)
#define OR1K_DELAYED(a, b) b; a
#define OR1K_DELAYED_NOP(a) a; l.nop
#elif defined(__OR1K_DELAY_COMPAT__)
#define OR1K_DELAYED(a, b) a; b; l.nop
#define OR1K_DELAYED_NOP(a) a; l.nop
#else
#error One of __OR1K_NODELAY__, __OR1K_DELAY__, or __OR1K_DELAY_COMPAT__ must be defined
#endif
#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
.global symbol ; \
l.movhi gpr, hi(symbol) ; \
l.ori gpr, gpr, lo(symbol)
#endif