508 lines
10 KiB
C++
508 lines
10 KiB
C++
//---------------------------------------------------------------------------
|
|
// NEOPOP : Emulator as in Dreamland
|
|
//
|
|
// Copyright (c) 2001-2002 by neopop_uk
|
|
//---------------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------------
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version. See also the license.txt file for
|
|
// additional informations.
|
|
//---------------------------------------------------------------------------
|
|
|
|
/*
|
|
//---------------------------------------------------------------------------
|
|
//=========================================================================
|
|
|
|
TLCS900h_disassemble_src.c
|
|
|
|
//=========================================================================
|
|
//---------------------------------------------------------------------------
|
|
|
|
History of changes:
|
|
===================
|
|
|
|
20 JUL 2002 - neopop_uk
|
|
=======================================
|
|
- Cleaned and tidied up for the source release
|
|
|
|
28 JUL 2002 - neopop_uk
|
|
=======================================
|
|
- Better disassembly of MUL/MULS/DIV/DIVS - operand size is shown.
|
|
|
|
//---------------------------------------------------------------------------
|
|
*/
|
|
|
|
//=========================================================================
|
|
|
|
#include "../neopop.h"
|
|
#include "TLCS900h_disassemble.h"
|
|
#include "TLCS900h_registers.h"
|
|
#include "TLCS900h_interpret.h"
|
|
|
|
//=========================================================================
|
|
|
|
namespace TLCS900H
|
|
{
|
|
|
|
static void PUSH()
|
|
{
|
|
sprintf(instr, "PUSH (%s)", extra);
|
|
}
|
|
|
|
static void RLD()
|
|
{
|
|
sprintf(instr, "RLD A,(%s)", extra);
|
|
}
|
|
|
|
static void RRD()
|
|
{
|
|
sprintf(instr, "RRD A,(%s)", extra);
|
|
}
|
|
|
|
static void LDI()
|
|
{
|
|
if ((first & 0xF) == 3)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDI.b (XDE+),(XHL+)"); break;
|
|
case 1: sprintf(instr, "LDI.w (XDE+),(XHL+)"); break;
|
|
}
|
|
}
|
|
|
|
if ((first & 0xF) == 5)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDI.b (XIX+),(XIY+)"); break;
|
|
case 1: sprintf(instr, "LDI.w (XIX+),(XIY+)"); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void LDIR()
|
|
{
|
|
if ((first & 0xF) == 3)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDIR.b (XDE+),(XHL+)"); break;
|
|
case 1: sprintf(instr, "LDIR.w (XDE+),(XHL+)"); break;
|
|
}
|
|
}
|
|
|
|
if ((first & 0xF) == 5)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDIR.b (XIX+),(XIY+)"); break;
|
|
case 1: sprintf(instr, "LDIR.w (XIX+),(XIY+)"); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void LDD()
|
|
{
|
|
if ((first & 0xF) == 3)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDD.b (XDE-),(XHL-)"); break;
|
|
case 1: sprintf(instr, "LDD.w (XDE-),(XHL-)"); break;
|
|
}
|
|
}
|
|
|
|
if ((first & 0xF) == 5)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDD.b (XIX-),(XIY-)"); break;
|
|
case 1: sprintf(instr, "LDD.w (XIX-),(XIY-)"); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void LDDR()
|
|
{
|
|
if ((first & 0xF) == 3)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDDR.b (XDE-),(XHL-)"); break;
|
|
case 1: sprintf(instr, "LDDR.w (XDE-),(XHL-)"); break;
|
|
}
|
|
}
|
|
|
|
if ((first & 0xF) == 5)
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "LDDR.b (XIX-),(XIY-)"); break;
|
|
case 1: sprintf(instr, "LDDR.w (XIX-),(XIY-)"); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void CPI()
|
|
{
|
|
sprintf(instr, "CPI");
|
|
}
|
|
|
|
static void CPIR()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "CPIR.b A,(%s+)", gprName[first & 7][2]); break;
|
|
case 1: sprintf(instr, "CPIR.w WA,(%s+)", gprName[first & 7][2]); break;
|
|
}
|
|
}
|
|
|
|
static void CPD()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "CPD.b A,(%s+)", gprName[first & 7][2]); break;
|
|
case 1: sprintf(instr, "CPD.w WA,(%s+)", gprName[first & 7][2]); break;
|
|
}
|
|
}
|
|
|
|
static void CPDR()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "CPDR.b A,(%s+)", gprName[first & 7][2]); break;
|
|
case 1: sprintf(instr, "CPDR.w WA,(%s+)", gprName[first & 7][2]); break;
|
|
}
|
|
}
|
|
|
|
static void LD16m()
|
|
{
|
|
sprintf(instr, "LD (0x%04X),(%s)", get16_dis(), extra);
|
|
}
|
|
|
|
static void LD()
|
|
{
|
|
sprintf(instr, "LD %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void EX()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "EX.b (%s),%s", extra, str_R); break;
|
|
case 1: sprintf(instr, "EX.w (%s),%s", extra, str_R); break;
|
|
}
|
|
|
|
}
|
|
|
|
static void ADDi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "ADD (%s), 0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "ADD (%s), 0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void ADCi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "ADC (%s), 0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "ADC (%s), 0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void SUBi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "SUB (%s), 0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "SUB (%s), 0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void SBCi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "SBC (%s), 0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "SBC (%s), 0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void ANDi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "AND (%s), 0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "AND (%s), 0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void XORi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "XOR (%s), 0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "XOR (%s), 0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void ORi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "OR (%s), 0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "OR (%s), 0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void CPi()
|
|
{
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "CP (%s),0x%02X", extra, get8_dis()); break;
|
|
case 1: sprintf(instr, "CP (%s),0x%04X", extra, get16_dis()); break;
|
|
}
|
|
}
|
|
|
|
static void MUL()
|
|
{
|
|
get_RR_Name();
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "MUL.b (%s),(%s)",str_R, extra); break;
|
|
case 1: sprintf(instr, "MUL.w (%s),(%s)",str_R, extra); break;
|
|
}
|
|
}
|
|
|
|
static void MULS()
|
|
{
|
|
get_RR_Name();
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "MULS.b (%s),(%s)",str_R, extra); break;
|
|
case 1: sprintf(instr, "MULS.w (%s),(%s)",str_R, extra); break;
|
|
}
|
|
}
|
|
|
|
static void DIV()
|
|
{
|
|
get_RR_Name();
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "DIV.b (%s),(%s)",str_R, extra); break;
|
|
case 1: sprintf(instr, "DIV.w (%s),(%s)",str_R, extra); break;
|
|
}
|
|
}
|
|
|
|
static void DIVS()
|
|
{
|
|
get_RR_Name();
|
|
switch(size)
|
|
{
|
|
case 0: sprintf(instr, "DIVS.b (%s),(%s)",str_R, extra); break;
|
|
case 1: sprintf(instr, "DIVS.w (%s),(%s)",str_R, extra); break;
|
|
}
|
|
}
|
|
|
|
static void INC()
|
|
{
|
|
uint8 val = (second & 7);
|
|
if (val == 0)
|
|
val = 8;
|
|
|
|
sprintf(instr, "INC %d,(%s)", val, extra);
|
|
}
|
|
|
|
static void DEC()
|
|
{
|
|
uint8 val = (second & 7);
|
|
if (val == 0)
|
|
val = 8;
|
|
|
|
sprintf(instr, "DEC %d,(%s)", val, extra);
|
|
}
|
|
|
|
static void RLC()
|
|
{
|
|
sprintf(instr, "RLC (%s)", extra);
|
|
}
|
|
|
|
static void RRC()
|
|
{
|
|
sprintf(instr, "RRC (%s)", extra);
|
|
}
|
|
|
|
static void RL()
|
|
{
|
|
sprintf(instr, "RL (%s)", extra);
|
|
}
|
|
|
|
static void RR()
|
|
{
|
|
sprintf(instr, "RR (%s)", extra);
|
|
}
|
|
|
|
static void SLA()
|
|
{
|
|
sprintf(instr, "SLA (%s)", extra);
|
|
}
|
|
|
|
static void SRA()
|
|
{
|
|
sprintf(instr, "SRA (%s)", extra);
|
|
}
|
|
|
|
static void SLL()
|
|
{
|
|
sprintf(instr, "SLL (%s)", extra);
|
|
}
|
|
|
|
static void SRL()
|
|
{
|
|
sprintf(instr, "SRL (%s)", extra);
|
|
}
|
|
|
|
static void ADDRm()
|
|
{
|
|
sprintf(instr, "ADD %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void ADDmR()
|
|
{
|
|
sprintf(instr, "ADD (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void ADCRm()
|
|
{
|
|
sprintf(instr, "ADC %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void ADCmR()
|
|
{
|
|
sprintf(instr, "ADC (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void SUBRm()
|
|
{
|
|
sprintf(instr, "SUB %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void SUBmR()
|
|
{
|
|
sprintf(instr, "SUB (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void SBCRm()
|
|
{
|
|
sprintf(instr, "SBC %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void SBCmR()
|
|
{
|
|
sprintf(instr, "SBC (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void ANDmR()
|
|
{
|
|
sprintf(instr, "AND (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void ANDRm()
|
|
{
|
|
sprintf(instr, "AND %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void XORmR()
|
|
{
|
|
sprintf(instr, "XOR (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void XORRm()
|
|
{
|
|
sprintf(instr, "XOR %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void ORmR()
|
|
{
|
|
sprintf(instr, "OR (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void ORRm()
|
|
{
|
|
sprintf(instr, "OR %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
static void CPmR()
|
|
{
|
|
sprintf(instr, "CP (%s),%s", extra, str_R);
|
|
}
|
|
|
|
static void CPRm()
|
|
{
|
|
sprintf(instr, "CP %s,(%s)", str_R, extra);
|
|
}
|
|
|
|
//=========================================================================
|
|
|
|
//Secondary (SRC) Instruction decode
|
|
static void (*decode[256])() =
|
|
{
|
|
/*0*/ 0, 0, 0, 0, PUSH, 0, RLD, RRD,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*1*/ LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR,
|
|
0, LD16m, 0, 0, 0, 0, 0, 0,
|
|
/*2*/ LD, LD, LD, LD, LD, LD, LD, LD,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*3*/ EX, EX, EX, EX, EX, EX, EX, EX,
|
|
ADDi, ADCi, SUBi, SBCi, ANDi, XORi, ORi, CPi,
|
|
/*4*/ MUL, MUL, MUL, MUL, MUL, MUL, MUL, MUL,
|
|
MULS, MULS, MULS, MULS, MULS, MULS, MULS, MULS,
|
|
/*5*/ DIV, DIV, DIV, DIV, DIV, DIV, DIV, DIV,
|
|
DIVS, DIVS, DIVS, DIVS, DIVS, DIVS, DIVS, DIVS,
|
|
/*6*/ INC, INC, INC, INC, INC, INC, INC, INC,
|
|
DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC,
|
|
/*7*/ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
RLC, RRC, RL, RR, SLA, SRA, SLL, SRL,
|
|
/*8*/ ADDRm, ADDRm, ADDRm, ADDRm, ADDRm, ADDRm, ADDRm, ADDRm,
|
|
ADDmR, ADDmR, ADDmR, ADDmR, ADDmR, ADDmR, ADDmR, ADDmR,
|
|
/*9*/ ADCRm, ADCRm, ADCRm, ADCRm, ADCRm, ADCRm, ADCRm, ADCRm,
|
|
ADCmR, ADCmR, ADCmR, ADCmR, ADCmR, ADCmR, ADCmR, ADCmR,
|
|
/*A*/ SUBRm, SUBRm, SUBRm, SUBRm, SUBRm, SUBRm, SUBRm, SUBRm,
|
|
SUBmR, SUBmR, SUBmR, SUBmR, SUBmR, SUBmR, SUBmR, SUBmR,
|
|
/*B*/ SBCRm, SBCRm, SBCRm, SBCRm, SBCRm, SBCRm, SBCRm, SBCRm,
|
|
SBCmR, SBCmR, SBCmR, SBCmR, SBCmR, SBCmR, SBCmR, SBCmR,
|
|
/*C*/ ANDRm, ANDRm, ANDRm, ANDRm, ANDRm, ANDRm, ANDRm, ANDRm,
|
|
ANDmR, ANDmR, ANDmR, ANDmR, ANDmR, ANDmR, ANDmR, ANDmR,
|
|
/*D*/ XORRm, XORRm, XORRm, XORRm, XORRm, XORRm, XORRm, XORRm,
|
|
XORmR, XORmR, XORmR, XORmR, XORmR, XORmR, XORmR, XORmR,
|
|
/*E*/ ORRm, ORRm, ORRm, ORRm, ORRm, ORRm, ORRm, ORRm,
|
|
ORmR, ORmR, ORmR, ORmR, ORmR, ORmR, ORmR, ORmR,
|
|
/*F*/ CPRm, CPRm, CPRm, CPRm, CPRm, CPRm, CPRm, CPRm,
|
|
CPmR, CPmR, CPmR, CPmR, CPmR, CPmR, CPmR, CPmR
|
|
};
|
|
|
|
//=============================================================================
|
|
|
|
void TLCS900h_disassemble_src(int opsize)
|
|
{
|
|
second = get8_dis(); //Get the second opcode
|
|
size = opsize;
|
|
|
|
//Prepare 'Big R'
|
|
sprintf(str_R, "%s", gprName[second & 7][size]);
|
|
|
|
if (decode[second])
|
|
(*decode[second])();
|
|
else
|
|
sprintf(instr, "unknown src instr. %02X", second);
|
|
}
|
|
};
|
|
|
|
//=============================================================================
|