macros.inc


/*
   Copyright (C) 1999 Marek Michalkiewicz <marekm@linux.org.pl>

   Permission to use, copy, modify, and distribute this software and
   its documentation for any purpose and without fee is hereby granted,
   without any conditions or restrictions.  This software is provided
   "as is" without express or implied warranty.
 */

#include "avr.inc"
#include "ctoasm.inc"

#ifndef EMPTY
  #define EMPTY ds.b 0  /* can't be empty - ava bug? */
#endif

#if FLASHEND > 0x1FFF  /* ATmega */
  #define VECTOR jmp
#else
  #define VECTOR rjmp
#endif

#ifndef BIG_CODE
  #if FLASHEND > 0xFFFF  /* ATmega103 */
    #define BIG_CODE 1
  #else
    #define BIG_CODE 0
  #endif
#endif

/*
   data-only pointers:
   - 16-bit (64K data), compatible with current avr-gcc "mode 0"
   - 24-bit (16M data), RAMPX and RAMPZ required "mode 1"
   generic pointers:
   - 16-bit (32K code + 32K data) "mode 2"
   - 24-bit (64K code + 64K data) "mode 3"
   - 24-bit (8M code + 64K data), RAMPZ for code only "mode 4"
   - 24-bit (8M code + 8M data), RAMPX for data, RAMPZ for code/data "mode 5"
   In generic pointers, code space is indicated by highest bit = 1.
   To use 24-bit pointers (PSImode, need changes to gcc), define BIG_PTR=1.
   This is the default on devices with big data space (RAMPX).
   To use generic pointers (16- or 24-bit), define GEN_PTR=1.
   This is the default if BIG_PTR=1 (reason: devices with big data
   space are likely to have plenty of code space too, so why not?).
   Devices with big data space (none yet) are detected by RAMPX defined.
   If only 16-bit pointers are used, RAMPX must be loaded with zero.
   Devices with big code space (ATmega103) are detected by device type.
   Devices that support lpm Rd, Z[+] (ATmega161) are detected by device
   type (ava doesn't support the new instructions yet; the instruction
   level used by ava should really be a set of separate defines, or
   bitmap for device features - for example: ATmega103 has ELPM but no
   MUL, ATmega161 has MUL but no ELPM, can't tell which is higher).

   Possible modes for each device (modes 0, 1 - access to data only):
   'a' = reduced capabilities (full size external SRAM not used, etc.)
   'b' = optimal, access to whole address space possible
   'c' = possible, but sub-optimal (pointers larger than address space)
   '-' = not possible (no RAMPX/RAMPZ registers present)

        Mode:	0	1		2	3	4	5

   AT90S2313	b	c		b	c	-	-
   AT90S2323	b	c		b	c	-	-
   AT90S2333	b	c		b	c	-	-
   AT90S2343	b	c		b	c	-	-
   ATtiny22	b	c		b	c	-	-
   AT90S4433	b	c		b	c	-	-
   AT90S4434	b	c		b	c	-	-
   AT90C8534	b	c		b	c	-	-
   AT90S8535	b	c		b	c	-	-

   AT90S4414	b	c		a	b	-	-
   AT90S8515	b	c		a	b	-	-
   ATmega161	b	c		a	b	-	-
   ATmega603	b	c		a	b	-	-

   ATmega103	b	c		a	a	b	-

   ???		a	b		a	a	a	b
 */

#ifndef BIG_PTR
  #ifdef RAMPX
    #define BIG_PTR 1
  #else
    #define BIG_PTR 0
  #endif
#endif

#ifndef GEN_PTR
  #if BIG_PTR
    #define GEN_PTR 1
  #else
    #define GEN_PTR 0
  #endif
#endif

#if GEN_PTR
  #if BIG_PTR
    #define GEN_TO_FLASH(hi, hhi) andi hhi, 0x7F
    #define JMP_IF_FLASH(hi, hhi, label)	\
	sbrc	hhi, 7				\
	rjmp	label
  #else
    #define GEN_TO_FLASH(hi, hhi) andi hi, 0x7F
    #define JMP_IF_FLASH(hi, hhi, label)	\
	sbrc	hi, 7				\
	rjmp	label
  #endif
#else
  #define JMP_IF_FLASH(hi, hhi, label) EMPTY
#endif

#ifdef RAMPX
  #if BIG_PTR
    #define OUT_RAMPX(hhi) out RAMPX, hhi
    #define OUT_RAMPZ(hhi) out RAMPZ, hhi
    #define DEC_XPTR ld __tmp_reg__, -X  /* handles RAMPX for us */
  #else
    /* On devices with big data space (none yet), RAMPX/RAMPZ
       must always be loaded (zero if using 16-bit pointers).  */
    #define OUT_RAMPX(hhi) out RAMPX, __zero_reg__
    #define OUT_RAMPZ(hhi) out RAMPZ, __zero_reg__
    #define DEC_XPTR sbiw XL, 1  /* faster if external SRAM is used */
  #endif
#else
  /* Devices with small data space, RAMPX not present.  */
  #define OUT_RAMPX(hhi) EMPTY
  #define OUT_RAMPZ(hhi) EMPTY
  #define DEC_XPTR sbiw XL, 1
#endif

#if USE_MOVW
  /* ATmega161 only, first register in (lo, hi) pair must be even.
     Idea for ava: replace invalid movw (odd register, or device
     without movw) with 2*mov, so that movw can always be used.  */
  #define LOAD_X(lo, hi) movw XL, lo
  #define LOAD_Z(lo, hi) movw ZL, lo
#else
  #define LOAD_X(lo, hi)		\
	mov	XL, lo			\
	mov	XH, hi

  #define LOAD_Z(lo, hi)		\
	mov	ZL, lo			\
	mov	ZH, hi
#endif

/* LOAD_X_CONST(p) loads constant P into pointer register [RAMPX:]X.  */
#ifdef RAMPX
  #define LOAD_X_CONST(p)		\
	ldi	XL, ((p) >> 16)		\
	out	RAMPX, XL		\
	ldi	XL, low(p)		\
	ldi	XH, high(p)
#else
  #define LOAD_X_CONST(p)		\
	ldi	XL, low(p)		\
	ldi	XH, high(p)
#endif

/*
   LPM_R0_ZPLUS_INIT is used before the loop to initialize RAMPZ
   for future devices with RAMPZ:Z auto-increment - [e]lpm r0, Z+.

   LPM_R0_ZPLUS_NEXT is used inside the loop to load a byte from
   the program memory at [RAMPZ:]Z to R0, and increment [RAMPZ:]Z.

   The argument in both macros is a register that contains the
   high byte (bits 23-16) of the address, bits 15-0 should be in
   the Z (r31:r30) register.  It can be any register except for:
   r0, r1 (__zero_reg__ - assumed to always contain 0), r30, r31.
 */

#if ATmega161
  #ifndef USE_LPM_ZPLUS
    #define USE_LPM_ZPLUS 1
  #endif
#endif

#if USE_LPM_ZPLUS
  #if BIG_CODE
    /* ELPM with RAMPZ:Z post-increment, load RAMPZ only once */
    #define LPM_R0_ZPLUS_INIT(hhi) out RAMPZ, hhi
    #define LPM_R0_ZPLUS_NEXT(hhi) dc.w 0x9007  /* elpm r0, Z+ */
  #else
    /* LPM with Z post-increment, max 64K, no RAMPZ (ATmega161) */
    #define LPM_R0_ZPLUS_INIT(hhi) EMPTY
    #define LPM_R0_ZPLUS_NEXT(hhi) dc.w	0x9005  /* lpm r0, Z+ */
  #endif
#else
  #if BIG_CODE
    /* ELPM without post-increment, load RAMPZ each time (ATmega103) */
    #define LPM_R0_ZPLUS_INIT(hhi) EMPTY
    #define LPM_R0_ZPLUS_NEXT(hhi)	\
	out	RAMPZ, hhi		\
	dc.w	0x95D8  /* elpm */	\
	adiw	ZL, 1			\
	adc	hhi, __zero_reg__
  #else
    /* LPM without post-increment, max 64K, no RAMPZ (AT90S*) */
    #define LPM_R0_ZPLUS_INIT(hhi) EMPTY
    #define LPM_R0_ZPLUS_NEXT(hhi)	\
	lpm				\
	adiw	ZL, 1
  #endif
#endif


Back