/* codeavr.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator Atmel AVR */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "bpemu.h"
#include "nls.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "asmitree.h"
#include "asmcode.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "onoff_common.h"
#include "chartrans.h"
#include "codeavr.h"
#define RegBankSize 32
#define IOAreaStdSize 64
#define IOAreaExtSize (IOAreaStdSize + 160)
#define IOAreaExt2Size (IOAreaExtSize + 256)
#define BitFlag_Data 0x800000ul
#define BitFlag_IO 0x400000ul
typedef enum
{
eCoreNone
,
eCoreMinTiny
,
eCore90S1200
,
eCoreClassic
, /* AT90Sxxxx */
eCoreTiny
, /* ATtiny up to 8KB flash */
eCoreTiny16K
,
eCoreMega
} tCPUCore
;
#define MinCoreMask(c) ((Word)(0xffffu << (c)))
typedef struct
{
Word Code
;
Word CoreMask
;
} FixedOrder
;
/* Data types are a bit squeezed to make struct fit into fewer bytes:
lower four bits of FlashEnd are always 0xf and are not stored: */
typedef struct
{
const char *pName
;
Word FlashEndD16
, RAMSize
, EESize
, IOAreaSize
;
Boolean RegistersMapped
;
Byte Core
;
} tCPUProps
;
static FixedOrder
*FixedOrders
, *Reg1Orders
, *Reg2Orders
;
static Boolean WrapFlag
;
static LongInt ORMask
, SignMask
, CodeSegSize
;
static const tCPUProps
*pCurrCPUProps
;
static IntType CodeAdrIntType
,
DataAdrIntType
;
static const char WrapFlagName
[] = "WRAPMODE";
/*---------------------------------------------------------------------------*/
static LongInt CutAdr
(LongInt Adr
)
{
if ((Adr
& SignMask
) != 0)
return (Adr
| ORMask
);
else
return (Adr
& SegLimits
[SegCode
]);
}
static Boolean ChkMinCore
(tCPUCore MinCore
)
{
if (pCurrCPUProps
->Core
< MinCore
)
{
WrError
(ErrNum_InstructionNotSupported
);
return False
;
}
return True
;
}
static Boolean ChkCoreMask
(Word CoreMask
)
{
if ((1 << pCurrCPUProps
->Core
) & CoreMask
)
return True
;
WrError
(ErrNum_InstructionNotSupported
);
return False
;
}
static void DissectBit_AVR
(char *pDest
, size_t DestSize
, LargeWord Inp
)
{
LongWord BitSpec
= Inp
;
as_snprintf
(pDest
, DestSize
, "0x%0*x(%c).%d",
(BitSpec
& BitFlag_IO
) ? 2 : 3,
(unsigned)((BitSpec
>> 3) & 0xffff),
(BitSpec
& BitFlag_Data
) ? SegShorts
[SegData
]
: ((BitSpec
& BitFlag_IO
) ? SegShorts
[SegIO
] : SegShorts
[SegNone
]),
(int)(BitSpec
& 7));
}
/*---------------------------------------------------------------------------*/
/* Argument Decoders */
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, Word *pResult)
* \brief check wether argument is CPU register
* \param pArg source code argument
* \param pResult register # if it's a register
* \return True if it's a register
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore
(const char *pArg
, Word
*pResult
)
{
Boolean OK
;
int l
= strlen(pArg
);
if ((l
< 2) || (l
> 3) || (as_toupper
(*pArg
) != 'R'))
return False
;
*pResult
= ConstLongInt
(pArg
+ 1, &OK
, 10);
return (OK
&& ((*pResult
>= 16) || (pCurrCPUProps
->Core
!= eCoreMinTiny
))
&& (*pResult
< 32));
}
/*!------------------------------------------------------------------------
* \fn DissectReg_AVR(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - AVR variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_AVR
(char *pDest
, size_t DestSize
, tRegInt Value
, tSymbolSize InpSize
)
{
switch (InpSize
)
{
case eSymbolSize8Bit
:
as_snprintf
(pDest
, DestSize
, "R%u", (unsigned)Value
);
break;
default:
as_snprintf
(pDest
, DestSize
, "%d-%u", (int)InpSize
, (unsigned)Value
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, Word *pResult)
* \brief check wether argument is CPU register, including register aliases
* \param pArg source code argument
* \param pResult register # if it's a register
* \return True if it's a register
* ------------------------------------------------------------------------ */
static Boolean DecodeReg
(const tStrComp
*pArg
, Word
*pResult
)
{
tRegDescr RegDescr
;
tEvalResult EvalResult
;
tRegEvalResult RegEvalResult
;
if (DecodeRegCore
(pArg
->str.
p_str, pResult
))
return True
;
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSize8Bit
, True
);
*pResult
= RegDescr.
Reg;
return (RegEvalResult
== eIsReg
);
}
static Boolean DecodeMem
(char * Asc
, Word
*Erg
)
{
if (as_strcasecmp
(Asc
, "X") == 0) *Erg
= 0x1c;
else if (as_strcasecmp
(Asc
, "X+") == 0) *Erg
= 0x1d;
else if (as_strcasecmp
(Asc
, "-X") == 0) *Erg
= 0x1e;
else if (as_strcasecmp
(Asc
, "Y" ) == 0) *Erg
= 0x08;
else if (as_strcasecmp
(Asc
, "Y+") == 0) *Erg
= 0x19;
else if (as_strcasecmp
(Asc
, "-Y") == 0) *Erg
= 0x1a;
else if (as_strcasecmp
(Asc
, "Z" ) == 0) *Erg
= 0x00;
else if (as_strcasecmp
(Asc
, "Z+") == 0) *Erg
= 0x11;
else if (as_strcasecmp
(Asc
, "-Z") == 0) *Erg
= 0x12;
else return False
;
return True
;
}
static Boolean DecodeBitArg2
(const tStrComp
*pRegArg
, const tStrComp
*pBitArg
, LongWord
*pResult
)
{
tEvalResult EvalResult
;
LongWord Addr
;
*pResult
= EvalStrIntExpressionWithResult
(pBitArg
, UInt3
, &EvalResult
);
if (!EvalResult.
OK)
return False
;
Addr
= EvalStrIntExpressionWithResult
(pRegArg
, DataAdrIntType
, &EvalResult
);
if (!EvalResult.
OK)
return False
;
if (EvalResult.
AddrSpaceMask & (1 << SegIO
))
{
if (!mFirstPassUnknown
(EvalResult.
Flags) && !ChkRange
(Addr
, 0, IOAreaStdSize
- 1))
return False
;
*pResult
|= BitFlag_IO
| (Addr
& 0x3f) << 3;
return True
;
}
else
{
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
if (!mFirstPassUnknown
(EvalResult.
Flags) && !ChkRange
(Addr
, 0, SegLimits
[SegData
]))
return False
;
*pResult
|= ((EvalResult.
AddrSpaceMask & (1 << SegData
)) ? BitFlag_Data
: 0) | (Addr
& 0x1ff) << 3;
return True
;
}
}
static Boolean DecodeBitArg
(int Start
, int Stop
, LongWord
*pResult
)
{
if (Start
== Stop
)
{
char *pPos
= QuotPos
(ArgStr
[Start
].
str.
p_str, '.');
tEvalResult EvalResult
;
if (pPos
)
{
tStrComp RegArg
, BitArg
;
StrCompSplitRef
(&RegArg
, &BitArg
, &ArgStr
[Start
], pPos
);
return DecodeBitArg2
(&RegArg
, &BitArg
, pResult
);
}
*pResult
= EvalStrIntExpressionWithResult
(&ArgStr
[Start
], UInt16
, &EvalResult
);
if (EvalResult.
OK)
ChkSpace
(SegBData
, EvalResult.
AddrSpaceMask);
return EvalResult.
OK;
}
else if (Stop
== Start
+ 1)
return DecodeBitArg2
(&ArgStr
[Start
], &ArgStr
[Stop
], pResult
);
else
{
WrError
(ErrNum_WrongArgCnt
);
return False
;
}
}
static const LongWord
AllRegMask
= 0xfffffffful
,
UpperHalfRegMask
= 0xffff0000ul
,
Reg16_23Mask
= 0x00ff0000ul
,
EvenRegMask
= 0x55555555ul
,
UpperEightEvenRegMask
= 0x55000000ul
;
static Boolean DecodeArgReg
(unsigned ArgIndex
, Word
*pReg
, LongWord RegMask
)
{
Boolean Result
;
Result
= DecodeReg
(&ArgStr
[ArgIndex
], pReg
);
if (Result
&& !((RegMask
>> *pReg
) & 1))
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[ArgIndex
]);
return False
;
}
return Result
;
}
/*!------------------------------------------------------------------------
* \fn GetWordCodeAddress(tStrComp *pArg, tEvalResult *EvalResult)
* \brief decode argument as code address and divide by two if in byte mode
* \param pArg address argument
* \param pEvalResult returns OK/failure
* \return (word) address
* ------------------------------------------------------------------------ */
static LongInt GetWordCodeAddress
(tStrComp
*pArg
, tEvalResult
*pEvalResult
)
{
LongInt Result
;
Result
= EvalStrIntExpressionWithResult
(pArg
, CodeAdrIntType
, pEvalResult
);
if (pEvalResult
->OK
)
{
ChkSpace
(SegCode
, pEvalResult
->AddrSpaceMask
);
if (!CodeSegSize
)
{
if (mFirstPassUnknown
(pEvalResult
->Flags
))
Result
&= ~1ul
;
if (Result
& 1)
{
WrStrErrorPos
(ErrNum_NotAligned
, pArg
);
pEvalResult
->OK
= False
;
}
else
Result
>>= 1;
}
}
return Result
;
}
/*!------------------------------------------------------------------------
* \fn GetNextCodeAddress(void)
* \brief retrieve (word) address of next instruction
* \return (word) address
* ------------------------------------------------------------------------ */
static LongInt GetNextCodeAddress
(void)
{
LongInt Result
= EProgCounter
();
if (!CodeSegSize
)
Result
>>= 1;
return Result
+ 1;
}
/*---------------------------------------------------------------------------*/
/* Individual Decoders */
/* Pseudo Instructions */
static void DecodePORT
(Word Index
)
{
UNUSED
(Index
);
CodeEquate
(SegIO
, 0, 0x3f);
}
static void DecodeSFR
(Word Index
)
{
LargeWord Start
= (pCurrCPUProps
->RegistersMapped
? RegBankSize
: 0);
UNUSED
(Index
);
CodeEquate
(SegData
, Start
, Start
+ pCurrCPUProps
->IOAreaSize
);
}
static void AppendCode
(Word Code
)
{
if (CodeSegSize
)
WAsmCode
[CodeLen
++] = Code
;
else
{
BAsmCode
[CodeLen
++] = Lo
(Code
);
BAsmCode
[CodeLen
++] = Hi
(Code
);
}
}
/* No Argument */
static void DecodeFixed
(Word Index
)
{
const FixedOrder
*pOrder
= FixedOrders
+ Index
;
if (ChkArgCnt
(0, 0) && ChkCoreMask
(pOrder
->CoreMask
))
AppendCode
(pOrder
->Code
);
}
static void DecodeRES
(Word Index
)
{
Boolean OK
;
Integer Size
;
tSymbolFlags Flags
;
UNUSED
(Index
);
Size
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], Int16
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
)) WrError
(ErrNum_FirstPassCalc
);
if (OK
&& !mFirstPassUnknown
(Flags
))
{
DontPrint
= True
;
if (!Size
) WrError
(ErrNum_NullResMem
);
CodeLen
= Size
;
BookKeeping
();
}
}
static Word WordAcc
;
static Boolean WordAccFull
;
static void PlaceValue
(Word Value
, Boolean IsByte
)
{
if (ActPC
!= SegCode
)
{
BAsmCode
[CodeLen
++] = Value
;
WordAccFull
= False
;
}
else if (IsByte
)
{
if (CodeSegSize
)
{
Value
&= 0xff;
if (WordAccFull
)
AppendCode
(WordAcc
|= (Value
<< 8));
else
WordAcc
= Value
;
WordAccFull
= !WordAccFull
;
}
else
{
BAsmCode
[CodeLen
++] = Value
;
WordAccFull
= False
;
}
}
else
{
if (CodeSegSize
)
AppendCode
(Value
);
else
{
BAsmCode
[CodeLen
++] = Lo
(Value
);
BAsmCode
[CodeLen
++] = Hi
(Value
);
}
WordAccFull
= False
;
}
}
static void DecodeDATA_AVR
(Word Index
)
{
Integer Trans
;
TempResult t
;
LongInt MinV
, MaxV
;
UNUSED
(Index
);
as_tempres_ini
(&t
);
MaxV
= ((ActPC
== SegCode
) && !Packing
) ? 65535 : 255;
MinV
= (-((MaxV
+ 1) >> 1));
WordAccFull
= FALSE
;
if (ChkArgCnt
(1, ArgCntMax
))
{
Boolean OK
= True
;
const tStrComp
*pArg
;
forallargs
(pArg
, OK
)
{
EvalStrExpression
(pArg
, &t
);
if (mFirstPassUnknown
(t.
Flags) && (t.
Typ == TempInt
)) t.
Contents.
Int &= MaxV
;
switch (t.
Typ)
{
case TempString
:
{
int z2
;
if (MultiCharToInt
(&t
, 2))
goto ToInt
;
if (as_chartrans_xlate_nonz_dynstr
(CurrTransTable
->p_table
, &t.
Contents.
str, pArg
))
OK
= False
;
else
for (z2
= 0; z2
< (int)t.
Contents.
str.
len; z2
++)
{
Trans
= ((usint
) t.
Contents.
str.
p_str[z2
]) & 0xff;
PlaceValue
(Trans
, True
);
}
break;
}
ToInt
:
case TempInt
:
if (ChkRange
(t.
Contents.
Int, MinV
, MaxV
))
PlaceValue
(t.
Contents.
Int, Packing
);
break;
case TempFloat
:
WrStrErrorPos
(ErrNum_StringOrIntButFloat
, pArg
);
/* fall-through */
default:
OK
= False
;
}
}
if (!OK
)
CodeLen
= 0;
else if (WordAccFull
)
{
WrError
(ErrNum_PaddingAdded
);
AppendCode
(WordAcc
);
}
}
as_tempres_free
(&t
);
}
/* one register 0..31 */
static void DecodeReg1
(Word Index
)
{
const FixedOrder
*pOrder
= Reg1Orders
+ Index
;
Word Reg
;
if (ChkArgCnt
(1, 1)
&& ChkCoreMask
(pOrder
->CoreMask
)
&& DecodeArgReg
(1, &Reg
, AllRegMask
))
AppendCode
(pOrder
->Code
| (Reg
<< 4));
}
/* two registers 0..31 */
static void DecodeReg2
(Word Index
)
{
const FixedOrder
*pOrder
= Reg2Orders
+ Index
;
Word Reg1
, Reg2
;
if (ChkArgCnt
(2, 2)
&& ChkCoreMask
(pOrder
->CoreMask
)
&& DecodeArgReg
(1, &Reg1
, AllRegMask
)
&& DecodeArgReg
(2, &Reg2
, AllRegMask
))
AppendCode
(pOrder
->Code
| (Reg2
& 15) | (Reg1
<< 4) | ((Reg2
& 16) << 5));
}
/* one register 0..31 with itself */
static void DecodeReg3
(Word Code
)
{
Word Reg
;
if (ChkArgCnt
(1, 1) && DecodeArgReg
(1, &Reg
, AllRegMask
))
AppendCode
(Code
| (Reg
& 15) | (Reg
<< 4) | ((Reg
& 16) << 5));
}
/* immediate with register */
static void DecodeImm
(Word Code
)
{
Word Reg
, Const
;
Boolean OK
;
if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &Reg
, UpperHalfRegMask
))
{
Const
= EvalStrIntExpression
(&ArgStr
[2], Int8
, &OK
);
if (OK
)
AppendCode
(Code
| ((Const
& 0xf0) << 4) | (Const
& 0x0f) | ((Reg
& 0x0f) << 4));
}
}
static void DecodeADIW
(Word Index
)
{
Word Reg
, Const
;
Boolean OK
;
if (ChkArgCnt
(2, 2)
&& ChkMinCore
(eCoreClassic
)
&& DecodeArgReg
(1, &Reg
, UpperEightEvenRegMask
))
{
Const
= EvalStrIntExpression
(&ArgStr
[2], UInt6
, &OK
);
if (OK
)
AppendCode
(0x9600 | Index
| ((Reg
& 6) << 3) | (Const
& 15) | ((Const
& 0x30) << 2));
}
}
/* transfer operations */
static void DecodeLDST
(Word Index
)
{
int RegI
, MemI
;
Word Reg
, Mem
;
if (ChkArgCnt
(2, 2))
{
RegI
= Index
? 2 : 1; /* ST */
MemI
= 3 - RegI
;
if (!DecodeArgReg
(RegI
, &Reg
, AllRegMask
));
else if (!DecodeMem
(ArgStr
[MemI
].
str.
p_str, &Mem
)) WrError
(ErrNum_InvAddrMode
);
else if ((pCurrCPUProps
->Core
== eCore90S1200
) && (Mem
!= 0)) WrError
(ErrNum_AddrMustBeAligned
);
else
{
AppendCode
(0x8000 | Index
| (Reg
<< 4) | (Mem
& 0x0f) | ((Mem
& 0x10) << 8));
if (((Mem
>= 0x1d) && (Mem
<= 0x1e) && (Reg
>= 26) && (Reg
<= 27)) /* X+/-X with X */
|| ((Mem
>= 0x19) && (Mem
<= 0x1a) && (Reg
>= 28) && (Reg
<= 29)) /* Y+/-Y with Y */
|| ((Mem
>= 0x11) && (Mem
<= 0x12) && (Reg
>= 30) && (Reg
<= 31))) /* Z+/-Z with Z */
WrError
(ErrNum_Unpredictable
);
}
}
}
static void DecodeLDDSTD
(Word Index
)
{
int RegI
, MemI
;
Word Reg
, Disp
;
Boolean OK
;
if (ChkArgCnt
(2, 2)
&& ChkMinCore
(eCoreClassic
))
{
char RegChar
;
RegI
= Index
? 2 : 1; /* STD */
MemI
= 3 - RegI
;
RegChar
= *ArgStr
[MemI
].
str.
p_str;
OK
= True
;
if (as_toupper
(RegChar
) == 'Y') Index
+= 8;
else if (as_toupper
(RegChar
) == 'Z');
else OK
= False
;
if (!OK
) WrError
(ErrNum_InvAddrMode
);
else if (DecodeArgReg
(RegI
, &Reg
, AllRegMask
))
{
*ArgStr
[MemI
].
str.
p_str = '0';
Disp
= EvalStrIntExpression
(&ArgStr
[MemI
], UInt6
, &OK
);
*ArgStr
[MemI
].
str.
p_str = RegChar
;
if (OK
)
AppendCode
(0x8000 | Index
| (Reg
<< 4) | (Disp
& 7) | ((Disp
& 0x18) << 7) | ((Disp
& 0x20) << 8));
}
}
}
static void DecodeINOUT
(Word Index
)
{
int RegI
, MemI
;
Word Reg
, Mem
;
if (ChkArgCnt
(2, 2))
{
RegI
= Index
? 2 : 1; /* OUT */
MemI
= 3 - RegI
;
if (DecodeArgReg
(RegI
, &Reg
, AllRegMask
))
{
tEvalResult EvalResult
;
Mem
= EvalStrIntExpressionWithResult
(&ArgStr
[MemI
], UInt6
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegIO
, EvalResult.
AddrSpaceMask);
AppendCode
(0xb000 | Index
| (Reg
<< 4) | (Mem
& 0x0f) | ((Mem
& 0xf0) << 5));
}
}
}
}
static void DecodeLDSSTS
(Word Index
)
{
int RegI
, MemI
;
Word Reg
;
if (ChkArgCnt
(2, 2)
&& ChkCoreMask
(MinCoreMask
(eCoreClassic
) | (1 << eCoreMinTiny
)))
{
RegI
= Index
? 2 : 1; /* STS */
MemI
= 3 - RegI
;
if (DecodeArgReg
(RegI
, &Reg
, AllRegMask
))
{
tEvalResult EvalResult
;
Word Address
= EvalStrIntExpressionWithResult
(&ArgStr
[MemI
], UInt16
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
AppendCode
(0x9000 | Index
| (Reg
<< 4));
AppendCode
(Address
);
}
}
}
}
/* bit operations */
static void DecodeBCLRSET
(Word Index
)
{
Word Bit
;
Boolean OK
;
if (ChkArgCnt
(1, 1))
{
Bit
= EvalStrIntExpression
(&ArgStr
[1], UInt3
, &OK
);
if (OK
)
AppendCode
(0x9408 | (Bit
<< 4) | Index
);
}
}
static void DecodeBit
(Word Code
)
{
Word Reg
, Bit
;
Boolean OK
;
if (!ChkArgCnt
(2, 2));
else if (DecodeArgReg
(1, &Reg
, AllRegMask
))
{
Bit
= EvalStrIntExpression
(&ArgStr
[2], UInt3
, &OK
);
if (OK
)
AppendCode
(Code
| (Reg
<< 4) | Bit
);
}
}
static void DecodeCBR
(Word Index
)
{
Word Reg
, Mask
;
Boolean OK
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &Reg
, UpperHalfRegMask
))
{
Mask
= EvalStrIntExpression
(&ArgStr
[2], Int8
, &OK
) ^ 0xff;
if (OK
)
AppendCode
(0x7000 | ((Mask
& 0xf0) << 4) | (Mask
& 0x0f) | ((Reg
& 0x0f) << 4));
}
}
static void DecodeSER
(Word Index
)
{
Word Reg
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 1) && DecodeArgReg
(1, &Reg
, UpperHalfRegMask
))
AppendCode
(0xef0f | ((Reg
& 0x0f) << 4));
}
static void DecodePBit
(Word Code
)
{
LongWord BitSpec
;
if (DecodeBitArg
(1, ArgCnt
, &BitSpec
))
{
Word Bit
= BitSpec
& 7,
Adr
= (BitSpec
>> 3) & 0xffff;
if (BitSpec
& BitFlag_Data
) WrError
(ErrNum_WrongSegment
);
if (ChkRange
(Adr
, 0, 31))
AppendCode
(Code
| Bit
| (Adr
<< 3));
}
}
/* branches */
static void DecodeRel
(Word Code
)
{
LongInt AdrInt
;
tEvalResult EvalResult
;
if (ChkArgCnt
(1, 1))
{
AdrInt
= GetWordCodeAddress
(&ArgStr
[1], &EvalResult
) - GetNextCodeAddress
();
if (EvalResult.
OK)
{
if (WrapFlag
) AdrInt
= CutAdr
(AdrInt
);
if (!mSymbolQuestionable
(EvalResult.
Flags) && ((AdrInt
< -64) || (AdrInt
> 63))) WrError
(ErrNum_JmpDistTooBig
);
else
AppendCode
(Code
| ((AdrInt
& 0x7f) << 3));
}
}
}
static void DecodeBRBSBC
(Word Index
)
{
Word Bit
;
LongInt AdrInt
;
tEvalResult EvalResult
;
if (ChkArgCnt
(2, 2))
{
Bit
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt3
, &EvalResult
);
if (EvalResult.
OK)
{
AdrInt
= GetWordCodeAddress
(&ArgStr
[2], &EvalResult
) - GetNextCodeAddress
();
if (EvalResult.
OK)
{
if (WrapFlag
) AdrInt
= CutAdr
(AdrInt
);
if (!mSymbolQuestionable
(EvalResult.
Flags) && ((AdrInt
< -64) || (AdrInt
> 63))) WrError
(ErrNum_JmpDistTooBig
);
else
AppendCode
(0xf000 | Index
| ((AdrInt
& 0x7f) << 3) | Bit
);
}
}
}
}
static void DecodeJMPCALL
(Word Index
)
{
LongInt AdrInt
;
tEvalResult EvalResult
;
if (ChkArgCnt
(1, 1)
&& ChkMinCore
(eCoreTiny16K
))
{
AdrInt
= GetWordCodeAddress
(&ArgStr
[1], &EvalResult
);
if (EvalResult.
OK)
{
AppendCode
(0x940c | Index
| ((AdrInt
& 0x3e0000) >> 13) | ((AdrInt
& 0x10000) >> 16));
AppendCode
(AdrInt
& 0xffff);
}
}
}
static void DecodeRJMPCALL
(Word Index
)
{
LongInt AdrInt
;
tEvalResult EvalResult
;
if (ChkArgCnt
(1, 1))
{
AdrInt
= GetWordCodeAddress
(&ArgStr
[1], &EvalResult
) - GetNextCodeAddress
();
if (EvalResult.
OK)
{
if (WrapFlag
) AdrInt
= CutAdr
(AdrInt
);
if (!mSymbolQuestionable
(EvalResult.
Flags) && ((AdrInt
< -2048) || (AdrInt
> 2047))) WrError
(ErrNum_JmpDistTooBig
);
else
AppendCode
(0xc000 | Index
| (AdrInt
& 0xfff));
}
}
}
static void DecodeMULS
(Word Index
)
{
Word Reg1
, Reg2
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkMinCore
(eCoreMega
)
&& DecodeArgReg
(1, &Reg1
, UpperHalfRegMask
)
&& DecodeArgReg
(2, &Reg2
, UpperHalfRegMask
))
AppendCode
(0x0200 | ((Reg1
& 15) << 4) | (Reg2
& 15));
}
static void DecodeMegaMUL
(Word Index
)
{
Word Reg1
, Reg2
;
if (ChkArgCnt
(2, 2)
&& ChkMinCore
(eCoreMega
)
&& DecodeArgReg
(1, &Reg1
, Reg16_23Mask
)
&& DecodeArgReg
(2, &Reg2
, Reg16_23Mask
))
AppendCode
(Index
| ((Reg1
& 7) << 4) | (Reg2
& 7));
}
static void DecodeMOVW
(Word Index
)
{
Word Reg1
, Reg2
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkMinCore
(eCoreTiny
)
&& DecodeArgReg
(1, &Reg1
, EvenRegMask
)
&& DecodeArgReg
(2, &Reg2
, EvenRegMask
))
AppendCode
(0x0100 | ((Reg1
>> 1) << 4) | (Reg2
>> 1));
}
static void DecodeLPM
(Word Index
)
{
Word Reg
, Adr
;
UNUSED
(Index
);
if (!ArgCnt
)
{
if (ChkMinCore
(eCoreClassic
))
AppendCode
(0x95c8);
}
else if (ArgCnt
== 2)
{
if (!ChkMinCore
(eCoreTiny
));
else if (!DecodeArgReg
(1, &Reg
, AllRegMask
));
else if (!DecodeMem
(ArgStr
[2].
str.
p_str, &Adr
)) WrError
(ErrNum_InvAddrMode
);
else if ((Adr
!= 0x00) && (Adr
!= 0x11)) WrError
(ErrNum_InvAddrMode
);
else
{
if (((Reg
== 30) || (Reg
== 31)) && (Adr
== 0x11)) WrError
(ErrNum_Unpredictable
);
AppendCode
(0x9004 | (Reg
<< 4) | (Adr
& 1));
}
}
else
(void)ChkArgCnt
(2, 2);
}
static void DecodeELPM
(Word Index
)
{
Word Reg
, Adr
;
UNUSED
(Index
);
if (!ChkMinCore
(eCoreMega
));
else if (!ArgCnt
)
AppendCode
(0x95d8);
else if (!ChkArgCnt
(2, 2));
else if (!DecodeArgReg
(1, &Reg
, AllRegMask
));
else if (!DecodeMem
(ArgStr
[2].
str.
p_str, &Adr
)) WrError
(ErrNum_InvAddrMode
);
else if ((Adr
!= 0x00) && (Adr
!= 0x11)) WrError
(ErrNum_InvAddrMode
);
else
{
if (((Reg
== 30) || (Reg
== 31)) && (Adr
== 0x11)) WrError
(ErrNum_Unpredictable
);
AppendCode
(0x9006 | (Reg
<< 4) | (Adr
& 1));
}
}
static void DecodeBIT
(Word Code
)
{
LongWord BitSpec
;
UNUSED
(Code
);
if (DecodeBitArg
(1, ArgCnt
, &BitSpec
))
{
*ListLine
= '=';
DissectBit_AVR
(ListLine
+ 1, STRINGSIZE
- 3, BitSpec
);
PushLocHandle
(-1);
EnterIntSymbol
(&LabPart
, BitSpec
, SegBData
, False
);
PopLocHandle
();
if (MakeUseList
)
{
if (AddChunk
(SegChunks
+ SegBData
, BitSpec
, 1, False
))
WrError
(ErrNum_Overlap
);
}
}
}
/*---------------------------------------------------------------------------*/
/* Dynamic Code Table Handling */
static void AddFixed
(const char *NName
, Word NMin
, Word NCode
)
{
order_array_rsv_end
(FixedOrders
, FixedOrder
);
FixedOrders
[InstrZ
].
Code = NCode
;
FixedOrders
[InstrZ
].
CoreMask = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeFixed
);
}
static void AddReg1
(const char *NName
, Word NMin
, Word NCode
)
{
order_array_rsv_end
(Reg1Orders
, FixedOrder
);
Reg1Orders
[InstrZ
].
Code = NCode
;
Reg1Orders
[InstrZ
].
CoreMask = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeReg1
);
}
static void AddReg2
(const char *NName
, Word NMin
, Word NCode
)
{
order_array_rsv_end
(Reg2Orders
, FixedOrder
);
Reg2Orders
[InstrZ
].
Code = NCode
;
Reg2Orders
[InstrZ
].
CoreMask = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeReg2
);
}
static void AddReg3
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeReg3
);
}
static void AddImm
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeImm
);
}
static void AddRel
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeRel
);
}
static void AddBit
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeBit
);
}
static void AddPBit
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodePBit
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(203);
InstrZ
= 0;
AddFixed
("IJMP" , MinCoreMask
(eCoreClassic
) | (1 << eCoreMinTiny
), 0x9409);
AddFixed
("ICALL", MinCoreMask
(eCoreClassic
) | (1 << eCoreMinTiny
), 0x9509);
AddFixed
("RET" , MinCoreMask
(eCoreMinTiny
), 0x9508); AddFixed
("RETI" , MinCoreMask
(eCoreMinTiny
), 0x9518);
AddFixed
("SEC" , MinCoreMask
(eCoreMinTiny
), 0x9408);
AddFixed
("CLC" , MinCoreMask
(eCoreMinTiny
), 0x9488); AddFixed
("SEN" , MinCoreMask
(eCoreMinTiny
), 0x9428);
AddFixed
("CLN" , MinCoreMask
(eCoreMinTiny
), 0x94a8); AddFixed
("SEZ" , MinCoreMask
(eCoreMinTiny
), 0x9418);
AddFixed
("CLZ" , MinCoreMask
(eCoreMinTiny
), 0x9498); AddFixed
("SEI" , MinCoreMask
(eCoreMinTiny
), 0x9478);
AddFixed
("CLI" , MinCoreMask
(eCoreMinTiny
), 0x94f8); AddFixed
("SES" , MinCoreMask
(eCoreMinTiny
), 0x9448);
AddFixed
("CLS" , MinCoreMask
(eCoreMinTiny
), 0x94c8); AddFixed
("SEV" , MinCoreMask
(eCoreMinTiny
), 0x9438);
AddFixed
("CLV" , MinCoreMask
(eCoreMinTiny
), 0x94b8); AddFixed
("SET" , MinCoreMask
(eCoreMinTiny
), 0x9468);
AddFixed
("CLT" , MinCoreMask
(eCoreMinTiny
), 0x94e8); AddFixed
("SEH" , MinCoreMask
(eCoreMinTiny
), 0x9458);
AddFixed
("CLH" , MinCoreMask
(eCoreMinTiny
), 0x94d8); AddFixed
("NOP" , MinCoreMask
(eCoreMinTiny
), 0x0000);
AddFixed
("SLEEP", MinCoreMask
(eCoreMinTiny
), 0x9588); AddFixed
("WDR" , MinCoreMask
(eCoreMinTiny
), 0x95a8);
AddFixed
("EIJMP", MinCoreMask
(eCoreMega
), 0x9419); AddFixed
("EICALL", MinCoreMask
(eCoreMega
), 0x9519);
AddFixed
("SPM" , MinCoreMask
(eCoreTiny
), 0x95e8);
AddFixed
("BREAK" , MinCoreMask
(eCoreTiny
) | (1 << eCoreMinTiny
), 0x9598);
InstrZ
= 0;
AddReg1
("COM" , MinCoreMask
(eCoreMinTiny
), 0x9400); AddReg1
("NEG" , MinCoreMask
(eCoreMinTiny
), 0x9401);
AddReg1
("INC" , MinCoreMask
(eCoreMinTiny
), 0x9403); AddReg1
("DEC" , MinCoreMask
(eCoreMinTiny
), 0x940a);
AddReg1
("PUSH" , MinCoreMask
(eCoreClassic
) | (1 << eCoreMinTiny
), 0x920f);
AddReg1
("POP" , MinCoreMask
(eCoreClassic
) | (1 << eCoreMinTiny
), 0x900f);
AddReg1
("LSR" , MinCoreMask
(eCoreMinTiny
), 0x9406); AddReg1
("ROR" , MinCoreMask
(eCoreMinTiny
), 0x9407);
AddReg1
("ASR" , MinCoreMask
(eCoreMinTiny
), 0x9405); AddReg1
("SWAP" , MinCoreMask
(eCoreMinTiny
), 0x9402);
InstrZ
= 0;
AddReg2
("ADD" , MinCoreMask
(eCoreMinTiny
), 0x0c00); AddReg2
("ADC" , MinCoreMask
(eCoreMinTiny
), 0x1c00);
AddReg2
("SUB" , MinCoreMask
(eCoreMinTiny
), 0x1800); AddReg2
("SBC" , MinCoreMask
(eCoreMinTiny
), 0x0800);
AddReg2
("AND" , MinCoreMask
(eCoreMinTiny
), 0x2000); AddReg2
("OR" , MinCoreMask
(eCoreMinTiny
), 0x2800);
AddReg2
("EOR" , MinCoreMask
(eCoreMinTiny
), 0x2400); AddReg2
("CPSE" , MinCoreMask
(eCoreMinTiny
), 0x1000);
AddReg2
("CP" , MinCoreMask
(eCoreMinTiny
), 0x1400); AddReg2
("CPC" , MinCoreMask
(eCoreMinTiny
), 0x0400);
AddReg2
("MOV" , MinCoreMask
(eCoreMinTiny
), 0x2c00); AddReg2
("MUL" , MinCoreMask
(eCoreMega
), 0x9c00);
AddReg3
("CLR" , 0x2400); AddReg3
("TST" , 0x2000); AddReg3
("LSL" , 0x0c00);
AddReg3
("ROL" , 0x1c00);
AddImm
("SUBI" , 0x5000); AddImm
("SBCI" , 0x4000); AddImm
("ANDI" , 0x7000);
AddImm
("ORI" , 0x6000); AddImm
("SBR" , 0x6000); AddImm
("CPI" , 0x3000);
AddImm
("LDI" , 0xe000);
AddRel
("BRCC" , 0xf400); AddRel
("BRCS" , 0xf000); AddRel
("BREQ" , 0xf001);
AddRel
("BRGE" , 0xf404); AddRel
("BRSH" , 0xf400); AddRel
("BRID" , 0xf407);
AddRel
("BRIE" , 0xf007); AddRel
("BRLO" , 0xf000); AddRel
("BRLT" , 0xf004);
AddRel
("BRMI" , 0xf002); AddRel
("BRNE" , 0xf401); AddRel
("BRHC" , 0xf405);
AddRel
("BRHS" , 0xf005); AddRel
("BRPL" , 0xf402); AddRel
("BRTC" , 0xf406);
AddRel
("BRTS" , 0xf006); AddRel
("BRVC" , 0xf403); AddRel
("BRVS" , 0xf003);
AddBit
("BLD" , 0xf800); AddBit
("BST" , 0xfa00);
AddBit
("SBRC" , 0xfc00); AddBit
("SBRS" , 0xfe00);
AddPBit
("CBI" , 0x9800); AddPBit
("SBI" , 0x9a00);
AddPBit
("SBIC", 0x9900); AddPBit
("SBIS", 0x9b00);
AddInstTable
(InstTable
, "ADIW", 0x0000, DecodeADIW
);
AddInstTable
(InstTable
, "SBIW", 0x0100, DecodeADIW
);
AddInstTable
(InstTable
, "LD", 0x0000, DecodeLDST
);
AddInstTable
(InstTable
, "ST", 0x0200, DecodeLDST
);
AddInstTable
(InstTable
, "LDD", 0x0000, DecodeLDDSTD
);
AddInstTable
(InstTable
, "STD", 0x0200, DecodeLDDSTD
);
AddInstTable
(InstTable
, "IN" , 0x0000, DecodeINOUT
);
AddInstTable
(InstTable
, "OUT", 0x0800, DecodeINOUT
);
AddInstTable
(InstTable
, "LDS", 0x0000, DecodeLDSSTS
);
AddInstTable
(InstTable
, "STS", 0x0200, DecodeLDSSTS
);
AddInstTable
(InstTable
, "BCLR", 0x0080, DecodeBCLRSET
);
AddInstTable
(InstTable
, "BSET", 0x0000, DecodeBCLRSET
);
AddInstTable
(InstTable
, "CBR", 0, DecodeCBR
);
AddInstTable
(InstTable
, "SER", 0, DecodeSER
);
AddInstTable
(InstTable
, "BRBC", 0x0400, DecodeBRBSBC
);
AddInstTable
(InstTable
, "BRBS", 0x0000, DecodeBRBSBC
);
AddInstTable
(InstTable
, "JMP" , 0, DecodeJMPCALL
);
AddInstTable
(InstTable
, "CALL", 2, DecodeJMPCALL
);
AddInstTable
(InstTable
, "RJMP" , 0x0000, DecodeRJMPCALL
);
AddInstTable
(InstTable
, "RCALL", 0x1000, DecodeRJMPCALL
);
AddInstTable
(InstTable
, "PORT", 0, DecodePORT
);
AddInstTable
(InstTable
, "SFR" , 0, DecodeSFR
);
AddInstTable
(InstTable
, "RES" , 0, DecodeRES
);
AddInstTable
(InstTable
, "REG" , 0, CodeREG
);
AddInstTable
(InstTable
, "BIT" , 0, DecodeBIT
);
AddInstTable
(InstTable
, "MULS", 0, DecodeMULS
);
AddInstTable
(InstTable
, "MULSU" , 0x0300, DecodeMegaMUL
);
AddInstTable
(InstTable
, "FMUL" , 0x0308, DecodeMegaMUL
);
AddInstTable
(InstTable
, "FMULS" , 0x0380, DecodeMegaMUL
);
AddInstTable
(InstTable
, "FMULSU", 0x0388, DecodeMegaMUL
);
AddInstTable
(InstTable
, "MOVW", 0, DecodeMOVW
);
AddInstTable
(InstTable
, "LPM" , 0, DecodeLPM
);
AddInstTable
(InstTable
, "ELPM", 0, DecodeELPM
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(FixedOrders
);
order_array_free
(Reg1Orders
);
order_array_free
(Reg2Orders
);
}
/*---------------------------------------------------------------------------*/
static void MakeCode_AVR
(void)
{
CodeLen
= 0; DontPrint
= False
;
if (Memo
("")) return;
/* instructions that do not require word alignment in byte mode */
if (Memo
("DATA"))
{
DecodeDATA_AVR
(0);
return;
}
if (DecodeIntelPseudo
(False
))
return;
/* All other instructions must be on an even address in byte mode.
In other words, they may not cross flash word boundaries: */
if (!CodeSegSize
)
{
if (Odd
(EProgCounter
()))
{
if (DoPadding
)
InsertPadding
(1, False
);
else
WrError
(ErrNum_AddrNotAligned
);
}
}
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_AVR
(void)
{
return (Memo
("PORT")
|| Memo
("REG")
|| Memo
("SFR")
|| Memo
("BIT"));
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_AVR(char *pArg, TempResult *pResult)
* \brief parse for built-in symbols
* \param pArg source argument
* \param pResult possible result
* ------------------------------------------------------------------------ */
static void InternSymbol_AVR
(char *pArg
, TempResult
*pResult
)
{
Word RegValue
;
if (DecodeRegCore
(pArg
, &RegValue
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= eSymbolSize8Bit
;
pResult
->Contents.
RegDescr.
Reg = RegValue
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_AVR
;
pResult
->Contents.
RegDescr.
compare = NULL
;
}
}
static Boolean ChkZeroArg
(void)
{
return (0 == ArgCnt
);
}
static void SwitchTo_AVR
(void *pUser
)
{
pCurrCPUProps
= (const tCPUProps
*)pUser
;
TurnWords
= False
;
SetIntConstMode
(eIntConstModeC
);
SetIsOccupiedFnc
= ChkZeroArg
;
PCSymbol
= "*";
HeaderID
= CodeSegSize
? 0x3b : 0x3d;
NOPCode
= 0x0000;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= (1 << SegCode
) | (1 << SegData
) | (1 << SegIO
);
Grans
[SegCode
] = ListGrans
[SegCode
] = 1 << CodeSegSize
; SegInits
[SegCode
] = 0;
Grans
[SegData
] = 1; ListGrans
[SegData
] = 1; SegInits
[SegData
] = 32;
Grans
[SegIO
] = 1; ListGrans
[SegIO
] = 1; SegInits
[SegIO
] = 0; SegLimits
[SegIO
] = 0x3f;
if (pCurrCPUProps
->EESize
)
{
ValidSegs
|= (1 << SegEEData
);
SegLimits
[SegEEData
] = pCurrCPUProps
->EESize
;
Grans
[SegEEData
] = 1; ListGrans
[SegEEData
] = 1; SegInits
[SegEEData
] = 0;
}
SegLimits
[SegCode
] = ((LongWord
)pCurrCPUProps
->FlashEndD16
) << 4 | 0xf;
if (!CodeSegSize
)
{
SegLimits
[SegCode
] = (SegLimits
[SegCode
] << 1) + 1;
AddONOFF
(DoPaddingName
, &DoPadding
, DoPaddingName
, False
);
}
SegLimits
[SegData
] = (pCurrCPUProps
->RegistersMapped
? RegBankSize
: 0)
+ pCurrCPUProps
->IOAreaSize
+ pCurrCPUProps
->RAMSize
- 1;
CodeAdrIntType
= GetSmallestUIntType
(SegLimits
[SegCode
]);
DataAdrIntType
= GetSmallestUIntType
(SegLimits
[SegData
]);
SignMask
= (SegLimits
[SegCode
] + 1) >> 1;
ORMask
= ((LongInt
) - 1) - SegLimits
[SegCode
];
onoff_packing_add
(False
);
AddONOFF
("WRAPMODE", &WrapFlag
, WrapFlagName
, False
);
SetFlag
(&WrapFlag
, WrapFlagName
, False
);
MakeCode
= MakeCode_AVR
;
IsDef
= IsDef_AVR
;
InternSymbol
= InternSymbol_AVR
;
DissectReg
= DissectReg_AVR
;
SwitchFrom
= DeinitFields
;
DissectBit
= DissectBit_AVR
;
InitFields
();
}
static const tCPUProps CPUProps
[] =
{
{ "AT90S1200" , 0x01f, 0x0000, 0x003f, IOAreaStdSize
, True
, eCore90S1200
},
{ "AT90S2313" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90S2323" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90S2333" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreClassic
}, /* == ATtiny22 */
{ "AT90S2343" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90S4414" , 0x07f, 0x0100, 0x00ff, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90S4433" , 0x07f, 0x0080, 0x00ff, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90S4434" , 0x07f, 0x0100, 0x00ff, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90S8515" , 0x0ff, 0x0200, 0x01ff, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90C8534" , 0x0ff, 0x0100, 0x01ff, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90S8535" , 0x0ff, 0x0200, 0x01ff, IOAreaStdSize
, True
, eCoreClassic
},
{ "AT90USB646" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "AT90USB647" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "AT90USB1286" , 0xfff, 0x2000, 0x0fff, IOAreaExtSize
, True
, eCoreMega
},
{ "AT90USB1287" , 0xfff, 0x2000, 0x0fff, IOAreaExtSize
, True
, eCoreMega
},
{ "AT43USB355" , 0x2ff, 0x0400, 0x0000, 0x2000-RegBankSize
, True
, eCoreClassic
}, /* allow USB registers @ 0x1fxx */
{ "ATTINY4" , 0x00f, 0x0020, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY5" , 0x00f, 0x0020, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY9" , 0x01f, 0x0020, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY10" , 0x01f, 0x0020, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY11" , 0x01f, 0x0000, 0x0000, IOAreaStdSize
, True
, eCore90S1200
},
{ "ATTINY12" , 0x01f, 0x0000, 0x003f, IOAreaStdSize
, True
, eCore90S1200
},
{ "ATTINY13" , 0x01f, 0x0040, 0x003f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY13A" , 0x01f, 0x0040, 0x003f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY15" , 0x01f, 0x0000, 0x003f, IOAreaStdSize
, True
, eCore90S1200
},
{ "ATTINY20" , 0x03f, 0x0080, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY24" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY24A" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY25" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY26" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY28" , 0x03f, 0x0000, 0x0000, IOAreaStdSize
, True
, eCore90S1200
},
{ "ATTINY40" , 0x07f, 0x0100, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY44" , 0x07f, 0x0100, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY44A" , 0x07f, 0x0100, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY45" , 0x07f, 0x0100, 0x00ff, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY48" , 0x07f, 0x0100, 0x003f, IOAreaExtSize
, True
, eCoreTiny
},
{ "ATTINY84" , 0x0ff, 0x0200, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY84A" , 0x0ff, 0x0200, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY85" , 0x0ff, 0x0200, 0x00ff, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY87" , 0x0ff, 0x0200, 0x01ff, IOAreaExtSize
, True
, eCoreTiny16K
},
{ "ATTINY88" , 0x0ff, 0x0200, 0x003f, IOAreaExtSize
, True
, eCoreTiny
},
{ "ATTINY102" , 0x01f, 0x0020, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY104" , 0x01f, 0x0020, 0x0000, IOAreaStdSize
, False
, eCoreMinTiny
},
{ "ATTINY167" , 0x1ff, 0x0200, 0x01ff, IOAreaExtSize
, True
, eCoreTiny16K
},
{ "ATTINY261" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY261A" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY43U" , 0x07f, 0x0100, 0x003f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY441" , 0x07f, 0x0100, 0x00ff, IOAreaExtSize
, True
, eCoreTiny
},
{ "ATTINY461" , 0x07f, 0x0100, 0x00ff, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY461A" , 0x07f, 0x0100, 0x00ff, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY828" , 0x0ff, 0x0200, 0x00ff, IOAreaExtSize
, True
, eCoreTiny
},
{ "ATTINY841" , 0x0ff, 0x0200, 0x00ff, IOAreaExtSize
, True
, eCoreTiny
},
{ "ATTINY861" , 0x0ff, 0x0200, 0x01ff, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY861A" , 0x0ff, 0x0200, 0x01ff, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY1634" , 0x1ff, 0x0400, 0x00ff, IOAreaExtSize
, True
, eCoreTiny16K
},
{ "ATTINY2313" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY2313A" , 0x03f, 0x0080, 0x007f, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATTINY4313" , 0x07f, 0x0100, 0x00ff, IOAreaStdSize
, True
, eCoreTiny
},
{ "ATMEGA48" , 0x07f, 0x0200, 0x00ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA8" , 0x0ff, 0x0400, 0x01ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA8515" , 0x0ff, 0x0200, 0x01ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA8535" , 0x0ff, 0x0200, 0x01ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA88" , 0x0ff, 0x0200, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA8U2" , 0x0ff, 0x0200, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA16" , 0x1ff, 0x0400, 0x01ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA161" , 0x1ff, 0x0400, 0x01ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA162" , 0x1ff, 0x0400, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA163" , 0x1ff, 0x0400, 0x01ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA164" , 0x1ff, 0x0400, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA165" , 0x1ff, 0x0200, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA168" , 0x1ff, 0x0400, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA169" , 0x1ff, 0x0400, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA16U2" , 0x1ff, 0x0200, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA16U4" , 0x1ff, 0x0500, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA32" , 0x3ff, 0x0800, 0x03ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA323" , 0x3ff, 0x0800, 0x03ff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA324" , 0x3ff, 0x0800, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA325" , 0x3ff, 0x0800, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA3250" , 0x3ff, 0x0800, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA328" , 0x3ff, 0x0800, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA329" , 0x3ff, 0x0800, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA3290" , 0x3ff, 0x0800, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA32U2" , 0x3ff, 0x0400, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA32U4" , 0x3ff, 0x0a00, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA32U6" , 0x3ff, 0x0a00, 0x03ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA406" , 0x4ff, 0x0800, 0x01ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA64" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA640" , 0x7ff, 0x2000, 0x0fff, IOAreaExt2Size
, True
, eCoreMega
},
{ "ATMEGA644" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA644RFR2" , 0x7ff, 0x2000, 0x07ff, IOAreaExt2Size
, True
, eCoreMega
},
{ "ATMEGA645" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA6450" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA649" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA6490" , 0x7ff, 0x1000, 0x07ff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA103" , 0xfff, 0x1000, 0x0fff, IOAreaStdSize
, True
, eCoreMega
},
{ "ATMEGA128" , 0xfff, 0x1000, 0x0fff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA1280" , 0xfff, 0x2000, 0x0fff, IOAreaExt2Size
, True
, eCoreMega
},
{ "ATMEGA1281" , 0xfff, 0x2000, 0x0fff, IOAreaExt2Size
, True
, eCoreMega
},
{ "ATMEGA1284" , 0xfff, 0x4000, 0x0fff, IOAreaExtSize
, True
, eCoreMega
},
{ "ATMEGA1284RFR2" , 0xfff, 0x4000, 0x0fff, IOAreaExt2Size
, True
, eCoreMega
},
{ "ATMEGA2560" , 0x1fff, 0x2000, 0x0fff, IOAreaExt2Size
, True
, eCoreMega
},
{ "ATMEGA2561" , 0x1fff, 0x2000, 0x0fff, IOAreaExt2Size
, True
, eCoreMega
},
{ "ATMEGA2564RFR2" , 0x1fff, 0x8000, 0x1fff, IOAreaExt2Size
, True
, eCoreMega
},
{ NULL
, 0x0, 0 , 0 , 0 , False
, eCoreNone
},
};
void codeavr_init
(void)
{
const tCPUProps
*pProp
;
static const tCPUArg AVRArgs
[] =
{
{ "CODESEGSIZE", 0, 1, 1, &CodeSegSize
},
{ NULL
, 0, 0, 0, NULL
}
};
for (pProp
= CPUProps
; pProp
->pName
; pProp
++)
(void)AddCPUUserWithArgs
(pProp
->pName
, SwitchTo_AVR
, (void*)pProp
, NULL
, AVRArgs
);
}