summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/nanoprocessor/nanoprocessor.cpp')
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor.cpp130
1 files changed, 79 insertions, 51 deletions
diff --git a/src/devices/cpu/nanoprocessor/nanoprocessor.cpp b/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
index 50e7f587cf7..d78c237727f 100644
--- a/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
+++ b/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
@@ -4,7 +4,6 @@
#include "emu.h"
#include "nanoprocessor.h"
#include "nanoprocessor_dasm.h"
-#include "debugger.h"
// Index of state variables
enum {
@@ -31,23 +30,31 @@ enum {
NANO_REG_FLAGS
};
-#define BIT_MASK(n) (1U << (n))
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)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))
+ template<typename T> void BIT_CLR(T& w , unsigned n)
+ {
+ w &= ~BIT_MASK<T>(n);
+ }
-// Bits in m_flags
-#define NANO_DC0_BIT 0 // DC0
-#define NANO_E_BIT (NANO_DC0_BIT + HP_NANO_DC_NO) // Extend flag
-#define NANO_I_BIT (NANO_E_BIT + 1) // Interrupt flag
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
DEFINE_DEVICE_TYPE(HP_NANOPROCESSOR, hp_nanoprocessor_device, "nanoprocessor", "Hewlett Packard HP-Nanoprocessor")
hp_nanoprocessor_device::hp_nanoprocessor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
cpu_device(mconfig, HP_NANOPROCESSOR, tag, owner, clock),
m_dc_changed_func(*this),
- m_read_dc_func(*this),
+ m_read_dc_func(*this, 0xff),
+ m_int_ack_func(*this, 0xff),
m_program_config("program", ENDIANNESS_BIG, 8, 11),
m_io_config("io", ENDIANNESS_BIG, 8, 4)
{
@@ -79,9 +86,9 @@ void hp_nanoprocessor_device::device_start()
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_cache = m_program->cache<0, 0, ENDIANNESS_BIG>();
- m_io = &space(AS_IO);
+ space(AS_PROGRAM).cache(m_cache);
+ space(AS_PROGRAM).specific(m_program);
+ space(AS_IO).specific(m_io);
save_item(NAME(m_reg_A));
save_item(NAME(m_reg_R));
@@ -91,13 +98,14 @@ void hp_nanoprocessor_device::device_start()
save_item(NAME(m_flags));
set_icountptr(m_icount);
-
- m_dc_changed_func.resolve_safe();
- m_read_dc_func.resolve_safe(0xff);
}
void hp_nanoprocessor_device::device_reset()
{
+ // IRL reset signal only sets the following things:
+ // DC7 (int. enable) = 0
+ // DC6..0 = 1
+ // PA = 0
m_reg_A = 0;
for (auto& reg : m_reg_R) {
reg = 0;
@@ -105,7 +113,7 @@ void hp_nanoprocessor_device::device_reset()
m_reg_PA = 0;
m_reg_SSR = 0;
m_reg_ISR = 0;
- m_flags = 0;
+ m_flags = ((1U << (HP_NANO_DC_NO - 1)) - 1) << NANO_DC0_BIT;
dc_update();
}
@@ -124,8 +132,9 @@ void hp_nanoprocessor_device::execute_run()
// outside of the NP, usually by ANDing the DC7 line with the interrupt
// request signal)
if (BIT(m_flags, NANO_I_BIT)) {
+ standard_irq_callback(0, m_reg_PA);
m_reg_ISR = m_reg_PA;
- m_reg_PA = (uint16_t)(standard_irq_callback(0) & 0xff);
+ m_reg_PA = m_int_ack_func();
// Vector fetching takes 1 cycle
m_icount -= 1;
dc_clr(HP_NANO_IE_DC);
@@ -177,6 +186,14 @@ std::unique_ptr<util::disasm_interface> hp_nanoprocessor_device::create_disassem
void hp_nanoprocessor_device::execute_one(uint8_t opcode)
{
+ // Apply indexing
+ if ((opcode & 0xe0) == 0xe0 ||
+ (opcode & 0xf0) == 0x90) {
+ // This is how the real hw does indexing. Altering the opcode in this way explains
+ // why a JAI instruction is turned into a JAS when R0:b3 = 1 (opcode 90..97 -> 98..9f)
+ opcode |= (m_reg_R[ 0 ] & 0x0f);
+ }
+
// Instructions without mask
switch (opcode) {
case 0x00:
@@ -197,27 +214,45 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
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);
+ // Handling of non-decimal digits comes from chip RE
+ {
+ uint8_t nibble_lo = m_reg_A & 0x0f;
+ uint8_t nibble_hi = m_reg_A & 0xf0;
+
+ if ((nibble_lo & 0x09) != 0x09) {
+ nibble_lo++;
+ } else {
+ nibble_lo = (nibble_lo + 1) & 0x05;
+ if ((nibble_hi & 0x90) != 0x90) {
+ nibble_hi += 0x10;
+ } else {
+ nibble_hi = (nibble_hi + 0x10) & 0x50;
+ BIT_SET(m_flags, NANO_E_BIT);
+ }
}
+ m_reg_A = nibble_hi | nibble_lo;
}
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);
+ // Handling of non-decimal digits comes from chip RE
+ {
+ uint8_t nibble_lo = m_reg_A & 0x0f;
+ uint8_t nibble_hi = m_reg_A & 0xf0;
+
+ if (nibble_lo) {
+ nibble_lo--;
+ } else {
+ nibble_lo = 9;
+ if (nibble_hi) {
+ nibble_hi -= 0x10;
+ } else {
+ nibble_hi = 0x90;
+ BIT_SET(m_flags, NANO_E_BIT);
+ }
}
+ m_reg_A = nibble_hi | nibble_lo;
}
break;
@@ -319,7 +354,7 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
// RTE
dc_set(HP_NANO_IE_DC);
// Intentional fall-through to RTI!
-
+ [[fallthrough]];
case 0xb0:
// RTI
m_reg_PA = m_reg_ISR;
@@ -337,9 +372,11 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
case 0xb9:
// RSE
+ // This op is implemented in the released NP mask set exactly as RTS (i.e.
+ // IE is not set). I'm implementing it here as described in the manual.
dc_set(HP_NANO_IE_DC);
// Intentional fall-through to RTS!
-
+ [[fallthrough]];
case 0xb8:
// RTS
{
@@ -421,20 +458,11 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
// JAS
m_reg_SSR = pa_offset(1);
// Intentional fall-through to JAI!
-
+ [[fallthrough]];
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;
+ uint16_t tmp = (uint16_t)(opcode & 7) << 8;
m_reg_PA = tmp | m_reg_A;
}
break;
@@ -454,12 +482,12 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
switch (opcode & 0xf0) {
case 0x40:
// INA
- m_reg_A = m_io->read_byte(opcode & 0xf);
+ m_reg_A = m_io.read_byte(opcode & 0xf);
break;
case 0x50:
// OTA
- m_io->write_byte(opcode & 0xf, m_reg_A);
+ m_io.write_byte(opcode & 0xf, m_reg_A);
break;
case 0x60:
@@ -474,7 +502,7 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
case 0xc0:
// OTR
- m_io->write_byte(opcode & 0xf, fetch());
+ m_io.write_byte(opcode & 0xf, fetch());
break;
case 0xd0:
@@ -484,12 +512,12 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
case 0xe0:
// LDI
- m_reg_A = m_reg_R[ (m_reg_R[ 0 ] | opcode) & 0xf ];
+ m_reg_A = m_reg_R[ opcode & 0xf ];
break;
case 0xf0:
// STI
- m_reg_R[ (m_reg_R[ 0 ] | opcode) & 0xf ] = m_reg_A;
+ m_reg_R[ opcode & 0xf ] = m_reg_A;
break;
default:
@@ -507,7 +535,7 @@ uint16_t hp_nanoprocessor_device::pa_offset(unsigned off) const
uint8_t hp_nanoprocessor_device::fetch(void)
{
- uint8_t res = m_cache->read_byte(m_reg_PA);
+ uint8_t res = m_cache.read_byte(m_reg_PA);
m_reg_PA = pa_offset(1);
return res;
}