/* codecp3f.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS */
/* */
/* Code Generator Olympia CP-3F */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "strutil.h"
#include "headids.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "motpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "codecp3f.h"
/*---------------------------------------------------------------------------*/
/* Address Decoders */
typedef enum
{
e_mode_none
= -1,
e_mode_a
= 0,
e_mode_v
= 1,
e_mode_w
= 2,
e_mode_x
= 3,
e_mode_y
= 4,
e_mode_s
= 5,
e_mode_t
= 6,
e_mode_st
= 7,
e_mode_imm
= 8,
e_mode_imm_short
= 9,
e_mode_dir
= 10,
e_mode_q
= 11,
e_mode_z
= 12,
e_mode_iz
= 13
} adr_mode_t
;
#define MModeA (1 << e_mode_a)
#define MModeV (1 << e_mode_v)
#define MModeW (1 << e_mode_w)
#define MModeX (1 << e_mode_x)
#define MModeY (1 << e_mode_y)
#define MModeS (1 << e_mode_s)
#define MModeT (1 << e_mode_t)
#define MModeST (1 << e_mode_st)
#define MModeQ (1 << e_mode_q)
#define MModeZ (1 << e_mode_z)
#define MModeIZ (1 << e_mode_iz)
#define MModeImm (1 << e_mode_imm)
#define MModeImmShort (1 << e_mode_imm_short)
#define MModeDir (1 << e_mode_dir)
typedef struct
{
adr_mode_t mode
;
Byte value
;
} adr_vals_t
;
/*!------------------------------------------------------------------------
* \fn reset_adr_vals(adr_vals_t *p_vals)
* \brief reset ecoded address argument to none
* \param p_vals argument to reset
* ------------------------------------------------------------------------ */
static void reset_adr_vals
(adr_vals_t
*p_vals
)
{
p_vals
->mode
= e_mode_none
;
p_vals
->value
= 0;
}
/*!------------------------------------------------------------------------
* \fn decode_adr(const tStrComp *p_arg, adr_vals_t *p_vals, unsigned mask, tSymbolSize op_size)
* \brief decode address expression
* \param p_arg source argument
* \param p_vals encoded mode
* \param mask bit mask of allowed modes
* \return deduced address mode
* ------------------------------------------------------------------------ */
static int chk_xy
(const char *p_arg
, const char *p_pattern
, Byte
*p_reg
)
{
for (; *p_arg
&& *p_pattern
; p_arg
++, p_pattern
++)
{
if (*p_pattern
== '*')
{
switch (as_toupper
(*p_arg
))
{
case 'X': *p_reg
= 0; break;
case 'Y': *p_reg
= 1; break;
default: return 1;
}
}
else if (as_toupper
(*p_arg
) != as_toupper
(*p_pattern
))
return 1;
}
return !(!*p_arg
&& !*p_pattern
);
}
static adr_mode_t decode_adr
(const tStrComp
*p_arg
, adr_vals_t
*p_vals
, unsigned mask
, tSymbolSize op_size
)
{
size_t l
= strlen(p_arg
->str.
p_str);
tEvalResult eval_result
;
reset_adr_vals
(p_vals
);
if (l
== 1)
{
const char reg_names
[] = "AVWXYST";
const char *p_pos
= strchr(reg_names
, as_toupper
(p_arg
->str.
p_str[0]));
if (p_pos
)
{
p_vals
->mode
= (adr_mode_t
)(e_mode_a
+ (p_pos
- reg_names
));
goto fini
;
}
}
if (*p_arg
->str.
p_str == '#')
{
int offset
= 1;
switch (op_size
)
{
case eSymbolSize24Bit
:
p_vals
->value
= EvalStrIntExpressionOffsWithResult
(p_arg
, offset
, UInt3
, &eval_result
);
if (eval_result.
OK)
p_vals
->mode
= e_mode_imm
;
goto fini
;
case eSymbolSize8Bit
:
{
Boolean force_short
= False
,
force_long
= False
,
opt_short
= !!(mask
& MModeImmShort
);
if (opt_short
)
switch (p_arg
->str.
p_str[offset
])
{
case '<':
force_short
= True
;
offset
++;
break;
case '>':
force_long
= True
;
offset
++;
break;
default:
break;
}
p_vals
->value
= EvalStrIntExpressionOffsWithResult
(p_arg
, offset
, force_short
? UInt4
: Int8
, &eval_result
);
if (eval_result.
OK)
{
if (!opt_short
)
p_vals
->mode
= e_mode_imm
;
else if (force_long
)
p_vals
->mode
= e_mode_imm
;
else
p_vals
->mode
= (p_vals
->value
< 16) ? e_mode_imm_short
: e_mode_imm
;
}
goto fini
;
}
default:
WrStrErrorPos
(ErrNum_UndefOpSizes
, p_arg
);
goto fini
;
}
}
if (!as_strcasecmp
(p_arg
->str.
p_str, "ST"))
{
p_vals
->mode
= e_mode_st
;
goto fini
;
}
if (!as_strcasecmp
(p_arg
->str.
p_str, "(ST)"))
{
p_vals
->mode
= e_mode_dir
;
p_vals
->value
= 12;
goto fini
;
}
if (!as_strcasecmp
(p_arg
->str.
p_str, "(ST)-"))
{
p_vals
->mode
= e_mode_dir
;
p_vals
->value
= 13;
goto fini
;
}
if (!as_strcasecmp
(p_arg
->str.
p_str, "(ST)+"))
{
p_vals
->mode
= e_mode_dir
;
p_vals
->value
= 14;
goto fini
;
}
if (!chk_xy
(p_arg
->str.
p_str, "Q(*)", &p_vals
->value
))
{
p_vals
->mode
= e_mode_q
;
goto fini
;
}
if (!chk_xy
(p_arg
->str.
p_str, "Z(*)", &p_vals
->value
))
{
p_vals
->mode
= e_mode_z
;
goto fini
;
}
if (!chk_xy
(p_arg
->str.
p_str, "(Z(*))", &p_vals
->value
))
{
p_vals
->mode
= e_mode_iz
;
goto fini
;
}
p_vals
->value
= EvalStrIntExpressionWithResult
(p_arg
, UInt4
, &eval_result
);
if (mFirstPassUnknownOrQuestionable
(eval_result.
Flags))
p_vals
->value
&= 7;
if (ChkRange
(p_vals
->value
, 0, 11))
{
ChkSpace
(SegData
, eval_result.
AddrSpaceMask);
p_vals
->mode
= e_mode_dir
;
goto fini
;
}
fini
:
if ((p_vals
->mode
!= e_mode_none
) && !((mask
>> p_vals
->mode
) & 1))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, p_arg
);
reset_adr_vals
(p_vals
);
}
return p_vals
->mode
;
}
/*---------------------------------------------------------------------------*/
/* Instruction Decoders */
/*!------------------------------------------------------------------------
* \fn decode_imm_4(Word code)
* \brief handle instructions with 4 bit immediate operand
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_imm_4
(Word code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean ok
;
BAsmCode
[0] = EvalStrIntExpression
(&ArgStr
[1], UInt4
, &ok
);
if (ok
)
{
BAsmCode
[0] = code
| (BAsmCode
[0] & 0x0f);
CodeLen
= 1;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_imm_3(Word code)
* \brief handle instructions with 3 bit immediate operand
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_imm_3
(Word code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean ok
;
BAsmCode
[0] = EvalStrIntExpression
(&ArgStr
[1], UInt3
, &ok
);
if (ok
)
{
BAsmCode
[0] = code
| (BAsmCode
[0] & 0x07);
CodeLen
= 1;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_imm_8(Word code)
* \brief handle instructions with 8 bit immediate operand
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_imm_8
(Word code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean ok
;
BAsmCode
[1] = EvalStrIntExpression
(&ArgStr
[1], Int8
, &ok
);
if (ok
)
{
BAsmCode
[0] = code
;
CodeLen
= 2;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_fixed(Word code)
* \brief handle instructions with no argument
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_fixed
(Word code
)
{
if (ChkArgCnt
(0, 0))
{
BAsmCode
[0] = code
;
CodeLen
= 1;
}
}
/*!------------------------------------------------------------------------
* \fn decode_reg(Word code)
* \brief handle instructions with register argument
* \param code machine code
* ------------------------------------------------------------------------ */
/* Original syntax assumes programmer knows that 12..14 refer
to (ST), (ST)+, (ST)-... */
static void decode_reg
(Word code
)
{
if (ChkArgCnt
(1, 1))
{
tEvalResult eval_result
;
BAsmCode
[0] = EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt4
, &eval_result
);
if (eval_result.
OK)
{
if (mFirstPassUnknownOrQuestionable
(eval_result.
Flags))
BAsmCode
[0] = 0;
if (ChkRange
(BAsmCode
[0], 0, 14))
{
BAsmCode
[0] |= code
;
CodeLen
= 1;
}
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_io(Word code)
* \brief handle instructions with I/O address operand
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_io
(Word code
)
{
if (ChkArgCnt
(1, 1))
{
tEvalResult eval_result
;
BAsmCode
[0] = EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt3
, &eval_result
);
if (eval_result.
OK)
{
ChkSpace
(SegIO
, eval_result.
AddrSpaceMask);
BAsmCode
[0] = code
| (BAsmCode
[0] & 0x07);
CodeLen
= 1;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_port(Word code)
* \brief handle PORt instruction
* ------------------------------------------------------------------------ */
static void decode_port
(Word code
)
{
UNUSED
(code
);
CodeEquate
(SegIO
, 0, SegLimits
[SegIO
]);
}
/*!------------------------------------------------------------------------
* \fn decode_jmp(Word code)
* \brief handle instructions with target address operand
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_jmp
(Word code
)
{
if (ChkArgCnt
(1, 1))
{
tEvalResult eval_result
;
Word address
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt14
, &eval_result
);
if (eval_result.
OK
&& ChkSamePage
(EProgCounter
(), address
, 11, eval_result.
Flags))
{
BAsmCode
[0] = code
| (Hi
(address
) & 7);
BAsmCode
[1] = Lo
(address
);
CodeLen
= 2;
}
}
}
/*!------------------------------------------------------------------------
* \fn void decode_ld(Word code)
* \brief decode virtual LD instruction
* ------------------------------------------------------------------------ */
static void decode_ld
(Word code
)
{
adr_vals_t src_adr_vals
, dest_adr_vals
;
UNUSED
(code
);
if (ChkArgCnt
(2, 2))
switch (decode_adr
(&ArgStr
[1], &dest_adr_vals
, MModeA
| MModeV
| MModeW
| MModeX
| MModeY
| MModeS
| MModeT
| MModeST
| MModeDir
| MModeQ
| MModeZ
| MModeIZ
, eSymbolSizeUnknown
))
{
case e_mode_a
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeV
| MModeW
| MModeX
| MModeY
| MModeDir
| MModeImm
| MModeImmShort
| MModeIZ
, eSymbolSize8Bit
))
{
case e_mode_v
:
case e_mode_w
:
case e_mode_x
:
case e_mode_y
:
BAsmCode
[0] = 0x08 | (src_adr_vals.
mode - e_mode_v
);
CodeLen
= 1;
break;
case e_mode_dir
:
BAsmCode
[0] = 0x80 | src_adr_vals.
value;
CodeLen
= 1;
break;
case e_mode_imm
:
BAsmCode
[0] = 0x04;
BAsmCode
[1] = src_adr_vals.
value;
CodeLen
= 2;
break;
case e_mode_imm_short
:
BAsmCode
[0] = 0xf0 | (src_adr_vals.
value & 15);
CodeLen
= 1;
break;
case e_mode_iz
:
BAsmCode
[0] = 0x06 | src_adr_vals.
value;
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_v
:
case e_mode_w
:
case e_mode_x
:
case e_mode_y
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeA
, eSymbolSize8Bit
))
{
case e_mode_a
:
BAsmCode
[0] = 0x18 | (dest_adr_vals.
mode - e_mode_v
);
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_s
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeImm
, eSymbolSize24Bit
))
{
case e_mode_imm
:
BAsmCode
[0] = 0x28 | (src_adr_vals.
value & 7);
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_t
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeA
| MModeImm
, eSymbolSize24Bit
))
{
case e_mode_a
:
BAsmCode
[0] = 0x01;
CodeLen
= 1;
break;
case e_mode_imm
:
BAsmCode
[0] = 0x38 | (src_adr_vals.
value & 7);
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_st
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeA
, eSymbolSizeUnknown
))
{
case e_mode_a
:
BAsmCode
[0] = 0x03;
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_q
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeA
, eSymbolSizeUnknown
))
{
case e_mode_a
:
BAsmCode
[0] = 0x16 | dest_adr_vals.
value;
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_z
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeA
, eSymbolSizeUnknown
))
{
case e_mode_a
:
BAsmCode
[0] = 0x12 | dest_adr_vals.
value;
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_iz
:
if (dest_adr_vals.
value) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
else switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeA
, eSymbolSizeUnknown
))
{
case e_mode_a
:
BAsmCode
[0] = 0x02 | dest_adr_vals.
value;
CodeLen
= 1;
break;
default:
break;
}
break;
case e_mode_dir
:
switch (decode_adr
(&ArgStr
[2], &src_adr_vals
, MModeA
, eSymbolSize8Bit
))
{
case e_mode_a
:
BAsmCode
[0] = 0x90 | dest_adr_vals.
value;
CodeLen
= 1;
break;
default:
break;
}
break;
default:
break;
}
}
/*!------------------------------------------------------------------------
* \fn void decode_ari(Word code)
* \brief decode virtual arithmetic instruction
* ------------------------------------------------------------------------ */
static void decode_ari
(Word code
)
{
adr_vals_t src_adr_vals
, dest_adr_vals
;
unsigned mask
;
Byte imm_code
= Hi
(code
), dir_code
= Lo
(code
);
if (!ChkArgCnt
(1, 2))
return;
if (ArgCnt
== 2)
{
if (decode_adr
(&ArgStr
[1], &dest_adr_vals
, MModeA
, eSymbolSize8Bit
) != e_mode_a
)
return;
}
mask
= ((imm_code
== 0xff) ? 0 : MModeImm
)
| ((dir_code
== 0xff) ? 0 : MModeDir
);
switch (decode_adr
(&ArgStr
[ArgCnt
], &src_adr_vals
, mask
, eSymbolSize8Bit
))
{
case e_mode_dir
:
BAsmCode
[0] = dir_code
| src_adr_vals.
value;
CodeLen
= 1;
break;
case e_mode_imm
:
BAsmCode
[0] = imm_code
;
BAsmCode
[1] = src_adr_vals.
value;
CodeLen
= 2;
break;
default:
break;
}
}
/*!------------------------------------------------------------------------
* \fn decode_srl_sla(Word code)
* \brief decode virtual shift instructions
* \param code machine code for single bit shift
* ------------------------------------------------------------------------ */
static void decode_srl_sla
(Word code
)
{
int shift_arg_index
;
Byte shift_cnt
;
switch (ArgCnt
)
{
case 1:
if (!as_strcasecmp
(ArgStr
[1].
str.
p_str, "A"))
goto acc_1
;
shift_arg_index
= 1;
goto eval_shift
;
case 0:
acc_1
:
shift_cnt
= 1;
break;
case 2:
{
adr_vals_t adr_vals
;
if (decode_adr
(&ArgStr
[1], &adr_vals
, MModeA
, eSymbolSize8Bit
) != e_mode_a
)
return;
shift_arg_index
= 2;
/* FALL-THRU */
}
eval_shift
:
{
tEvalResult eval_result
;
shift_cnt
= EvalStrIntExpressionWithResult
(&ArgStr
[shift_arg_index
], UInt8
, &eval_result
);
if (!eval_result.
OK)
return;
if (mFirstPassUnknownOrQuestionable
(eval_result.
Flags))
shift_cnt
= 1;
if ((shift_cnt
!= 1) && (shift_cnt
!= 4))
{
WrStrErrorPos
(ErrNum_InvShiftArg
, &ArgStr
[shift_arg_index
]);
return;
}
break;
}
default:
(void)ChkArgCnt
(0, 2);
return;
}
BAsmCode
[0] = code
| ((shift_cnt
> 1) ? 2 : 0);
CodeLen
= 1;
}
/*---------------------------------------------------------------------------*/
/* Code Table Handling */
/*!------------------------------------------------------------------------
* \fn init_fields(void)
* \brief build up instruction hash table
* ------------------------------------------------------------------------ */
static void init_fields
(void)
{
InstTable
= CreateInstTable
(101);
AddInstTable
(InstTable
, "LAS", 0xf0, decode_imm_4
);
AddInstTable
(InstTable
, "LSS", 0x28, decode_imm_3
);
AddInstTable
(InstTable
, "LTS", 0x38, decode_imm_3
);
AddInstTable
(InstTable
, "LAL", 0x04, decode_imm_8
);
AddInstTable
(InstTable
, "ANL", 0x05, decode_imm_8
);
AddInstTable
(InstTable
, "EOL", 0x0c, decode_imm_8
);
AddInstTable
(InstTable
, "ORL", 0x0d, decode_imm_8
);
AddInstTable
(InstTable
, "ADL", 0x0e, decode_imm_8
);
AddInstTable
(InstTable
, "CML", 0x0f, decode_imm_8
);
AddInstTable
(InstTable
, "LAV", 0x08, decode_fixed
);
AddInstTable
(InstTable
, "LAW", 0x09, decode_fixed
);
AddInstTable
(InstTable
, "LAX", 0x0a, decode_fixed
);
AddInstTable
(InstTable
, "LAY", 0x0b, decode_fixed
);
AddInstTable
(InstTable
, "SAV", 0x18, decode_fixed
);
AddInstTable
(InstTable
, "SAW", 0x19, decode_fixed
);
AddInstTable
(InstTable
, "SAX", 0x1a, decode_fixed
);
AddInstTable
(InstTable
, "SAY", 0x1b, decode_fixed
);
AddInstTable
(InstTable
, "SAT", 0x01, decode_fixed
);
AddInstTable
(InstTable
, "SST", 0x03, decode_fixed
);
AddInstTable
(InstTable
, "ALS", 0x1c, decode_fixed
);
AddInstTable
(InstTable
, "ARS", 0x1d, decode_fixed
);
AddInstTable
(InstTable
, "ALF", 0x1e, decode_fixed
);
AddInstTable
(InstTable
, "ARF", 0x1f, decode_fixed
);
AddInstTable
(InstTable
, "RET", 0x00, decode_fixed
);
AddInstTable
(InstTable
, "SIX", 0x02, decode_fixed
);
AddInstTable
(InstTable
, "LIX", 0x06, decode_fixed
);
AddInstTable
(InstTable
, "LIY", 0x07, decode_fixed
);
AddInstTable
(InstTable
, "SQX", 0x16, decode_fixed
);
AddInstTable
(InstTable
, "SQY", 0x17, decode_fixed
);
AddInstTable
(InstTable
, "SZX", 0x12, decode_fixed
);
AddInstTable
(InstTable
, "SZY", 0x13, decode_fixed
);
AddInstTable
(InstTable
, "LAR", 0x80, decode_reg
);
AddInstTable
(InstTable
, "SAR", 0x90, decode_reg
);
AddInstTable
(InstTable
, "ADR", 0xa0, decode_reg
);
AddInstTable
(InstTable
, "ANR", 0xb0, decode_reg
);
AddInstTable
(InstTable
, "EOR", 0xc0, decode_reg
);
AddInstTable
(InstTable
, "DER", 0xd0, decode_reg
);
AddInstTable
(InstTable
, "DAR", 0xe0, decode_reg
);
AddInstTable
(InstTable
, "INP", 0x20, decode_io
);
AddInstTable
(InstTable
, "OUT", 0x30, decode_io
);
AddInstTable
(InstTable
, "PORT", 0, decode_port
);
AddInstTable
(InstTable
, "JMP", 0x40, decode_jmp
);
AddInstTable
(InstTable
, "JAZ", 0x48, decode_jmp
);
AddInstTable
(InstTable
, "JAN", 0x50, decode_jmp
);
AddInstTable
(InstTable
, "JAP", 0x58, decode_jmp
);
AddInstTable
(InstTable
, "JSD", 0x60, decode_jmp
);
AddInstTable
(InstTable
, "JCN", 0x68, decode_jmp
);
AddInstTable
(InstTable
, "JCZ", 0x70, decode_jmp
);
AddInstTable
(InstTable
, "JSB", 0x78, decode_jmp
);
AddInstTable
(InstTable
, "GOS", 0x78, decode_jmp
);
AddInstTable
(InstTable
, "LD", 0, decode_ld
);
AddInstTable
(InstTable
, "ADD", 0x0ea0, decode_ari
);
AddInstTable
(InstTable
, "AND", 0x05b0, decode_ari
);
AddInstTable
(InstTable
, "XOR", 0x0cc0, decode_ari
);
AddInstTable
(InstTable
, "OR" , 0x0dff, decode_ari
);
AddInstTable
(InstTable
, "CP" , 0x0fff, decode_ari
);
AddInstTable
(InstTable
, "DEC", 0xffd0, decode_ari
);
AddInstTable
(InstTable
, "SLA", 0x1c, decode_srl_sla
);
AddInstTable
(InstTable
, "SRL", 0x1d, decode_srl_sla
);
AddInstTable
(InstTable
, "DC", 0, DecodeMotoBYT
);
AddInstTable
(InstTable
, "DS", 0, DecodeMotoDFS
);
}
/*!------------------------------------------------------------------------
* \fn deinit_fields(void)
* \brief tear down instruction hash table
* ------------------------------------------------------------------------ */
static void deinit_fields
(void)
{
DestroyInstTable
(InstTable
);
}
/*---------------------------------------------------------------------------*/
/* Interface Functions */
/*!------------------------------------------------------------------------
* \fn make_code_cp3f(void)
* \brief machine instruction dispatcher
* ------------------------------------------------------------------------ */
static void make_code_cp3f
(void)
{
CodeLen
= 0; DontPrint
= False
;
/* to be ignored */
if (Memo
("")) return;
/* pseudo instructions */
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
/*!------------------------------------------------------------------------
* \fn switch_from_cp3f(void)
* \brief cleanups after switch from target
* ------------------------------------------------------------------------ */
static void switch_from_cp3f
(void)
{
deinit_fields
();
}
/*!------------------------------------------------------------------------
* \fn is_def_cp_3f(void)
* \brief does instruction use label field?
* ------------------------------------------------------------------------ */
static Boolean is_def_cp3f
(void)
{
return Memo
("PORT");
}
/*!------------------------------------------------------------------------
* \fn switch_to_cp_3f(void)
* \brief prepare to assemble code for this target
* ------------------------------------------------------------------------ */
static void switch_to_cp3f
(void)
{
const TFamilyDescr
*p_descr
= FindFamilyByName
("CP-3F");
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
p_descr
= FindFamilyByName
("CP-3F");
PCSymbol
= "$";
HeaderID
= p_descr
->Id
;
NOPCode
= 0x00;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= (1 << SegCode
) | (1 << SegData
) | (1 << SegIO
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegLimits
[SegCode
] = 0x3fff;
Grans
[SegData
] = 1; ListGrans
[SegData
] = 1; SegLimits
[SegData
] = 0x2f;
Grans
[SegIO
] = 1; ListGrans
[SegIO
] = 1; SegLimits
[SegIO
] = 0x7;
MakeCode
= make_code_cp3f
;
SwitchFrom
= switch_from_cp3f
;
IsDef
= is_def_cp3f
;
init_fields
();
}
/*!------------------------------------------------------------------------
* \fn codecp3f__init(void)
* \brief register CP-3F target
* ------------------------------------------------------------------------ */
void codecp3f_init
(void)
{
(void)AddCPU
("CP-3F" , switch_to_cp3f
);
(void)AddCPU
("M380" , switch_to_cp3f
);
(void)AddCPU
("LP8000" , switch_to_cp3f
);
}