1  /* Copyright (C) 2019-2023 Free Software Foundation, Inc.
       2  
       3     This file is part of LIBF7, which is part of GCC.
       4  
       5     GCC is free software; you can redistribute it and/or modify it under
       6     the terms of the GNU General Public License as published by the Free
       7     Software Foundation; either version 3, or (at your option) any later
       8     version.
       9  
      10     GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11     WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13     for more details.
      14  
      15     Under Section 7 of GPL version 3, you are granted additional
      16     permissions described in the GCC Runtime Library Exception, version
      17     3.1, as published by the Free Software Foundation.
      18  
      19     You should have received a copy of the GNU General Public License and
      20     a copy of the GCC Runtime Library Exception along with this program;
      21     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      22     <http://www.gnu.org/licenses/>.  */
      23  
      24  #ifndef ASM_DEFS_H
      25  #define ASM_DEFS_H
      26  
      27  #ifdef __AVR__
      28  #ifdef __ASSEMBLER__
      29  /*****************************************************************/
      30  /* Stuff for Assembler-only                                      */
      31  /*****************************************************************/
      32  
      33  #if defined (__AVR_TINY__)
      34      #define __tmp_reg__  16
      35      #define __zero_reg__ 17
      36  #else
      37      #define __tmp_reg__  0
      38      #define __zero_reg__ 1
      39  #endif /* AVR_TINY */
      40  
      41  #define __SREG__ 0x3f
      42  #define __SP_L__ 0x3d
      43  #if defined (__AVR_HAVE_SPH__)
      44  #define __SP_H__ 0x3e
      45  #endif
      46  
      47  #if !defined ASM_DEFS_HAVE_DEFUN
      48  .macro DEFUN name
      49      .global \name
      50      .func \name
      51      \name:
      52  .endm
      53  
      54  .macro ENDF name
      55      .size \name, .-\name
      56      .endfunc
      57  .endm
      58  
      59  .macro LABEL name
      60      .global \name
      61      \name:
      62  .endm
      63  #endif /* HAVE_DEFUN */
      64  
      65  
      66  #if defined (__AVR_HAVE_JMP_CALL__)
      67      #define XCALL call
      68      #define XJMP  jmp
      69  #else
      70      #define XCALL rcall
      71      #define XJMP  rjmp
      72  #endif
      73  
      74  #if defined (__AVR_HAVE_EIJMP_EICALL__)
      75      #define XICALL  eicall
      76      #define XIJMP   eijmp
      77      #define PC_SIZE 3
      78  #else
      79      #define XICALL  icall
      80      #define XIJMP   ijmp
      81      #define PC_SIZE 2
      82  #endif
      83  
      84  .macro skipnext
      85      cpse r16, r16
      86  .endm
      87  
      88  /*
      89      Factor out support of MOVW.  Usage is like
      90  
      91          wmov  30, 24
      92  
      93      to move R25:R24 to R31:R30, i.e. plain register numbers
      94      are required and no register prefix 'R'.
      95  */
      96  
      97  #if defined (__AVR_HAVE_MOVW__)
      98  #define wmov    movw
      99  #else
     100      .macro  wmov dst src
     101      ..dst = \dst
     102      ..src = \src
     103      ..regno = 0
     104      .irp    reg,                                                \
     105              r0,  r1,  r2,  r3,  r4,  r5,  r6,   r7,  r8,  r9,   \
     106              r10, r11, r12, r13, r14, r15, r16, r17, r18, r19,   \
     107              r20, r21, r22, r23, r24, r25, r26, r27, r28, r29,   \
     108              r30, r31
     109          .ifc  \reg,\dst
     110              ..dst = ..regno
     111          .endif
     112          .ifc  \reg,\src
     113              ..src = ..regno
     114          .endif
     115          ..regno = ..regno + 1
     116      .endr
     117  
     118      ..regno = 0
     119  
     120      .irp    reg,                                                \
     121              R0,  R1,  R2,  R3,  R4,  R5,  R6,   R7,  R8,  R9,   \
     122              R10, R11, R12, R13, R14, R15, R16, R17, R18, R19,   \
     123              R20, R21, R22, R23, R24, R25, R26, R27, R28, R29,   \
     124              R30, R31
     125          .ifc  \reg,\dst
     126              ..dst = ..regno
     127          .endif
     128          .ifc  \reg,\src
     129              ..src = ..regno
     130          .endif
     131          ..regno = ..regno + 1
     132      .endr
     133  
     134      ..regno = 0
     135  
     136      .irp    reg,                        \
     137              X, x, XL, xl, Xl, xL, x, x  \
     138              Y, y, YL, yl, Yl, yL, y, y, \
     139              Z, z, ZL, zl, Zl, zL, z, z
     140          .ifc  \reg,\dst
     141              ..dst = (..regno / 8) + 26
     142          .endif
     143          .ifc  \reg,\src
     144              ..src = (..regno / 8) + 26
     145          .endif
     146          ..regno = ..regno + 1
     147      .endr
     148  
     149      mov     ..dst+0, ..src+0
     150      mov     ..dst+1, ..src+1
     151      .endm
     152  #endif /* MOVW */
     153  
     154  
     155  #if !defined (__AVR_TINY__)
     156  /*
     157      Convenience macro for easy use of __prologue_saves__ from libgcc.
     158      Push the N_PUSHED callee-saved registers  Y, R17, R16, R15, ...
     159      with 0 <= N_PUSHED <= 18.  The frame pointer (Y) is set up according
     160      to a frame size of N_FRAME.  Clobbers TMP_REG.
     161      For the code of __prologue_saves__ from libgcc see
     162      http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs.S?revision=267494&view=markup#l2159
     163  */
     164  
     165  .macro do_prologue_saves n_pushed n_frame=0
     166      ldi r26, lo8(\n_frame)
     167      ldi r27, hi8(\n_frame)
     168      ldi r30, lo8(gs(.L_prologue_saves.\@))
     169      ldi r31, hi8(gs(.L_prologue_saves.\@))
     170      XJMP __prologue_saves__ + ((18 - (\n_pushed)) * 2)
     171  .L_prologue_saves.\@:
     172  .endm
     173  
     174  /*
     175      Convenience macro for easy use of __epilogue_restores__ from libgcc.
     176      Undo the effect of __prologue_saves__.  Clobbers TMP_REG.
     177      For the code of __epilogue_restores__ from libgcc see
     178      http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs.S?revision=267494&view=markup#l2216
     179  */
     180  
     181  .macro do_epilogue_restores n_pushed n_frame=0
     182      in      r28, __SP_L__
     183  #ifdef __AVR_HAVE_SPH__
     184      in      r29, __SP_H__
     185  .if \n_frame > 63
     186      subi    r28, lo8(-\n_frame)
     187      sbci    r29, hi8(-\n_frame)
     188  .elseif \n_frame > 0
     189      adiw    r28, \n_frame
     190  .endif
     191  #else
     192      clr     r29
     193  .if \n_frame > 0
     194      subi    r28, lo8(-\n_frame)
     195  .endif
     196  #endif /* HAVE SPH */
     197      ldi     r30, \n_pushed
     198      XJMP __epilogue_restores__ + ((18 - (\n_pushed)) * 2)
     199  .endm
     200  
     201  #endif /* AVR_TINY */
     202  
     203  #else /* Assembler */
     204  /*****************************************************************/
     205  /* Space for C/C++ only Stuff                                    */
     206  /*****************************************************************/
     207  #endif /* Assembler */
     208  
     209  /*****************************************************************/
     210  /* Space for Generic Stuff (Assembler, C, C++)                   */
     211  /*****************************************************************/
     212  
     213  #ifdef __AVR_PM_BASE_ADDRESS__
     214      /*
     215          Devices with a linear address space:  Flash memory is seen in the
     216          RAM address space at an offset of __AVR_PM_BASE_ADDRESS__ and can
     217          be accessed by LD*.  This is the case for devices like ATtiny40
     218          (avrtiny) or ATtiny1616 and ATmega4808 (avrxmega3).  The default
     219          linker script locates .rodata in the .text output section and
     220          at the required offset.
     221      */
     222      #define RODATA_SECTION  .rodata.asm
     223      #define USE_LD  1
     224      #define USE_LPM 0
     225  #else /* PM_BASE_ADDRESS */
     226      /*
     227          No linear address space.  As .rodata is located in RAM, we have to
     228          use .progmem.data (located in flash) and LPM to read the data.
     229          This will also work for devices from avrxmega3.
     230      */
     231      #define RODATA_SECTION  .progmem.data.asm
     232      #define USE_LD  0
     233      #define USE_LPM 1
     234  #endif /* PM_BASE_ADDRESS */
     235  
     236  #endif /* target AVR */
     237  #endif /* ASM_DEFS_H */