/* code16c5x.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* AS - Codegenerator fuer PIC16C5x */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include "strutil.h"
#include "chunks.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "fourpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "code16c5x.h"
static CPUVar CPU16C54
, CPU16C55
, CPU16C56
, CPU16C57
;
/*-------------------------------------------------------------------------*/
static void DecodeFixed
(Word Code
)
{
if (ChkArgCnt
(0, 0))
{
CodeLen
= 1;
WAsmCode
[0] = Code
;
}
}
static void DecodeLit
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean OK
;
Word AdrWord
= EvalStrIntExpression
(&ArgStr
[1], Int8
, &OK
);
if (OK
)
{
CodeLen
= 1;
WAsmCode
[0] = Code
+ (AdrWord
& 0xff);
}
}
}
static void DecodeAri
(Word Code
)
{
Word DefaultDir
= (Code
>> 15) & 1, AdrWord
;
Code
&= 0x7fff;
if (ChkArgCnt
(1, 2))
{
tEvalResult EvalResult
;
AdrWord
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt5
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
WAsmCode
[0] = Code
+ (AdrWord
& 0x1f);
if (ArgCnt
== 1)
{
CodeLen
= 1;
WAsmCode
[0] += DefaultDir
<< 5;
}
else if (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "W"))
CodeLen
= 1;
else if (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "F"))
{
CodeLen
= 1;
WAsmCode
[0] += 0x20;
}
else
{
AdrWord
= EvalStrIntExpressionWithResult
(&ArgStr
[2], UInt1
, &EvalResult
);
if (EvalResult.
OK)
{
CodeLen
= 1;
WAsmCode
[0] += AdrWord
<< 5;
}
}
}
}
}
static void DecodeBit
(Word Code
)
{
if (ChkArgCnt
(2, 2))
{
tEvalResult EvalResult
;
Word AdrWord
= EvalStrIntExpressionWithResult
(&ArgStr
[2], UInt3
, &EvalResult
);
if (EvalResult.
OK)
{
WAsmCode
[0] = EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt5
, &EvalResult
);
if (EvalResult.
OK)
{
CodeLen
= 1;
WAsmCode
[0] += Code
+ (AdrWord
<< 5);
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
}
}
}
static void DecodeF
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
tEvalResult EvalResult
;
Word AdrWord
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt5
, &EvalResult
);
if (EvalResult.
OK)
{
CodeLen
= 1;
WAsmCode
[0] = Code
+ AdrWord
;
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
}
}
static void DecodeTRIS
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(1, 1))
{
tEvalResult EvalResult
;
Word AdrWord
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt3
, &EvalResult
);
if (EvalResult.
OK)
if (ChkRange
(AdrWord
, 5, 7))
{
CodeLen
= 1;
WAsmCode
[0] = 0x000 + AdrWord
;
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
}
}
static void DecodeCALL_GOTO
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
tEvalResult EvalResult
;
Word AdrWord
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt16
, &EvalResult
);
if (EvalResult.
OK)
{
if (AdrWord
> SegLimits
[SegCode
]) WrError
(ErrNum_OverRange
);
else if ((Code
& 0x100) && ((AdrWord
& 0x100) != 0)) WrError
(ErrNum_NotFromThisAddress
);
else
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
if (((ProgCounter
() ^ AdrWord
) & 0x200) != 0)
WAsmCode
[CodeLen
++] = 0x4a3 + ((AdrWord
& 0x200) >> 1); /* BCF/BSF 3,5 */
if (((ProgCounter
() ^ AdrWord
) & 0x400) != 0)
WAsmCode
[CodeLen
++] = 0x4c3 + ((AdrWord
& 0x400) >> 2); /* BCF/BSF 3,6 */
WAsmCode
[CodeLen
++] = Code
+ (AdrWord
& (Code
& 0x100 ? 0xff : 0x1ff));
}
}
}
}
static void DecodeSFR
(Word Code
)
{
UNUSED
(Code
);
CodeEquate
(SegData
, 0, 0x1f);
}
static void DecodeDATA_16C5x
(Word Code
)
{
UNUSED
(Code
);
DecodeDATA
(Int12
, Int8
);
}
static void DecodeZERO
(Word Code
)
{
Word Size
;
Boolean ValOK
;
tSymbolFlags Flags
;
UNUSED
(Code
);
if (ChkArgCnt
(1, 1))
{
Size
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], Int16
, &ValOK
, &Flags
);
if (mFirstPassUnknown
(Flags
)) WrError
(ErrNum_FirstPassCalc
);
if (ValOK
&& !mFirstPassUnknown
(Flags
))
{
if (SetMaxCodeLen
(Size
<< 1)) WrError
(ErrNum_CodeOverflow
);
else
{
CodeLen
= Size
;
memset(WAsmCode
, 0, 2 * Size
);
}
}
}
}
/*-------------------------------------------------------------------------*/
static void AddFixed
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeFixed
);
}
static void AddLit
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeLit
);
}
static void AddAri
(const char *NName
, Word NCode
, Word NDef
)
{
AddInstTable
(InstTable
, NName
, NCode
| (NDef
<< 15), DecodeAri
);
}
static void AddBit
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeBit
);
}
static void AddF
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeF
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(103);
AddInstTable
(InstTable
, "TRIS", 0, DecodeTRIS
);
AddInstTable
(InstTable
, "CALL", 0x0900, DecodeCALL_GOTO
);
AddInstTable
(InstTable
, "GOTO", 0x0a00, DecodeCALL_GOTO
);
AddInstTable
(InstTable
, "SFR", 0, DecodeSFR
);
AddInstTable
(InstTable
, "RES", 0, DecodeRES
);
AddInstTable
(InstTable
, "DATA", 0, DecodeDATA_16C5x
);
AddInstTable
(InstTable
, "ZERO", 0, DecodeZERO
);
AddFixed
("CLRW" , 0x040);
AddFixed
("NOP" , 0x000);
AddFixed
("CLRWDT", 0x004);
AddFixed
("OPTION", 0x002);
AddFixed
("SLEEP" , 0x003);
AddLit
("ANDLW", 0xe00);
AddLit
("IORLW", 0xd00);
AddLit
("MOVLW", 0xc00);
AddLit
("RETLW", 0x800);
AddLit
("XORLW", 0xf00);
AddAri
("ADDWF" , 0x1c0, 0);
AddAri
("ANDWF" , 0x140, 0);
AddAri
("COMF" , 0x240, 1);
AddAri
("DECF" , 0x0c0, 1);
AddAri
("DECFSZ", 0x2c0, 1);
AddAri
("INCF" , 0x280, 1);
AddAri
("INCFSZ", 0x3c0, 1);
AddAri
("IORWF" , 0x100, 0);
AddAri
("MOVF" , 0x200, 0);
AddAri
("RLF" , 0x340, 1);
AddAri
("RRF" , 0x300, 1);
AddAri
("SUBWF" , 0x080, 0);
AddAri
("SWAPF" , 0x380, 1);
AddAri
("XORWF" , 0x180, 0);
AddBit
("BCF" , 0x400);
AddBit
("BSF" , 0x500);
AddBit
("BTFSC", 0x600);
AddBit
("BTFSS", 0x700);
AddF
("CLRF" , 0x060);
AddF
("MOVWF", 0x020);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
}
/*-------------------------------------------------------------------------*/
static void MakeCode_16C5X
(void)
{
CodeLen
= 0;
DontPrint
= False
;
/* zu ignorierendes */
if (Memo
(""))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_16C5X
(void)
{
return Memo
("SFR");
}
static void SwitchFrom_16C5X
(void)
{
DeinitFields
();
}
static void SwitchTo_16C5X
(void)
{
TurnWords
= False
;
SetIntConstMode
(eIntConstModeMoto
);
PCSymbol
= "*";
HeaderID
= 0x71;
NOPCode
= 0x000;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= (1 << SegCode
) + (1 << SegData
);
Grans
[SegCode
] = 2; ListGrans
[SegCode
] = 2; SegInits
[SegCode
] = 0;
if (MomCPU
== CPU16C56
)
SegLimits
[SegCode
] = 1023;
else if (MomCPU
== CPU16C57
)
SegLimits
[SegCode
] = 2047;
else
SegLimits
[SegCode
] = 511;
Grans
[SegData
] = 1; ListGrans
[SegData
] = 1; SegInits
[SegCode
] = 0;
SegLimits
[SegData
] = 0x1f;
MakeCode
= MakeCode_16C5X
;
IsDef
= IsDef_16C5X
;
SwitchFrom
= SwitchFrom_16C5X
;
InitFields
();
}
void code16c5x_init
(void)
{
CPU16C54
= AddCPU
("16C54", SwitchTo_16C5X
);
CPU16C55
= AddCPU
("16C55", SwitchTo_16C5X
);
CPU16C56
= AddCPU
("16C56", SwitchTo_16C5X
);
CPU16C57
= AddCPU
("16C57", SwitchTo_16C5X
);
}