Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
/* code3201x.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator TMS3201x-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.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 "code3201x.h"
typedef struct
{
Word Code
;
Word AllowShifts
;
} AdrShiftOrder
;
typedef struct
{
Word Code
;
Integer Min
, Max
;
Word Mask
;
} ImmOrder
;
static Word AdrMode
;
static Boolean AdrOK
;
static CPUVar CPU32010
, CPU32015
;
static AdrShiftOrder
*AdrShiftOrders
;
static ImmOrder
*ImmOrders
;
/*----------------------------------------------------------------------------*/
static Word EvalARExpression
(const tStrComp
*pArg
, Boolean
*OK
)
{
*OK
= True
;
if (!as_strcasecmp
(pArg
->str.
p_str, "AR0"))
return 0;
if (!as_strcasecmp
(pArg
->str.
p_str, "AR1"))
return 1;
return EvalStrIntExpression
(pArg
, UInt1
, OK
);
}
static void DecodeAdr
(const tStrComp
*pArg
, int Aux
, Boolean Must1
)
{
Byte h
;
char *p
;
char *Arg
= pArg
->str.
p_str;
AdrOK
= False
;
if ((!strcmp(pArg
->str.
p_str, "*")) || (!strcmp(pArg
->str.
p_str, "*-")) || (!strcmp(pArg
->str.
p_str, "*+")))
{
AdrMode
= 0x88;
if (strlen(Arg
) == 2)
AdrMode
+= (pArg
->str.
p_str[1] == '+') ? 0x20 : 0x10;
if (Aux
<= ArgCnt
)
{
h
= EvalARExpression
(&ArgStr
[Aux
], &AdrOK
);
if (AdrOK
)
{
AdrMode
&= 0xf7;
AdrMode
+= h
;
}
}
else
AdrOK
= True
;
}
else if (ChkArgCnt
(1, Aux
- 1))
{
tEvalResult EvalResult
;
h
= 0;
if ((strlen(pArg
->str.
p_str) > 3) && (!as_strncasecmp
(pArg
->str.
p_str, "DAT", 3)))
{
AdrOK
= True
;
for (p
= pArg
->str.
p_str + 3; *p
!= '\0'; p
++)
if ((*p
> '9') || (*p
< '0'))
AdrOK
= False
;
if (AdrOK
)
{
h
= EvalStrIntExpressionOffsWithResult
(pArg
, 3, UInt8
, &EvalResult
);
AdrOK
= EvalResult.
OK;
}
}
if (!AdrOK
)
{
h
= EvalStrIntExpressionWithResult
(pArg
, Int8
, &EvalResult
);
AdrOK
= EvalResult.
OK;
}
if (AdrOK
)
{
if (Must1
&& (h
< 0x80) && !mFirstPassUnknown
(EvalResult.
Flags))
{
WrError
(ErrNum_UnderRange
);
AdrOK
= False
;
}
else
{
AdrMode
= h
& 0x7f;
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
}
}
}
/*----------------------------------------------------------------------------*/
/* kein Argument */
static void DecodeFixed
(Word Code
)
{
if (ChkArgCnt
(0, 0))
{
CodeLen
= 1;
WAsmCode
[0] = Code
;
}
}
/* Spruenge */
static void DecodeJmp
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean OK
;
WAsmCode
[1] = EvalStrIntExpression
(&ArgStr
[1], UInt12
, &OK
);
if (OK
)
{
CodeLen
= 2;
WAsmCode
[0] = Code
;
}
}
}
/* nur Adresse */
static void DecodeAdrInst
(Word Code
)
{
if (ChkArgCnt
(1, 2))
{
DecodeAdr
(&ArgStr
[1], 2, Code
& 1);
if (AdrOK
)
{
CodeLen
= 1;
WAsmCode
[0] = (Code
& 0xfffe) + AdrMode
;
}
}
}
/* Adresse & schieben */
static void DecodeAdrShift
(Word Index
)
{
Boolean HasSh
;
int AuxArgIndex
;
const AdrShiftOrder
*pOrder
= AdrShiftOrders
+ Index
;
if (ChkArgCnt
(1, 3))
{
if (*ArgStr
[1].
str.
p_str == '*')
{
switch (ArgCnt
)
{
case 1:
HasSh
= False
;
AuxArgIndex
= 3;
break;
case 2:
if (!as_strncasecmp
(ArgStr
[2].
str.
p_str, "AR", 2))
{
HasSh
= False
;
AuxArgIndex
= 2;
}
else
{
HasSh
= True
;
AuxArgIndex
= 3;
}
break;
default: /* 3 */
HasSh
= True
;
AuxArgIndex
= 3;
}
}
else
{
AuxArgIndex
= 3;
HasSh
= (ArgCnt
== 2);
}
DecodeAdr
(&ArgStr
[1], AuxArgIndex
, False
);
if (AdrOK
)
{
Boolean OK
;
Word AdrWord
;
if (!HasSh
)
{
OK
= True
;
AdrWord
= 0;
}
else
{
tSymbolFlags Flags
;
AdrWord
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], Int4
, &OK
, &Flags
);
if (OK
&& mFirstPassUnknown
(Flags
))
AdrWord
= 0;
}
if (OK
)
{
if ((pOrder
->AllowShifts
& (1 << AdrWord
)) == 0) WrError
(ErrNum_InvShiftArg
);
else
{
CodeLen
= 1;
WAsmCode
[0] = pOrder
->Code
+ AdrMode
+ (AdrWord
<< 8);
}
}
}
}
}
/* Ein/Ausgabe */
static void DecodeIN_OUT
(Word Code
)
{
if (ChkArgCnt
(2, 3))
{
DecodeAdr
(&ArgStr
[1], 3, False
);
if (AdrOK
)
{
tEvalResult EvalResult
;
Word AdrWord
= EvalStrIntExpressionWithResult
(&ArgStr
[2], UInt3
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegIO
, EvalResult.
AddrSpaceMask);
CodeLen
= 1;
WAsmCode
[0] = Code
+ AdrMode
+ (AdrWord
<< 8);
}
}
}
}
/* konstantes Argument */
static void DecodeImm
(Word Index
)
{
const ImmOrder
*pOrder
= ImmOrders
+ Index
;
if (ChkArgCnt
(1, 1))
{
Boolean OK
;
tSymbolFlags Flags
;
LongInt AdrLong
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], Int32
, &OK
, &Flags
);
if (OK
)
{
if (mFirstPassUnknown
(Flags
))
AdrLong
&= pOrder
->Mask
;
if (AdrLong
< pOrder
->Min
) WrError
(ErrNum_UnderRange
);
else if (AdrLong
> pOrder
->Max
) WrError
(ErrNum_OverRange
);
else
{
CodeLen
= 1;
WAsmCode
[0] = pOrder
->Code
+ (AdrLong
& pOrder
->Mask
);
}
}
}
}
/* mit Hilfsregistern */
static void DecodeLARP
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(1, 1))
{
Boolean OK
;
Word AdrWord
= EvalARExpression
(&ArgStr
[1], &OK
);
if (OK
)
{
CodeLen
= 1;
WAsmCode
[0] = 0x6880 + AdrWord
;
}
}
}
static void DecodeLAR_SAR
(Word Code
)
{
if (ChkArgCnt
(2, 3))
{
Boolean OK
;
Word AdrWord
= EvalARExpression
(&ArgStr
[1], &OK
);
if (OK
)
{
DecodeAdr
(&ArgStr
[2], 3, False
);
if (AdrOK
)
{
CodeLen
= 1;
WAsmCode
[0] = Code
+ AdrMode
+ (AdrWord
<< 8);
}
}
}
}
static void DecodeLARK
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(2, 2))
{
Boolean OK
;
Word AdrWord
= EvalARExpression
(&ArgStr
[1], &OK
);
if (OK
)
{
WAsmCode
[0] = EvalStrIntExpression
(&ArgStr
[2], Int8
, &OK
);
if (OK
)
{
CodeLen
= 1;
WAsmCode
[0] = Lo
(WAsmCode
[0]) + 0x7000 + (AdrWord
<< 8);
}
}
}
}
static void DecodePORT
(Word Code
)
{
UNUSED
(Code
);
CodeEquate
(SegIO
, 0, 7);
}
static void DecodeDATA_3201x
(Word Code
)
{
UNUSED
(Code
);
DecodeDATA
(Int16
, Int16
);
}
/*----------------------------------------------------------------------------*/
static void AddFixed
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeFixed
);
}
static void AddJmp
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeJmp
);
}
static void AddAdr
(const char *NName
, Word NCode
, Word NMust1
)
{
AddInstTable
(InstTable
, NName
, NCode
| NMust1
, DecodeAdrInst
);
}
static void AddAdrShift
(const char *NName
, Word NCode
, Word NAllow
)
{
order_array_rsv_end
(AdrShiftOrders
, AdrShiftOrder
);
AdrShiftOrders
[InstrZ
].
Code = NCode
;
AdrShiftOrders
[InstrZ
].
AllowShifts = NAllow
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeAdrShift
);
}
static void AddImm
(const char *NName
, Word NCode
, Integer NMin
, Integer NMax
, Word NMask
)
{
order_array_rsv_end
(ImmOrders
, ImmOrder
);
ImmOrders
[InstrZ
].
Code = NCode
;
ImmOrders
[InstrZ
].
Min = NMin
;
ImmOrders
[InstrZ
].
Max = NMax
;
ImmOrders
[InstrZ
].
Mask = NMask
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeImm
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(203);
AddInstTable
(InstTable
, "IN", 0x4000, DecodeIN_OUT
);
AddInstTable
(InstTable
, "OUT", 0x4800, DecodeIN_OUT
);
AddInstTable
(InstTable
, "LARP", 0, DecodeLARP
);
AddInstTable
(InstTable
, "LAR", 0x3800, DecodeLAR_SAR
);
AddInstTable
(InstTable
, "SAR", 0x3000, DecodeLAR_SAR
);
AddInstTable
(InstTable
, "LARK", 0, DecodeLARK
);
AddInstTable
(InstTable
, "PORT", 0, DecodePORT
);
AddInstTable
(InstTable
, "RES", 0, DecodeRES
);
AddInstTable
(InstTable
, "DATA", 0, DecodeDATA_3201x
);
AddFixed
("ABS" , 0x7f88); AddFixed
("APAC" , 0x7f8f);
AddFixed
("CALA" , 0x7f8c); AddFixed
("DINT" , 0x7f81);
AddFixed
("EINT" , 0x7f82); AddFixed
("NOP" , 0x7f80);
AddFixed
("PAC" , 0x7f8e); AddFixed
("POP" , 0x7f9d);
AddFixed
("PUSH" , 0x7f9c); AddFixed
("RET" , 0x7f8d);
AddFixed
("ROVM" , 0x7f8a); AddFixed
("SOVM" , 0x7f8b);
AddFixed
("SPAC" , 0x7f90); AddFixed
("ZAC" , 0x7f89);
AddJmp
("B" , 0xf900); AddJmp
("BANZ" , 0xf400);
AddJmp
("BGEZ" , 0xfd00); AddJmp
("BGZ" , 0xfc00);
AddJmp
("BIOZ" , 0xf600); AddJmp
("BLEZ" , 0xfb00);
AddJmp
("BLZ" , 0xfa00); AddJmp
("BNZ" , 0xfe00);
AddJmp
("BV" , 0xf500); AddJmp
("BZ" , 0xff00);
AddJmp
("CALL" , 0xf800);
AddAdr
("ADDH" , 0x6000, False
); AddAdr
("ADDS" , 0x6100, False
);
AddAdr
("AND" , 0x7900, False
); AddAdr
("DMOV" , 0x6900, False
);
AddAdr
("LDP" , 0x6f00, False
); AddAdr
("LST" , 0x7b00, False
);
AddAdr
("LT" , 0x6a00, False
); AddAdr
("LTA" , 0x6c00, False
);
AddAdr
("LTD" , 0x6b00, False
); AddAdr
("MAR" , 0x6800, False
);
AddAdr
("MPY" , 0x6d00, False
); AddAdr
("OR" , 0x7a00, False
);
AddAdr
("SST" , 0x7c00, True
); AddAdr
("SUBC" , 0x6400, False
);
AddAdr
("SUBH" , 0x6200, False
); AddAdr
("SUBS" , 0x6300, False
);
AddAdr
("TBLR" , 0x6700, False
); AddAdr
("TBLW" , 0x7d00, False
);
AddAdr
("XOR" , 0x7800, False
); AddAdr
("ZALH" , 0x6500, False
);
AddAdr
("ZALS" , 0x6600, False
);
InstrZ
= 0;
AddAdrShift
("ADD" , 0x0000, 0xffff);
AddAdrShift
("LAC" , 0x2000, 0xffff);
AddAdrShift
("SACH" , 0x5800, 0x0013);
AddAdrShift
("SACL" , 0x5000, 0x0001);
AddAdrShift
("SUB" , 0x1000, 0xffff);
InstrZ
= 0;
AddImm
("LACK", 0x7e00, 0, 255, 0xff);
AddImm
("LDPK", 0x6e00, 0, 1, 0x1);
AddImm
("MPYK", 0x8000, -4096, 4095, 0x1fff);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(AdrShiftOrders
);
order_array_free
(ImmOrders
);
}
/*----------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn InternSymbol_3201X(char *pArg, TempResult *pResult)
* \brief parse for built-in symbols
* \param pArg source argument
* \param pResult possible result
* ------------------------------------------------------------------------ */
static void InternSymbol_3201X
(char *pArg
, TempResult
*pResult
)
{
if ((strlen(pArg
) == 3)
&& (as_toupper
(pArg
[0]) == 'P')
&& (as_toupper
(pArg
[1]) == 'A')
&& ((pArg
[2] >= '0') && (pArg
[2] <= '7')))
{
as_tempres_set_int
(pResult
, pArg
[2] - '0');
pResult
->AddrSpaceMask
|= 1 << SegIO
;
}
}
static void MakeCode_3201X
(void)
{
CodeLen
= 0;
DontPrint
= False
;
/* zu ignorierendes */
if (Memo
(""))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_3201X
(void)
{
return (Memo
("PORT"));
}
static void SwitchFrom_3201X
(void)
{
DeinitFields
();
}
static void SwitchTo_3201X
(void)
{
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
PCSymbol
= "$";
HeaderID
= 0x74;
NOPCode
= 0x7f80;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= (1 << SegCode
)|(1 << SegData
)|(1 << SegIO
);
Grans
[SegCode
] = 2; ListGrans
[SegCode
] = 2; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = 0xfff;
Grans
[SegData
] = 2; ListGrans
[SegData
] = 2; SegInits
[SegData
] = 0;
SegLimits
[SegData
] = (MomCPU
== CPU32010
) ? 0x8f : 0xff;
Grans
[SegIO
] = 2; ListGrans
[SegIO
] = 2; SegInits
[SegIO
] = 0;
SegLimits
[SegIO
] = 7;
MakeCode
= MakeCode_3201X
;
IsDef
= IsDef_3201X
;
InternSymbol
= InternSymbol_3201X
;
SwitchFrom
= SwitchFrom_3201X
;
InitFields
();
}
void code3201x_init
(void)
{
CPU32010
= AddCPU
("32010", SwitchTo_3201X
);
CPU32015
= AddCPU
("32015", SwitchTo_3201X
);
}