/* codeko09.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Code Generator Konami 052001 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codevars.h"
#include "headids.h"
#include "motpseudo.h"
#include "code6809.h"
#include "codeko09.h"
typedef enum
{
e_adr_mode_none = -1,
e_adr_mode_imm = 1,
e_adr_mode_ind = 2
} adr_mode_t;
#define adr_mode_mask_imm (1 << e_adr_mode_imm)
#define adr_mode_mask_ind (1 << e_adr_mode_ind)
#define adr_mode_mask_no_imm (adr_mode_mask_ind)
#define adr_mode_mask_all (adr_mode_mask_imm | adr_mode_mask_no_imm)
typedef struct
{
adr_mode_t mode;
int cnt;
Byte vals[5];
} adr_vals_t;
static const char reg_16_names[4] = { 'X','Y','U','S' };
static LongInt DPRValue;
/*!------------------------------------------------------------------------
* \fn decode_cpu_reg(const char *p_asc, Byte *p_ret)
* \brief decode CPU register names for TFR/EXG
* \param p_asc source argument
* \param p_ret resulting encoded value
* \return True if known register
* ------------------------------------------------------------------------ */
static Boolean decode_cpu_reg(const char *p_asc, Byte *p_ret)
{
#define reg_cnt as_array_size(reg_names)
static const char reg_names[][2] =
{
"X", "Y", "U", "S", "A", "B"
};
static const Byte reg_vals[reg_cnt] =
{
2 , 3 , 5 , 4 , 0 , 1
};
size_t z;
for (z = 0; z < reg_cnt; z++)
if (!as_strcasecmp(p_asc, reg_names[z]))
{
*p_ret = reg_vals[z];
return True;
}
return False;
}
/*!------------------------------------------------------------------------
* \fn DecodeAdr(int ArgStartIdx, int ArgEndIdx,
tSymbolSize op_size, unsigned mode_mask, adr_vals_t *p_vals)
* \brief decode/evaluate address expression
* \param ArgStartIdx 1st argument of expression
* \param ArgEndIdx last argument of expression
* \param op_size operand size (8/16)
* \param mode_mask bit mask of allowed modes
* \param p_vals dest buffer
* \return encoded addressing mode
* ------------------------------------------------------------------------ */
static void reset_adr_vals(adr_vals_t *p_vals)
{
p_vals->mode = e_adr_mode_none;
p_vals->cnt = 0;
}
#define IDX_PCREG 7
static Boolean code_reg(const char *p_arg, Byte *p_ret)
{
if (!as_strcasecmp(p_arg, "PCR") || !as_strcasecmp(p_arg, "PC"))
{
*p_ret = IDX_PCREG;
return True;
}
return False;
else
{
static const char Regs[6] = "XY\aUS";
const char *p
= strchr(Regs
, as_toupper
(*p_arg
));
if (!p)
return False;
*p_ret = p - Regs + 2;
return True;
}
}
static unsigned ChkZero(const char *s, Byte *Erg)
{
if (*s == '>')
{
*Erg = 1;
return 1;
}
else if (*s == '<')
{
*Erg = 2;
return 1;
}
else
{
*Erg = 0;
return 0;
}
}
static Boolean MayShort(Integer Arg)
{
return ((Arg >= -128) && (Arg < 127));
}
static Boolean IsZeroOrEmpty(const tStrComp *pArg)
{
Boolean OK;
LongInt Value;
if (!*pArg->str.p_str)
return True;
Value = EvalStrIntExpression(pArg, Int32, &OK);
return OK && !Value;
}
static adr_mode_t DecodeAdr(int ArgStartIdx, int ArgEndIdx,
tSymbolSize op_size, unsigned mode_mask, adr_vals_t *p_vals)
{
tStrComp *pStartArg, *pEndArg, IndirComps[2];
String temp;
Word AdrWord;
Boolean IndFlag, OK;
Byte EReg, ZeroMode;
char *p;
unsigned Offset;
Integer AdrInt;
int AdrArgCnt = ArgEndIdx - ArgStartIdx + 1, end_arg_len;
const unsigned OpcodeLen = 1;
reset_adr_vals(p_vals);
pStartArg = &ArgStr[ArgStartIdx];
pEndArg = &ArgStr[ArgEndIdx];
/* immediate */
if ((*pStartArg->str.p_str == '#') && (AdrArgCnt == 1))
{
switch (op_size)
{
case eSymbolSize16Bit:
AdrWord = EvalStrIntExpressionOffs(pStartArg, 1, Int16, &OK);
if (OK)
{
p_vals->vals[0] = Hi(AdrWord);
p_vals->vals[1] = Lo(AdrWord);
p_vals->cnt = 2;
}
break;
case eSymbolSize8Bit:
p_vals->vals[0] = EvalStrIntExpressionOffs(pStartArg, 1, Int8, &OK);
if (OK)
p_vals->cnt = 1;
break;
default:
OK = False;
break;
}
if (OK)
p_vals->mode = e_adr_mode_imm;
goto chk_mode;
}
/* indirekter Ausdruck ? */
if ((*pStartArg
->str.
p_str == '[') && (pStartArg
->str.
p_str[strlen(pStartArg
->str.
p_str) - 1] == ']'))
{
tStrComp Arg, Remainder;
IndFlag = True;
StrCompRefRight(&Arg, pStartArg, 1);
StrCompShorten(&Arg, 1);
AdrArgCnt = 0;
do
{
p = QuotPos(Arg.str.p_str, ',');
if (p)
StrCompSplitRef(&IndirComps[AdrArgCnt], &Remainder, &Arg, p);
else
IndirComps[AdrArgCnt] = Arg;
KillPrefBlanksStrCompRef(&IndirComps[AdrArgCnt]);
KillPostBlanksStrComp(&IndirComps[AdrArgCnt]);
AdrArgCnt++;
if (p)
Arg = Remainder;
}
while (p && (AdrArgCnt < 2));
pStartArg = &IndirComps[0];
pEndArg = &IndirComps[AdrArgCnt - 1];
}
else
IndFlag = False;
/* Predekrement ? */
end_arg_len
= strlen(pEndArg
->str.
p_str);
if ((AdrArgCnt >= 1) && (AdrArgCnt <= 2) && (end_arg_len >= 2) && (*pEndArg->str.p_str == '-') && (code_reg(pEndArg->str.p_str + 1, &EReg)))
{
if ((AdrArgCnt == 2) && !IsZeroOrEmpty(pStartArg)) WrError(ErrNum_InvAddrMode);
else
{
p_vals->cnt = 1;
p_vals->vals[0] = 0x02 + (EReg << 4) + (Ord(IndFlag) << 3);
p_vals->mode = e_adr_mode_ind;
}
goto chk_mode;
}
if ((AdrArgCnt
>= 1) && (AdrArgCnt
<= 2) && (end_arg_len
>= 3) && (!strncmp(pEndArg
->str.
p_str, "--", 2)) && (code_reg
(pEndArg
->str.
p_str + 2, &EReg
)))
{
if ((AdrArgCnt == 2) && !IsZeroOrEmpty(pStartArg)) WrError(ErrNum_InvAddrMode);
else
{
p_vals->cnt = 1;
p_vals->vals[0] = 0x03 + (EReg << 4) + (Ord(IndFlag) << 3);
p_vals->mode = e_adr_mode_ind;
}
goto chk_mode;
}
/* Postinkrement ? */
if ((AdrArgCnt >= 1) && (AdrArgCnt <= 2) && (end_arg_len >= 2) && (pEndArg->str.p_str[end_arg_len - 1] == '+'))
{
memcpy(temp
, pEndArg
->str.
p_str, end_arg_len
- 1);
temp[end_arg_len - 1] = '\0';
if (code_reg(temp, &EReg))
{
if ((AdrArgCnt == 2) && !IsZeroOrEmpty(pStartArg)) WrError(ErrNum_InvAddrMode);
else
{
p_vals->cnt = 1;
p_vals->vals[0] = 0x00 + (EReg << 4) + (Ord(IndFlag) << 3);
p_vals->mode = e_adr_mode_ind;
}
goto chk_mode;
}
}
if ((AdrArgCnt
>= 1) && (AdrArgCnt
<= 2) && (end_arg_len
>= 3) && (!strncmp(pEndArg
->str.
p_str + end_arg_len
- 2, "++", 2)))
{
memcpy(temp
, pEndArg
->str.
p_str, end_arg_len
- 2);
temp[end_arg_len - 2] = '\0';
if (code_reg(temp, &EReg))
{
if ((AdrArgCnt == 2) && !IsZeroOrEmpty(pStartArg)) WrError(ErrNum_InvAddrMode);
else
{
p_vals->cnt = 1;
p_vals->vals[0] = 0x01 + (EReg << 4) + (Ord(IndFlag) << 3);
p_vals->mode = e_adr_mode_ind;
}
goto chk_mode;
}
}
/* 16-Bit-Register (mit Index) ? */
if ((AdrArgCnt <= 2) && (AdrArgCnt >= 1) && (code_reg(pEndArg->str.p_str, &EReg)))
{
p_vals->vals[0] = (EReg << 4) + (Ord(IndFlag) << 3);
/* nur 16-Bit-Register */
if (AdrArgCnt == 1)
{
p_vals->cnt = 1;
p_vals->vals[0] |= 0x06;
p_vals->mode = e_adr_mode_ind;
goto chk_mode;
}
/* mit Index */
if (!as_strcasecmp(pStartArg->str.p_str, "A"))
{
p_vals->cnt = 1;
p_vals->vals[0] |= 0x80;
p_vals->mode = e_adr_mode_ind;
goto chk_mode;
}
if (!as_strcasecmp(pStartArg->str.p_str, "B"))
{
p_vals->cnt = 1;
p_vals->vals[0] |= 0x81;
p_vals->mode = e_adr_mode_ind;
goto chk_mode;
}
if (!as_strcasecmp(pStartArg->str.p_str, "D"))
{
p_vals->cnt = 1;
p_vals->vals[0] += 0x87;
p_vals->mode = e_adr_mode_ind;
goto chk_mode;
}
/* Displacement auswerten */
Offset = ChkZero(pStartArg->str.p_str, &ZeroMode);
if (EReg == IDX_PCREG)
AdrInt = EvalStrIntExpressionOffs(pStartArg, Offset, UInt16, &OK)
- (EProgCounter() + 2 + OpcodeLen);
else if (ZeroMode > 1)
AdrInt = EvalStrIntExpressionOffs(pStartArg, Offset, SInt8, &OK);
else
AdrInt = EvalStrIntExpressionOffs(pStartArg, Offset, SInt16, &OK);
if (!OK)
goto chk_mode;
/* Displacement 0 ? */
if ((ZeroMode == 0) && (AdrInt == 0))
{
p_vals->cnt = 1;
p_vals->vals[0] += 0x06;
p_vals->mode = e_adr_mode_ind;
goto chk_mode;
}
/* 8-Bit-Displacement */
else if ((ZeroMode == 2) || ((ZeroMode == 0) && (MayShort(AdrInt))))
{
if (!MayShort(AdrInt)) WrError(ErrNum_NoShortAddr);
else
{
p_vals->mode = e_adr_mode_ind;
p_vals->cnt = 2;
p_vals->vals[0] += 0x04;
p_vals->vals[1] = Lo(AdrInt);
}
goto chk_mode;
}
/* 16-Bit-Displacement */
else
{
p_vals->mode = e_adr_mode_ind;
p_vals->cnt = 3;
p_vals->vals[0] += 0x05;
if (EReg == IDX_PCREG)
AdrInt--;
p_vals->vals[1] = Hi(AdrInt);
p_vals->vals[2] = Lo(AdrInt);
goto chk_mode;
}
}
/* absolute/direct */
if (AdrArgCnt == 1)
{
tSymbolFlags Flags;
Offset = ChkZero(pStartArg->str.p_str, &ZeroMode);
AdrInt = EvalStrIntExpressionOffsWithFlags(pStartArg, Offset, UInt16, &OK, &Flags);
if (mFirstPassUnknown(Flags) && (ZeroMode == 2))
AdrInt = (AdrInt & 0xff) | (DPRValue << 8);
if (OK)
{
if ((ZeroMode == 2) || ((ZeroMode == 0) && (Hi(AdrInt) == DPRValue)))
{
if (Hi(AdrInt) != DPRValue) WrError(ErrNum_NoShortAddr);
else
{
p_vals->mode = e_adr_mode_ind;
p_vals->cnt = 2;
p_vals->vals[0] = 0xc4 | (Ord(IndFlag) << 3);
p_vals->vals[1] = Lo(AdrInt);
}
}
else
{
p_vals->mode = e_adr_mode_ind;
p_vals->cnt = 3;
p_vals->vals[0] = 0x07 | (Ord(IndFlag) << 3);
p_vals->vals[1] = Hi(AdrInt);
p_vals->vals[2] = Lo(AdrInt);
}
}
goto chk_mode;
}
if (p_vals->mode == e_adr_mode_none)
WrError(ErrNum_InvAddrMode);
chk_mode:
if ((p_vals->mode != e_adr_mode_none) && !((mode_mask >> p_vals->mode) & 1))
{
WrError(ErrNum_InvAddrMode);
reset_adr_vals(p_vals);
}
return p_vals->mode;
}
/*!------------------------------------------------------------------------
* \fn append_adr_vals(const adr_vals_t *p_vals)
* \brief append encoded addressing mode to instruction
* \param p_vals what to append
* ------------------------------------------------------------------------ */
static void append_adr_vals(const adr_vals_t *p_vals)
{
memcpy(&BAsmCode
[CodeLen
], p_vals
->vals
, p_vals
->cnt
);
CodeLen += p_vals->cnt;
}
/*-------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn decode_inh(Word code)
* \brief decode instructions without argument
* ------------------------------------------------------------------------ */
static void decode_inh(Word code)
{
if (ChkArgCnt(0, 0))
BAsmCode[CodeLen++] = Lo(code);
}
/*!------------------------------------------------------------------------
* \fn decode_imm_8(Word code)
* \brief decode instructions with 8 bit immediate argument
* ------------------------------------------------------------------------ */
static void decode_imm_8(Word code)
{
if (ChkArgCnt(1, 1))
{
adr_vals_t adr_vals;
switch (DecodeAdr(1, ArgCnt, eSymbolSize8Bit, adr_mode_mask_imm, &adr_vals))
{
case e_adr_mode_imm:
BAsmCode[CodeLen++] = code;
BAsmCode[CodeLen++] = adr_vals.vals[0];
break;
default:
break;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_idx(Word code)
* \brief decode instructions with indexed argument
* ------------------------------------------------------------------------ */
static void decode_idx(Word code)
{
if (ChkArgCnt(1, 2))
{
adr_vals_t adr_vals;
switch (DecodeAdr(1, ArgCnt, eSymbolSizeUnknown, adr_mode_mask_ind, &adr_vals))
{
case e_adr_mode_ind:
BAsmCode[CodeLen++] = code;
append_adr_vals(&adr_vals);
break;
default:
break;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_ari(Word code)
* \brief decode instructions with indexed or immediate argument
* ------------------------------------------------------------------------ */
static void decode_ari(Word code)
{
if (ChkArgCnt(1, 2))
{
adr_vals_t adr_vals;
switch (DecodeAdr(1, ArgCnt, (code & 0x8000) ? eSymbolSize16Bit : eSymbolSize8Bit, adr_mode_mask_all, &adr_vals))
{
case e_adr_mode_imm:
BAsmCode[CodeLen++] = Lo(code) + 0;
goto append;
case e_adr_mode_ind:
BAsmCode[CodeLen++] = Lo(code) + (Hi(code) & 0x7f);
goto append;
append:
append_adr_vals(&adr_vals);
break;
default:
break;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_branch_8_core(Word code)
* \brief decode instructions with 8 bit displacement
* ------------------------------------------------------------------------ */
static void decode_branch_8_core(unsigned arg_index, Word code)
{
tEvalResult eval_result;
LongInt dist = EvalStrIntExpressionWithResult(&ArgStr[arg_index], UInt16, &eval_result)
- (EProgCounter() + 2);
if (eval_result.OK)
{
if (!RangeCheck(dist, SInt8) && !mSymbolQuestionable(eval_result.Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
BAsmCode[CodeLen++] = code;
BAsmCode[CodeLen++] = dist & 0xff;
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_branch_8(Word code)
* \brief decode instructions with 8 bit displacement
* ------------------------------------------------------------------------ */
static void decode_branch_8(Word code)
{
if (ChkArgCnt(1, 1))
decode_branch_8_core(1, code);
}
/*!------------------------------------------------------------------------
* \fn decode_branch_16(Word code)
* \brief decode instructions with 16 bit displacement
* ------------------------------------------------------------------------ */
static void decode_branch_16(Word code)
{
if (ChkArgCnt(1, 1))
{
tEvalResult eval_result;
LongInt dist = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &eval_result)
- (EProgCounter() + 3);
if (eval_result.OK)
{
if (!RangeCheck(dist, SInt16) && !mSymbolQuestionable(eval_result.Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
BAsmCode[CodeLen++] = code;
BAsmCode[CodeLen++] = (dist >> 8) & 0xff;
BAsmCode[CodeLen++] = dist & 0xff;
}
}
}
}
/*!------------------------------------------------------------------------
* \fn decode_div(Word code)
* \brief decode DIV instruction
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_div(Word code)
{
if (!ChkArgCnt(2, 2));
else if (as_strcasecmp(ArgStr[1].str.p_str, "X")) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
else if (as_strcasecmp(ArgStr[2].str.p_str, "B")) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
else
BAsmCode[CodeLen++] = code;
}
/*!------------------------------------------------------------------------
* \fn decode_move(Word code)
* \brief decode L(MOVE) instruction
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_move(Word code)
{
if (!ChkArgCnt(3, 3));
else if (as_strcasecmp(ArgStr[1].str.p_str, "Y")) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
else if (as_strcasecmp(ArgStr[2].str.p_str, "X")) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
else if (as_strcasecmp(ArgStr[3].str.p_str, "U")) WrStrErrorPos(ErrNum_InvReg, &ArgStr[3]);
else
BAsmCode[CodeLen++] = code;
}
/*!------------------------------------------------------------------------
* \fn decode_bset(Word code)
* \brief decode BSETx instruction
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_bset(Word code)
{
if (!ChkArgCnt(2, 2));
else if (as_strcasecmp(ArgStr[1].str.p_str, "X")) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
else if (as_strcasecmp(ArgStr[2].str.p_str, "U")) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
else
BAsmCode[CodeLen++] = code;
}
/*!------------------------------------------------------------------------
* \fn decode_exg_tfr(Word code)
* \brief decode EXG/TFR instruction
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_exg_tfr(Word code)
{
DecodeTFR_TFM_EXG_6809(code, False, decode_cpu_reg, True);
}
/*!------------------------------------------------------------------------
* \fn decode_dec(Word code)
* \brief handle DEC instruction
* \param code machine code
* ------------------------------------------------------------------------ */
static void decode_dec(Word code)
{
switch (ArgCnt)
{
case 3:
if (as_strcasecmp(ArgStr[2].str.p_str, "JNZ")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
else if (!as_strcasecmp(ArgStr[1].str.p_str, "B"))
decode_branch_8_core(3, code);
else if (!as_strcasecmp(ArgStr[1].str.p_str, "X"))
decode_branch_8_core(3, code + 1);
else
WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
break;
case 2:
decode_idx(0x8e);
break;
default:
(void)ChkArgCnt(2, 3);
}
}
/*!------------------------------------------------------------------------
* \fn init_fields(void)
* \brief create hash table
* ------------------------------------------------------------------------ */
static void add_acc_idx(const char *p_name, Word code)
{
char name[10];
as_snprintf(name, sizeof(name), "%sA", p_name);
AddInstTable(InstTable, name , code + 0, decode_inh);
as_snprintf(name, sizeof(name), "%sB", p_name);
AddInstTable(InstTable, name , code + 1, decode_inh);
AddInstTable(InstTable, p_name, code + 2, decode_idx);
}
static void add_acc_idx_16(const char *p_name, Word code)
{
char name[10];
as_snprintf(name, sizeof(name), "%sD", p_name);
AddInstTable(InstTable, name, code + 0, decode_inh);
as_snprintf(name, sizeof(name), "%sW", p_name);
AddInstTable(InstTable, name, code + 1, decode_idx);
}
static void add_reg_16(const char *p_name, Word code, Word code_incr, InstProc proc)
{
char name[10];
size_t z;
for (z = 0; z < as_array_size(reg_16_names); z++)
{
as_snprintf(name, sizeof(name), "%s%c", p_name, reg_16_names[z]);
AddInstTable(InstTable, name, code + (z * code_incr), proc);
}
}
static void add_reg_stack(const char *p_name, Word code, InstProc proc)
{
char name[10];
size_t z;
for (z = 2; z < as_array_size(reg_16_names); z++)
{
as_snprintf(name, sizeof(name), "%s%c", p_name, reg_16_names[z]);
AddInstTable(InstTable, name, code + (3 - z), proc);
}
}
static void add_ari_8(const char *p_name, Word code)
{
char name[10];
as_snprintf(name, sizeof(name), "%sA", p_name);
AddInstTable(InstTable, name, 0x0200 | code, decode_ari);
as_snprintf(name, sizeof(name), "%sB", p_name);
AddInstTable(InstTable, name, 0x0200 | (code + 1), decode_ari);
}
static void add_branch(const char *p_name, Word code)
{
char name[10];
AddInstTable(InstTable, p_name, code, decode_branch_8);
as_snprintf(name, sizeof(name), "L%s", p_name);
AddInstTable(InstTable, name, code + 8, decode_branch_16);
}
static void init_fields(void)
{
InstTable = CreateInstTable(207);
SetDynamicInstTable(InstTable);
add_reg_16("LEA", 0x08, 1, decode_idx);
add_reg_stack("PSH", 0x0c, DecodeStack_6809);
add_reg_stack("PUL", 0x0e, DecodeStack_6809);
add_ari_8("LD" , 0x10);
add_ari_8("ADD" , 0x14);
add_ari_8("ADC" , 0x18);
add_ari_8("SUB" , 0x1c);
add_ari_8("SBC" , 0x20);
add_ari_8("AND" , 0x24);
add_ari_8("BIT" , 0x28);
add_ari_8("EOR" , 0x2c);
add_ari_8("OR" , 0x30);
add_ari_8("CMP" , 0x34);
AddInstTable(InstTable, "SETLINES", 0x0138, decode_ari);
AddInstTable(InstTable, "STA", 0x3a, decode_idx);
AddInstTable(InstTable, "STB", 0x3b, decode_idx);
AddInstTable(InstTable, "ANDCC", 0x3c, decode_imm_8);
AddInstTable(InstTable, "ORCC", 0x3d, decode_imm_8);
AddInstTable(InstTable, "EXG", 0x3e, decode_exg_tfr);
AddInstTable(InstTable, "TFR", 0x3f, decode_exg_tfr);
AddInstTable(InstTable, "LDD", 0x8140, decode_ari);
add_reg_16("LD", 0x8142, 2, decode_ari);
AddInstTable(InstTable, "CMPD", 0x814a, decode_ari);
add_reg_16("CMP", 0x814c, 2, decode_ari);
AddInstTable(InstTable, "ADDD", 0x8154, decode_ari);
AddInstTable(InstTable, "SUBD", 0x8156, decode_ari);
AddInstTable(InstTable, "STD", 0x58, decode_ari);
add_branch("BRA", 0x60);
add_branch("BHI", 0x61);
add_branch("BCC", 0x62);
add_branch("BNE", 0x63);
add_branch("BVC", 0x64);
add_branch("BPL", 0x65);
add_branch("BGE", 0x66);
add_branch("BGT", 0x67);
add_branch("BRN", 0x70);
add_branch("BLS", 0x71);
add_branch("BCS", 0x72);
add_branch("BEQ", 0x73);
add_branch("BVS", 0x74);
add_branch("BMI", 0x75);
add_branch("BLT", 0x76);
add_branch("BLE", 0x77);
add_reg_16("ST", 0x59, 1, decode_ari);
add_acc_idx("CLR" , 0x80);
add_acc_idx("COM" , 0x83);
add_acc_idx("NEG" , 0x86);
add_acc_idx("INC" , 0x89);
AddInstTable(InstTable, "DECA" , 0x8c + 0, decode_inh);
AddInstTable(InstTable, "DECB" , 0x8c + 1, decode_inh);
AddInstTable(InstTable, "RTS", 0x8f, decode_inh);
add_acc_idx("TST" , 0x90);
add_acc_idx("LSR" , 0x93);
add_acc_idx("ROR" , 0x96);
add_acc_idx("ASR" , 0x99);
add_acc_idx("ASL" , 0x9c);
AddInstTable(InstTable, "RTI", 0x9f, decode_inh);
add_acc_idx("ROL" , 0xa0);
AddInstTable(InstTable, "LSRW", 0xa3, decode_idx);
AddInstTable(InstTable, "RORW", 0xa4, decode_idx);
AddInstTable(InstTable, "ASRW", 0xa5, decode_idx);
AddInstTable(InstTable, "ASLW", 0xa6, decode_idx);
AddInstTable(InstTable, "ROLW", 0xa7, decode_idx);
AddInstTable(InstTable, "JMP", 0xa8, decode_idx);
AddInstTable(InstTable, "JSR", 0xa9, decode_idx);
AddInstTable(InstTable, "BSR" , 0xaa, decode_branch_8);
AddInstTable(InstTable, "LBSR" , 0xab, decode_branch_16);
AddInstTable(InstTable, "DEC" , 0xac, decode_dec);
AddInstTable(InstTable, "NOP" , NOPCode, decode_inh);
AddInstTable(InstTable, "ABX" , 0xb0, decode_inh);
AddInstTable(InstTable, "DAA" , 0xb1, decode_inh);
AddInstTable(InstTable, "SEX" , 0xb2, decode_inh);
AddInstTable(InstTable, "MUL" , 0xb3, decode_inh);
AddInstTable(InstTable, "LMUL", 0xb4, decode_inh);
AddInstTable(InstTable, "DIV" , 0xb5, decode_div);
AddInstTable(InstTable, "BMOVE", 0xb6, decode_move);
AddInstTable(InstTable, "MOVE", 0xb7, decode_move);
AddInstTable(InstTable, "LSRD", 0x01b8, decode_ari);
AddInstTable(InstTable, "RORD", 0x01ba, decode_ari);
AddInstTable(InstTable, "ASRD", 0x01bc, decode_ari);
AddInstTable(InstTable, "ASLD", 0x01be, decode_ari);
AddInstTable(InstTable, "ROLD", 0x01c0, decode_ari);
add_acc_idx_16("CLR", 0xc2);
add_acc_idx_16("NEG", 0xc4);
add_acc_idx_16("INC", 0xc6);
add_acc_idx_16("DEC", 0xc8);
add_acc_idx_16("TST", 0xca);
AddInstTable(InstTable, "ABSA" , 0xcc, decode_inh);
AddInstTable(InstTable, "ABSB" , 0xcd, decode_inh);
AddInstTable(InstTable, "ABSD" , 0xce, decode_inh);
AddInstTable(InstTable, "BSETA", 0xcf, decode_bset);
AddInstTable(InstTable, "BSETD", 0xd0, decode_bset);
init_moto8_pseudo(InstTable, e_moto_8_be | e_moto_8_db | e_moto_8_dw);
}
/*!------------------------------------------------------------------------
* \fn deinit_fields(void)
* \brief destroy hash table
* ------------------------------------------------------------------------ */
static void deinit_fields(void)
{
DestroyInstTable(InstTable);
}
/*!------------------------------------------------------------------------
* \fn decode_attr_part_ko09(void)
* \brief parse attribute part
* ------------------------------------------------------------------------ */
static Boolean decode_attr_part_ko09(void)
{
if (strlen(AttrPart.
str.
p_str) > 1)
{
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return False;
}
/* Deduce operand size. No size is zero-length string -> '\0' */
return DecodeMoto16AttrSize(*AttrPart.str.p_str, &AttrPartOpSize[0], False);
}
/*!------------------------------------------------------------------------
* \fn make_code_ko09(void)
* \brief handle machine instructions
* ------------------------------------------------------------------------ */
static void make_code_ko09(void)
{
tSymbolSize op_size;
CodeLen = 0;
DontPrint = False;
op_size = (AttrPartOpSize[0] != eSymbolSizeUnknown) ? AttrPartOpSize[0] : eSymbolSize8Bit;
/* to be ignored */
if (Memo(""))
return;
/* pseudo instructions */
if (DecodeMoto16Pseudo(op_size, True))
return;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
/*!------------------------------------------------------------------------
* \fn is_def_ko09(void)
* \brief label part consumed by instruction?
* ------------------------------------------------------------------------ */
static Boolean is_def_ko09(void)
{
return False;
}
/*!------------------------------------------------------------------------
* \fn switch_to_ko09(void)
* \brief switch to target
* ------------------------------------------------------------------------ */
static void switch_to_ko09(void)
{
const TFamilyDescr *p_descr = FindFamilyByName("052001");
static const ASSUMERec ASSUME09s[] =
{
{ "DPR", &DPRValue, 0, 0xff, 0x100, NULL }
};
TurnWords = False;
SetIntConstMode(eIntConstModeMoto);
PCSymbol = "*";
HeaderID = p_descr->Id;
NOPCode = 0xae;
DivideChars = ",";
HasAttrs = True;
AttrChars = ".";
ValidSegs = (1 << SegCode);
Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
SegLimits[SegCode] = 0xffff;
DecodeAttrPart = decode_attr_part_ko09;
MakeCode = make_code_ko09;
IsDef = is_def_ko09;
SwitchFrom = deinit_fields;
init_fields();
AddMoto16PseudoONOFF(False);
pASSUMERecs = ASSUME09s;
ASSUMERecCnt = as_array_size(ASSUME09s);
}
/*!------------------------------------------------------------------------
* \fn codeko09_init(void)
* \brief attach target
* ------------------------------------------------------------------------ */
void codeko09_init(void)
{
(void)AddCPU("052001", switch_to_ko09);
}