cpu/xtensa.cpp, skeleton/hudson_poems.cpp: Added initial emulation for CPU core, and Poems hardware that utilizes it [David Haywood] (#11824)

* Xtensa work, alongside Poems hardware improvements to show the core is functional [David Haywood]
---------
Co-authored-by: David Haywood <hazemamewip@hotmail.com>
This commit is contained in:
mamehaze 2023-12-10 23:13:32 +00:00 committed by GitHub
parent 8aa103ebc4
commit 90c1511a6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 3347 additions and 319 deletions

View File

@ -3919,10 +3919,14 @@ if CPUS["XTENSA"] then
files {
MAME_DIR .. "src/devices/cpu/xtensa/xtensa.cpp",
MAME_DIR .. "src/devices/cpu/xtensa/xtensa.h",
MAME_DIR .. "src/devices/cpu/xtensa/xtensa_helper.cpp",
MAME_DIR .. "src/devices/cpu/xtensa/xtensa_helper.h",
}
end
if opt_tool(CPUS, "XTENSA") then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/xtensa/xtensad.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/xtensa/xtensad.h")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/xtensa/xtensa_helper.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/xtensa/xtensa_helper.h")
end

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,45 @@
// license:BSD-3-Clause
// copyright-holders:AJR
// copyright-holders:AJR, David Haywood
#ifndef MAME_CPU_XTENSA_XTENSA_H
#define MAME_CPU_XTENSA_XTENSA_H
#pragma once
#include "xtensa_helper.h"
class xtensa_device : public cpu_device
{
public:
xtensa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
enum {
AS_EXTREGS = AS_OPCODES + 1,
};
enum {
XTENSA_PC,
XTENSA_WINDOW,
XTENSA_INTENABLE,
XTENSA_LOOPBEGIN,
XTENSA_LOOPEND,
XTENSA_LOOPCOUNT,
XTENSA_A0, XTENSA_A1, XTENSA_A2, XTENSA_A3,
XTENSA_A4, XTENSA_A5, XTENSA_A6, XTENSA_A7,
XTENSA_A8, XTENSA_A9, XTENSA_A10, XTENSA_A11,
XTENSA_A12, XTENSA_A13, XTENSA_A14, XTENSA_A15
XTENSA_A12, XTENSA_A13, XTENSA_A14, XTENSA_A15,
};
void set_irq_vector(int bit, u32 vector)
{
m_irq_vectors[bit] = vector;
}
void set_startupvector(u32 vector)
{
m_startupvector = vector;
}
protected:
// device-level overrides
virtual void device_start() override;
@ -38,13 +58,154 @@ protected:
private:
// address space
address_space_config m_space_config;
address_space_config m_extregs_config;
memory_access<32, 2, 0, ENDIANNESS_LITTLE>::cache m_cache;
memory_access<32, 2, 0, ENDIANNESS_LITTLE>::specific m_space;
u32 extreg_windowbase_r();
void extreg_windowbase_w(u32 data);
u32 extreg_windowstart_r();
void extreg_windowstart_w(u32 data);
u32 extreg_lbeg_r();
void extreg_lbeg_w(u32 data);
u32 extreg_lend_r();
void extreg_lend_w(u32 data);
u32 extreg_lcount_r();
void extreg_lcount_w(u32 data);
u32 extreg_ps_r();
void extreg_ps_w(u32 data);
u32 extreg_cacheattr_r();
void extreg_cacheattr_w(u32 data);
u32 extreg_epc1_r();
void extreg_epc1_w(u32 data);
u32 extreg_epc2_r();
void extreg_epc2_w(u32 data);
u32 extreg_epc3_r();
void extreg_epc3_w(u32 data);
u32 extreg_epc4_r();
void extreg_epc4_w(u32 data);
u32 extreg_epc5_r();
void extreg_epc5_w(u32 data);
u32 extreg_eps2_r();
void extreg_eps2_w(u32 data);
u32 extreg_eps3_r();
void extreg_eps3_w(u32 data);
u32 extreg_eps4_r();
void extreg_eps4_w(u32 data);
u32 extreg_eps5_r();
void extreg_eps5_w(u32 data);
u32 extreg_excsave1_r();
void extreg_excsave1_w(u32 data);
u32 extreg_excsave2_r();
void extreg_excsave2_w(u32 data);
u32 extreg_excsave3_r();
void extreg_excsave3_w(u32 data);
u32 extreg_excsave4_r();
void extreg_excsave4_w(u32 data);
u32 extreg_excsave5_r();
void extreg_excsave5_w(u32 data);
u32 extreg_ibreaka0_r();
void extreg_ibreaka0_w(u32 data);
u32 extreg_dbreaka0_r();
void extreg_dbreaka0_w(u32 data);
u32 extreg_dbreakc0_r();
void extreg_dbreakc0_w(u32 data);
u32 extreg_icountlevel_r();
void extreg_icountlevel_w(u32 data);
u32 extreg_ccompare0_r();
void extreg_ccompare0_w(u32 data);
u32 extreg_intenable_r();
void extreg_intenable_w(u32 data);
u32 extreg_intclr_r();
void extreg_intclr_w(u32 data);
u32 extreg_intset_r();
void extreg_intset_w(u32 data);
u32 extreg_ccount_r();
void extreg_ccount_w(u32 data);
u32 extreg_exccause_r();
void extreg_exccause_w(u32 data);
u32 extreg_sar_r();
void extreg_sar_w(u32 data);
void set_irqpri(u8 val);
u8 get_irqpri();
void clear_irqpri(u8 val);
void set_callinc(u8 val);
u8 get_callinc();
void ext_regs(address_map &map);
bool handle_bz(u32 inst);
void handle_retw();
void check_interrupts();
void getop_and_execute();
inline u32 get_reg(u8 reg);
inline void set_reg(u8 reg, u32 value);
inline u32 get_mem32(u32 addr);
inline void set_mem32(u32 addr, u32 data);
inline u8 get_mem8(u32 addr);
inline void set_mem8(u32 addr, u8 data);
inline u16 get_mem16(u32 addr);
inline void set_mem16(u32 addr, u16 data);
void handle_reserved(u32 inst);
void switch_windowbase(s32 change);
// internal state
std::vector<u32> m_a_real; // actually 32 or 64 physical registers with Windowed extension
u32 m_a[16];
u32 m_pc;
s32 m_icount;
u32 m_extreg_windowbase;
u32 m_extreg_windowstart;
u32 m_extreg_sar;
u32 m_extreg_lbeg;
u32 m_extreg_lend;
u32 m_extreg_lcount;
u32 m_extreg_ps;
u32 m_extreg_cacheattr;
u32 m_extreg_epc1;
u32 m_extreg_epc2;
u32 m_extreg_epc3;
u32 m_extreg_epc4;
u32 m_extreg_epc5;
u32 m_extreg_eps2;
u32 m_extreg_eps3;
u32 m_extreg_eps4;
u32 m_extreg_eps5;
u32 m_extreg_excsave1;
u32 m_extreg_excsave2;
u32 m_extreg_excsave3;
u32 m_extreg_excsave4;
u32 m_extreg_excsave5;
u32 m_extreg_ibreaka0;
u32 m_extreg_dbreaka0;
u32 m_extreg_dbreakc0;
u32 m_extreg_icountlevel;
u32 m_extreg_ccompare0;
u32 m_extreg_intenable;
u32 m_extreg_intclr;
u32 m_extreg_intset;
u32 m_extreg_ccount;
u32 m_extreg_exccause;
u32 m_nextpc;
// config
u32 m_num_physical_regs;
u32 m_irq_vectors[32];
u32 m_startupvector;
xtensa_helper m_helper;
};
DECLARE_DEVICE_TYPE(XTENSA, xtensa_device)

View File

@ -0,0 +1,230 @@
#include "emu.h"
#include "xtensa_helper.h"
const char *const xtensa_helper::special_regs[256] =
{
"lbeg", "lend", "lcount", // Loop Option (0-2)
"sar", // Core Architecture (3)
"br", // Boolean Option (4)
"litbase", // Extended L32R Option (5)
"", "", "", "", "", "",
"scompare1", // Conditional Store Option (12)
"", "", "",
"acclo", "acchi", // MAC16 Option (16-17)
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"m0", "m1", "m2", "m3", // MAC16 Option (32-35)
"", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"WindowBase", "WindowStart", // Windowed Register Option (72-73)
"", "", "", "", "", "", "", "", "",
"ptevaddr", // MMU Option (83)
"", "", "", "", "",
"mmid", // Trace Port Option (89)
"rasid", "itlbcfg", "dtlbcfg", // MMU Option (90-92)
"", "", "",
"ibreakenable", // Debug Option (96)
"",
"cacheattr", // XEA1 Only (98)
"atomctl", // Conditional Store Option (99)
"", "", "", "",
"ddr", // Debug Option (104)
"",
"mepc", "meps", "mesave", "mesr", "mecr", "mevaddr", // Memory ECC/Parity Option (106-111)
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"ibreaka0", "ibreaka1", // Debug Option (128-129)
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"dbreaka0", "dbreaka1", // Debug Option (144-145)
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"dbreakc0", "dbreakc1", // Debug Option (160-161)
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"epc1", // Exception Option (177)
"epc2", "epc3", "epc4", "epc5", "epc6", "epc7", // High-Priority Interrupt Option (178-183)
"", "", "", "", "", "", "", "",
"depc", // Exception Option (192)
"",
"eps2", "eps3", "eps4", "eps5", "eps6", "eps7", // High-Priority Interrupt Option (194-199)
"", "", "", "", "", "", "", "", "",
"excsave1", // Exception Option (209)
"excsave2", "excsave3", "excsave4", "excsave5", "excsave6", "excsave7", // High-Priority Interrupt Option (210-215)
"", "", "", "", "", "", "", "",
"cpenable", // Coprocessor Option (224)
"",
"intset", "intclr", "intenable", // Interrupt Option (226-228)
"",
"ps", // various options (230)
"vecbase", // Relocatable Vector Option (231)
"exccause", // Exception Option (232)
"debugcause", // Debug Option (233)
"ccount", // Timer Interrupt Option (234)
"prid", // Processor ID Option (235)
"icount", "icountlevel", // Debug Option (236-237)
"excvaddr", // Exception Option (238)
"",
"ccompare0", "ccompare1", "ccompare2", // Timer Interrupt Option (240-242)
"",
"misc0", "misc1", "misc2", "misc3", // Miscellaneous Special Registers Option (244-247)
"", "", "", "", "", "", "", ""
};
const char *const xtensa_helper::s_st1_ops[16] =
{
"ssr", "ssl",
"ssa8l", "ssa8b",
"ssai", "",
"rer", "wer",
"rotw", "",
"", "",
"", "",
"nsa", "nsau"
};
const char *const xtensa_helper::s_tlb_ops[16] =
{
"", "", "", "ritlb0",
"iitlb", "pitlb", "witlb", "ritlb1",
"", "", "", "rdtlb0",
"idtlb", "pdtlb", "wdtlb", "rdtlb1"
};
const char *const xtensa_helper::s_rst2_ops[16] =
{
"andb", "andbc", "orb", "orbc", "xorb", "", "", "",
"mull", "", "muluh", "mulsh",
"quou", "quos", "remu", "rems"
};
const char *const xtensa_helper::s_rst3_ops[16] =
{
"rsr", "wsr",
"sext", "clamps",
"min", "max",
"minu", "maxu",
"moveqz", "movnez",
"movltz", "movgez",
"movf", "movt",
"rur", "wur"
};
const char *const xtensa_helper::s_fp0_ops[16] =
{
"add.s", "sub.s", "mul.s", "",
"madd.s", "msub.s", "", "",
"round.s", "trunc.s", "floor.s", "ceil.s",
"float.s", "ufloat.s", "utrunc.s", ""
};
const char *const xtensa_helper::s_fp1_ops[16] =
{
"", "un.s",
"oeq.s", "ueq.s",
"olt.s", "ult.s",
"ole.s", "ule.s",
"moveqz.s", "movltz.s",
"movltz.s", "movgez.s",
"movf.s", "movt.s",
"", ""
};
const char *const xtensa_helper::s_lsai_ops[16] =
{
"l8ui", "l16ui", "l32i", "",
"s8i", "s16i", "s32i", "",
"", "l16si", "movi", "l32ai",
"addi", "addmi", "s32c1i", "s32ri"
};
const char *const xtensa_helper::s_cache_ops[16] =
{
"dpfr", "dpfw",
"dpfro", "dpfwo",
"dhwb", "dhwbi",
"dhi", "dii",
"", "",
"", "",
"ipf", "",
"ihi", "iii"
};
const char *const xtensa_helper::s_lsci_ops[4] =
{
"lsi", "ssi", "lsiu", "ssiu"
};
const char *const xtensa_helper::s_mac16_ops[4] =
{
"umul", "mul", "mula", "muls"
};
const char *const xtensa_helper::s_mac16_half[4] =
{
"ll", "hl", "lh", "hh"
};
const char *const xtensa_helper::s_bz_ops[4] =
{
"beqz", "bnez", "bltz", "bgez"
};
const char *const xtensa_helper::s_bi0_ops[4] =
{
"beqi", "bnei", "blti", "bgei"
};
const int32_t xtensa_helper::s_b4const[16] =
{
-1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
};
const uint32_t xtensa_helper::s_b4constu[16] =
{
32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
};
const char *const xtensa_helper::s_b_ops[16] =
{
"bnone", "beq", "blt", "bltu", "ball", "bbc", "bbci", "bbci",
"bany", "bne", "bge", "bgeu", "bnall", "bbs", "bbsi", "bbsih"
};
std::string xtensa_helper::format_imm(uint32_t imm)
{
if (s32(imm) < 0)
{
if (s32(imm < -9))
{
return util::string_format("-0x%X", -imm);
}
else
{
return util::string_format("-%X", -imm);
}
}
else
{
if (imm > 9)
{
return util::string_format("0x%X", imm);
}
else
{
return util::string_format("%X", imm);
}
}
}
std::string xtensa_helper::special_reg(uint8_t n, bool wsr)
{
if (n == 226 && !wsr)
return "interrupt";
const char *s = xtensa_helper::special_regs[n];
if (s[0] == '\0')
return util::string_format("s%u", n);
else
return s;
}

View File

@ -0,0 +1,33 @@
// license:BSD-3-Clause
// copyright-holders:AJR
#ifndef MAME_CPU_XTENSA_XTENSA_HELPER_H
#define MAME_CPU_XTENSA_XTENSA_HELPER_H
#pragma once
class xtensa_helper
{
public:
static const char *const special_regs[256];
static const char *const s_st1_ops[16];
static const char *const s_tlb_ops[16];
static const char *const s_rst2_ops[16];
static const char *const s_rst3_ops[16];
static const char *const s_fp0_ops[16];
static const char *const s_fp1_ops[16];
static const char *const s_lsai_ops[16];
static const char *const s_cache_ops[16];
static const char *const s_lsci_ops[4];
static const char *const s_mac16_ops[4];
static const char *const s_mac16_half[4];
static const char *const s_bz_ops[4];
static const char *const s_bi0_ops[4];
static const int32_t s_b4const[16];
static const uint32_t s_b4constu[16];
static const char *const s_b_ops[16];
std::string format_imm(uint32_t imm);
std::string special_reg(uint8_t n, bool wsr);
};
#endif

View File

@ -18,6 +18,7 @@
#include "emu.h"
#include "xtensad.h"
#include "xtensa_helper.h"
xtensa_disassembler::xtensa_disassembler()
: util::disasm_interface()
@ -29,220 +30,6 @@ u32 xtensa_disassembler::opcode_alignment() const
return 1;
}
namespace {
static const char *const s_special_regs[256] =
{
"lbeg", "lend", "lcount", // Loop Option (0-2)
"sar", // Core Architecture (3)
"br", // Boolean Option (4)
"litbase", // Extended L32R Option (5)
"", "", "", "", "", "",
"scompare1", // Conditional Store Option (12)
"", "", "",
"acclo", "acchi", // MAC16 Option (16-17)
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"m0", "m1", "m2", "m3", // MAC16 Option (32-35)
"", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"WindowBase", "WindowStart", // Windowed Register Option (72-73)
"", "", "", "", "", "", "", "", "",
"ptevaddr", // MMU Option (83)
"", "", "", "", "",
"mmid", // Trace Port Option (89)
"rasid", "itlbcfg", "dtlbcfg", // MMU Option (90-92)
"", "", "",
"ibreakenable", // Debug Option (96)
"",
"cacheattr", // XEA1 Only (98)
"atomctl", // Conditional Store Option (99)
"", "", "", "",
"ddr", // Debug Option (104)
"",
"mepc", "meps", "mesave", "mesr", "mecr", "mevaddr", // Memory ECC/Parity Option (106-111)
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"ibreaka0", "ibreaka1", // Debug Option (128-129)
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"dbreaka0", "dbreaka1", // Debug Option (144-145)
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
"dbreakc0", "dbreakc1", // Debug Option (160-161)
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"epc1", // Exception Option (177)
"epc2", "epc3", "epc4", "epc5", "epc6", "epc7", // High-Priority Interrupt Option (178-183)
"", "", "", "", "", "", "", "",
"depc", // Exception Option (192)
"",
"eps2", "eps3", "eps4", "eps5", "eps6", "eps7", // High-Priority Interrupt Option (194-199)
"", "", "", "", "", "", "", "", "",
"excsave1", // Exception Option (209)
"excsave2", "excsave3", "excsave4", "excsave5", "excsave6", "excsave7", // High-Priority Interrupt Option (210-215)
"", "", "", "", "", "", "", "",
"cpenable", // Coprocessor Option (224)
"",
"intset", "intclr", "intenable", // Interrupt Option (226-228)
"",
"ps", // various options (230)
"vecbase", // Relocatable Vector Option (231)
"exccause", // Exception Option (232)
"debugcause", // Debug Option (233)
"ccount", // Timer Interrupt Option (234)
"prid", // Processor ID Option (235)
"icount", "icountlevel", // Debug Option (236-237)
"excvaddr", // Exception Option (238)
"",
"ccompare0", "ccompare1", "ccompare2", // Timer Interrupt Option (240-242)
"",
"misc0", "misc1", "misc2", "misc3", // Miscellaneous Special Registers Option (244-247)
"", "", "", "", "", "", "", ""
};
static const char *const s_st1_ops[16] =
{
"ssr", "ssl",
"ssa8l", "ssa8b",
"ssai", "",
"rer", "wer",
"rotw", "",
"", "",
"", "",
"nsa", "nsau"
};
static const char *const s_tlb_ops[16] =
{
"", "", "", "ritlb0",
"iitlb", "pitlb", "witlb", "ritlb1",
"", "", "", "rdtlb0",
"idtlb", "pdtlb", "wdtlb", "rdtlb1"
};
static const char *const s_rst2_ops[16] =
{
"andb", "andbc", "orb", "orbc", "xorb", "", "", "",
"mull", "", "muluh", "mulsh",
"quou", "quos", "remu", "rems"
};
static const char *const s_rst3_ops[16] =
{
"rsr", "wsr",
"sext", "clamps",
"min", "max",
"minu", "maxu",
"moveqz", "movnez",
"movltz", "movgez",
"movf", "movt",
"rur", "wur"
};
static const char *const s_fp0_ops[16] =
{
"add.s", "sub.s", "mul.s", "",
"madd.s", "msub.s", "", "",
"round.s", "trunc.s", "floor.s", "ceil.s",
"float.s", "ufloat.s", "utrunc.s", ""
};
static const char *const s_fp1_ops[16] =
{
"", "un.s",
"oeq.s", "ueq.s",
"olt.s", "ult.s",
"ole.s", "ule.s",
"moveqz.s", "movltz.s",
"movltz.s", "movgez.s",
"movf.s", "movt.s",
"", ""
};
static const char *const s_lsai_ops[16] =
{
"l8ui", "l16ui", "l32i", "",
"s8i", "s16i", "s32i", "",
"", "l16si", "movi", "l32ai",
"addi", "addmi", "s32c1i", "s32ri"
};
static const char *const s_cache_ops[16] =
{
"dpfr", "dpfw",
"dpfro", "dpfwo",
"dhwb", "dhwbi",
"dhi", "dii",
"", "",
"", "",
"ipf", "",
"ihi", "iii"
};
static const char *const s_lsci_ops[4] =
{
"lsi", "ssi", "lsiu", "ssiu"
};
static const char *const s_mac16_ops[4] =
{
"umul", "mul", "mula", "muls"
};
static const char *const s_mac16_half[4] =
{
"ll", "hl", "lh", "hh"
};
static const char *const s_bz_ops[4] =
{
"beqz", "bnez", "bltz", "bgez"
};
static const char *const s_bi0_ops[4] =
{
"beqi", "bnei", "blti", "bgei"
};
static const s32 s_b4const[16] =
{
-1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
};
static const u32 s_b4constu[16] =
{
32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
};
static const char *const s_b_ops[16] =
{
"bnone", "beq", "blt", "bltu", "ball", "bbc", "bbci", "bbci",
"bany", "bne", "bge", "bgeu", "bnall", "bbs", "bbsi", "bbsih"
};
} // anonymous namespace
void xtensa_disassembler::format_imm(std::ostream &stream, u32 imm)
{
if (s32(imm) < 0)
{
stream << '-';
imm = -imm;
}
if (imm > 9)
stream << "0x";
util::stream_format(stream, "%X", imm);
}
std::string xtensa_disassembler::special_reg(u8 n, bool wsr)
{
if (n == 226 && !wsr)
return "interrupt";
const char *s = s_special_regs[n];
if (s[0] == '\0')
return util::string_format("s%u", n);
else
return s;
}
offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const xtensa_disassembler::data_buffer &opcodes, const xtensa_disassembler::data_buffer &params)
{
u32 inst = opcodes.r16(pc);
@ -439,7 +226,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 12, 4))
{
case 0b0000: case 0b0001: case 0b0010: case 0b0011: // SSR, SSL, SSA8L, SSA8B
util::stream_format(stream, "%-8sa%d", s_st1_ops[BIT(inst, 12, 4)], BIT(inst, 8, 4));
util::stream_format(stream, "%-8sa%d", m_helper.s_st1_ops[BIT(inst, 12, 4)], BIT(inst, 8, 4));
break;
case 0b0100: // SSAI
@ -448,7 +235,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
case 0b0110: case 0b0111: // RER, WER
case 0b1110: case 0b1111: // NSA, NSAU (with Miscellaneous Operations Option)
util::stream_format(stream, "%-8sa%d, a%d", s_st1_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4));
util::stream_format(stream, "%-8sa%d, a%d", m_helper.s_st1_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4));
break;
case 0b1000: // ROTW (with Windowed Register Option)
@ -466,11 +253,11 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
{
case 0b0011: case 0b0101: case 0b0110: case 0b0111: // RITLB0, PITLB, WITLB, RITLB1
case 0b1011: case 0b1101: case 0b1110: case 0b1111: // RDTLB0, PDTLB, WDTLB, RDTLB1
util::stream_format(stream, "%-8sa%d, a%d", s_tlb_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4));
util::stream_format(stream, "%-8sa%d, a%d", m_helper.s_tlb_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4));
break;
case 0b0100: case 0b1100: // IITLB, IDTLB
util::stream_format(stream, "%-8sa%d", s_tlb_ops[BIT(inst, 12, 4)], BIT(inst, 8, 4));
util::stream_format(stream, "%-8sa%d", m_helper.s_tlb_ops[BIT(inst, 12, 4)], BIT(inst, 8, 4));
break;
default:
@ -514,8 +301,8 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
case 0b0001: // RST1
switch (BIT(inst, 20, 4))
{
case 0b0000: case 0b0001: // SLLI (shift count is 0..31)
util::stream_format(stream, "%-8sa%d, a%d, %d", "slli", BIT(inst, 12, 4), BIT(inst, 4, 4), BIT(inst, 8, 4) + (BIT(inst, 20) ? 16 : 0));
case 0b0000: case 0b0001: // SLLI (shift count is 1..31)
util::stream_format(stream, "%-8sa%d, a%d, %d", "slli", BIT(inst, 12, 4), BIT(inst, 8, 4), 32 - (BIT(inst, 4, 4) + (BIT(inst, 20) ? 16 : 0)));
break;
case 0b0010: case 0b0011: // SRAI (shift count is 0..31)
@ -527,7 +314,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
break;
case 0b0110: // XSR (added in T1040)
util::stream_format(stream, "xsr.%-3s a%d", special_reg(BIT(inst, 8, 8), true), BIT(inst, 4, 4));
util::stream_format(stream, "xsr.%-3s a%d", m_helper.special_reg(BIT(inst, 8, 8), true), BIT(inst, 4, 4));
break;
case 0b0111: // ACCER (added in RC-2009.0)
@ -631,12 +418,12 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 20, 4))
{
case 0b0000: case 0b0001: case 0b0010: case 0b0011: case 0b0100: // ANDB, ANDBC, ORB, ORBC, XORB (with Boolean Option)
util::stream_format(stream, "%-8sb%d, b%d, b%d", s_rst2_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sb%d, b%d, b%d", m_helper.s_rst2_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1000: case 0b1010: case 0b1011: // MULL, MULUH, MULSH (with 32-bit Integer Multiply Option)
case 0b1100: case 0b1101: case 0b1110: case 0b1111: // QUOU, QUOS, REMU, REMS (with 32-bit Integer Divide Option)
util::stream_format(stream, "%-8sa%d, a%d, a%d", s_rst2_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sa%d, a%d, a%d", m_helper.s_rst2_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
default:
@ -649,24 +436,24 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 20, 4))
{
case 0b0000: case 0b0001: // RSR, WSR
util::stream_format(stream, "%s.%-3d a%d", s_rst3_ops[BIT(inst, 20, 4)], special_reg(BIT(inst, 8, 8), BIT(inst, 20)), BIT(inst, 4, 4));
util::stream_format(stream, "%s.%-3d a%d", m_helper.s_rst3_ops[BIT(inst, 20, 4)], m_helper.special_reg(BIT(inst, 8, 8), BIT(inst, 20)), BIT(inst, 4, 4));
break;
case 0b0010: case 0b0011: // SEXT, CLAMPS (with Miscellaneous Operations Option)
util::stream_format(stream, "%-8sa%d, a%d, %d", s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4) + 7);
util::stream_format(stream, "%-8sa%d, a%d, %d", m_helper.s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4) + 7);
break;
case 0b0100: case 0b0101: case 0b0110: case 0b0111: // MIN, MAX, MINU, MAXU (with Miscellaneous Operations Option)
case 0b1000: case 0b1001: case 0b1010: case 0b1011: // MOVEQZ, MOVNEZ, MOVLTZ, MOVGEZ
util::stream_format(stream, "%-8sa%d, a%d, a%d", s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sa%d, a%d, a%d", m_helper.s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1100: case 0b1101: // MOVF, MOVT (with Boolean Option)
util::stream_format(stream, "%-8sa%d, a%d, b%d", s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sa%d, a%d, b%d", m_helper.s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1110: case 0b1111: // RUR, WUR (TODO: TIE user_register names)
util::stream_format(stream, "%s.u%-2d a%d", s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 4, 8), BIT(inst, 12, 4));
util::stream_format(stream, "%s.u%-2d a%d", m_helper.s_rst3_ops[BIT(inst, 20, 4)], BIT(inst, 4, 8), BIT(inst, 12, 4));
break;
}
break;
@ -708,13 +495,11 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 20, 4))
{
case 0b0000: // L32E
util::stream_format(stream, "%-8sa%d, a%d, ", "l32e", BIT(inst, 4, 4), BIT(inst, 8, 4));
format_imm(stream, int(BIT(inst, 12, 4)) * 4 - 64);
util::stream_format(stream, "%-8sa%d, a%d, %s", "l32e", BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm(int(BIT(inst, 12, 4)) * 4 - 64));
break;
case 0b0100: // S32E
util::stream_format(stream, "%-8sa%d, a%d, ", "s32e", BIT(inst, 4, 4), BIT(inst, 8, 4));
format_imm(stream, int(BIT(inst, 12, 4)) * 4 - 64);
util::stream_format(stream, "%-8sa%d, a%d, %s", "s32e", BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm(int(BIT(inst, 12, 4)) * 4 - 64));
break;
default:
@ -727,15 +512,15 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 20, 4))
{
case 0b0000: case 0b0001: case 0b0010: case 0b0100: case 0b0101: // ADD.S, SUB.S, MUL.S, MADD.S, MSUB.S
util::stream_format(stream, "%-8sf%d, f%d, f%d", s_fp0_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sf%d, f%d, f%d", m_helper.s_fp0_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1000: case 0b1001: case 0b1010: case 0b1011: case 0b1110: // ROUND.S, TRUNC.S, FLOOR.S, CEIL.S, UTRUNC.S
util::stream_format(stream, "%-7s a%d, f%d, %d", s_fp0_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-7s a%d, f%d, %d", m_helper.s_fp0_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1100: case 0b1101: // FLOAT.S, UFLOAT.S
util::stream_format(stream, "%-7s f%d, a%d, %d", s_fp0_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-7s f%d, a%d, %d", m_helper.s_fp0_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1111: // FP1OP
@ -777,15 +562,15 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 20, 4))
{
case 0b0001: case 0b0010: case 0b0011: case 0b0100: case 0b0101: case 0b0110: case 0b0111: // UN.S, OEQ.S, UEQ.S, OLT.S, ULT.S, OLE.S, ULE.S
util::stream_format(stream, "%-8sb%d, f%d, f%d", s_fp1_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sb%d, f%d, f%d", m_helper.s_fp1_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1000: case 0b1001: case 0b1010: case 0b1011: // MOVEQZ.S, MOVNEZ.S, MOVLTZ.S, MOVGEZ.S
util::stream_format(stream, "%-8sf%d, f%d, a%d", s_fp1_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sf%d, f%d, a%d", m_helper.s_fp1_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1100: case 0b1101: // MOVF.S, MOVT.S
util::stream_format(stream, "%-8sf%d, f%d, b%d", s_fp1_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%-8sf%d, f%d, b%d", m_helper.s_fp1_ops[BIT(inst, 20, 4)], BIT(inst, 12, 4), BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
default:
@ -808,20 +593,17 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 12, 4))
{
case 0b0000: case 0b0100: // L8UI, S8I
util::stream_format(stream, "%-8sa%d, a%d, ", s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4));
format_imm(stream, inst >> 16);
util::stream_format(stream, "%-8sa%d, a%d, %s", m_helper.s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm(inst >> 16));
break;
case 0b0001: case 0b0101: case 0b1001: // L16UI, S16I, L16SI
util::stream_format(stream, "%-8sa%d, a%d, ", s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4));
format_imm(stream, (inst >> 16) * 2);
util::stream_format(stream, "%-8sa%d, a%d, %s", m_helper.s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm((inst >> 16) * 2));
break;
case 0b0010: case 0b0110: // L32I, S32I
case 0b1011: case 0b1111: // L32AI, S32RI (with Multiprocessor Synchronization Option)
case 0b1110: // S32C1I (with Conditional Store Option)
util::stream_format(stream, "%-8sa%d, a%d, ", s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4));
format_imm(stream, (inst >> 16) * 4);
util::stream_format(stream, "%-8sa%d, a%d, %s", m_helper.s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm((inst >> 16) * 4));
break;
case 0b0111: // CACHE
@ -830,36 +612,30 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
case 0b0000: case 0b0001: case 0b0010: case 0b0011: // DPFR, DPFW, DPFRO, DPFWO (with Data Cache Option)
case 0b0100: case 0b0101: case 0b0110: case 0b0111: // DHWB, DHWBI, DHI, DII (with Data Cache Option)
case 0b1100: case 0b1110: case 0b1111: // IPF, IHI, III (with Instruction Cache Option)
util::stream_format(stream, "%-8sa%d, ", s_cache_ops[BIT(inst, 4, 4)], BIT(inst, 8, 4));
format_imm(stream, (inst >> 16) * 4);
util::stream_format(stream, "%-8sa%d, %s", m_helper.s_cache_ops[BIT(inst, 4, 4)], BIT(inst, 8, 4), m_helper.format_imm((inst >> 16) * 4));
break;
case 0b1000: // DCE (with Data Cache Option)
switch (BIT(inst, 16, 4))
{
case 0b0000: // DPFL (with Data Cache Index Lock Option)
util::stream_format(stream, "%-8sa%d, ", "dpfl", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "dpfl", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
case 0b0010: // DHU (with Data Cache Index Lock Option)
util::stream_format(stream, "%-8sa%d, ", "dhu", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "dhu", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
case 0b0011: // DIU (with Data Cache Index Lock Option)
util::stream_format(stream, "%-8sa%d, ", "diu", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "diu", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
case 0b0100: // DIWB (added in T1050)
util::stream_format(stream, "%-8sa%d, ", "diwb", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "diwb", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
case 0b0101: // DIWBI (added in T1050)
util::stream_format(stream, "%-8sa%d, ", "diwbi", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "diwbi", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
}
break;
@ -868,18 +644,15 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
switch (BIT(inst, 16, 4))
{
case 0b0000: // IPFL
util::stream_format(stream, "%-8sa%d, ", "ipfl", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "ipfl", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
case 0b0010: // IHU
util::stream_format(stream, "%-8sa%d, ", "ihu", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "ihu", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
case 0b0011: // IIU
util::stream_format(stream, "%-8sa%d, ", "iiu", BIT(inst, 8, 4));
format_imm(stream, (inst >> 20) * 4);
util::stream_format(stream, "%-8sa%d, %s", "iiu", BIT(inst, 8, 4), m_helper.format_imm((inst >> 20) * 4));
break;
default:
@ -895,13 +668,11 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
break;
case 0b1010: // MOVI
util::stream_format(stream, "%-8sa%d, ", "movi", BIT(inst, 4, 4));
format_imm(stream, util::sext((inst & 0x000f00) + (inst >> 16), 12));
util::stream_format(stream, "%-8sa%d, %s", "movi", BIT(inst, 4, 4), m_helper.format_imm(util::sext((inst & 0x000f00) + (inst >> 16), 12)));
break;
case 0b1100: case 0b1101: // ADDI, ADDMI
util::stream_format(stream, "%-8sa%d, a%d, ", s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 8, 4), BIT(inst, 4, 4));
format_imm(stream, s8(u8(inst >> 16)) * (BIT(inst, 12) ? 256 : 1));
util::stream_format(stream, "%-8sa%d, a%d, %s", m_helper.s_lsai_ops[BIT(inst, 12, 4)], BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm(s8(u8(inst >> 16)) * (BIT(inst, 12) ? 256 : 1)));
break;
default:
@ -914,8 +685,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
if (BIT(inst, 12, 2) == 0)
{
// LSI, SSI, LSIU, SSIU
util::stream_format(stream, "%-8sf%d, a%d, ", s_lsci_ops[BIT(inst, 14, 2)], BIT(inst, 4, 4), BIT(inst, 8, 4));
format_imm(stream, BIT(inst, 16, 8) * 4);
util::stream_format(stream, "%-8sf%d, a%d, %s", m_helper.s_lsci_ops[BIT(inst, 14, 2)], BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm(BIT(inst, 16, 8) * 4));
return 3 | SUPPORTED;
}
else
@ -929,8 +699,8 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
{
case 0b0000: case 0b0001: // MACID, MACCD
if (BIT(inst, 18, 2) == 0b10)
util::stream_format(stream, "%s.dd.%s.%s m%d, a%d, m%d, m%d", s_mac16_ops[BIT(inst, 18, 2)],
s_mac16_half[BIT(inst, 16, 2)],
util::stream_format(stream, "%s.dd.%s.%s m%d, a%d, m%d, m%d", m_helper.s_mac16_ops[BIT(inst, 18, 2)],
m_helper.s_mac16_half[BIT(inst, 16, 2)],
BIT(inst, 20) ? "lddec" : "ldinc",
BIT(inst, 12, 2), BIT(inst, 8, 4),
BIT(inst, 14), BIT(inst, 6) + 2);
@ -943,8 +713,8 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
case 0b0100: case 0b0101: // MACIA, MACCA
if (BIT(inst, 18, 2) == 0b10)
util::stream_format(stream, "%s.da.%s.%s m%d, a%d, m%d, a%d", s_mac16_ops[BIT(inst, 18, 2)],
s_mac16_half[BIT(inst, 16, 2)],
util::stream_format(stream, "%s.da.%s.%s m%d, a%d, m%d, a%d", m_helper.s_mac16_ops[BIT(inst, 18, 2)],
m_helper.s_mac16_half[BIT(inst, 16, 2)],
BIT(inst, 20) ? "lddec" : "ldinc",
BIT(inst, 12, 2), BIT(inst, 8, 4),
BIT(inst, 14), BIT(inst, 4, 4));
@ -957,7 +727,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
case 0b0010: // MACDD
if (BIT(inst, 18, 2) != 0b00)
util::stream_format(stream, "%s.dd.%s m%d, m%d", s_mac16_ops[BIT(inst, 18, 2)], s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 14), BIT(inst, 6) + 2);
util::stream_format(stream, "%s.dd.%s m%d, m%d", m_helper.s_mac16_ops[BIT(inst, 18, 2)], m_helper.s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 14), BIT(inst, 6) + 2);
else
{
util::stream_format(stream, "%-8s0x%02X ; reserved", "db", inst & 0xff);
@ -967,7 +737,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
case 0b0011: // MACAD
if (BIT(inst, 18, 2) != 0b00)
util::stream_format(stream, "%s.ad.%s a%d, m%d", s_mac16_ops[BIT(inst, 18, 2)], s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 8, 4), BIT(inst, 6) + 2);
util::stream_format(stream, "%s.ad.%s a%d, m%d", m_helper.s_mac16_ops[BIT(inst, 18, 2)], m_helper.s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 8, 4), BIT(inst, 6) + 2);
else
{
util::stream_format(stream, "%-8s0x%02X ; reserved", "db", inst & 0xff);
@ -977,7 +747,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
case 0b0110: // MACDA
if (BIT(inst, 18, 2) != 0b00)
util::stream_format(stream, "%s.da.%s m%d, a%d", s_mac16_ops[BIT(inst, 18, 2)], s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 14), BIT(inst, 4, 4));
util::stream_format(stream, "%s.da.%s m%d, a%d", m_helper.s_mac16_ops[BIT(inst, 18, 2)], m_helper.s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 14), BIT(inst, 4, 4));
else
{
util::stream_format(stream, "%-8s0x%02X ; reserved", "db", inst & 0xff);
@ -986,7 +756,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
break;
case 0b0111: // MACAA
util::stream_format(stream, "%s.aa.%s a%d, a%d", s_mac16_ops[BIT(inst, 18, 2)], s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 8, 4), BIT(inst, 4, 4));
util::stream_format(stream, "%s.aa.%s a%d, a%d", m_helper.s_mac16_ops[BIT(inst, 18, 2)], m_helper.s_mac16_half[BIT(inst, 16, 2)], BIT(inst, 8, 4), BIT(inst, 4, 4));
break;
case 0b1000: case 0b1001: // MACI, MACC
@ -1026,21 +796,18 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
break;
case 0b01: // BZ
util::stream_format(stream, "%-8sa%d, 0x%08X", s_bz_ops[BIT(inst, 6, 2)], BIT(inst, 8, 4), pc + 4 + util::sext(inst >> 12, 12));
util::stream_format(stream, "%-8sa%d, 0x%08X", m_helper.s_bz_ops[BIT(inst, 6, 2)], BIT(inst, 8, 4), pc + 4 + util::sext(inst >> 12, 12));
return 3 | STEP_COND | SUPPORTED;
case 0b10: // BI0
util::stream_format(stream, "%-8sa%d, ", s_bi0_ops[BIT(inst, 6, 2)], BIT(inst, 8, 4));
format_imm(stream, s_b4const[BIT(inst, 12, 4)]);
util::stream_format(stream, ", 0x%08X", pc + 4 + s8(u8(inst >> 16)));
util::stream_format(stream, "%-8sa%d, %s, 0x%08X", m_helper.s_bi0_ops[BIT(inst, 6, 2)], BIT(inst, 8, 4), m_helper.format_imm(m_helper.s_b4const[BIT(inst, 12, 4)]), pc + 4 + s8(u8(inst >> 16)));
return 3 | STEP_COND | SUPPORTED;
case 0b11: // BI1
switch (BIT(inst, 6, 2))
{
case 0b00: // ENTRY
util::stream_format(stream, "%-8sa%d, ", "entry", BIT(inst, 8, 4));
format_imm(stream, (inst >> 12) * 4);
util::stream_format(stream, "%-8sa%d, %s", "entry", BIT(inst, 8, 4), m_helper.format_imm((inst >> 12) * 4));
break;
case 0b01: // B1
@ -1069,9 +836,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
break;
case 0b10: case 0b11: // BLTUI, BGEUI
util::stream_format(stream, "%-8sa%d, ", BIT(inst, 6) ? "bgeui" : "bltui", BIT(inst, 8, 4));
format_imm(stream, s_b4constu[BIT(inst, 4, 4)]);
util::stream_format(stream, ", 0x%08X", pc + 4 + s8(u8(inst >> 16)));
util::stream_format(stream, "%-8sa%d, %s, 0x%08X", BIT(inst, 6) ? "bgeui" : "bltui", BIT(inst, 8, 4), m_helper.format_imm(m_helper.s_b4constu[BIT(inst, 12, 4)]), pc + 4 + s8(u8(inst >> 16)));
return 3 | STEP_COND | SUPPORTED;
}
break;
@ -1079,21 +844,20 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
return 3 | SUPPORTED;
case 0b0111: // B
if (BIT(inst, 9, 2) == 0b11)
if (BIT(inst, 13, 2) == 0b11)
{
// BBCI, BBSI
util::stream_format(stream, "%-8sa%d, %d, 0x%08X", BIT(inst, 11) ? "bbsi" : "bbci", BIT(inst, 8, 4), BIT(inst, 4, 4) + (BIT(inst, 12) ? 4 : 0), pc + 4 + s8(u8(inst >> 16)));
util::stream_format(stream, "%-8sa%d, %d, 0x%08X", BIT(inst, 15) ? "bbsi" : "bbci", BIT(inst, 8, 4), BIT(inst, 4, 4) + (BIT(inst, 12) ? 16 : 0), pc + 4 + s8(u8(inst >> 16)));
}
else
{
// BNONE, BEQ, BLT, BLTU, BALL, BBC, BBCI, BANY, BNE, BGE, BGEU, BNALL, BBS
util::stream_format(stream, "%-8sa%d, a%d, 0x%08X", s_b_ops[BIT(inst, 12, 4)], BIT(inst, 8, 4), BIT(inst, 4, 4), pc + 4 + s8(u8(inst >> 16)));
util::stream_format(stream, "%-8sa%d, a%d, 0x%08X", m_helper.s_b_ops[BIT(inst, 12, 4)], BIT(inst, 8, 4), BIT(inst, 4, 4), pc + 4 + s8(u8(inst >> 16)));
}
return 3 | STEP_COND | SUPPORTED;
case 0b1000: case 0b1001: // L32I.N (with Code Density Option)
util::stream_format(stream, "%-8sa%d, a%d, ", BIT(inst, 0) ? "s32i.n" : "l32i.n", BIT(inst, 4, 4), BIT(inst, 8, 4));
format_imm(stream, BIT(inst, 12, 4) * 4);
util::stream_format(stream, "%-8sa%d, a%d, %s", BIT(inst, 0) ? "s32i.n" : "l32i.n", BIT(inst, 4, 4), BIT(inst, 8, 4), m_helper.format_imm(BIT(inst, 12, 4) * 4));
return 2 | SUPPORTED;
case 0b1010: // ADD.N (with Code Density Option)
@ -1108,8 +872,7 @@ offs_t xtensa_disassembler::disassemble(std::ostream &stream, offs_t pc, const x
if (!BIT(inst, 7))
{
// 7-bit immediate field uses asymmetric sign extension (range is -32..95)
util::stream_format(stream, "%-8sa%d, ", "movi.n", BIT(inst, 8, 4));
format_imm(stream, int((inst & 0x0070) + BIT(inst, 12, 4) - (BIT(inst, 5, 2) == 0b11 ? 128 : 0)));
util::stream_format(stream, "%-8sa%d, %s", "movi.n", BIT(inst, 8, 4), m_helper.format_imm(int((inst & 0x0070) + BIT(inst, 12, 4) - (BIT(inst, 5, 2) == 0b11 ? 128 : 0))));
return 2 | SUPPORTED;
}
else

View File

@ -6,6 +6,8 @@
#pragma once
#include "xtensa_helper.h"
class xtensa_disassembler : public util::disasm_interface
{
public:
@ -18,10 +20,7 @@ protected:
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
private:
// formatting helpers
static void format_imm(std::ostream &stream, u32 imm);
static std::string special_reg(u8 n, bool wsr);
xtensa_helper m_helper;
};
#endif // MAME_CPU_XTENSA_XTENSAD_H

View File

@ -23,15 +23,27 @@
2005/11/17 !!! (Mini-Game Collection)
2005/11/24 ! (Kid's Floor Mat)
-------------
Marimba Tengoku has a secret test menu, see notes near input port definition.
The ROM check code for that menu is at 0x661010 in ROM and does a full 32-bit word sum
of the ROM, comparing it against the value stored in the last 4 bytes (it passes)
*/
#include "emu.h"
#include "cpu/xtensa/xtensa.h"
#include "machine/timer.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#define LOG_SPRITEBASE (1U << 1)
#define VERBOSE (0)
#include "logmacro.h"
namespace {
@ -40,65 +52,665 @@ class hudson_poems_state : public driver_device
public:
hudson_poems_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu")
m_maincpu(*this, "maincpu"),
m_palette(*this, "palette"),
m_screen(*this, "screen"),
m_gfxdecode(*this, "gfxdecode"),
m_mainram(*this, "mainram"),
m_palram(*this, "palram")
{ }
void hudson_poems(machine_config &config);
void init_marimba();
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void draw_tile(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 tile, int xx, int yy, int gfxbase, int extrapal);
void draw_tile8(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 tile, int xx, int yy, int gfxbase, int extrapal);
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void draw_tilemap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int which, int priority);
u32 poems_random_r();
void unk_trigger_w(offs_t offset, u32 data, u32 mem_mask);
TIMER_DEVICE_CALLBACK_MEMBER(screen_scanline);
template<int Which> void tilemap_map(address_map &map, u32 base);
void mem_map(address_map &map);
required_device<cpu_device> m_maincpu;
u32 poems_8020010_r();
u32 poems_count_r();
u32 poems_unk_r();
u32 poems_8000038_r(offs_t offset, u32 mem_mask);
u32 poems_8000200_r(offs_t offset, u32 mem_mask);
u32 unk_aa04_r(offs_t offset, u32 mem_mask);
void unk_aa00_w(offs_t offset, u32 data, u32 mem_mask);
void fade_w(offs_t offset, u32 data, u32 mem_mask);
void unktable_w(offs_t offset, u32 data, u32 mem_mask);
void unktable_reset_w(offs_t offset, u32 data, u32 mem_mask);
void set_palette_val(int entry);
void palette_w(offs_t offset, u32 data, u32 mem_mask);
void mainram_w(offs_t offset, u32 data, u32 mem_mask);
void spritegfx_base_w(offs_t offset, u32 data, u32 mem_mask);
void spritelist_base_w(offs_t offset, u32 data, u32 mem_mask);
template<int Layer> void tilemap_base_w(offs_t offset, u32 data, u32 mem_mask);
template<int Layer> void tilemap_unk_w(offs_t offset, u32 data, u32 mem_mask);
template<int Layer> void tilemap_cfg_w(offs_t offset, u32 data, u32 mem_mask);
template<int Layer> void tilemap_scr_w(offs_t offset, u32 data, u32 mem_mask);
template<int Layer> void tilemap_high_w(offs_t offset, u32 data, u32 mem_mask);
template<int Layer> u32 tilemap_base_r(offs_t offset, u32 mem_mask);
template<int Layer> u32 tilemap_high_r(offs_t offset, u32 mem_mask);
template<int Layer> u32 tilemap_unk_r(offs_t offset, u32 mem_mask);
template<int Layer> u32 tilemap_cfg_r(offs_t offset, u32 mem_mask);
template<int Layer> u32 tilemap_scr_r(offs_t offset, u32 mem_mask);
u16 m_unktable[256];
u16 m_unktableoffset;
u32 m_spritegfxbase[4];
u32 m_spritelistbase;
u32 m_tilemapbase[4];
u32 m_tilemapunk[4];
u32 m_tilemapcfg[4];
u32 m_tilemapscr[4];
u32 m_tilemaphigh[4];
s32 m_hackcounter;
required_device<xtensa_device> m_maincpu;
required_device<palette_device> m_palette;
required_device<screen_device> m_screen;
required_device<gfxdecode_device> m_gfxdecode;
required_shared_ptr<u32> m_mainram;
required_shared_ptr<u32> m_palram;
};
void hudson_poems_state::machine_start()
{
save_item(NAME(m_unktable));
save_item(NAME(m_unktableoffset));
save_item(NAME(m_spritegfxbase));
save_item(NAME(m_spritelistbase));
save_item(NAME(m_tilemapbase));
save_item(NAME(m_tilemapunk));
save_item(NAME(m_tilemapcfg));
save_item(NAME(m_tilemapscr));
save_item(NAME(m_tilemaphigh));
save_item(NAME(m_hackcounter));
}
void hudson_poems_state::machine_reset()
{
m_maincpu->set_pc(0x20010058);
m_unktableoffset = 0;
m_hackcounter = 0;
for (int i = 0; i < 4; i++)
{
m_spritegfxbase[i] = m_tilemapbase[i] = m_tilemaphigh[i] = m_tilemapunk[i] = m_tilemapcfg[i] = m_tilemapscr[i] = 0;
}
}
/*
You can unlock the test menu on boot by inputing a 3 step sequence while the Konami logo is being shown:
Step 1 checks if you input white or yellow 2 times
Step 2 checks if you input red or blue 2 times
Step 3 checks if you input white or green 3 times
These are not grouped inputs, so for step 1 you must input white x2 or yellow x2 instead of white x1 and yellow x1 for it to count.
*/
static INPUT_PORTS_START( hudson_poems )
PORT_START( "IN1" )
PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("White")
PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("Yellow (Select Up)")
PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Red (Ok)")
PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("Blue (Select Down)")
PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("Green")
INPUT_PORTS_END
uint32_t hudson_poems_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
void hudson_poems_state::draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int spritebase = (m_spritelistbase & 0x0003ffff) / 4;
gfx_element *gfx = m_gfxdecode->gfx(2);
for (int i = 0; i < 64; i++)
{
const u16 spriteword0 = m_mainram[(spritebase + i * 2) + 0] & 0xffff;
const u16 spriteword1 = m_mainram[(spritebase + i * 2) + 0] >> 16;
const u16 spriteword2 = m_mainram[(spritebase + i * 2) + 1] & 0xffff;
const u16 spriteword3 = m_mainram[(spritebase + i * 2) + 1] >> 16;
const int x = (spriteword3 & 0x03ff);
const int y = (spriteword2 & 0x03ff);
int tilenum = spriteword1 & 0x03ff;
const int pal = (spriteword2 & 0x7c00)>>10;
// is it selecting from multiple tile pages (which can have different bases?) (probably from a register somewhere)
const int tilebase = (m_spritegfxbase[(spriteword0 & 0x0300)>>8] & 0x0003ffff) / 32; // m_spritegfxbase contains a full memory address pointer to RAM
tilenum += tilebase;
/* based on code analysis of function at 006707A4
word0 ( 0abb bbBB ---- -dFf ) OR ( 1abb bbcc dddd dddd ) a = ? b = alpha blend? (toggles between all bits on and off for battery logo) BB = sprite base F = flipX f = flipY
word1 ( wwhh ---t tttt tttt ) - other bits are used, but pulled from ram? t = tile number? ww = width hh = height
word2 ( 0Ppp ppyy yyyy yyyy ) P = palette bank p = palette y = ypos
word3 ( aabb bbxx xxxx xxxx ) x = xpos
*/
const int alpha = (spriteword0 & 0x3c00)>>10;
const int flipx = spriteword0 & 2;
const int flipy = spriteword0 & 1;
int height = (spriteword1 & 0x3000)>>12;
height = 1 << height;
int width = (spriteword1 & 0xc000)>>14;
width = 1 << width;
if (alpha == 0x00)
continue;
if (spriteword0 & 0x8000)
{
// unsure for now
}
else
{
const int basetilenum = tilenum;
for (int xx = 0; xx < width; xx++)
{
int xpos, ypos;
if (!flipx)
xpos = x + xx * 8;
else
xpos = x + (((width-1) * 8) - xx * 8);
for (int yy = 0; yy < height; yy++)
{
if (!flipy)
ypos = y + yy * 8;
else
ypos = y + (((height-1) * 8) - yy * 8);
if (alpha == 0xf)
gfx->transpen(bitmap, cliprect, basetilenum + xx + (yy * 0x20), pal, flipx, flipy, xpos, ypos, 0);
else
gfx->alpha(bitmap, cliprect, basetilenum + xx + (yy * 0x20), pal, flipx, flipy, xpos, ypos, 0, 0xff-(alpha<<4));
}
}
}
}
/*
popmessage("%08x %08x\n%08x %08x\n%08x %08x\n%08x %08x\n", m_mainram[spritebase + 0], m_mainram[spritebase + 1],
m_mainram[spritebase + 2], m_mainram[spritebase + 3],
m_mainram[spritebase + 4], m_mainram[spritebase + 5],
m_mainram[spritebase + 6], m_mainram[spritebase + 7]);
*/
}
void hudson_poems_state::draw_tilemap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int which, int priority)
{
int width, base, bpp, gfxbase, extrapal;
// guess, could be more/less bits, or somewhere else entirely, works for the 2 scenes that need it
const int thispriority = (m_tilemapcfg[which] & 0x01f00000) >> 20;
if (thispriority != priority)
return;
// seems to get set for disabled layers
if (m_tilemapcfg[which] & 0x02000000)
return;
extrapal = 0;
if (m_tilemapunk[which] == 2)
width = 512;
else
width = 256;
if (m_tilemapcfg[which] & 0x20000000)
bpp = 8;
else
bpp = 4;
if (m_tilemapcfg[which] & 0x00080000)
extrapal = 1;
else
extrapal = 0;
// contains a full 32-bit address
base = (m_tilemapbase[which] & 0x0003ffff) / 4;
// contains a full 32-bit address. for this to work in the test mode the interrupts must be disabled as soon as test mode is entered, otherwise the pointer
// gets overwritten with an incorrect one. Test mode does not require interrupts to function, although the bit we use to disable them is likely incorrect.
// this does NOT really seem to be tied to tilemap number, probably from a config reg
// this reg?
const int whichbase = (m_tilemapcfg[which] & 0x00000060) >> 5;
gfxbase = (m_spritegfxbase[whichbase] & 0x0003ffff);
int yscroll = (m_tilemapscr[which] >> 16) & 0x7ff;
if (yscroll & 0x400)
yscroll -= 0x800;
int xscroll = (m_tilemapscr[which] >> 0) & 0x7ff;
if (xscroll & 0x400)
xscroll -= 0x800;
const int tilemap_drawheight = ((m_tilemaphigh[which] >> 16) & 0xff);
int tilemap_drawwidth = ((m_tilemaphigh[which] >> 0) & 0x1ff);
// clamp to size of tilemap (test mode has 256 wide tilemap in RAM, but sets full 320 width?)
if (tilemap_drawwidth > width)
tilemap_drawwidth = width;
// note m_tilemaphigh seems to be in pixels, we currently treat it as tiles
// these could actually be 'end pos' regs, with unknown start regs currently always set to 0
for (int y = 0; y < tilemap_drawheight / 8; y++)
{
const int ypos = (y * 8 + yscroll) & 0x1ff;
for (int x = 0; x < tilemap_drawwidth / 8 / 2; x++)
{
u32 tiles = m_mainram[base + (y * width / 8 / 2) + x];
const int xpos = (x * 16 + xscroll) & 0x1ff;
if (bpp == 4)
{
draw_tile(screen, bitmap, cliprect, (tiles & 0xffff), xpos, ypos, gfxbase, extrapal);
draw_tile(screen, bitmap, cliprect, ((tiles >> 16) & 0xffff), xpos + 8, ypos, gfxbase, extrapal);
}
else if (bpp == 8)
{
draw_tile8(screen, bitmap, cliprect, (tiles & 0xffff), xpos, ypos, gfxbase, extrapal);
draw_tile8(screen, bitmap, cliprect, ((tiles >> 16) & 0xffff), xpos + 8, ypos, gfxbase, extrapal);
}
}
}
}
void hudson_poems_state::spritegfx_base_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA(&m_spritegfxbase[offset]);
LOGMASKED(LOG_SPRITEBASE, "%s: spritegfx_base_w %d %08x\n", machine().describe_context(), offset, data);
}
void hudson_poems_state::spritelist_base_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA(&m_spritelistbase);
}
template<int Layer> void hudson_poems_state::tilemap_base_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_tilemapbase[Layer]); }
template<int Layer> void hudson_poems_state::tilemap_cfg_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_tilemapcfg[Layer]); }
template<int Layer> void hudson_poems_state::tilemap_unk_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_tilemapunk[Layer]); }
template<int Layer> void hudson_poems_state::tilemap_high_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_tilemaphigh[Layer]); }
template<int Layer> void hudson_poems_state::tilemap_scr_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_tilemapscr[Layer]); }
template<int Layer> u32 hudson_poems_state::tilemap_base_r(offs_t offset, u32 mem_mask) { return m_tilemapbase[Layer]; }
template<int Layer> u32 hudson_poems_state::tilemap_high_r(offs_t offset, u32 mem_mask) { return m_tilemaphigh[Layer]; }
template<int Layer> u32 hudson_poems_state::tilemap_unk_r(offs_t offset, u32 mem_mask) { return m_tilemapunk[Layer]; }
template<int Layer> u32 hudson_poems_state::tilemap_cfg_r(offs_t offset, u32 mem_mask) { return m_tilemapcfg[Layer]; }
template<int Layer> u32 hudson_poems_state::tilemap_scr_r(offs_t offset, u32 mem_mask) { return m_tilemapscr[Layer]; }
void hudson_poems_state::draw_tile(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 tile, int xx, int yy, int gfxbase, int extrapal)
{
gfx_element *gfx = m_gfxdecode->gfx(2);
const int flipx = tile & 0x0800;
const int flipy = tile & 0x0400;
int pal = (tile & 0xf000)>>12;
pal += extrapal * 0x10;
tile &= 0x3ff;
tile += gfxbase / 32;
gfx->transpen(bitmap,cliprect,tile,pal,flipx,flipy,xx,yy, 0);
}
void hudson_poems_state::draw_tile8(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 tile, int xx, int yy, int gfxbase, int extrapal)
{
gfx_element *gfx = m_gfxdecode->gfx(3);
const int flipx = tile & 0x0800;
const int flipy = tile & 0x0400;
int pal = 0;//(tile & 0xf000)>>8;
pal += extrapal;
tile &= 0x3ff;
tile += gfxbase / 64;
gfx->transpen(bitmap,cliprect,tile,pal,flipx,flipy,xx,yy, 0);
}
u32 hudson_poems_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0, cliprect);
for (int pri = 0x1f; pri >= 0; pri--)
{
draw_tilemap(screen, bitmap, cliprect, 0, pri);
draw_tilemap(screen, bitmap, cliprect, 1, pri); // title screen background
draw_tilemap(screen, bitmap, cliprect, 2, pri); // seems to be status bar in the game demo, but suggests that tilegfx base isn't tied to tilmap number
draw_tilemap(screen, bitmap, cliprect, 3, pri); // background for the character in game demo etc.
}
draw_sprites(screen, bitmap, cliprect);
return 0;
}
u32 hudson_poems_state::poems_unk_r()
{
return 0x00000000;
}
u32 hudson_poems_state::poems_random_r()
{
return machine().rand();
}
u32 hudson_poems_state::poems_count_r()
{
return ((m_hackcounter++) & 0x3) ? 0xffffffff : 0;
}
u32 hudson_poems_state::poems_8020010_r()
{
return 0x4;
}
u32 hudson_poems_state::unk_aa04_r(offs_t offset, u32 mem_mask)
{
return ((m_hackcounter++) & 0x3) ? 0xffffffff : 0;
}
void hudson_poems_state::unk_aa00_w(offs_t offset, u32 data, u32 mem_mask)
{
logerror("%s: unk_aa00_w %08x %08x\n", machine().describe_context(), data, mem_mask);
}
u32 hudson_poems_state::poems_8000038_r(offs_t offset, u32 mem_mask)
{
if (!machine().side_effects_disabled())
if (m_maincpu->pc() != 0x2c000b5a)
logerror("%s: poems_8000038_r %08x\n", machine().describe_context(), mem_mask);
if (m_mainram[0x1baf8/4] == 0x00000000)
return 0xffffffff;
else
return 0x00000000;
}
u32 hudson_poems_state::poems_8000200_r(offs_t offset, u32 mem_mask)
{
if (!machine().side_effects_disabled())
logerror("%s: poems_8000200_r %08x\n", machine().describe_context(), mem_mask);
// in some places it loops on bit 0 being clear, in other places it seems to simply be used like an ack
return 0x00000001;
}
void hudson_poems_state::set_palette_val(int entry)
{
const u16 datax = m_palram[entry];
const int b = ((datax) & 0x001f) >> 0;
const int g = ((datax) & 0x03e0) >> 5;
const int r = ((datax) & 0x7c00) >> 10;
m_palette->set_pen_color(entry, pal5bit(r), pal5bit(g), pal5bit(b));
}
void hudson_poems_state::palette_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA(&m_palram[offset]);
set_palette_val(offset);
}
void hudson_poems_state::fade_w(offs_t offset, u32 data, u32 mem_mask)
{
logerror("%s: fade_w %08x %08x\n", machine().describe_context(), data, mem_mask);
u8 val = 0x1f - ((data >> 16) & 0x1f);
const double intensity = (double)(val & 0x1f) / (double)0x1f;
for (int i = 0; i < 0x200; i++)
m_palette->set_pen_contrast(i, intensity);
}
void hudson_poems_state::unktable_w(offs_t offset, u32 data, u32 mem_mask)
{
if (mem_mask & 0x0000ffff)
{
if (m_unktableoffset < 256)
{
m_unktable[m_unktableoffset] = data & 0x0000ffff;
set_palette_val(m_unktableoffset);
m_unktableoffset++;
}
}
if (mem_mask & 0xffff0000)
{
if (m_unktableoffset < 256)
{
m_unktable[m_unktableoffset] = (data & 0xffff0000)>>16;
set_palette_val(m_unktableoffset);
m_unktableoffset++;
}
}
}
void hudson_poems_state::unktable_reset_w(offs_t offset, u32 data, u32 mem_mask)
{
m_unktableoffset = 0;
}
void hudson_poems_state::unk_trigger_w(offs_t offset, u32 data, u32 mem_mask)
{
logerror("%s: unk_trigger_w %08x %08x\n", machine().describe_context(), data, mem_mask);
m_maincpu->set_input_line(0x4, ASSERT_LINE);
}
void hudson_poems_state::mainram_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA(&m_mainram[offset]);
m_gfxdecode->gfx(2)->mark_dirty(offset / 8);
m_gfxdecode->gfx(3)->mark_dirty(offset / 16);
}
template<int Which>
void hudson_poems_state::tilemap_map(address_map &map, u32 base)
{
map(base+0x00, base+0x03).rw(FUNC(hudson_poems_state::tilemap_cfg_r<Which>), FUNC(hudson_poems_state::tilemap_cfg_w<Which>));
map(base+0x04, base+0x07).rw(FUNC(hudson_poems_state::tilemap_base_r<Which>), FUNC(hudson_poems_state::tilemap_base_w<Which>));
map(base+0x08, base+0x0b).rw(FUNC(hudson_poems_state::tilemap_unk_r<Which>), FUNC(hudson_poems_state::tilemap_unk_w<Which>)); // usually 1 or 2 (tilemap width in ram?)
map(base+0x0c, base+0x0f).ram(); // usually 0 or 1
map(base+0x10, base+0x13).ram(); // not used?
map(base+0x14, base+0x17).ram(); // not used?
map(base+0x18, base+0x1b).rw(FUNC(hudson_poems_state::tilemap_high_r<Which>), FUNC(hudson_poems_state::tilemap_high_w<Which>)); // top word is display height, bottom word seems to be display width
map(base+0x1c, base+0x1f).rw(FUNC(hudson_poems_state::tilemap_scr_r<Which>), FUNC(hudson_poems_state::tilemap_scr_w<Which>)); // top word is y scroll, bottom word is x scroll
map(base+0x20, base+0x23).ram(); // used, always 00001000 (maybe zoom?)
map(base+0x24, base+0x27).ram(); // not used?
map(base+0x28, base+0x2b).ram(); // not used?
map(base+0x2c, base+0x2f).ram(); // used, always 00001000 (maybe zoom?)
map(base+0x30, base+0x33).ram(); // not used?
map(base+0x34, base+0x37).ram(); // not used?
map(base+0x38, base+0x3b).ram(); // not used?
map(base+0x3c, base+0x3f).ram(); // not used?
}
void hudson_poems_state::mem_map(address_map &map)
{
map(0x20000000, 0x207fffff).rom().region("maincpu", 0);
map(0x2c000000, 0x2c7fffff).ram();
map(0x00000000, 0x007fffff).mirror(0x20000000).rom().region("maincpu", 0);
/////////////////// unknown
map(0x04000040, 0x04000043).r(FUNC(hudson_poems_state::poems_random_r)).nopw();
map(0x04000140, 0x04000143).r(FUNC(hudson_poems_state::poems_random_r)).nopw();
map(0x04000240, 0x04000243).r(FUNC(hudson_poems_state::poems_random_r)).nopw();
map(0x04000340, 0x04000343).r(FUNC(hudson_poems_state::poems_random_r)).nopw();
//map(0x04000324, 0x04000327).nopw(); // uploads a table here from ROM after uploading fixed values from ROM to some other addresses
map(0x0400033c, 0x0400033f).w(FUNC(hudson_poems_state::unk_trigger_w)); // maybe DMA?
map(0x04001000, 0x04001003).r(FUNC(hudson_poems_state::poems_random_r)).nopw();
map(0x0400100c, 0x0400100f).nopr(); // read in various places at end of calls, every frame, but result seems to go unused?
map(0x04002040, 0x04002043).portr("IN1");
/////////////////// palette / regs?
map(0x08000038, 0x0800003b).r(FUNC(hudson_poems_state::poems_8000038_r));
//map(0x0800003c, 0x0800003f).nopw(); // used close to the fade write code, writes FFFFFFFF
//map(0x08000048, 0x0800004b).nopw(); // ^^
//map(0x0800004c, 0x0800004f).nopw(); // ^^
//map(0x08000050, 0x08000053).nopw(); // ^^ 16-bit write, sometimes writes 00000101 & 0000FFFF
//map(0x08000054, 0x08000057).nopw(); // ^^ writes 15555555 while fading
map(0x0800005c, 0x0800005f).w(FUNC(hudson_poems_state::fade_w));
// are these runtime registers, or DMA sources?
map(0x08000070, 0x0800007f).w(FUNC(hudson_poems_state::spritegfx_base_w)); // ^^ sometimes writes 2C009C00 (one of the tile data bases)
// registers 0x080 - 0x0bf are tilemap 0
tilemap_map<0>(map, 0x08000080);
// registers 0x0c0 - 0x0ff are tilemap 1
tilemap_map<1>(map, 0x080000c0);
// registers 0x100 - 0x13f are tilemap 2
tilemap_map<2>(map, 0x08000100);
// registers 0x140 - 0x17f are tilemap 3
tilemap_map<3>(map, 0x08000140);
// registers at 0x180 are sprites
//map(0x08000180, 0x08000183).nopw(); // gets set to 0000007F on startup (list length?)
map(0x08000184, 0x08000187).w(FUNC(hudson_poems_state::spritelist_base_w)); // gets set to 2C009400 on startup
map(0x08000800, 0x08000fff).ram().w(FUNC(hudson_poems_state::palette_w)).share("palram");
/////////////////// sound regs??
map(0x08008000, 0x08008003).nopw();
map(0x08008200, 0x08008203).r(FUNC(hudson_poems_state::poems_8000200_r));
map(0x08008204, 0x08008207).nopr().nopw(); // read only seems to be used to ack after write, value doesn't matter, similar code to 200 above
map(0x08008400, 0x08008403).nopw();
map(0x08008a00, 0x08008a7f).ram(); // filled with 32 copies of '0x0001'
map(0x08008c00, 0x08008c7f).ram(); // filled with 32 copies of '0x0003'
map(0x08009000, 0x080093ff).ram(); // filled with 32 copies of '0x0200, 0x0004, 0x0000, 0x0100, 0x0c02, 0x0000, 0x0000, 0x0000'
map(0x08009400, 0x080097ff).ram(); // filled with 32 copies of '0x0000, 0x3fff, 0x0000, 0x0000, 0x3fff, 0x0000, 0x0000, 0x0000'
map(0x08009800, 0x08009bff).ram(); // filled with 32 copies of '0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000'
map(0x0800a000, 0x0800a003).nopw();
map(0x0800a004, 0x0800a007).nopw();
map(0x0800aa00, 0x0800aa03).w(FUNC(hudson_poems_state::unk_aa00_w)); // writes 2c020000, which is the top of RAM? (or middle?)
map(0x0800aa04, 0x0800aa07).r(FUNC(hudson_poems_state::unk_aa04_r));
map(0x0800b000, 0x0800b003).w(FUNC(hudson_poems_state::unktable_w)); // writes a table of increasing 16-bit values here
map(0x0800b004, 0x0800b007).w(FUNC(hudson_poems_state::unktable_reset_w));
map(0x0800c040, 0x0800c05f).ram();
///////////////////
map(0x08020000, 0x08020003).nopr().nopw();
map(0x08020004, 0x08020007).nopr().nopw();
map(0x08020008, 0x0802000b).nopr();
map(0x08020010, 0x08020013).r(FUNC(hudson_poems_state::poems_8020010_r));
map(0x08020014, 0x08020017).nopw(); // writes 0x10
map(0x08020018, 0x0802001b).r(FUNC(hudson_poems_state::poems_unk_r)).nopw(); // writes 0x10
map(0x08020020, 0x08020023).r(FUNC(hudson_poems_state::poems_count_r));
///////////////////
map(0x2c000000, 0x2c03ffff).ram().w(FUNC(hudson_poems_state::mainram_w)).share("mainram");
}
static GFXDECODE_START( gfx_poems )
GFXDECODE_ENTRY( "maincpu", 0, gfx_8x8x4_packed_lsb, 0, 16 )
GFXDECODE_ENTRY( "maincpu", 0, gfx_8x8x8_raw, 0, 1 )
GFXDECODE_RAM( "mainram", 0, gfx_8x8x4_packed_lsb, 0, 32 )
GFXDECODE_RAM( "mainram", 0, gfx_8x8x8_raw, 0, 2 )
GFXDECODE_END
TIMER_DEVICE_CALLBACK_MEMBER(hudson_poems_state::screen_scanline)
{
const int scanline = param;
if (scanline == 100)
{
if (m_tilemapunk[0] != 1) // wrong, this is probably just tilemap size, with 1 being 256 and 2 being 512, but prevents unwanted IRQs in Test Mode
m_maincpu->set_input_line(0x10, ASSERT_LINE);
}
if (scanline == 150)
{
m_maincpu->set_input_line(0x04, CLEAR_LINE);
}
}
void hudson_poems_state::hudson_poems(machine_config &config)
{
// 27Mhz XTAL
// Xtensa based CPU?
// 27Mhz XTAL, Xtensa based CPU
XTENSA(config, m_maincpu, 27_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &hudson_poems_state::mem_map);
// the vectors can be configured when the CPU is manufactured, so treat as config options
m_maincpu->set_startupvector(0x00000040);
m_maincpu->set_irq_vector(4, 0x2c0001b4); // 0x10
m_maincpu->set_irq_vector(1, 0x2c000194); // 0x02
m_maincpu->set_irq_vector(2, 0x2c000194); // 0x04
// 0x2c0001b4 these are also valid vectors
// 0x2c0001c4
// 0x2c0001d4
// 0x2c000000 is a register window exception (4)
// 0x2c000040 is a register window exception (4)
// 0x2c000080 is a register window exception (8)
// 0x2c0000c0 is a register window exception (8)
// 0x2c000100 is a register window exception (12)
// 0x2c000140 is a register window exception (12)
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
screen.set_size(320, 240); // resolution not confirmed
screen.set_size(320, 240);
screen.set_visarea(0, 320-1, 0, 240-1);
screen.set_screen_update(FUNC(hudson_poems_state::screen_update));
TIMER(config, "scantimer").configure_scanline(FUNC(hudson_poems_state::screen_scanline), "screen", 0, 1);
GFXDECODE(config, m_gfxdecode, "palette", gfx_poems);
PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 0x200);
SPEAKER(config, "speaker").front_center();
}
void hudson_poems_state::init_marimba()
{
}
ROM_START( marimba )
ROM_REGION( 0x800000, "maincpu", 0 )
ROM_LOAD( "marimbatengoku.u2", 0x000000, 0x800000, CRC(b2ac0c5b) SHA1(48f3cdf399b032d86234125eeac3fb1cdc73538a) ) // glob with TSOP pads
@ -110,4 +722,4 @@ ROM_END
} // anonymous namespace
CONS( 2005, marimba, 0, 0, hudson_poems, hudson_poems, hudson_poems_state, empty_init, "Konami", "Marimba Tengoku (Japan)", MACHINE_IS_SKELETON )
CONS( 2005, marimba, 0, 0, hudson_poems, hudson_poems, hudson_poems_state, init_marimba, "Konami", "Marimba Tengoku (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND )