Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
/* codeace.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegeneratormodul ACE-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include "bpemu.h"
#include "strutil.h"
#include "chunks.h"
#include "headids.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "codeace.h"
enum
{
ModNone
= -1,
ModAcc
= 0,
ModX
= 1,
ModXInd
= 2,
ModXDisp
= 3,
ModDir
= 4,
ModImm
= 5
};
#define MModAcc (1 << ModAcc)
#define MModX (1 << ModX)
#define MModXInd (1 << ModXInd)
#define MModXDisp (1 << ModXDisp)
#define MModDir (1 << ModDir)
#define MModImm (1 << ModImm)
typedef struct
{
Byte ImmCode
, DirCode
, IndCode
, DispCode
;
} AriOrder
;
typedef struct
{
Byte AccCode
, XCode
, DirCode
;
} SingOrder
;
typedef struct
{
Byte AccCode
, XIndCode
, DirCode
;
} BitOrder
;
enum { D_CPUACE1101
, D_CPUACE1202
};
static CPUVar CPUACE1101
, CPUACE1202
;
static AriOrder
*AriOrders
;
static SingOrder
*SingOrders
;
static BitOrder
*BitOrders
;
static ShortInt AdrMode
;
static Byte AdrVal
;
static Word WAdrVal
;
static Boolean BigFlag
, OpSize
;
/*---------------------------------------------------------------------------*/
static void ChkAdr
(Word Mask
)
{
if ((AdrMode
== ModXDisp
) && !ChkMinCPUExt
(CPUACE1202
, ErrNum_AddrModeNotSupported
))
AdrMode
= ModNone
;
else if ((AdrMode
!= ModNone
) && ((Mask
& (1 << AdrMode
)) == 0))
{
AdrMode
= ModNone
; WrError
(ErrNum_InvAddrMode
);
}
}
static void DecodeAdr
(const tStrComp
*pArg
, Word Mask
)
{
Boolean OK
, DispOcc
, XOcc
;
int ArgLen
;
char *p
;
AdrMode
= ModNone
;
/* Register ? */
if (!as_strcasecmp
(pArg
->str.
p_str, "A"))
AdrMode
= ModAcc
;
else if (!as_strcasecmp
(pArg
->str.
p_str, "X"))
AdrMode
= ModX
;
/* immediate ? */
else if (*pArg
->str.
p_str== '#')
{
if (OpSize
)
WAdrVal
= EvalStrIntExpressionOffs
(pArg
, 1, Int12
, &OK
);
else
AdrVal
= EvalStrIntExpressionOffs
(pArg
, 1, Int8
, &OK
);
if (OK
) AdrMode
= ModImm
;
}
/* indirekt ? */
else if (*pArg
->str.
p_str == '[')
{
ArgLen
= strlen(pArg
->str.
p_str);
if (pArg
->str.
p_str[ArgLen
- 1] != ']') WrError
(ErrNum_InvAddrMode
);
else
{
tStrComp Arg
, Remainder
;
StrCompRefRight
(&Arg
, pArg
, 1);
StrCompShorten
(&Arg
, 1);
DispOcc
= XOcc
= False
;
do
{
p
= QuotPos
(Arg.
str.
p_str, ',');
if (p
)
StrCompSplitRef
(&Arg
, &Remainder
, &Arg
, p
);
KillPrefBlanksStrComp
(&Arg
);
KillPostBlanksStrComp
(&Arg
);
if (!as_strcasecmp
(Arg.
str.
p_str, "X"))
if (XOcc
)
{
WrError
(ErrNum_InvAddrMode
); break;
}
else
XOcc
= True
;
else if (DispOcc
)
{
WrError
(ErrNum_InvAddrMode
); break;
}
else
{
AdrVal
= EvalStrIntExpressionOffs
(&Arg
, !!(*Arg.
str.
p_str == '#'), UInt8
, &OK
);
if (!OK
) break;
DispOcc
= True
;
}
if (p
)
Arg
= Remainder
;
}
while (p
);
if (!p
)
AdrMode
= (DispOcc
&& (AdrVal
!= 0)) ? ModXDisp
: ModXInd
;
}
}
/* direkt */
else
{
if (OpSize
)
WAdrVal
= EvalStrIntExpression
(pArg
, UInt12
, &OK
);
else
AdrVal
= EvalStrIntExpression
(pArg
, UInt8
, &OK
);
if (OK
) AdrMode
= ModDir
;
}
ChkAdr
(Mask
);
}
/*---------------------------------------------------------------------------*/
static void DecodeFixed
(Word Code
)
{
if (ChkArgCnt
(0, 0))
{
BAsmCode
[0] = Code
;
CodeLen
= 1;
}
}
static void DecodeAri
(Word Index
)
{
AriOrder
*porder
= AriOrders
+ Index
;
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
);
if (AdrMode
!= ModNone
)
{
DecodeAdr
(&ArgStr
[2], MModImm
| MModDir
| MModXInd
| MModXDisp
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = porder
->ImmCode
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModDir
:
BAsmCode
[0] = porder
->DirCode
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModXInd
:
BAsmCode
[0] = porder
->IndCode
;
CodeLen
= 1;
break;
case ModXDisp
:
BAsmCode
[0] = porder
->DispCode
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
}
}
}
static void DecodeSing
(Word Index
)
{
SingOrder
*porder
= SingOrders
+ Index
;
if (ChkArgCnt
(1, 1))
{
DecodeAdr
(&ArgStr
[1], MModDir
| MModX
| MModAcc
);
switch (AdrMode
)
{
case ModDir
:
BAsmCode
[0] = porder
->DirCode
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModAcc
:
BAsmCode
[0] = porder
->AccCode
;
CodeLen
= 1;
break;
case ModX
:
BAsmCode
[0] = porder
->XCode
;
CodeLen
= 1;
break;
}
}
}
static void DecodeBit
(Word Index
)
{
Byte Bit
, Mask
;
BitOrder
*porder
= BitOrders
+ Index
;
Boolean OK
;
if (ChkArgCnt
(2, 2))
{
Bit
= EvalStrIntExpression
(&ArgStr
[1], UInt8
, &OK
);
if (OK
)
{
Mask
= 0;
if (porder
->AccCode
!= 0xff) Mask
|= MModAcc
;
if (porder
->XIndCode
!= 0xff) Mask
|= MModXInd
;
if (porder
->DirCode
!= 0xff) Mask
|= MModDir
;
DecodeAdr
(&ArgStr
[2], Mask
);
switch (AdrMode
)
{
case ModAcc
:
BAsmCode
[0] = porder
->AccCode
;
if (porder
->AccCode
& 7)
{
BAsmCode
[1] = 1 << Bit
;
if (porder
->AccCode
& 1)
BAsmCode
[1] = 255 - BAsmCode
[1];
CodeLen
= 2;
}
else
{
BAsmCode
[0] |= Bit
;
CodeLen
= 1;
}
break;
case ModXInd
:
BAsmCode
[0] = porder
->XIndCode
+ Bit
;
CodeLen
= 1;
break;
case ModDir
:
BAsmCode
[0] = porder
->DirCode
+ Bit
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
}
}
}
static void DecodeIFEQ
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModX
| MModDir
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModImm
| MModDir
| MModXInd
| MModXDisp
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x65;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModDir
:
BAsmCode
[0] = 0x56;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModXInd
:
BAsmCode
[0] = 0x09;
CodeLen
= 1;
break;
case ModXDisp
:
BAsmCode
[0] = 0x76;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
break;
case ModX
:
OpSize
= True
;
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x26;
BAsmCode
[1] = Lo
(WAdrVal
);
BAsmCode
[2] = Hi
(WAdrVal
);
CodeLen
= 3;
break;
}
break;
case ModDir
:
BAsmCode
[1] = AdrVal
;
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x20;
BAsmCode
[2] = AdrVal
;
CodeLen
= 3;
break;
}
break;
}
}
}
static void DecodeIFGT
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModX
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModImm
| MModDir
| MModXInd
| MModXDisp
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x67;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModDir
:
BAsmCode
[0] = 0x55;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModXInd
:
BAsmCode
[0] = 0x0a;
CodeLen
= 1;
break;
case ModXDisp
:
BAsmCode
[0] = 0x77;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
break;
case ModX
:
OpSize
= True
;
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x27;
BAsmCode
[1] = Lo
(WAdrVal
);
BAsmCode
[2] = Hi
(WAdrVal
);
CodeLen
= 3;
break;
}
break;
}
}
}
static void DecodeIFLT
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModX
);
switch (AdrMode
)
{
case ModX
:
OpSize
= True
;
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x28;
BAsmCode
[1] = Lo
(WAdrVal
);
BAsmCode
[2] = Hi
(WAdrVal
);
CodeLen
= 3;
break;
}
break;
}
}
}
static void DecodeJMPJSR
(Word Index
)
{
if (ChkArgCnt
(1, 1))
{
OpSize
= True
;
DecodeAdr
(&ArgStr
[1], MModDir
| MModXDisp
);
switch (AdrMode
)
{
case ModDir
:
BAsmCode
[0] = 0x24 - Index
;
BAsmCode
[1] = Lo
(WAdrVal
);
BAsmCode
[2] = Hi
(WAdrVal
);
CodeLen
= 3;
break;
case ModXDisp
:
BAsmCode
[0] = 0x7e + Index
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
}
}
static void DecodeJP
(Word Index
)
{
LongInt Dist
;
Boolean OK
;
tSymbolFlags Flags
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 1))
{
Dist
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], UInt12
, &OK
, &Flags
) - (EProgCounter
() + 1);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && ((Dist
> 31) || (Dist
< -31))) WrError
(ErrNum_JmpDistTooBig
);
else
{
BAsmCode
[0] = (Dist
>= 0) ? 0xe0 + Dist
: 0xc0 - Dist
;
CodeLen
= 1;
}
}
}
}
static void DecodeLD
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModX
| MModDir
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModImm
| MModDir
| MModXInd
| MModXDisp
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x51;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModDir
:
BAsmCode
[0] = 0x46;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModXInd
:
BAsmCode
[0] = 0x0e;
CodeLen
= 1;
break;
case ModXDisp
:
BAsmCode
[0] = 0x52;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
break;
case ModX
:
OpSize
= True
;
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x25;
BAsmCode
[1] = Lo
(WAdrVal
);
BAsmCode
[2] = Hi
(WAdrVal
);
CodeLen
= 3;
break;
}
break;
case ModDir
:
BAsmCode
[1] = AdrVal
;
DecodeAdr
(&ArgStr
[2], MModImm
| MModDir
);
switch (AdrMode
)
{
case ModImm
:
BAsmCode
[0] = 0x21;
BAsmCode
[2] = AdrVal
;
CodeLen
= 3;
break;
case ModDir
:
BAsmCode
[0] = 0x22;
BAsmCode
[2] = BAsmCode
[1];
BAsmCode
[1] = AdrVal
;
CodeLen
= 3;
break;
}
break;
}
}
}
static void DecodeRotate
(Word Index
)
{
if (ChkArgCnt
(1, 1))
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModDir
);
switch (AdrMode
)
{
case ModAcc
:
BAsmCode
[0] = 0x15 - Index
- Index
;
CodeLen
= 1;
break;
case ModDir
:
BAsmCode
[0] = 0x79 + Index
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
}
}
static void DecodeST
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModDir
| MModXInd
| MModXDisp
);
switch (AdrMode
)
{
case ModDir
:
BAsmCode
[0] = 0x47;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModXInd
:
BAsmCode
[0] = 0x11;
CodeLen
= 1;
break;
case ModXDisp
:
BAsmCode
[0] = 0x40;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
break;
}
}
}
static void DecodeSFR
(Word Code
)
{
UNUSED
(Code
);
CodeEquate
(SegCode
, 0, 0xff);
}
/*---------------------------------------------------------------------------*/
static void AddFixed
(const char *NName
, Byte NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeFixed
);
}
static void AddAri
(const char *NName
, Byte NImm
, Byte NDir
, Byte NInd
, Byte NDisp
)
{
order_array_rsv_end
(AriOrders
, AriOrder
);
AriOrders
[InstrZ
].
ImmCode = NImm
;
AriOrders
[InstrZ
].
DirCode = NDir
;
AriOrders
[InstrZ
].
IndCode = NInd
;
AriOrders
[InstrZ
].
DispCode = NDisp
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeAri
);
}
static void AddSing
(const char *NName
, Byte NAcc
, Byte NX
, Byte NDir
)
{
order_array_rsv_end
(SingOrders
, SingOrder
);
SingOrders
[InstrZ
].
AccCode = NAcc
;
SingOrders
[InstrZ
].
XCode = NX
;
SingOrders
[InstrZ
].
DirCode = NDir
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeSing
);
}
static void AddBit
(const char *NName
, Byte NAcc
, Byte NIndX
, Byte NDir
)
{
order_array_rsv_end
(BitOrders
, BitOrder
);
BitOrders
[InstrZ
].
AccCode = NAcc
;
BitOrders
[InstrZ
].
XIndCode = NIndX
;
BitOrders
[InstrZ
].
DirCode = NDir
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeBit
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(101);
InstrZ
= 0;
AddFixed
("IFC" ,0x19); AddFixed
("IFNC" ,0x1f); AddFixed
("INTR" ,0x00);
AddFixed
("INVC" ,0x12); AddFixed
("NOP" ,0x1c); AddFixed
("RC" ,0x1e);
AddFixed
("RET" ,0x17); AddFixed
("RETI" ,0x18); AddFixed
("SC" ,0x1d);
InstrZ
= 0;
AddAri
("ADC" , 0x60, 0x42, 0x02, 0x70);
AddAri
("ADD" , 0x66, 0x43, 0x03, 0x71);
AddAri
("AND" , 0x61, 0x50, 0x04, 0x72);
AddAri
("IFNE", 0x57, 0x54, 0x0b, 0x78);
AddAri
("OR" , 0x62, 0x44, 0x05, 0x73);
AddAri
("SUBC", 0x63, 0x53, 0x06, 0x74);
AddAri
("XOR" , 0x64, 0x45, 0x07, 0x75);
InstrZ
= 0;
AddSing
("CLR" , 0x16, 0x0f, 0x7d);
AddSing
("DEC" , 0x1a, 0x0c, 0x7b);
AddSing
("INC" , 0x1b, 0x0d, 0x7c);
InstrZ
= 0;
AddBit
("IFBIT", 0xa0, 0xa8, 0x58);
AddBit
("LDC" , 0xff, 0xff, 0x80);
AddBit
("RBIT" , 0x61, 0xb8, 0x68);
AddBit
("SBIT" , 0x62, 0xb0, 0x48);
AddBit
("STC" , 0xff, 0xff, 0x88);
AddInstTable
(InstTable
, "IFEQ", 0, DecodeIFEQ
);
AddInstTable
(InstTable
, "IFGT", 0, DecodeIFGT
);
AddInstTable
(InstTable
, "IFLT", 0, DecodeIFLT
);
AddInstTable
(InstTable
, "JMP" , 0, DecodeJMPJSR
);
AddInstTable
(InstTable
, "JSR" , 1, DecodeJMPJSR
);
AddInstTable
(InstTable
, "JP" , 0, DecodeJP
);
AddInstTable
(InstTable
, "LD" , 0, DecodeLD
);
AddInstTable
(InstTable
, "RLC" , 0, DecodeRotate
);
AddInstTable
(InstTable
, "RRC" , 1, DecodeRotate
);
AddInstTable
(InstTable
, "ST" , 0, DecodeST
);
AddInstTable
(InstTable
, "SFR" , 0, DecodeSFR
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(AriOrders
);
order_array_free
(SingOrders
);
order_array_free
(BitOrders
);
}
/*---------------------------------------------------------------------------*/
static void MakeCode_ACE
(void)
{
CodeLen
= 0; DontPrint
= False
; BigFlag
= False
; OpSize
= False
;
/* zu ignorierendes */
if (Memo
("")) return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo
(BigFlag
)) return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_ACE
(void)
{
return (Memo
("SFR"));
}
static void SwitchFrom_ACE
(void)
{
DeinitFields
();
}
static void SwitchTo_ACE
(void)
{
const TFamilyDescr
*Descr
;
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
Descr
= FindFamilyByName
("ACE");
PCSymbol
= "$";
HeaderID
= Descr
->Id
;
NOPCode
= 0x1c;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= (1 << SegCode
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegLimits
[SegCode
] = 0xfff;
switch (MomCPU
- CPUACE1101
)
{
case D_CPUACE1101
:
SegInits
[SegCode
] = 0xc00;
break;
case D_CPUACE1202
:
SegInits
[SegCode
] = 0x800;
break;
}
MakeCode
= MakeCode_ACE
;
IsDef
= IsDef_ACE
;
SwitchFrom
= SwitchFrom_ACE
;
InitFields
();
}
void codeace_init
(void)
{
CPUACE1101
= AddCPU
("ACE1101", SwitchTo_ACE
);
CPUACE1202
= AddCPU
("ACE1202", SwitchTo_ACE
);
}