summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author fulivi <fulivi@users.noreply.github.com>2021-07-05 15:40:56 +0200
committer GitHub <noreply@github.com>2021-07-05 23:40:56 +1000
commit0f3d87919e2820c94e1efbea0131fb23ee25fade (patch)
tree21c2d85f17d0c15b915eeca04875a36c21d02524
parent753cf8dfeec422773be592c91fac1012d9ca593a (diff)
cpu/nanoprocessor: Improvements based on chip reverse-engineering. (#8253)
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor.cpp100
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor.h16
2 files changed, 81 insertions, 35 deletions
diff --git a/src/devices/cpu/nanoprocessor/nanoprocessor.cpp b/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
index ad54f006bfa..e218f53e505 100644
--- a/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
+++ b/src/devices/cpu/nanoprocessor/nanoprocessor.cpp
@@ -31,16 +31,23 @@ 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")
@@ -100,6 +107,10 @@ void hp_nanoprocessor_device::device_start()
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;
@@ -107,7 +118,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();
}
@@ -180,6 +191,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:
@@ -200,27 +219,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;
@@ -340,6 +377,8 @@ 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]];
@@ -427,17 +466,8 @@ void hp_nanoprocessor_device::execute_one(uint8_t opcode)
[[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;
@@ -487,12 +517,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:
diff --git a/src/devices/cpu/nanoprocessor/nanoprocessor.h b/src/devices/cpu/nanoprocessor/nanoprocessor.h
index e5260a950e6..2aa8cf3a4ab 100644
--- a/src/devices/cpu/nanoprocessor/nanoprocessor.h
+++ b/src/devices/cpu/nanoprocessor/nanoprocessor.h
@@ -50,6 +50,17 @@
// The HP manual of Nanoprocessor is available here:
// http://www.hp9845.net/9845/downloads/manuals/Nanoprocessor.pdf
// Thanks to anyone who made the manual available.
+//
+// My reverse engineering of Nanoprocessor from mask set
+// https://github.com/fulivi/nanoprocessor_re
+//
+// Mask set is published here
+// http://cpushack.com/2020/08/20/hp-nanoprocessor-mask-set/
+//
+// Ken Shirriff's articles
+// http://www.righto.com/2020/09/inside-hp-nanoprocessor-high-speed.html
+// http://www.righto.com/2020/09/hp-nanoprocessor-part-ii-reverse.html
+//
#ifndef MAME_CPU_NANOPROCESSOR_NANOPROCESSOR_H
#define MAME_CPU_NANOPROCESSOR_NANOPROCESSOR_H
@@ -110,6 +121,11 @@ private:
uint16_t m_reg_ISR; // Interrupt stack register
uint16_t m_flags; // Flags: extend flag (E) & direct control lines (DC0-7)
+ // Bits in m_flags
+ static constexpr unsigned NANO_DC0_BIT = 0; // DC0
+ static constexpr unsigned NANO_E_BIT = NANO_DC0_BIT + HP_NANO_DC_NO; // Extend flag
+ static constexpr unsigned NANO_I_BIT = NANO_E_BIT + 1; // Interrupt flag
+
address_space_config m_program_config;
address_space_config m_io_config;