Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
/* code68.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator fuer 68xx Prozessoren */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmpars.h"
#include "asmallg.h"
#include "asmsub.h"
#include "errmsg.h"
#include "codepseudo.h"
#include "motpseudo.h"
#include "asmitree.h"
#include "codevars.h"
#include "cpu2phys.h"
#include "function.h"
#include "nlmessages.h"
#include "as.rsc"
#include "code68.h"
/*---------------------------------------------------------------------------*/
typedef struct
{
CPUVar MinCPU
, MaxCPU
;
Word Code
;
} FixedOrder
;
typedef struct
{
CPUVar MinCPU
;
Word Code
;
} RelOrder
;
typedef struct
{
Boolean MayImm
;
CPUVar MinCPU
; /* Shift andere ,Y */
Byte PageShift
; /* 0 : nix Pg 2 */
Byte Code
; /* 1 : Pg 3 Pg 4 */
} ALU16Order
; /* 2 : nix Pg 4 */
/* 3 : Pg 2 Pg 3 */
enum
{
ModNone
= -1,
ModAcc
= 0,
ModDir
= 1,
ModExt
= 2,
ModInd
= 3,
ModImm
= 4
};
#define MModAcc (1 << ModAcc)
#define MModDir (1 << ModDir)
#define MModExt (1 << ModExt)
#define MModInd (1 << ModInd)
#define MModImm (1 << ModImm)
#define Page2Prefix 0x18
#define Page3Prefix 0x1a
#define Page4Prefix 0xcd
static tSymbolSize OpSize
;
static Byte PrefCnt
; /* Anzahl Befehlspraefixe */
static ShortInt AdrMode
; /* Ergebnisadressmodus */
static Byte AdrPart
; /* Adressierungsmodusbits im Opcode */
static Byte AdrVals
[4]; /* Adressargument */
static FixedOrder
*FixedOrders
;
static RelOrder
*RelOrders
;
static ALU16Order
*ALU16Orders
;
static LongInt Reg_MMSIZ
, Reg_MMWBR
, Reg_MM1CR
, Reg_MM2CR
, Reg_INIT
, Reg_INIT2
, Reg_CONFIG
;
static CPUVar CPU6800
, CPU6801
, CPU6301
, CPU6811
, CPU68HC11K4
;
/*---------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn compute_window(Byte w_size_code, Byte cpu_start_code, LongInt phys_start_code, LongWord phys_offset)
* \brief compute single window from MMU registers
* \param w_size_code MMSIZ bits (0..3)
* \param cpu_start_code Reg_MMWBR bits (0,2,4,6...14)
* \param phys_start_code Reg_MMxCR bits
* \param phys_offset offset in physical space
* ------------------------------------------------------------------------ */
static void compute_window
(Byte w_size_code
, Byte cpu_start_code
, LongInt phys_start_code
, LongWord phys_offset
)
{
if (w_size_code
)
{
Word size
, cpu_start
;
LongWord phys_start
;
/* window size */
size
= 0x1000 << w_size_code
;
/* CPU space start address: assume 8K window, systematically clip out bits for
larger windows */
cpu_start
= (Word
)cpu_start_code
<< 12;
if (w_size_code
> 1)
cpu_start
&= ~
0x2000;
if (w_size_code
> 2)
cpu_start
= (cpu_start
== 0xc000) ? 0x8000 : cpu_start
;
/* physical space start: mask out lower bits according to window size */
phys_start
= ((phys_start_code
& 0x7f & (~
((1 << w_size_code
) - 1))) << 12) + phys_offset
;
/* set addresses */
cpu_2_phys_area_add
(SegCode
, cpu_start
, phys_start
, size
);
}
}
static void SetK4Ranges
(void)
{
Word ee_bank
, io_bank
, ram_bank
;
cpu_2_phys_area_clear
(SegCode
);
/* Add window 1 after window 2, since it has higher priority and may partially overlap window 2 */
compute_window
((Reg_MMSIZ
>> 4) & 0x3, (Reg_MMWBR
>> 4) & 0x0e, Reg_MM2CR
, 0x90000);
compute_window
(Reg_MMSIZ
& 0x3, Reg_MMWBR
& 0x0e, Reg_MM1CR
, 0x10000);
/* Internal registers, RAM and EEPROM (if enabled) have priority in CPU address space: */
if (Reg_CONFIG
& 1)
{
ee_bank
= ((Reg_INIT
& 15) << 12) + 0x0d80;
cpu_2_phys_area_add
(SegCode
, ee_bank
, ee_bank
, 640);
}
io_bank
= (Reg_INIT
& 15) << 12;
cpu_2_phys_area_add
(SegCode
, io_bank
, io_bank
, 128);
/* If RAM position overlaps registers, 128 bytes of RAM get relocated to upper end: */
ram_bank
= ((Reg_INIT
>> 4) & 15) << 12;
if (ram_bank
== io_bank
)
ram_bank
+= 128;
cpu_2_phys_area_add
(SegCode
, ram_bank
, ram_bank
, 768);
/* Fill the remainder of CPU address space with 1:1 mappings: */
cpu_2_phys_area_fill
(SegCode
, 0x0000, 0xffff);
}
/*---------------------------------------------------------------------------*/
static Boolean DecodeAcc
(const char *pArg
, Byte
*pReg
)
{
static const char Regs
[] = "AB";
if (strlen(pArg
) == 1)
{
const char *pPos
= strchr(Regs
, as_toupper
(*pArg
));
if (pPos
)
{
*pReg
= pPos
- Regs
;
return True
;
}
}
return False
;
}
static void DecodeAdr
(int StartInd
, int StopInd
, Byte Erl
)
{
tStrComp
*pStartArg
= &ArgStr
[StartInd
];
Boolean OK
, ErrOcc
;
tSymbolFlags Flags
;
Word AdrWord
;
Byte Bit8
;
AdrMode
= ModNone
;
AdrPart
= 0;
ErrOcc
= False
;
/* eine Komponente ? */
if (StartInd
== StopInd
)
{
/* Akkumulatoren ? */
if (DecodeAcc
(pStartArg
->str.
p_str, &AdrPart
))
{
if (MModAcc
& Erl
)
AdrMode
= ModAcc
;
}
/* immediate ? */
else if ((strlen(pStartArg
->str.
p_str) > 1) && (*pStartArg
->str.
p_str == '#'))
{
if (MModImm
& Erl
)
{
if (OpSize
== eSymbolSize16Bit
)
{
AdrWord
= EvalStrIntExpressionOffs
(pStartArg
, 1, Int16
, &OK
);
if (OK
)
{
AdrMode
= ModImm
;
AdrVals
[AdrCnt
++] = Hi
(AdrWord
);
AdrVals
[AdrCnt
++] = Lo
(AdrWord
);
}
else
ErrOcc
= True
;
}
else
{
AdrVals
[AdrCnt
] = EvalStrIntExpressionOffs
(pStartArg
, 1, Int8
, &OK
);
if (OK
)
{
AdrMode
= ModImm
;
AdrCnt
++;
}
else
ErrOcc
= True
;
}
}
}
/* absolut ? */
else
{
unsigned Offset
= 0;
Bit8
= 0;
if (pStartArg
->str.
p_str[Offset
] == '<')
{
Bit8
= 2;
Offset
++;
}
else if (pStartArg
->str.
p_str[Offset
] == '>')
{
Bit8
= 1;
Offset
++;
}
if (MomCPU
== CPU68HC11K4
)
{
LargeWord AdrLWord
= EvalStrIntExpressionOffsWithFlags
(pStartArg
, Offset
, UInt21
, &OK
, &Flags
);
if (OK
)
{
if (!def_phys_2_cpu
(SegCode
, &AdrLWord
))
{
WrError
(ErrNum_InAccPage
);
AdrWord
= AdrLWord
& 0xffffu
;
}
else
AdrWord
= AdrLWord
;
}
}
else
AdrWord
= EvalStrIntExpressionOffsWithFlags
(pStartArg
, Offset
, UInt16
, &OK
, &Flags
);
if (OK
)
{
if ((MModDir
& Erl
) && (Bit8
!= 1) && ((Bit8
== 2) || (!(MModExt
& Erl
)) || (Hi
(AdrWord
) == 0)))
{
if ((Hi
(AdrWord
) != 0) && !mFirstPassUnknown
(Flags
))
{
WrError
(ErrNum_NoShortAddr
);
ErrOcc
= True
;
}
else
{
AdrMode
= ModDir
;
AdrPart
= 1;
AdrVals
[AdrCnt
++] = Lo
(AdrWord
);
}
}
else if ((MModExt
& Erl
)!=0)
{
AdrMode
= ModExt
;
AdrPart
= 3;
AdrVals
[AdrCnt
++] = Hi
(AdrWord
);
AdrVals
[AdrCnt
++] = Lo
(AdrWord
);
}
}
else
ErrOcc
= True
;
}
}
/* zwei Komponenten ? */
else if (StartInd
+ 1 == StopInd
)
{
Boolean IsX
= !as_strcasecmp
(ArgStr
[StopInd
].
str.
p_str, "X"),
IsY
= !as_strcasecmp
(ArgStr
[StopInd
].
str.
p_str, "Y");
/* indiziert ? */
if (IsX
|| IsY
)
{
if (MModInd
& Erl
)
{
AdrWord
= EvalStrIntExpression
(pStartArg
, UInt8
, &OK
);
if (OK
)
{
if (IsY
&& !ChkMinCPUExt
(CPU6811
, ErrNum_AddrModeNotSupported
))
ErrOcc
= True
;
else
{
AdrVals
[AdrCnt
++] = Lo
(AdrWord
);
AdrMode
= ModInd
;
AdrPart
= 2;
if (IsY
)
{
BAsmCode
[PrefCnt
++] = 0x18;
}
}
}
else
ErrOcc
= True
;
}
}
else
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[StopInd
]);
ErrOcc
= True
;
}
}
else
{
char Str
[100];
as_snprintf
(Str
, sizeof(Str
), getmessage
(Num_ErrMsgAddrArgCnt
), 1, 2, StopInd
- StartInd
+ 1);
WrXError
(ErrNum_WrongArgCnt
, Str
);
ErrOcc
= True
;
}
if ((!ErrOcc
) && (AdrMode
== ModNone
))
WrError
(ErrNum_InvAddrMode
);
}
static void AddPrefix
(Byte Prefix
)
{
BAsmCode
[PrefCnt
++] = Prefix
;
}
static void Try2Split
(int Src
)
{
char *p
;
size_t SrcLen
;
KillPrefBlanksStrComp
(&ArgStr
[Src
]);
KillPostBlanksStrComp
(&ArgStr
[Src
]);
SrcLen
= strlen(ArgStr
[Src
].
str.
p_str);
p
= ArgStr
[Src
].
str.
p_str + SrcLen
- 1;
while ((p
> ArgStr
[Src
].
str.
p_str) && !as_isspace
(*p
))
p
--;
if (p
> ArgStr
[Src
].
str.
p_str)
{
InsertArg
(Src
+ 1, SrcLen
);
StrCompSplitRight
(&ArgStr
[Src
], &ArgStr
[Src
+ 1], p
);
KillPostBlanksStrComp
(&ArgStr
[Src
]);
KillPrefBlanksStrComp
(&ArgStr
[Src
+ 1]);
}
}
/*---------------------------------------------------------------------------*/
static void DecodeFixed
(Word Index
)
{
const FixedOrder
*forder
= FixedOrders
+ Index
;
if (!ChkArgCnt
(0, 0));
else if (!ChkRangeCPU
(forder
->MinCPU
, forder
->MaxCPU
));
else if (Hi
(forder
->Code
) != 0)
{
CodeLen
= 2;
BAsmCode
[0] = Hi
(forder
->Code
);
BAsmCode
[1] = Lo
(forder
->Code
);
}
else
{
CodeLen
= 1;
BAsmCode
[0] = Lo
(forder
->Code
);
}
}
static void DecodeRel
(Word Index
)
{
const RelOrder
*pOrder
= &RelOrders
[Index
];
Integer AdrInt
;
Boolean OK
;
tSymbolFlags Flags
;
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(pOrder
->MinCPU
))
{
AdrInt
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], Int16
, &OK
, &Flags
);
if (OK
)
{
AdrInt
-= EProgCounter
() + 2;
if (((AdrInt
< -128) || (AdrInt
> 127)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
CodeLen
= 2;
BAsmCode
[0] = pOrder
->Code
;
BAsmCode
[1] = Lo
(AdrInt
);
}
}
}
}
static void DecodeALU16
(Word Index
)
{
const ALU16Order
*forder
= ALU16Orders
+ Index
;
OpSize
= eSymbolSize16Bit
;
if (ChkArgCnt
(1, 2)
&& ChkMinCPU
(forder
->MinCPU
))
{
DecodeAdr
(1, ArgCnt
, (forder
->MayImm
? MModImm
: 0) | MModInd
| MModExt
| MModDir
);
if (AdrMode
!= ModNone
)
{
switch (forder
->PageShift
)
{
case 1:
if (PrefCnt
== 1)
BAsmCode
[PrefCnt
- 1] = Page4Prefix
;
else
AddPrefix
(Page3Prefix
);
break;
case 2:
if (PrefCnt
== 1)
BAsmCode
[PrefCnt
- 1] = Page4Prefix
;
break;
case 3:
if (PrefCnt
== 0)
AddPrefix
((AdrMode
== ModInd
) ? Page3Prefix
: Page2Prefix
);
break;
}
BAsmCode
[PrefCnt
] = forder
->Code
+ (AdrPart
<< 4);
CodeLen
= PrefCnt
+ 1 + AdrCnt
;
memcpy(BAsmCode
+ 1 + PrefCnt
, AdrVals
, AdrCnt
);
}
}
}
static void DecodeBit63
(Word Code
)
{
if (ChkArgCnt
(2, 3)
&& ChkExactCPU
(CPU6301
))
{
DecodeAdr
(1, 1, MModImm
);
if (AdrMode
!= ModNone
)
{
DecodeAdr
(2, ArgCnt
, MModDir
| MModInd
);
if (AdrMode
!= ModNone
)
{
BAsmCode
[PrefCnt
] = Code
;
if (AdrMode
== ModDir
)
BAsmCode
[PrefCnt
] |= 0x10;
CodeLen
= PrefCnt
+ 1 + AdrCnt
;
memcpy(BAsmCode
+ 1 + PrefCnt
, AdrVals
, AdrCnt
);
}
}
}
}
static void DecodeJMP
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(1, 2))
{
DecodeAdr
(1, ArgCnt
, MModExt
| MModInd
);
if (AdrMode
!= ModImm
)
{
CodeLen
= PrefCnt
+ 1 + AdrCnt
;
BAsmCode
[PrefCnt
] = 0x4e + (AdrPart
<< 4);
memcpy(BAsmCode
+ 1 + PrefCnt
, AdrVals
, AdrCnt
);
}
}
}
static void DecodeJSR
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(1, 2))
{
DecodeAdr
(1, ArgCnt
, MModExt
| MModInd
| ((MomCPU
>= CPU6801
) ? MModDir
: 0));
if (AdrMode
!= ModImm
)
{
CodeLen
=PrefCnt
+ 1 + AdrCnt
;
BAsmCode
[PrefCnt
] = 0x8d + (AdrPart
<< 4);
memcpy(BAsmCode
+ 1 + PrefCnt
, AdrVals
, AdrCnt
);
}
}
}
static void DecodeBRxx
(Word Index
)
{
Boolean OK
;
Byte Mask
;
Integer AdrInt
;
if (ArgCnt
== 1)
{
Try2Split
(1);
Try2Split
(1);
}
else if (ArgCnt
== 2)
{
Try2Split
(ArgCnt
);
Try2Split
(2);
}
if (ChkArgCnt
(3, 4)
&& ChkMinCPU
(CPU6811
))
{
Mask
= EvalStrIntExpressionOffs
(&ArgStr
[ArgCnt
- 1], !!(*ArgStr
[ArgCnt
- 1].
str.
p_str == '#'), Int8
, &OK
);
if (OK
)
{
DecodeAdr
(1, ArgCnt
- 2, MModDir
| MModInd
);
if (AdrMode
!= ModNone
)
{
AdrInt
= EvalStrIntExpression
(&ArgStr
[ArgCnt
], Int16
, &OK
);
if (OK
)
{
AdrInt
-= EProgCounter
() + 3 + PrefCnt
+ AdrCnt
;
if ((AdrInt
< -128) || (AdrInt
> 127)) WrError
(ErrNum_JmpDistTooBig
);
else
{
CodeLen
= PrefCnt
+ 3 + AdrCnt
;
BAsmCode
[PrefCnt
] = 0x12 + Index
;
if (AdrMode
== ModInd
)
BAsmCode
[PrefCnt
] += 12;
memcpy(BAsmCode
+ PrefCnt
+ 1, AdrVals
, AdrCnt
);
BAsmCode
[PrefCnt
+ 1 + AdrCnt
] = Mask
;
BAsmCode
[PrefCnt
+ 2 + AdrCnt
] = Lo
(AdrInt
);
}
}
}
}
}
}
static void DecodeBxx
(Word Index
)
{
Byte Mask
;
Boolean OK
;
int AddrStart
, AddrEnd
;
tStrComp
*pMaskArg
;
if (MomCPU
== CPU6301
)
{
pMaskArg
= &ArgStr
[1];
AddrStart
= 2;
AddrEnd
= ArgCnt
;
}
else
{
if ((ArgCnt
>= 1) && (ArgCnt
<= 2)) Try2Split
(ArgCnt
);
pMaskArg
= &ArgStr
[ArgCnt
];
AddrStart
= 1;
AddrEnd
= ArgCnt
- 1;
}
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPU6301
))
{
Mask
= EvalStrIntExpressionOffs
(pMaskArg
, !!(*pMaskArg
->str.
p_str == '#'),
(MomCPU
== CPU6301
) ? UInt3
: Int8
, &OK
);
if (OK
&& (MomCPU
== CPU6301
))
{
Mask
= 1 << Mask
;
if (Index
== 1) Mask
= 0xff - Mask
;
}
if (OK
)
{
DecodeAdr
(AddrStart
, AddrEnd
, MModDir
| MModInd
);
if (AdrMode
!= ModNone
)
{
CodeLen
= PrefCnt
+ 2 + AdrCnt
;
if (MomCPU
== CPU6301
)
{
BAsmCode
[PrefCnt
] = 0x62 - Index
;
if (AdrMode
== ModDir
)
BAsmCode
[PrefCnt
] += 0x10;
BAsmCode
[1 + PrefCnt
] = Mask
;
memcpy(BAsmCode
+ 2 + PrefCnt
, AdrVals
, AdrCnt
);
}
else
{
BAsmCode
[PrefCnt
] = 0x14 + Index
;
if (AdrMode
== ModInd
)
BAsmCode
[PrefCnt
] += 8;
memcpy(BAsmCode
+ 1 + PrefCnt
, AdrVals
, AdrCnt
);
BAsmCode
[1 + PrefCnt
+ AdrCnt
] = Mask
;
}
}
}
}
}
static void DecodeBTxx
(Word Index
)
{
Boolean OK
;
Byte AdrByte
;
if (ChkArgCnt
(2, 3)
&& ChkExactCPU
(CPU6301
))
{
AdrByte
= EvalStrIntExpressionOffs
(&ArgStr
[1], !!(*ArgStr
[1].
str.
p_str == '#'), UInt3
, &OK
);
if (OK
)
{
DecodeAdr
(2, ArgCnt
, MModDir
| MModInd
);
if (AdrMode
!= ModNone
)
{
CodeLen
= PrefCnt
+ 2 + AdrCnt
;
BAsmCode
[1 + PrefCnt
] = 1 << AdrByte
;
memcpy(BAsmCode
+ 2 + PrefCnt
, AdrVals
, AdrCnt
);
BAsmCode
[PrefCnt
] = 0x65 + Index
;
if (AdrMode
== ModDir
)
BAsmCode
[PrefCnt
] += 0x10;
}
}
}
}
static void DecodeALU8
(Word Code
)
{
Byte Reg
;
int MinArgCnt
= Hi
(Code
) & 3;
/* dirty hack: LDA/STA/ORA, and first arg is not A or B, treat like LDAA/STAA/ORAA: */
if ((MinArgCnt
== 2)
&& (as_toupper
(OpPart.
str.
p_str[2]) == 'A')
&& (ArgCnt
>= 1)
&& !DecodeAcc
(ArgStr
[1].
str.
p_str, &Reg
))
MinArgCnt
= 1;
if (ChkArgCnt
(MinArgCnt
, MinArgCnt
+ 1))
{
DecodeAdr
(MinArgCnt
, ArgCnt
, ((Code
& 0x8000) ? MModImm
: 0) | MModInd
| MModExt
| MModDir
);
if (AdrMode
!= ModNone
)
{
BAsmCode
[PrefCnt
] = Lo
(Code
) | (AdrPart
<< 4);
if (MinArgCnt
== 1)
{
AdrMode
= ModAcc
;
AdrPart
= (Code
& 0x4000) >> 14;
}
else
DecodeAdr
(1, 1, MModAcc
);
if (AdrMode
!= ModNone
)
{
BAsmCode
[PrefCnt
] |= AdrPart
<< 6;
CodeLen
= PrefCnt
+ 1 + AdrCnt
;
memcpy(BAsmCode
+ 1 + PrefCnt
, AdrVals
, AdrCnt
);
}
}
}
}
static void DecodeSing8
(Word Code
)
{
if (ChkArgCnt
(1, 2))
{
DecodeAdr
(1, ArgCnt
, MModAcc
| MModExt
| MModInd
);
if (AdrMode
!=ModNone
)
{
CodeLen
= PrefCnt
+ 1 + AdrCnt
;
BAsmCode
[PrefCnt
] = Code
| (AdrPart
<< 4);
memcpy(BAsmCode
+ 1 + PrefCnt
, AdrVals
, AdrCnt
);
}
}
}
static void DecodeSing8_Acc
(Word Code
)
{
if (ChkArgCnt
(0, 0))
{
BAsmCode
[PrefCnt
] = Code
;
CodeLen
= PrefCnt
+ 1;
}
}
static void DecodePSH_PUL
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
DecodeAdr
(1, 1, MModAcc
);
if (AdrMode
!= ModNone
)
{
CodeLen
= 1;
BAsmCode
[0]=Code
| AdrPart
;
}
}
}
static void DecodePRWINS
(Word Code
)
{
UNUSED
(Code
);
if (ChkExactCPU
(CPU68HC11K4
))
{
printf("\nMMSIZ $%02x MMWBR $%02x MM1CR $%02x MM2CR $%02x INIT $%02x INIT2 $%02x CONFIG $%02x\n",
(unsigned)Reg_MMSIZ
, (unsigned)Reg_MMWBR
, (unsigned)Reg_MM1CR
, (unsigned)Reg_MM2CR
,
(unsigned)Reg_INIT
, (unsigned)Reg_INIT2
, (unsigned)Reg_CONFIG
);
cpu_2_phys_area_dump
(SegCode
, stdout
);
}
}
/*---------------------------------------------------------------------------*/
static void AddFixed
(const char *NName
, CPUVar NMin
, CPUVar NMax
, Word NCode
)
{
order_array_rsv_end
(FixedOrders
, FixedOrder
);
FixedOrders
[InstrZ
].
MinCPU = NMin
;
FixedOrders
[InstrZ
].
MaxCPU = NMax
;
FixedOrders
[InstrZ
].
Code = NCode
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeFixed
);
}
static void AddRel
(const char *NName
, CPUVar NMin
, Word NCode
)
{
order_array_rsv_end
(RelOrders
, RelOrder
);
RelOrders
[InstrZ
].
MinCPU = NMin
;
RelOrders
[InstrZ
].
Code = NCode
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeRel
);
}
static void AddALU8
(const char *NamePlain
, const char *NameA
, const char *NameB
, const char *NameB2
, Boolean MayImm
, Byte NCode
)
{
Word BaseCode
= NCode
| (MayImm
? 0x8000 : 0);
AddInstTable
(InstTable
, NamePlain
, BaseCode
| (2 << 8), DecodeALU8
);
AddInstTable
(InstTable
, NameA
, BaseCode
| (1 << 8), DecodeALU8
);
AddInstTable
(InstTable
, NameB
, BaseCode
| (1 << 8) | 0x4000, DecodeALU8
);
if (NameB2
)
AddInstTable
(InstTable
, NameB2
, BaseCode
| (1 << 8) | 0x4000, DecodeALU8
);
}
static void AddALU16
(const char *NName
, Boolean NMay
, CPUVar NMin
, Byte NShift
, Byte NCode
)
{
order_array_rsv_end
(ALU16Orders
, ALU16Order
);
ALU16Orders
[InstrZ
].
MayImm = NMay
;
ALU16Orders
[InstrZ
].
MinCPU = NMin
;
ALU16Orders
[InstrZ
].
PageShift = NShift
;
ALU16Orders
[InstrZ
].
Code = NCode
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeALU16
);
}
static void AddSing8
(const char *NamePlain
, const char *NameA
, const char *NameB
, Byte NCode
)
{
AddInstTable
(InstTable
, NamePlain
, NCode
, DecodeSing8
);
AddInstTable
(InstTable
, NameA
, NCode
| 0, DecodeSing8_Acc
);
AddInstTable
(InstTable
, NameB
, NCode
| 0x10, DecodeSing8_Acc
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(317);
AddInstTable
(InstTable
, "JMP" , 0, DecodeJMP
);
AddInstTable
(InstTable
, "JSR" , 0, DecodeJSR
);
AddInstTable
(InstTable
, "BRCLR", 1, DecodeBRxx
);
AddInstTable
(InstTable
, "BRSET", 0, DecodeBRxx
);
AddInstTable
(InstTable
, "BCLR" , 1, DecodeBxx
);
AddInstTable
(InstTable
, "BSET" , 0, DecodeBxx
);
AddInstTable
(InstTable
, "BTST" , 6, DecodeBTxx
);
AddInstTable
(InstTable
, "BTGL" , 0, DecodeBTxx
);
InstrZ
= 0;
AddFixed
("ABA" ,CPU6800
, CPU68HC11K4
, 0x001b); AddFixed
("ABX" ,CPU6801
, CPU68HC11K4
, 0x003a);
AddFixed
("ABY" ,CPU6811
, CPU68HC11K4
, 0x183a); AddFixed
("ASLD" ,CPU6801
, CPU68HC11K4
, 0x0005);
AddFixed
("CBA" ,CPU6800
, CPU68HC11K4
, 0x0011); AddFixed
("CLC" ,CPU6800
, CPU68HC11K4
, 0x000c);
AddFixed
("CLI" ,CPU6800
, CPU68HC11K4
, 0x000e); AddFixed
("CLV" ,CPU6800
, CPU68HC11K4
, 0x000a);
AddFixed
("DAA" ,CPU6800
, CPU68HC11K4
, 0x0019); AddFixed
("DES" ,CPU6800
, CPU68HC11K4
, 0x0034);
AddFixed
("DEX" ,CPU6800
, CPU68HC11K4
, 0x0009); AddFixed
("DEY" ,CPU6811
, CPU68HC11K4
, 0x1809);
AddFixed
("FDIV" ,CPU6811
, CPU68HC11K4
, 0x0003); AddFixed
("IDIV" ,CPU6811
, CPU68HC11K4
, 0x0002);
AddFixed
("INS" ,CPU6800
, CPU68HC11K4
, 0x0031); AddFixed
("INX" ,CPU6800
, CPU68HC11K4
, 0x0008);
AddFixed
("INY" ,CPU6811
, CPU68HC11K4
, 0x1808); AddFixed
("LSLD" ,CPU6801
, CPU68HC11K4
, 0x0005);
AddFixed
("LSRD" ,CPU6801
, CPU68HC11K4
, 0x0004); AddFixed
("MUL" ,CPU6801
, CPU68HC11K4
, 0x003d);
AddFixed
("NOP" ,CPU6800
, CPU68HC11K4
, 0x0001); AddFixed
("PSHX" ,CPU6801
, CPU68HC11K4
, 0x003c);
AddFixed
("PSHY" ,CPU6811
, CPU68HC11K4
, 0x183c); AddFixed
("PULX" ,CPU6801
, CPU68HC11K4
, 0x0038);
AddFixed
("PULY" ,CPU6811
, CPU68HC11K4
, 0x1838); AddFixed
("RTI" ,CPU6800
, CPU68HC11K4
, 0x003b);
AddFixed
("RTS" ,CPU6800
, CPU68HC11K4
, 0x0039); AddFixed
("SBA" ,CPU6800
, CPU68HC11K4
, 0x0010);
AddFixed
("SEC" ,CPU6800
, CPU68HC11K4
, 0x000d); AddFixed
("SEI" ,CPU6800
, CPU68HC11K4
, 0x000f);
AddFixed
("SEV" ,CPU6800
, CPU68HC11K4
, 0x000b); AddFixed
("SLP" ,CPU6301
, CPU6301
, 0x001a);
AddFixed
("STOP" ,CPU6811
, CPU68HC11K4
, 0x00cf); AddFixed
("SWI" ,CPU6800
, CPU68HC11K4
, 0x003f);
AddFixed
("TAB" ,CPU6800
, CPU68HC11K4
, 0x0016); AddFixed
("TAP" ,CPU6800
, CPU68HC11K4
, 0x0006);
AddFixed
("TBA" ,CPU6800
, CPU68HC11K4
, 0x0017); AddFixed
("TPA" ,CPU6800
, CPU68HC11K4
, 0x0007);
AddFixed
("TSX" ,CPU6800
, CPU68HC11K4
, 0x0030); AddFixed
("TSY" ,CPU6811
, CPU68HC11K4
, 0x1830);
AddFixed
("TXS" ,CPU6800
, CPU68HC11K4
, 0x0035); AddFixed
("TYS" ,CPU6811
, CPU68HC11K4
, 0x1835);
AddFixed
("WAI" ,CPU6800
, CPU68HC11K4
, 0x003e);
AddFixed
("XGDX" ,CPU6301
, CPU68HC11K4
, (MomCPU
== CPU6301
) ? 0x0018 : 0x008f);
AddFixed
("XGDY" ,CPU6811
, CPU68HC11K4
, 0x188f);
InstrZ
= 0;
AddRel
("BCC", CPU6800
, 0x24);
AddRel
("BCS", CPU6800
, 0x25);
AddRel
("BEQ", CPU6800
, 0x27);
AddRel
("BGE", CPU6800
, 0x2c);
AddRel
("BGT", CPU6800
, 0x2e);
AddRel
("BHI", CPU6800
, 0x22);
AddRel
("BHS", CPU6800
, 0x24);
AddRel
("BLE", CPU6800
, 0x2f);
AddRel
("BLO", CPU6800
, 0x25);
AddRel
("BLS", CPU6800
, 0x23);
AddRel
("BLT", CPU6800
, 0x2d);
AddRel
("BMI", CPU6800
, 0x2b);
AddRel
("BNE", CPU6800
, 0x26);
AddRel
("BPL", CPU6800
, 0x2a);
AddRel
("BRA", CPU6800
, 0x20);
AddRel
("BRN", CPU6801
, 0x21);
AddRel
("BSR", CPU6800
, 0x8d);
AddRel
("BVC", CPU6800
, 0x28);
AddRel
("BVS", CPU6800
, 0x29);
AddALU8
("ADC", "ADCA", "ADCB", NULL
, True
, 0x89);
AddALU8
("ADD", "ADDA", "ADDB", NULL
, True
, 0x8b);
AddALU8
("AND", "ANDA", "ANDB", NULL
, True
, 0x84);
AddALU8
("BIT", "BITA", "BITB", NULL
, True
, 0x85);
AddALU8
("CMP", "CMPA", "CMPB", NULL
, True
, 0x81);
AddALU8
("EOR", "EORA", "EORB", NULL
, True
, 0x88);
AddALU8
("LDA", "LDAA", "LDAB", "LDB", True
, 0x86);
AddALU8
("ORA", "ORAA", "ORAB", "ORB", True
, 0x8a);
AddALU8
("SBC", "SBCA", "SBCB", NULL
, True
, 0x82);
AddALU8
("STA", "STAA", "STAB", "STB", False
, 0x87);
AddALU8
("SUB", "SUBA", "SUBB", NULL
, True
, 0x80);
InstrZ
= 0;
AddALU16
("ADDD", True
, CPU6801
, 0, 0xc3);
AddALU16
("CPD" , True
, CPU6811
, 1, 0x83);
AddALU16
("CMPD", True
, CPU6811
, 1, 0x83);
AddALU16
("CPX" , True
, CPU6800
, 2, 0x8c);
AddALU16
("CMPX", True
, CPU6800
, 2, 0x8c);
AddALU16
("CPY" , True
, CPU6811
, 3, 0x8c);
AddALU16
("CMPY", True
, CPU6811
, 3, 0x8c);
AddALU16
("LDD" , True
, CPU6801
, 0, 0xcc);
AddALU16
("LDS" , True
, CPU6800
, 0, 0x8e);
AddALU16
("LDX" , True
, CPU6800
, 2, 0xce);
AddALU16
("LDY" , True
, CPU6811
, 3, 0xce);
AddALU16
("STD" , False
, CPU6801
, 0, 0xcd);
AddALU16
("STS" , False
, CPU6800
, 0, 0x8f);
AddALU16
("STX" , False
, CPU6800
, 2, 0xcf);
AddALU16
("STY" , False
, CPU6811
, 3, 0xcf);
AddALU16
("SUBD", True
, CPU6801
, 0, 0x83);
AddSing8
("ASL", "ASLA", "ASLB", 0x48);
AddSing8
("ASR", "ASRA", "ASRB", 0x47);
AddSing8
("CLR", "CLRA", "CLRB", 0x4f);
AddSing8
("COM", "COMA", "COMB", 0x43);
AddSing8
("DEC", "DECA", "DECB", 0x4a);
AddSing8
("INC", "INCA", "INCB", 0x4c);
AddSing8
("LSL", "LSLA", "LSLB", 0x48);
AddSing8
("LSR", "LSRA", "LSRB", 0x44);
AddSing8
("NEG", "NEGA", "NEGB", 0x40);
AddSing8
("ROL", "ROLA", "ROLB", 0x49);
AddSing8
("ROR", "RORA", "RORB", 0x46);
AddSing8
("TST", "TSTA", "TSTB", 0x4d);
AddInstTable
(InstTable
, "PSH" , 0x36, DecodePSH_PUL
);
AddInstTable
(InstTable
, "PSHA", 0x36, DecodeSing8_Acc
);
AddInstTable
(InstTable
, "PSHB", 0x37, DecodeSing8_Acc
);
AddInstTable
(InstTable
, "PUL" , 0x32, DecodePSH_PUL
);
AddInstTable
(InstTable
, "PULA", 0x32, DecodeSing8_Acc
);
AddInstTable
(InstTable
, "PULB", 0x33, DecodeSing8_Acc
);
AddInstTable
(InstTable
, "AIM", 0x61, DecodeBit63
);
AddInstTable
(InstTable
, "EIM", 0x65, DecodeBit63
);
AddInstTable
(InstTable
, "OIM", 0x62, DecodeBit63
);
AddInstTable
(InstTable
, "TIM", 0x6b, DecodeBit63
);
AddInstTable
(InstTable
, "PRWINS", 0, DecodePRWINS
);
init_moto8_pseudo
(InstTable
, e_moto_8_be
| e_moto_8_db
| e_moto_8_dw
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(FixedOrders
);
order_array_free
(RelOrders
);
order_array_free
(ALU16Orders
);
}
static Boolean DecodeAttrPart_68
(void)
{
if (strlen(AttrPart.
str.
p_str) > 1)
{
WrStrErrorPos
(ErrNum_UndefAttr
, &AttrPart
);
return False
;
}
return DecodeMoto16AttrSize
(*AttrPart.
str.
p_str, &AttrPartOpSize
[0], False
);
}
static void MakeCode_68
(void)
{
CodeLen
= 0;
DontPrint
= False
;
PrefCnt
= 0;
AdrCnt
= 0;
/* Operandengroesse festlegen */
OpSize
= (AttrPartOpSize
[0] != eSymbolSizeUnknown
) ? AttrPartOpSize
[0] : eSymbolSize8Bit
;
/* zu ignorierendes */
if (*OpPart.
str.
p_str == '\0')
return;
/* Pseudoanweisungen */
if (DecodeMoto16Pseudo
(OpSize
, True
))
return;
/* gehashtes */
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static void InitCode_68
(void)
{
Reg_MMSIZ
= Reg_MMWBR
= Reg_MM1CR
= Reg_MM2CR
= 0;
}
static Boolean IsDef_68
(void)
{
return False
;
}
static void SwitchTo_68
(void)
{
TurnWords
= False
;
SetIntConstMode
(eIntConstModeMoto
);
PCSymbol
= "*";
HeaderID
= 0x61;
NOPCode
= 0x01;
DivideChars
= ",";
HasAttrs
= True
;
AttrChars
= ".";
ValidSegs
= 1 << SegCode
;
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = (MomCPU
== CPU68HC11K4
) ? 0x10ffffl
: 0xffff;
DecodeAttrPart
= DecodeAttrPart_68
;
MakeCode
= MakeCode_68
;
IsDef
= IsDef_68
;
SwitchFrom
= DeinitFields
;
InitFields
();
AddMoto16PseudoONOFF
(False
);
if (MomCPU
== CPU68HC11K4
)
{
static const ASSUMERec ASSUMEHC11s
[] =
{
{"MMSIZ" , &Reg_MMSIZ
, 0, 0xff, 0, SetK4Ranges
},
{"MMWBR" , &Reg_MMWBR
, 0, 0xff, 0, SetK4Ranges
},
{"MM1CR" , &Reg_MM1CR
, 0, 0xff, 0, SetK4Ranges
},
{"MM2CR" , &Reg_MM2CR
, 0, 0xff, 0, SetK4Ranges
},
{"INIT" , &Reg_INIT
, 0, 0xff, 0, SetK4Ranges
},
{"INIT2" , &Reg_INIT2
, 0, 0xff, 0, SetK4Ranges
},
{"CONFIG", &Reg_CONFIG
, 0, 0xff, 0, SetK4Ranges
},
};
pASSUMERecs
= ASSUMEHC11s
;
ASSUMERecCnt
= as_array_size
(ASSUMEHC11s
);
SetK4Ranges
();
}
else
cpu_2_phys_area_clear
(SegCode
);
}
void code68_init
(void)
{
CPU6800
= AddCPU
("6800", SwitchTo_68
);
CPU6801
= AddCPU
("6801", SwitchTo_68
);
CPU6301
= AddCPU
("6301", SwitchTo_68
);
CPU6811
= AddCPU
("6811", SwitchTo_68
);
CPU68HC11K4
= AddCPU
("68HC11K4", SwitchTo_68
);
AddInitPassProc
(InitCode_68
);
}