mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-25 05:44:49 +08:00
238 lines
6.7 KiB
C
238 lines
6.7 KiB
C
/* Copyright (C) 2019-2021 Free Software Foundation, Inc.
|
|
|
|
This file is part of LIBF7, which is part of GCC.
|
|
|
|
GCC 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
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
Under Section 7 of GPL version 3, you are granted additional
|
|
permissions described in the GCC Runtime Library Exception, version
|
|
3.1, as published by the Free Software Foundation.
|
|
|
|
You should have received a copy of the GNU General Public License and
|
|
a copy of the GCC Runtime Library Exception along with this program;
|
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef ASM_DEFS_H
|
|
#define ASM_DEFS_H
|
|
|
|
#ifdef __AVR__
|
|
#ifdef __ASSEMBLER__
|
|
/*****************************************************************/
|
|
/* Stuff for Assembler-only */
|
|
/*****************************************************************/
|
|
|
|
#if defined (__AVR_TINY__)
|
|
#define __tmp_reg__ 16
|
|
#define __zero_reg__ 17
|
|
#else
|
|
#define __tmp_reg__ 0
|
|
#define __zero_reg__ 1
|
|
#endif /* AVR_TINY */
|
|
|
|
#define __SREG__ 0x3f
|
|
#define __SP_L__ 0x3d
|
|
#if defined (__AVR_HAVE_SPH__)
|
|
#define __SP_H__ 0x3e
|
|
#endif
|
|
|
|
#if !defined ASM_DEFS_HAVE_DEFUN
|
|
.macro DEFUN name
|
|
.global \name
|
|
.func \name
|
|
\name:
|
|
.endm
|
|
|
|
.macro ENDF name
|
|
.size \name, .-\name
|
|
.endfunc
|
|
.endm
|
|
|
|
.macro LABEL name
|
|
.global \name
|
|
\name:
|
|
.endm
|
|
#endif /* HAVE_DEFUN */
|
|
|
|
|
|
#if defined (__AVR_HAVE_JMP_CALL__)
|
|
#define XCALL call
|
|
#define XJMP jmp
|
|
#else
|
|
#define XCALL rcall
|
|
#define XJMP rjmp
|
|
#endif
|
|
|
|
#if defined (__AVR_HAVE_EIJMP_EICALL__)
|
|
#define XICALL eicall
|
|
#define XIJMP eijmp
|
|
#define PC_SIZE 3
|
|
#else
|
|
#define XICALL icall
|
|
#define XIJMP ijmp
|
|
#define PC_SIZE 2
|
|
#endif
|
|
|
|
.macro skipnext
|
|
cpse r16, r16
|
|
.endm
|
|
|
|
/*
|
|
Factor out support of MOVW. Usage is like
|
|
|
|
wmov 30, 24
|
|
|
|
to move R25:R24 to R31:R30, i.e. plain register numbers
|
|
are required and no register prefix 'R'.
|
|
*/
|
|
|
|
#if defined (__AVR_HAVE_MOVW__)
|
|
#define wmov movw
|
|
#else
|
|
.macro wmov dst src
|
|
..dst = \dst
|
|
..src = \src
|
|
..regno = 0
|
|
.irp reg, \
|
|
r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, \
|
|
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
|
|
r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \
|
|
r30, r31
|
|
.ifc \reg,\dst
|
|
..dst = ..regno
|
|
.endif
|
|
.ifc \reg,\src
|
|
..src = ..regno
|
|
.endif
|
|
..regno = ..regno + 1
|
|
.endr
|
|
|
|
..regno = 0
|
|
|
|
.irp reg, \
|
|
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, \
|
|
R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, \
|
|
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, \
|
|
R30, R31
|
|
.ifc \reg,\dst
|
|
..dst = ..regno
|
|
.endif
|
|
.ifc \reg,\src
|
|
..src = ..regno
|
|
.endif
|
|
..regno = ..regno + 1
|
|
.endr
|
|
|
|
..regno = 0
|
|
|
|
.irp reg, \
|
|
X, x, XL, xl, Xl, xL, x, x \
|
|
Y, y, YL, yl, Yl, yL, y, y, \
|
|
Z, z, ZL, zl, Zl, zL, z, z
|
|
.ifc \reg,\dst
|
|
..dst = (..regno / 8) + 26
|
|
.endif
|
|
.ifc \reg,\src
|
|
..src = (..regno / 8) + 26
|
|
.endif
|
|
..regno = ..regno + 1
|
|
.endr
|
|
|
|
mov ..dst+0, ..src+0
|
|
mov ..dst+1, ..src+1
|
|
.endm
|
|
#endif /* MOVW */
|
|
|
|
|
|
#if !defined (__AVR_TINY__)
|
|
/*
|
|
Convenience macro for easy use of __prologue_saves__ from libgcc.
|
|
Push the N_PUSHED callee-saved registers Y, R17, R16, R15, ...
|
|
with 0 <= N_PUSHED <= 18. The frame pointer (Y) is set up according
|
|
to a frame size of N_FRAME. Clobbers TMP_REG.
|
|
For the code of __prologue_saves__ from libgcc see
|
|
http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs.S?revision=267494&view=markup#l2159
|
|
*/
|
|
|
|
.macro do_prologue_saves n_pushed n_frame=0
|
|
ldi r26, lo8(\n_frame)
|
|
ldi r27, hi8(\n_frame)
|
|
ldi r30, lo8(gs(.L_prologue_saves.\@))
|
|
ldi r31, hi8(gs(.L_prologue_saves.\@))
|
|
XJMP __prologue_saves__ + ((18 - (\n_pushed)) * 2)
|
|
.L_prologue_saves.\@:
|
|
.endm
|
|
|
|
/*
|
|
Convenience macro for easy use of __epilogue_restores__ from libgcc.
|
|
Undo the effect of __prologue_saves__. Clobbers TMP_REG.
|
|
For the code of __epilogue_restores__ from libgcc see
|
|
http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs.S?revision=267494&view=markup#l2216
|
|
*/
|
|
|
|
.macro do_epilogue_restores n_pushed n_frame=0
|
|
in r28, __SP_L__
|
|
#ifdef __AVR_HAVE_SPH__
|
|
in r29, __SP_H__
|
|
.if \n_frame > 63
|
|
subi r28, lo8(-\n_frame)
|
|
sbci r29, hi8(-\n_frame)
|
|
.elseif \n_frame > 0
|
|
adiw r28, \n_frame
|
|
.endif
|
|
#else
|
|
clr r29
|
|
.if \n_frame > 0
|
|
subi r28, lo8(-\n_frame)
|
|
.endif
|
|
#endif /* HAVE SPH */
|
|
ldi r30, \n_pushed
|
|
XJMP __epilogue_restores__ + ((18 - (\n_pushed)) * 2)
|
|
.endm
|
|
|
|
#endif /* AVR_TINY */
|
|
|
|
#else /* Assembler */
|
|
/*****************************************************************/
|
|
/* Space for C/C++ only Stuff */
|
|
/*****************************************************************/
|
|
#endif /* Assembler */
|
|
|
|
/*****************************************************************/
|
|
/* Space for Generic Stuff (Assembler, C, C++) */
|
|
/*****************************************************************/
|
|
|
|
#ifdef __AVR_PM_BASE_ADDRESS__
|
|
/*
|
|
Devices with a linear address space: Flash memory is seen in the
|
|
RAM address space at an offset of __AVR_PM_BASE_ADDRESS__ and can
|
|
be accessed by LD*. This is the case for devices like ATtiny40
|
|
(avrtiny) or ATtiny1616 and ATmega4808 (avrxmega3). The default
|
|
linker script locates .rodata in the .text output section and
|
|
at the required offset.
|
|
*/
|
|
#define RODATA_SECTION .rodata.asm
|
|
#define USE_LD 1
|
|
#define USE_LPM 0
|
|
#else /* PM_BASE_ADDRESS */
|
|
/*
|
|
No linear address space. As .rodata is located in RAM, we have to
|
|
use .progmem.data (located in flash) and LPM to read the data.
|
|
This will also work for devices from avrxmega3.
|
|
*/
|
|
#define RODATA_SECTION .progmem.data.asm
|
|
#define USE_LD 0
|
|
#define USE_LPM 1
|
|
#endif /* PM_BASE_ADDRESS */
|
|
|
|
#endif /* target AVR */
|
|
#endif /* ASM_DEFS_H */
|