summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author fulivi <fulivi@users.noreply.github.com>2016-10-27 12:02:40 +0200
committer fulivi <fulivi@users.noreply.github.com>2016-11-03 14:52:41 +0100
commit5f54097e533a6acaa36147511604d01bd7835d87 (patch)
treec444e1c4b2627e7e9d26c0ce3f7206e63328efa9 /src
parent07588d32057e517197af069251c33f0bcb9ddb58 (diff)
nanoprocessor: initial support. Disassembler only is known to work at this point.
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor.cpp517
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor.h85
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor_dasm.cpp137
-rw-r--r--src/tools/unidasm.cpp2
4 files changed, 741 insertions, 0 deletions
diff --git a/src/devices/cpu/nanoprocessor/nanoprocessor.cpp b/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
new file mode 100644
index 00000000000..4c4e8cb7607
--- /dev/null
+++ b/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
@@ -0,0 +1,517 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+
+#include "emu.h"
+#include "debugger.h"
+#include "nanoprocessor.h"
+
+// Index of state variables
+enum {
+ NANO_REG_A,
+ NANO_REG_R0,
+ NANO_REG_R1,
+ NANO_REG_R2,
+ NANO_REG_R3,
+ NANO_REG_R4,
+ NANO_REG_R5,
+ NANO_REG_R6,
+ NANO_REG_R7,
+ NANO_REG_R8,
+ NANO_REG_R9,
+ NANO_REG_R10,
+ NANO_REG_R11,
+ NANO_REG_R12,
+ NANO_REG_R13,
+ NANO_REG_R14,
+ NANO_REG_R15,
+ NANO_REG_PA,
+ NANO_REG_SSR,
+ NANO_REG_ISR,
+ NANO_REG_FLAGS
+};
+
+#define BIT_MASK(n) (1U << (n))
+
+// Macros to clear/set single bits
+#define BIT_CLR(w , n) ((w) &= ~BIT_MASK(n))
+#define BIT_SET(w , n) ((w) |= BIT_MASK(n))
+
+// Bits in m_flags
+#define NANO_DC0_BIT 0 // DC0
+#define NANO_IE_BIT (NANO_DC0_BIT + 7) // DC7 is usually interrupt enable
+#define NANO_E_BIT (NANO_DC0_BIT + HP_NANO_DC_NO) // Extend flag
+#define NANO_I_BIT (NANO_E_BIT + 1) // Interrupt flag
+
+const device_type HP_NANOPROCESSOR = &device_creator<hp_nanoprocessor_device>;
+
+hp_nanoprocessor_device::hp_nanoprocessor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ cpu_device(mconfig , HP_NANOPROCESSOR , "HP-Nanoprocessor" , tag , owner , clock , "nanoprocessor" , __FILE__),
+ m_dc_changed_func(*this),
+ m_program_config("program" , ENDIANNESS_BIG , 8 , 11),
+ m_io_config("io" , ENDIANNESS_BIG , 8 , 4)
+{
+}
+
+void hp_nanoprocessor_device::device_start()
+{
+ state_add(NANO_REG_A , "A" , m_reg_A);
+ state_add(NANO_REG_R0 , "R0" , m_reg_R[ 0 ]);
+ state_add(NANO_REG_R1 , "R1" , m_reg_R[ 1 ]);
+ state_add(NANO_REG_R2 , "R2" , m_reg_R[ 2 ]);
+ state_add(NANO_REG_R3 , "R3" , m_reg_R[ 3 ]);
+ state_add(NANO_REG_R4 , "R4" , m_reg_R[ 4 ]);
+ state_add(NANO_REG_R5 , "R5" , m_reg_R[ 5 ]);
+ state_add(NANO_REG_R6 , "R6" , m_reg_R[ 6 ]);
+ state_add(NANO_REG_R7 , "R7" , m_reg_R[ 7 ]);
+ state_add(NANO_REG_R8 , "R8" , m_reg_R[ 8 ]);
+ state_add(NANO_REG_R9 , "R9" , m_reg_R[ 9 ]);
+ state_add(NANO_REG_R10 , "R10" , m_reg_R[ 10 ]);
+ state_add(NANO_REG_R11 , "R11" , m_reg_R[ 11 ]);
+ state_add(NANO_REG_R12 , "R12" , m_reg_R[ 12 ]);
+ state_add(NANO_REG_R13 , "R13" , m_reg_R[ 13 ]);
+ state_add(NANO_REG_R14 , "R14" , m_reg_R[ 14 ]);
+ state_add(NANO_REG_R15 , "R15" , m_reg_R[ 15 ]);
+ state_add(NANO_REG_PA , "PA" , m_reg_PA).formatstr("%03x");
+ state_add(STATE_GENPC , "GENPC" , m_reg_PA).noshow();
+ state_add(STATE_GENPCBASE , "GENPCBASE" , m_reg_PA).noshow();
+ state_add(NANO_REG_SSR , "SSR" , m_reg_SSR).formatstr("%03x");
+ state_add(NANO_REG_ISR , "ISR" , m_reg_ISR).formatstr("%03x");
+ state_add(STATE_GENFLAGS , "GENFLAGS" , m_flags).noshow().formatstr("%10s");
+
+ m_program = &space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+ m_io = &space(AS_IO);
+
+ save_item(NAME(m_reg_A));
+ save_item(NAME(m_reg_R));
+ save_item(NAME(m_reg_PA));
+ save_item(NAME(m_reg_SSR));
+ save_item(NAME(m_reg_ISR));
+ save_item(NAME(m_flags));
+
+ m_icountptr = &m_icount;
+
+ m_dc_changed_func.resolve_safe();
+}
+
+void hp_nanoprocessor_device::device_reset()
+{
+ m_reg_A = 0;
+ for (auto& reg : m_reg_R) {
+ reg = 0;
+ }
+ m_reg_PA = 0;
+ m_reg_SSR = 0;
+ m_reg_ISR = 0;
+ m_flags = 0;
+ dc_update();
+}
+
+void hp_nanoprocessor_device::execute_run()
+{
+ do {
+ // Check for interrupts (interrupt line is always enabled. Masking is done
+ // outside of the NP, usually by ANDing the DC7 line with the interrupt
+ // request signal)
+ if (BIT(m_flags , NANO_I_BIT)) {
+ m_reg_ISR = m_reg_PA;
+ m_reg_PA = (uint16_t)(standard_irq_callback(0) & 0xff);
+ BIT_CLR(m_flags, NANO_IE_BIT);
+ dc_update();
+ // Vector fetching takes 1 cycle
+ m_icount -= 1;
+ } else {
+ debugger_instruction_hook(this , m_reg_PA);
+
+ uint8_t opcode = fetch();
+ execute_one(opcode);
+ // All opcodes execute in 2 cycles
+ m_icount -= 2;
+ }
+ } while (m_icount > 0);
+}
+
+void hp_nanoprocessor_device::execute_set_input(int linenum, int state)
+{
+ if (linenum == 0) {
+ if (state) {
+ BIT_SET(m_flags, NANO_I_BIT);
+ } else {
+ BIT_CLR(m_flags, NANO_I_BIT);
+ }
+ }
+}
+
+void hp_nanoprocessor_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ if (entry.index() == STATE_GENFLAGS) {
+ // DC7 is reported as "I" because it is usually used as interrupt enable
+ str = string_format("%c %c%c%c%c%c%c%c%c" , BIT(m_flags , NANO_E_BIT) ? 'E' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 7) ? 'I' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 6) ? '6' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 5) ? '5' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 4) ? '4' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 3) ? '3' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 2) ? '2' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 1) ? '1' : ' ',
+ BIT(m_flags , NANO_DC0_BIT + 0) ? '0' : ' ');
+ }
+
+}
+
+offs_t hp_nanoprocessor_device::disasm_disassemble(char *buffer, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
+{
+ extern CPU_DISASSEMBLE(hp_nanoprocessor);
+ return CPU_DISASSEMBLE_NAME(hp_nanoprocessor)(this , buffer , pc , oprom , opram , options);
+}
+
+void hp_nanoprocessor_device::execute_one(uint8_t opcode)
+{
+ // Instructions without mask
+ switch (opcode) {
+ case 0x00:
+ // INB
+ m_reg_A++;
+ if (m_reg_A == 0) {
+ BIT_SET(m_flags, NANO_E_BIT);
+ }
+ break;
+
+ case 0x01:
+ // DEB
+ m_reg_A--;
+ if (m_reg_A == 0xff) {
+ BIT_SET(m_flags, NANO_E_BIT);
+ }
+ break;
+
+ case 0x02:
+ // IND
+ // Handling of non-decimal digits is entirely arbitrary
+ m_reg_A++;
+ if ((m_reg_A & 0x0f) >= 10) {
+ m_reg_A += 6;
+ if (m_reg_A >= 0xa0) {
+ m_reg_A += 0x60;
+ BIT_SET(m_flags, NANO_E_BIT);
+ }
+ }
+ break;
+
+ case 0x03:
+ // DED
+ // Handling of non-decimal digits is entirely arbitrary
+ m_reg_A--;
+ if ((m_reg_A & 0x0f) >= 10) {
+ m_reg_A -= 6;
+ if (m_reg_A >= 0xa0) {
+ m_reg_A -= 0x60;
+ BIT_SET(m_flags, NANO_E_BIT);
+ }
+ }
+ break;
+
+ case 0x04:
+ // CLA
+ m_reg_A = 0;
+ break;
+
+ case 0x05:
+ // CMA
+ m_reg_A = ~m_reg_A;
+ break;
+
+ case 0x06:
+ // RSA
+ m_reg_A >>= 1;
+ break;
+
+ case 0x07:
+ // LSA
+ m_reg_A <<= 1;
+ break;
+
+ case 0x08:
+ // SGT
+ if (m_reg_A > m_reg_R[ 0 ]) {
+ skip();
+ }
+ break;
+
+ case 0x09:
+ // SLT
+ if (m_reg_A < m_reg_R[ 0 ]) {
+ skip();
+ }
+ break;
+
+ case 0x0a:
+ // SEQ
+ if (m_reg_A == m_reg_R[ 0 ]) {
+ skip();
+ }
+ break;
+
+ case 0x0b:
+ // SAZ
+ if (m_reg_A == 0) {
+ skip();
+ }
+ break;
+
+ case 0x0c:
+ // SLE
+ if (m_reg_A <= m_reg_R[ 0 ]) {
+ skip();
+ }
+ break;
+
+ case 0x0d:
+ // SGE
+ if (m_reg_A >= m_reg_R[ 0 ]) {
+ skip();
+ }
+ break;
+
+ case 0x0e:
+ // SNE
+ if (m_reg_A != m_reg_R[ 0 ]) {
+ skip();
+ }
+ break;
+
+ case 0x0f:
+ // SAN
+ if (m_reg_A != 0) {
+ skip();
+ }
+ break;
+
+ case 0x1f:
+ // SES
+ if (BIT(m_flags , NANO_E_BIT)) {
+ skip();
+ }
+ break;
+
+ case 0x3f:
+ // SEZ
+ if (!BIT(m_flags , NANO_E_BIT)) {
+ skip();
+ }
+ break;
+
+ case 0x5f:
+ // NOP
+ break;
+
+ case 0xb1:
+ // RTE
+ dc_set(NANO_IE_BIT);
+ // Intentional fall-through to RTI!
+
+ case 0xb0:
+ // RTI
+ m_reg_PA = m_reg_ISR;
+ break;
+
+ case 0xb4:
+ // STE
+ BIT_SET(m_flags, NANO_E_BIT);
+ break;
+
+ case 0xb5:
+ // CLE
+ BIT_CLR(m_flags, NANO_E_BIT);
+ break;
+
+ case 0xb9:
+ // RSE
+ dc_set(NANO_IE_BIT);
+ // Intentional fall-through to RTS!
+
+ case 0xb8:
+ // RTS
+ {
+ uint16_t tmp = m_reg_SSR;
+ m_reg_SSR = pa_offset(1);
+ m_reg_PA = tmp;
+ }
+ break;
+
+ case 0xcf:
+ // LDR
+ m_reg_A = fetch();
+ break;
+
+ default:
+ // Instructions with 0xf8 mask
+ switch (opcode & 0xf8) {
+ case 0x10:
+ // SBS
+ if (BIT(m_reg_A , opcode & 7)) {
+ skip();
+ }
+ break;
+
+ case 0x18:
+ // SFS
+ if (BIT(m_flags , NANO_DC0_BIT + (opcode & 7))) {
+ skip();
+ }
+ break;
+
+ case 0x20:
+ // SBN
+ BIT_SET(m_reg_A, opcode & 7);
+ break;
+
+ case 0x28:
+ // STC
+ dc_set(opcode & 7);
+ break;
+
+ case 0x30:
+ // SBZ
+ if (!BIT(m_reg_A , opcode & 7)) {
+ skip();
+ }
+ break;
+
+ case 0x38:
+ // SFZ
+ if (!BIT(m_flags , NANO_DC0_BIT + (opcode & 7))) {
+ skip();
+ }
+ break;
+
+ case 0x80:
+ // JMP
+ m_reg_PA = ((uint16_t)(opcode & 7) << 8) | fetch();
+ break;
+
+ case 0x88:
+ // JSB
+ {
+ uint16_t tmp = ((uint16_t)(opcode & 7) << 8) | fetch();
+ m_reg_SSR = m_reg_PA;
+ m_reg_PA = tmp;
+ }
+ break;
+
+ case 0x98:
+ // JAS
+ m_reg_SSR = pa_offset(1);
+ // Intentional fall-through to JAI!
+
+ case 0x90:
+ // JAI
+ // On HP doc there's a mysterious warning about JAI:
+ // "Due to the indexing structure, a JAI instruction executed with
+ // R03 set will be executed as a JAS instruction"
+ // My idea on the meaning: NP recycles the instruction register to form
+ // the bitwise OR of bits 3-0 of R0 and of opcode (see LDI/STI
+ // instructions). Presumably this was done to save on flip-flop count.
+ // So, if bit 3 of R0 (R03) is set when executing JAI the instruction
+ // register turns JAI into JAS.
+ // This effect is not simulated here at the moment.
+ {
+ uint16_t tmp = (uint16_t)((m_reg_R[ 0 ] | opcode) & 7) << 8;
+ m_reg_PA = tmp | m_reg_A;
+ }
+ break;
+
+ case 0xa0:
+ // CBN
+ BIT_CLR(m_reg_A, opcode & 7);
+ break;
+
+ case 0xa8:
+ // CLC
+ dc_clr(opcode & 7);
+ break;
+
+ default:
+ // Instructions with 0xf0 mask
+ switch (opcode & 0xf0) {
+ case 0x40:
+ // INA
+ m_reg_A = m_io->read_byte(opcode & 0xf);
+ break;
+
+ case 0x50:
+ // OTA
+ m_io->write_byte(opcode & 0xf , m_reg_A);
+ break;
+
+ case 0x60:
+ // LDA
+ m_reg_A = m_reg_R[ opcode & 0xf ];
+ break;
+
+ case 0x70:
+ // STA
+ m_reg_R[ opcode & 0xf ] = m_reg_A;
+ break;
+
+ case 0xc0:
+ // OTR
+ m_io->write_byte(opcode & 0xf , fetch());
+ break;
+
+ case 0xd0:
+ // STR
+ m_reg_R[ opcode & 0xf ] = fetch();
+ break;
+
+ case 0xe0:
+ // LDI
+ m_reg_A = m_reg_R[ (m_reg_R[ 0 ] | opcode) & 0xf ];
+ break;
+
+ case 0xf0:
+ // STI
+ m_reg_R[ (m_reg_R[ 0 ] | opcode) & 0xf ] = m_reg_A;
+ break;
+
+ default:
+ logerror("Unknown opcode %02x @ 0x03x\n" , opcode , m_reg_PA);
+ break;
+ }
+ }
+ }
+}
+
+uint16_t hp_nanoprocessor_device::pa_offset(unsigned off) const
+{
+ return (uint16_t)((m_reg_PA + off) & HP_NANO_PC_MASK);
+}
+
+uint8_t hp_nanoprocessor_device::fetch(void)
+{
+ uint8_t res = m_direct->read_byte(m_reg_PA);
+ m_reg_PA = pa_offset(1);
+ return res;
+}
+
+void hp_nanoprocessor_device::skip(void)
+{
+ m_reg_PA = pa_offset(2);
+}
+
+void hp_nanoprocessor_device::dc_update(void)
+{
+ m_dc_changed_func((uint8_t)(m_flags & ((1U << HP_NANO_DC_NO) - 1)));
+}
+
+void hp_nanoprocessor_device::dc_set(unsigned bit_no)
+{
+ BIT_SET(m_flags, NANO_DC0_BIT + bit_no);
+ dc_update();
+}
+
+void hp_nanoprocessor_device::dc_clr(unsigned bit_no)
+{
+ BIT_CLR(m_flags, NANO_DC0_BIT + bit_no);
+ dc_update();
+}
diff --git a/src/devices/cpu/nanoprocessor/nanoprocessor.h b/src/devices/cpu/nanoprocessor/nanoprocessor.h
new file mode 100644
index 00000000000..ad7351f8f3a
--- /dev/null
+++ b/src/devices/cpu/nanoprocessor/nanoprocessor.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+//
+// *****************************
+// Emulator for HP nanoprocessor
+// *****************************
+//
+#ifndef _NANOPROCESSOR_H_
+#define _NANOPROCESSOR_H_
+
+#define HP_NANO_REGS 16 // Number of GP registers
+#define HP_NANO_PC_MASK 0x7ff // Mask of PC meaningful bits: 11 bits available
+#define HP_NANO_DC_NO 8 // Number of direct control lines (DC7 is typically used as interrupt mask)
+
+// DC changed callback
+// The callback receives a 8-bit word holding the state of all DC lines.
+// DC0 is in bit 0, DC1 in bit 1 and so on.
+// Keep in mind that DC7 usually masks the interrupt signal.
+#define MCFG_HP_NANO_DC_CHANGED(_devcb) \
+ hp_nanoprocessor_device::set_dc_changed_func(*device , DEVCB_##_devcb);
+
+class hp_nanoprocessor_device : public cpu_device
+{
+public:
+ hp_nanoprocessor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<class _Object> static devcb_base &set_dc_changed_func(device_t &device, _Object object) { return downcast<hp_nanoprocessor_device &>(device).m_dc_changed_func.set_callback(object); }
+
+ // device_t overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual uint32_t execute_min_cycles() const override { return 2; }
+ // 3 cycles is for int. acknowledge + 1 instruction
+ virtual uint32_t execute_max_cycles() const override { return 3; }
+ virtual uint32_t execute_input_lines() const override { return 1; }
+ virtual uint32_t execute_default_irq_vector() const override { return 0xff; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int linenum, int state) override;
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum) const override {
+ return (spacenum == AS_PROGRAM) ? &m_program_config : ((spacenum == AS_IO) ? &m_io_config : nullptr);
+ }
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // device_disasm_interface overrides
+ virtual uint32_t disasm_min_opcode_bytes() const override { return 1; }
+ virtual uint32_t disasm_max_opcode_bytes() const override { return 2; }
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
+
+private:
+ devcb_write8 m_dc_changed_func;
+ int m_icount;
+
+ // State of processor
+ uint8_t m_reg_A; // Accumulator
+ uint8_t m_reg_R[ HP_NANO_REGS ]; // General purpose registers
+ uint16_t m_reg_PA; // Program counter ("Program Address" in HP doc)
+ uint16_t m_reg_SSR; // Subroutine stack register
+ uint16_t m_reg_ISR; // Interrupt stack register
+ uint16_t m_flags; // Flags: extend flag (E) & direct control lines (DC0-7)
+
+ address_space_config m_program_config;
+ address_space_config m_io_config;
+
+ address_space *m_program;
+ direct_read_data *m_direct;
+ address_space *m_io;
+
+ void execute_one(uint8_t opcode);
+ uint16_t pa_offset(unsigned off) const;
+ uint8_t fetch(void);
+ void skip(void);
+ void dc_update(void);
+ void dc_set(unsigned bit_no);
+ void dc_clr(unsigned bit_no);
+};
+
+extern const device_type HP_NANOPROCESSOR;
+
+#endif /* _NANOPROCESSOR_H_ */
diff --git a/src/devices/cpu/nanoprocessor/nanoprocessor_dasm.cpp b/src/devices/cpu/nanoprocessor/nanoprocessor_dasm.cpp
new file mode 100644
index 00000000000..73c53231940
--- /dev/null
+++ b/src/devices/cpu/nanoprocessor/nanoprocessor_dasm.cpp
@@ -0,0 +1,137 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+// *******************************
+// * HP nanoprocessor disassembler
+// *******************************
+
+#include "emu.h"
+#include "debugger.h"
+#include "nanoprocessor.h"
+
+typedef void (*fn_dis_param)(char *buffer , uint8_t opcode , const uint8_t* opram);
+
+typedef struct {
+ uint8_t m_op_mask;
+ uint8_t m_opcode;
+ const char *m_mnemonic;
+ fn_dis_param m_param_fn;
+ uint32_t m_dasm_flags;
+} dis_entry_t;
+
+static void param_bitno(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ *buffer++ = '0' + (opcode & 7);
+ *buffer = '\0';
+}
+
+static void param_ds(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ sprintf(buffer , "DS%u" , opcode & 0xf);
+}
+
+static void param_reg(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ sprintf(buffer , "R%u" , opcode & 0xf);
+}
+
+static void param_11bit(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ unsigned tmp = ((unsigned)(opcode & 7) << 8) | *opram;
+ sprintf(buffer , "0x%03x" , tmp);
+}
+
+static void param_page_no(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ *buffer++ = '0' + (opcode & 7);
+ *buffer = '\0';
+}
+
+static void param_byte(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ sprintf(buffer , "0x%02x" , *opram);
+}
+
+static void param_ds_byte(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ sprintf(buffer , "DS%u,0x%02x" , opcode & 0xf , *opram);
+}
+
+static void param_reg_byte(char *buffer , uint8_t opcode , const uint8_t* opram)
+{
+ sprintf(buffer , "R%u,0x%02x" , opcode & 0xf , *opram);
+}
+
+static const dis_entry_t dis_table[] = {
+ {0xff , 0x00 , "INB" , nullptr , 1},
+ {0xff , 0x01 , "DEB" , nullptr , 1},
+ {0xff , 0x02 , "IND" , nullptr , 1},
+ {0xff , 0x03 , "DED" , nullptr , 1},
+ {0xff , 0x04 , "CLA" , nullptr , 1},
+ {0xff , 0x05 , "CMA" , nullptr , 1},
+ {0xff , 0x06 , "RSA" , nullptr , 1},
+ {0xff , 0x07 , "LSA" , nullptr , 1},
+ {0xff , 0x08 , "SGT" , nullptr , 1},
+ {0xff , 0x09 , "SLT" , nullptr , 1},
+ {0xff , 0x0a , "SEQ" , nullptr , 1},
+ {0xff , 0x0b , "SAZ" , nullptr , 1},
+ {0xff , 0x0c , "SLE" , nullptr , 1},
+ {0xff , 0x0d , "SGE" , nullptr , 1},
+ {0xff , 0x0e , "SNE" , nullptr , 1},
+ {0xff , 0x0f , "SAN" , nullptr , 1},
+ {0xf8 , 0x10 , "SBS" , param_bitno , 1},
+ {0xff , 0x1f , "SES" , nullptr , 1},
+ {0xf8 , 0x18 , "SFS" , param_bitno , 1},
+ {0xf8 , 0x20 , "SBN" , param_bitno , 1},
+ {0xff , 0x2f , "ENI" , nullptr , 1},
+ {0xf8 , 0x28 , "STC" , param_bitno , 1},
+ {0xf8 , 0x30 , "SBZ" , param_bitno , 1},
+ {0xff , 0x3f , "SEZ" , nullptr , 1},
+ {0xf8 , 0x38 , "SFZ" , param_bitno , 1},
+ {0xf0 , 0x40 , "INA" , param_ds , 1},
+ {0xff , 0x5f , "NOP" , nullptr , 1},
+ {0xf0 , 0x50 , "OTA" , param_ds , 1},
+ {0xf0 , 0x60 , "LDA" , param_reg , 1},
+ {0xf0 , 0x70 , "STA" , param_reg , 1},
+ {0xf8 , 0x80 , "JMP" , param_11bit , 2},
+ {0xf8 , 0x88 , "JSB" , param_11bit , 2 | DASMFLAG_STEP_OVER},
+ {0xf8 , 0x90 , "JAI" , param_page_no , 1},
+ {0xf8 , 0x98 , "JAS" , param_page_no , 1 | DASMFLAG_STEP_OVER},
+ {0xf8 , 0xa0 , "CBN" , param_bitno , 1},
+ {0xff , 0xaf , "DSI" , nullptr , 1},
+ {0xf8 , 0xa8 , "CLC" , param_bitno , 1},
+ {0xff , 0xb0 , "RTI" , nullptr , 1 | DASMFLAG_STEP_OUT},
+ {0xff , 0xb1 , "RTE" , nullptr , 1 | DASMFLAG_STEP_OUT},
+ {0xff , 0xb4 , "STE" , nullptr , 1},
+ {0xff , 0xb5 , "CLE" , nullptr , 1},
+ {0xff , 0xb8 , "RTS" , nullptr , 1 | DASMFLAG_STEP_OUT},
+ {0xff , 0xb9 , "RSE" , nullptr , 1 | DASMFLAG_STEP_OUT},
+ {0xff , 0xcf , "LDR" , param_byte , 2},
+ {0xf0 , 0xc0 , "OTR" , param_ds_byte , 2},
+ {0xf0 , 0xd0 , "STR" , param_reg_byte , 2},
+ {0xf0 , 0xe0 , "LDI" , param_reg , 1},
+ {0xf0 , 0xf0 , "STI" , param_reg , 1},
+ // Catchall for undefined opcodes
+ {0x00 , 0x00 , "???" , nullptr , 1}
+};
+
+CPU_DISASSEMBLE(hp_nanoprocessor)
+{
+ const uint8_t opcode = *oprom;
+ char operand[ 16 ];
+
+ opram++;
+
+ for (const dis_entry_t& ent : dis_table) {
+ if ((opcode & ent.m_op_mask) == ent.m_opcode) {
+ strcpy(buffer , ent.m_mnemonic);
+ strcat(buffer , " ");
+ if (ent.m_param_fn != nullptr) {
+ ent.m_param_fn(operand , opcode , opram);
+ strcat(buffer , operand);
+ }
+ return ent.m_dasm_flags | DASMFLAG_SUPPORTED;
+ }
+ }
+ // Should never ever happen
+ return 0;
+}
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 98d6a4f2c91..f72a5734f23 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -104,6 +104,7 @@ CPU_DISASSEMBLE( hd63701 );
CPU_DISASSEMBLE( hmcs40 );
CPU_DISASSEMBLE( hp_hybrid );
CPU_DISASSEMBLE( hp_5061_3001 );
+CPU_DISASSEMBLE( hp_nanoprocessor );
CPU_DISASSEMBLE( hyperstone_generic );
CPU_DISASSEMBLE( i4004 );
CPU_DISASSEMBLE( i8008 );
@@ -313,6 +314,7 @@ static const dasm_table_entry dasm_table[] =
{ "mips3be", _32be, 0, CPU_DISASSEMBLE_NAME(mips3be) },
{ "mips3le", _32le, 0, CPU_DISASSEMBLE_NAME(mips3le) },
{ "mn10200", _16le, 0, CPU_DISASSEMBLE_NAME(mn10200) },
+ { "nanoprocessor",_8bit, 0, CPU_DISASSEMBLE_NAME(hp_nanoprocessor) },
{ "nec", _8bit, 0, CPU_DISASSEMBLE_NAME(nec) },
{ "nsc8105", _8bit, 0, CPU_DISASSEMBLE_NAME(nsc8105) },
{ "pdp1", _32be, 0, CPU_DISASSEMBLE_NAME(pdp1) },