Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
/* code7720.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* Makroassembler AS */
/* */
/* Codegenerator NEC uPD772x */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "strutil.h"
#include "nls.h"
#include "bpemu.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmcode.h"
#include "asmitree.h"
#include "headids.h"
#include "codevars.h"
#include "codepseudo.h"
#include "onoff_common.h"
#include "errmsg.h"
#include "chartrans.h"
#include "code7720.h"
/*---------------------------------------------------------------------------*/
typedef struct
{
const char *Name
;
LongWord Code
;
} TReg
;
typedef enum
{
MoveField
,
ALUField
,
DPLField
,
DPHField
,
RPField
,
RetField
} OpComps
;
static CPUVar CPU7720
, CPU7725
;
static LongWord ActCode
;
static Boolean InOp
;
static Byte UsedOpFields
;
static Byte TypePos
, ImmValPos
, AddrPos
, ALUPos
, DPLPos
, AccPos
, ALUSrcPos
;
static IntType MemInt
;
static Word ROMEnd
, DROMEnd
, RAMEnd
;
static TReg
*DestRegs
, *SrcRegs
, *ALUSrcRegs
;
static PInstTable OpTable
;
/*---------------------------------------------------------------------------*/
/* Hilfsroutinen */
static Boolean DecodeReg
(char *Asc
, LongWord
*Code
, TReg
*Regs
)
{
int z
;
for (z
= 0; Regs
[z
].
Name; z
++)
if (!as_strcasecmp
(Asc
, Regs
[z
].
Name))
{
*Code
= Regs
[z
].
Code;
return True
;
}
return False
;
}
static Boolean ChkOpPresent
(OpComps Comp
)
{
if ((UsedOpFields
&(1l << Comp
)) != 0)
{
WrError
(ErrNum_InvParAddrMode
); return False
;
}
else
{
UsedOpFields
|= 1l << Comp
; return True
;
}
}
/*---------------------------------------------------------------------------*/
/* Dekoder */
static void DecodeJmp
(Word Code
)
{
Word Dest
;
Boolean OK
;
if (ChkArgCnt
(1, 1))
{
Dest
= EvalStrIntExpression
(&ArgStr
[1], MemInt
, &OK
);
if (OK
)
{
DAsmCode
[0] = (2l << TypePos
) + (((LongWord
)Code
) << 13) + (Dest
<< AddrPos
);
CodeLen
= 1;
}
}
}
static void DecodeDATA_7720
(Word Index
)
{
LongInt MinV
, MaxV
;
TempResult t
;
as_tempres_ini
(&t
);
UNUSED
(Index
);
if (ActPC
== SegCode
)
MaxV
= (MomCPU
>= CPU7725
) ? 16777215 : 8388607;
else
MaxV
= 65535;
MinV
= (-((MaxV
+ 1) >> 1));
if (ChkArgCnt
(1, ArgCntMax
))
{
Boolean OK
= True
;
tStrComp
*pArg
;
forallargs
(pArg
, OK
)
{
EvalStrExpression
(pArg
, &t
);
if (mFirstPassUnknown
(t.
Flags) && (t.
Typ == TempInt
))
t.
Contents.
Int &= MaxV
;
switch (t.
Typ)
{
case TempString
:
{
if (MultiCharToInt
(&t
, 3))
goto ToInt
;
if (as_chartrans_xlate_nonz_dynstr
(CurrTransTable
->p_table
, &t.
Contents.
str, pArg
))
OK
= False
;
else if (ActPC
== SegCode
)
string_2_dasm_code
(&t.
Contents.
str, Packing
? ((MomCPU
>= CPU7725
) ? 3 : 2) : 1, True
);
else
string_2_wasm_code
(&t.
Contents.
str, Packing
? 2 : 1, True
);
break;
}
case TempInt
:
ToInt
:
OK
= ChkRange
(t.
Contents.
Int, MinV
, MaxV
);
if (OK
)
{
if (ActPC
== SegCode
)
DAsmCode
[CodeLen
++] = t.
Contents.
Int & MaxV
;
else
WAsmCode
[CodeLen
++] = t.
Contents.
Int;
}
break;
case TempFloat
:
WrStrErrorPos
(ErrNum_StringOrIntButFloat
, pArg
);
/* fall-through */
default:
OK
= False
;
}
}
}
as_tempres_free
(&t
);
}
static void DecodeRES
(Word Index
)
{
Word Size
;
Boolean OK
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 1))
{
tSymbolFlags Flags
;
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 void DecodeALU2
(Word Code
)
{
LongWord Acc
= 0xff, Src
;
char ch
;
if (!ChkOpPresent
(ALUField
))
return;
if (!ChkArgCnt
(2, 2));
else if (!DecodeReg
(ArgStr
[2].
str.
p_str, &Src
, ALUSrcRegs
)) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[2]);
else
{
if ((strlen(ArgStr
[1].
str.
p_str) == 4) && (!as_strncasecmp
(ArgStr
[1].
str.
p_str, "ACC", 3)))
{
ch
= as_toupper
(ArgStr
[1].
str.
p_str[3]);
if ((ch
>='A') && (ch
<='B'))
Acc
= ch
- 'A';
}
if (Acc
== 0xff)
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
ActCode
|= (((LongWord
)Code
) << ALUPos
) + (Acc
<< AccPos
) + (Src
<< ALUSrcPos
);
}
}
static void DecodeALU1
(Word Code
)
{
LongWord Acc
= 0xff;
char ch
;
if (!ChkOpPresent
(ALUField
))
return;
if (ChkArgCnt
(1, 1))
{
if ((strlen(ArgStr
[1].
str.
p_str) == 4) && (!as_strncasecmp
(ArgStr
[1].
str.
p_str, "ACC", 3)))
{
ch
= as_toupper
(ArgStr
[1].
str.
p_str[3]);
if ((ch
>= 'A') && (ch
<= 'B'))
Acc
= ch
- 'A';
}
if (Acc
== 0xff)
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
ActCode
|= (((LongWord
)Code
) << ALUPos
) + (Acc
<< AccPos
);
}
}
static void DecodeNOP
(Word Index
)
{
UNUSED
(Index
);
if (!ChkOpPresent
(ALUField
))
return;
}
static void DecodeDPL
(Word Index
)
{
if (!ChkOpPresent
(DPLField
))
return;
if (ChkArgCnt
(0, 0))
ActCode
|= (((LongWord
)Index
) << DPLPos
);
}
static void DecodeDPH
(Word Index
)
{
if (!ChkOpPresent
(DPHField
))
return;
if (ChkArgCnt
(0, 0))
ActCode
|= (((LongWord
)Index
) << 9);
}
static void DecodeRP
(Word Index
)
{
if (!ChkOpPresent
(RPField
))
return;
if (ChkArgCnt
(0, 0))
ActCode
|= (((LongWord
)Index
) << 8);
}
static void DecodeRET
(Word Index
)
{
UNUSED
(Index
);
if (!ChkOpPresent
(RetField
))
return;
if (ChkArgCnt
(0, 0))
ActCode
|= (1l << TypePos
);
}
static void DecodeLDI
(Word Index
)
{
LongWord Value
;
LongWord Reg
;
Boolean OK
;
UNUSED
(Index
);
if (!ChkArgCnt
(2, 2));
else if (!DecodeReg
(ArgStr
[1].
str.
p_str, &Reg
, DestRegs
)) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
{
Value
= EvalStrIntExpression
(&ArgStr
[2], Int16
, &OK
);
if (OK
)
{
DAsmCode
[0] = (3l << TypePos
) + Reg
+ (Value
<< ImmValPos
);
CodeLen
= 1;
}
}
}
static void DecodeOP
(Word Index
)
{
char *p
;
int z
;
UNUSED
(Index
);
UsedOpFields
= 0;
ActCode
= 0;
if (ArgCnt
>= 1)
{
p
= FirstBlank
(ArgStr
[1].
str.
p_str);
if (p
)
{
StrCompSplitLeft
(&ArgStr
[1], &OpPart
, p
);
NLS_UpString
(OpPart.
str.
p_str);
KillPrefBlanksStrComp
(&ArgStr
[1]);
}
else
{
StrCompCopy
(&OpPart
, &ArgStr
[1]);
for (z
= 1; z
< ArgCnt
; z
++)
StrCompCopy
(&ArgStr
[z
], &ArgStr
[z
+ 1]);
ArgCnt
--;
}
if (!LookupInstTable
(OpTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
DAsmCode
[0] = ActCode
;
CodeLen
= 1;
}
static void DecodeMOV
(Word Index
)
{
LongWord Dest
, Src
;
UNUSED
(Index
);
if (!ChkOpPresent
(MoveField
))
return;
if (!ChkArgCnt
(2, 2));
else if (!DecodeReg
(ArgStr
[1].
str.
p_str, &Dest
, DestRegs
)) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else if (!DecodeReg
(ArgStr
[2].
str.
p_str, &Src
, SrcRegs
)) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[2]);
else
ActCode
|= Dest
+ (Src
<< 4);
}
/*---------------------------------------------------------------------------*/
/* Tabellenverwaltung */
static void AddJmp
(const char *NName
, Word NCode
)
{
if ((MomCPU
< CPU7725
) && (Odd
(NCode
)))
return;
AddInstTable
(InstTable
, NName
, (MomCPU
== CPU7725
) ? NCode
: NCode
>> 1, DecodeJmp
);
}
static void AddALU2
(const char *NName
, Word NCode
)
{
AddInstTable
(OpTable
, NName
, NCode
, DecodeALU2
);
}
static void AddALU1
(const char *NName
, Word NCode
)
{
AddInstTable
(OpTable
, NName
, NCode
, DecodeALU1
);
}
static void AddDestReg
(const char *NName
, LongWord NCode
)
{
order_array_rsv_end
(DestRegs
, TReg
);
DestRegs
[InstrZ
].
Name = NName
;
DestRegs
[InstrZ
++].
Code = NCode
;
}
static void AddSrcReg
(const char *NName
, LongWord NCode
)
{
order_array_rsv_end
(SrcRegs
, TReg
);
SrcRegs
[InstrZ
].
Name = NName
;
SrcRegs
[InstrZ
++].
Code = NCode
;
}
static void AddALUSrcReg
(const char *NName
, LongWord NCode
)
{
order_array_rsv_end
(ALUSrcRegs
, TReg
);
ALUSrcRegs
[InstrZ
].
Name = NName
;
ALUSrcRegs
[InstrZ
++].
Code = NCode
;
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(101);
OpTable
= CreateInstTable
(79);
AddInstTable
(InstTable
, "LDI", 0, DecodeLDI
);
AddInstTable
(InstTable
, "LD", 0, DecodeLDI
);
AddInstTable
(InstTable
, "OP", 0, DecodeOP
);
AddInstTable
(InstTable
, "DATA", 0, DecodeDATA_7720
);
AddInstTable
(InstTable
, "RES", 0, DecodeRES
);
AddInstTable
(OpTable
, "MOV", 0, DecodeMOV
);
AddInstTable
(OpTable
, "NOP", 0, DecodeNOP
);
AddInstTable
(OpTable
, "DPNOP", 0, DecodeDPL
);
AddInstTable
(OpTable
, "DPINC", 1, DecodeDPL
);
AddInstTable
(OpTable
, "DPDEC", 2, DecodeDPL
);
AddInstTable
(OpTable
, "DPCLR", 3, DecodeDPL
);
AddInstTable
(OpTable
, "M0", 0, DecodeDPH
);
AddInstTable
(OpTable
, "M1", 1, DecodeDPH
);
AddInstTable
(OpTable
, "M2", 2, DecodeDPH
);
AddInstTable
(OpTable
, "M3", 3, DecodeDPH
);
AddInstTable
(OpTable
, "M4", 4, DecodeDPH
);
AddInstTable
(OpTable
, "M5", 5, DecodeDPH
);
AddInstTable
(OpTable
, "M6", 6, DecodeDPH
);
AddInstTable
(OpTable
, "M7", 7, DecodeDPH
);
if (MomCPU
>= CPU7725
)
{
AddInstTable
(OpTable
, "M8", 8, DecodeDPH
);
AddInstTable
(OpTable
, "M9", 9, DecodeDPH
);
AddInstTable
(OpTable
, "MA", 10, DecodeDPH
);
AddInstTable
(OpTable
, "MB", 11, DecodeDPH
);
AddInstTable
(OpTable
, "MC", 12, DecodeDPH
);
AddInstTable
(OpTable
, "MD", 13, DecodeDPH
);
AddInstTable
(OpTable
, "ME", 14, DecodeDPH
);
AddInstTable
(OpTable
, "MF", 15, DecodeDPH
);
}
AddInstTable
(OpTable
, "RPNOP", 0, DecodeRP
);
AddInstTable
(OpTable
, "RPDEC", 1, DecodeRP
);
AddInstTable
(OpTable
, "RET", 1, DecodeRET
);
AddJmp
("JMP" , 0x100); AddJmp
("CALL" , 0x140);
AddJmp
("JNCA" , 0x080); AddJmp
("JCA" , 0x082);
AddJmp
("JNCB" , 0x084); AddJmp
("JCB" , 0x086);
AddJmp
("JNZA" , 0x088); AddJmp
("JZA" , 0x08a);
AddJmp
("JNZB" , 0x08c); AddJmp
("JZB" , 0x08e);
AddJmp
("JNOVA0", 0x090); AddJmp
("JOVA0" , 0x092);
AddJmp
("JNOVB0", 0x094); AddJmp
("JOVB0" , 0x096);
AddJmp
("JNOVA1", 0x098); AddJmp
("JOVA1" , 0x09a);
AddJmp
("JNOVB1", 0x09c); AddJmp
("JOVB1" , 0x09e);
AddJmp
("JNSA0" , 0x0a0); AddJmp
("JSA0" , 0x0a2);
AddJmp
("JNSB0" , 0x0a4); AddJmp
("JSB0" , 0x0a6);
AddJmp
("JNSA1" , 0x0a8); AddJmp
("JSA1" , 0x0aa);
AddJmp
("JNSB1" , 0x0ac); AddJmp
("JSB1" , 0x0ae);
AddJmp
("JDPL0" , 0x0b0); AddJmp
("JDPLF" , 0x0b2);
AddJmp
("JNSIAK", 0x0b4); AddJmp
("JSIAK" , 0x0b6);
AddJmp
("JNSOAK", 0x0b8); AddJmp
("JSOAK" , 0x0ba);
AddJmp
("JNRQM" , 0x0bc); AddJmp
("JRQM" , 0x0be);
AddJmp
("JDPLN0", 0x0b1); AddJmp
("JDPLNF" , 0x0b3);
AddALU2
("OR" , 1); AddALU2
("AND" , 2); AddALU2
("XOR" , 3);
AddALU2
("SUB" , 4); AddALU2
("ADD" , 5); AddALU2
("SBB" , 6);
AddALU2
("ADC" , 7); AddALU2
("CMP" ,10);
AddALU1
("DEC" , 8); AddALU1
("INC" , 9); AddALU1
("SHR1", 11);
AddALU1
("SHL1", 12); AddALU1
("SHL2", 13); AddALU1
("SHL4", 14);
AddALU1
("XCHG", 15);
InstrZ
= 0;
AddDestReg
("@NON", 0); AddDestReg
("@A" , 1);
AddDestReg
("@B" , 2); AddDestReg
("@TR" , 3);
AddDestReg
("@DP" , 4); AddDestReg
("@RP" , 5);
AddDestReg
("@DR" , 6); AddDestReg
("@SR" , 7);
AddDestReg
("@SOL", 8); AddDestReg
("@SOM", 9);
AddDestReg
("@K" , 10); AddDestReg
("@KLR", 11);
AddDestReg
("@KLM", 12); AddDestReg
("@L" , 13);
if (MomCPU
== CPU7725
) AddDestReg
("@TRB", 14);
AddDestReg
("@MEM", 15);
AddDestReg
(NULL
, 0);
InstrZ
= 0;
AddSrcReg
("NON" , 0); AddSrcReg
("A" , 1);
AddSrcReg
("B" , 2); AddSrcReg
("TR" , 3);
AddSrcReg
("DP" , 4); AddSrcReg
("RP" , 5);
AddSrcReg
("RO" , 6); AddSrcReg
("SGN" , 7);
AddSrcReg
("DR" , 8); AddSrcReg
("DRNF", 9);
AddSrcReg
("SR" , 10); AddSrcReg
("SIM" , 11);
AddSrcReg
("SIL" , 12); AddSrcReg
("K" , 13);
AddSrcReg
("L" , 14); AddSrcReg
("MEM" , 15);
AddSrcReg
(NULL
, 0);
InstrZ
= 0;
AddALUSrcReg
("RAM", 0); AddALUSrcReg
("IDB", 1);
AddALUSrcReg
("M" , 2); AddALUSrcReg
("N" , 3);
AddALUSrcReg
(NULL
, 0);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
DestroyInstTable
(OpTable
);
order_array_free
(DestRegs
);
order_array_free
(SrcRegs
);
order_array_free
(ALUSrcRegs
);
}
/*---------------------------------------------------------------------------*/
/* Callbacks */
static void MakeCode_7720
(void)
{
Boolean NextOp
;
/* Nullanweisung */
if (Memo
("") && !*AttrPart.
str.
p_str && (ArgCnt
== 0))
return;
/* direkte Anweisungen */
NextOp
= Memo
("OP");
if (LookupInstTable
(InstTable
, OpPart.
str.
p_str))
{
InOp
= NextOp
; return;
}
/* wenn eine parallele Op-Anweisung offen ist, noch deren Komponenten testen */
if ((InOp
) && (LookupInstTable
(OpTable
, OpPart.
str.
p_str)))
{
RetractWords
(1);
DAsmCode
[0] = ActCode
;
CodeLen
= 1;
return;
}
/* Hae??? */
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_7720
(void)
{
return False
;
}
static void SwitchFrom_7720
(void)
{
DeinitFields
();
}
static void SwitchTo_7720
(void)
{
const TFamilyDescr
*FoundDescr
;
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
if (MomCPU
== CPU7725
)
{
FoundDescr
= FindFamilyByName
("7725");
MemInt
= UInt11
;
ROMEnd
= 0x7ff; DROMEnd
= 0x3ff; RAMEnd
= 0xff;
TypePos
= 22;
ImmValPos
= 6;
AddrPos
= 2;
ALUPos
= 16;
DPLPos
= 13;
AccPos
= 15;
ALUSrcPos
= 20;
}
else
{
FoundDescr
= FindFamilyByName
("7720");
MemInt
= UInt9
;
ROMEnd
= 0x1ff; DROMEnd
= 0x1ff; RAMEnd
= 0x7f;
TypePos
= 21;
ImmValPos
= 5;
AddrPos
= 4;
ALUPos
= 15;
DPLPos
= 12;
AccPos
= 14;
ALUSrcPos
= 19;
}
PCSymbol
= "$";
HeaderID
= FoundDescr
->Id
;
NOPCode
= 0x000000;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= (1l << SegCode
) | (1l << SegData
) | (1l << SegRData
);
Grans
[SegCode
] = 4; ListGrans
[SegCode
] = 4; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = ROMEnd
;
Grans
[SegData
] = 2; ListGrans
[SegData
] = 2; SegInits
[SegData
] = 0;
SegLimits
[SegData
] = RAMEnd
;
Grans
[SegRData
] = 2; ListGrans
[SegRData
] = 2; SegInits
[SegRData
] = 0;
SegLimits
[SegRData
] = DROMEnd
;
MakeCode
= MakeCode_7720
;
IsDef
= IsDef_7720
;
SwitchFrom
= SwitchFrom_7720
;
onoff_packing_add
(True
);
InOp
= False
;
UsedOpFields
= 0;
ActCode
= 0;
InitFields
();
}
/*---------------------------------------------------------------------------*/
/* Initialisierung */
void code7720_init
(void)
{
CPU7720
= AddCPU
("7720", SwitchTo_7720
);
CPU7725
= AddCPU
("7725", SwitchTo_7720
);
}