summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/powerpc')
-rw-r--r--src/devices/cpu/powerpc/ppc.h121
-rw-r--r--src/devices/cpu/powerpc/ppc_dasm.cpp649
-rw-r--r--src/devices/cpu/powerpc/ppc_dasm.h35
-rw-r--r--src/devices/cpu/powerpc/ppccom.cpp249
-rw-r--r--src/devices/cpu/powerpc/ppccom.h12
-rw-r--r--src/devices/cpu/powerpc/ppcdrc.cpp271
-rw-r--r--src/devices/cpu/powerpc/ppcfe.cpp96
7 files changed, 980 insertions, 453 deletions
diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h
index 4e4e1e144e2..ce715b59dc1 100644
--- a/src/devices/cpu/powerpc/ppc.h
+++ b/src/devices/cpu/powerpc/ppc.h
@@ -13,12 +13,16 @@
#pragma once
+#include "ppc_dasm.h"
+
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "cpu/drcumlsh.h"
#include "divtlb.h"
+#include <algorithm>
+
/***************************************************************************
CONSTANTS
@@ -75,9 +79,18 @@ enum
PPC_R30,
PPC_R31,
PPC_CR,
+ PPC_MQ,
PPC_LR,
PPC_CTR,
PPC_XER,
+ PPC_BAT0U,
+ PPC_BAT0L,
+ PPC_BAT1U,
+ PPC_BAT1L,
+ PPC_BAT2U,
+ PPC_BAT2L,
+ PPC_BAT3U,
+ PPC_BAT3L,
PPC_F0,
PPC_F1,
@@ -147,7 +160,6 @@ enum
PPC_SR15
};
-
/* compiler-specific options */
#define PPCDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
#define PPCDRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */
@@ -212,7 +224,10 @@ public:
void set_bus_frequency(uint32_t bus_frequency) { c_bus_frequency = bus_frequency; }
void set_bus_frequency(const XTAL &xtal) { set_bus_frequency(xtal.value()); }
- void ppc_set_dcstore_callback(write32_delegate callback);
+ void set_serial_clock(uint32_t serial_clock) { c_serial_clock = serial_clock; }
+ void set_serial_clock(const XTAL &xtal) { set_serial_clock(xtal.value()); }
+
+ void ppc_set_dcstore_callback(write32sm_delegate callback);
void ppcdrc_set_options(uint32_t options);
void ppcdrc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base);
@@ -245,20 +260,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 1; }
- virtual uint32_t execute_max_cycles() const override { return 40; }
- virtual uint32_t execute_input_lines() const override { return 1; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 40; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
// device_state_interface overrides
virtual void state_export(const device_state_entry &entry) override;
@@ -292,7 +306,10 @@ protected:
address_space_config m_program_config;
address_space *m_program;
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_cache32;
+ memory_access<32, 3, 0, ENDIANNESS_BIG>::cache m_cache64;
uint32_t c_bus_frequency;
+ uint32_t c_serial_clock;
struct internal_ppc_state
{
@@ -461,29 +478,39 @@ protected:
/* architectural distinctions */
powerpc_flavor m_flavor;
- uint32_t m_cap;
- uint8_t m_cache_line_size;
- uint32_t m_tb_divisor;
+ uint32_t m_cap;
+ uint8_t m_cache_line_size;
+ uint32_t m_tb_divisor;
/* PowerPC 4xx-specific state */
/* PowerPC 4XX-specific serial port state */
struct ppc4xx_spu_state
{
- uint8_t regs[9];
- uint8_t txbuf;
- uint8_t rxbuf;
+ ppc4xx_spu_state(device_t &owner) : timer(nullptr), tx_cb(owner) { }
+
+ void clear()
+ {
+ std::fill(std::begin(regs), std::end(regs), 0);
+ txbuf = rxbuf = 0;
+ std::fill(std::begin(rxbuffer), std::end(rxbuffer), 0);
+ rxin = rxout = 0;
+ }
+
+ uint8_t regs[9];
+ uint8_t txbuf;
+ uint8_t rxbuf;
emu_timer * timer;
- uint8_t rxbuffer[256];
- uint32_t rxin, rxout;
- write8_delegate tx_cb;
+ uint8_t rxbuffer[256];
+ uint32_t rxin, rxout;
+ write8smo_delegate tx_cb;
};
ppc4xx_spu_state m_spu;
emu_timer * m_fit_timer;
emu_timer * m_pit_timer;
emu_timer * m_wdog_timer;
- uint32_t m_pit_reload;
- uint32_t m_irqstate;
+ uint32_t m_pit_reload;
+ uint32_t m_irqstate;
emu_timer * m_buffered_dma_timer[4];
int m_buffered_dma_rate[4];
@@ -493,17 +520,20 @@ protected:
uint32_t m_system_clock;
uint32_t m_cpu_clock;
+ uint32_t m_serial_clock;
uint64_t m_tb_zero_cycles;
uint64_t m_dec_zero_cycles;
+ uint64_t m_rtc_zero_cycles;
emu_timer * m_decrementer_int_timer;
- read32_delegate m_dcr_read_func;
- write32_delegate m_dcr_write_func;
- write32_delegate m_dcstore_cb;
+ read32sm_delegate m_dcr_read_func;
+ write32sm_delegate m_dcr_write_func;
+
+ write32sm_delegate m_dcstore_cb;
- read32_delegate m_ext_dma_read_cb[4];
- write32_delegate m_ext_dma_write_cb[4];
+ read32_delegate::array<4> m_ext_dma_read_cb;
+ write32sm_delegate::array<4> m_ext_dma_write_cb;
/* PowerPC function pointers for memory accesses/exceptions */
#ifdef PPC_H_INCLUDED_FROM_PPC_C
@@ -623,7 +653,7 @@ protected:
void set_timebase(uint64_t newtb);
uint32_t get_decrementer();
void set_decrementer(uint32_t newdec);
- uint32_t ppccom_translate_address_internal(int intention, offs_t &address);
+ uint32_t ppccom_translate_address_internal(int intention, bool debug, offs_t &address);
void ppc4xx_set_irq_line(uint32_t bitmask, int state);
int ppc4xx_get_irq_line(uint32_t bitmask);
void ppc4xx_dma_update_irq_states();
@@ -672,6 +702,8 @@ protected:
void log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist);
void log_opcode_desc(const opcode_desc *desclist, int indent);
+private:
+ powerpc_disassembler m_dasm;
};
@@ -679,9 +711,6 @@ protected:
//{
//public:
// ppc403_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-//
-//protected:
-// virtual uint32_t execute_input_lines() const { return 8; }
//};
//
//
@@ -689,9 +718,6 @@ protected:
//{
//public:
// ppc405_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-//
-//protected:
-// virtual uint32_t execute_input_lines() const { return 8; }
//};
@@ -734,6 +760,9 @@ class ppc601_device : public ppc_device
{
public:
ppc601_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
};
@@ -743,26 +772,36 @@ public:
ppc604_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
+class ppc740_device : public ppc_device
+{
+public:
+ ppc740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class ppc750_device : public ppc_device
+{
+public:
+ ppc750_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
class ppc4xx_device : public ppc_device
{
public:
- void ppc4xx_spu_set_tx_handler(write8_delegate callback);
+ void ppc4xx_spu_set_tx_handler(write8smo_delegate callback);
void ppc4xx_spu_receive_byte(uint8_t byteval);
void ppc4xx_set_dma_read_handler(int channel, read32_delegate callback, int rate);
- void ppc4xx_set_dma_write_handler(int channel, write32_delegate callback, int rate);
- void ppc4xx_set_dcr_read_handler(read32_delegate dcr_read_func);
- void ppc4xx_set_dcr_write_handler(write32_delegate dcr_write_func);
+ void ppc4xx_set_dma_write_handler(int channel, write32sm_delegate callback, int rate);
+ void ppc4xx_set_dcr_read_handler(read32sm_delegate dcr_read_func);
+ void ppc4xx_set_dcr_write_handler(write32sm_delegate dcr_write_func);
- DECLARE_READ8_MEMBER( ppc4xx_spu_r );
- DECLARE_WRITE8_MEMBER( ppc4xx_spu_w );
+ uint8_t ppc4xx_spu_r(offs_t offset);
+ void ppc4xx_spu_w(offs_t offset, uint8_t data);
- void internal_ppc4xx(address_map &map);
+ void internal_ppc4xx(address_map &map) ATTR_COLD;
protected:
ppc4xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, powerpc_flavor flavor, uint32_t cap, uint32_t tb_divisor);
- virtual uint32_t execute_input_lines() const override { return 5; }
virtual void execute_set_input(int inputnum, int state) override;
};
@@ -798,5 +837,7 @@ DECLARE_DEVICE_TYPE(MPC8240, mpc8240_device)
DECLARE_DEVICE_TYPE(PPC403GA, ppc403ga_device)
DECLARE_DEVICE_TYPE(PPC403GCX, ppc403gcx_device)
DECLARE_DEVICE_TYPE(PPC405GP, ppc405gp_device)
+DECLARE_DEVICE_TYPE(PPC740, ppc740_device)
+DECLARE_DEVICE_TYPE(PPC750, ppc750_device)
#endif // MAME_CPU_POWERPC_PPC_H
diff --git a/src/devices/cpu/powerpc/ppc_dasm.cpp b/src/devices/cpu/powerpc/ppc_dasm.cpp
index aad939efffe..85ed3914e3e 100644
--- a/src/devices/cpu/powerpc/ppc_dasm.cpp
+++ b/src/devices/cpu/powerpc/ppc_dasm.cpp
@@ -28,219 +28,331 @@
* and print instructions.
*/
+constexpr int I_COMMON = powerpc_disassembler::I_POWER | powerpc_disassembler::I_POWERPC;
+
const powerpc_disassembler::IDESCR powerpc_disassembler::itab[] =
{
- { "add", D_OP(31)|D_XO(266), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "addc", D_OP(31)|D_XO(10), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "adde", D_OP(31)|D_XO(138), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "addi", D_OP(14), M_RT|M_RA|M_SIMM, F_RT_RA_0_SIMM, 0 },
- { "addic", D_OP(12), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
- { "addic.", D_OP(13), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
- { "addis", D_OP(15), M_RT|M_RA|M_SIMM, F_ADDIS, 0 },
- { "addme", D_OP(31)|D_XO(234), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
- { "addze", D_OP(31)|D_XO(202), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
- { "and", D_OP(31)|D_XO(28), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "andc", D_OP(31)|D_XO(60), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "andi.", D_OP(28), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
- { "andis.", D_OP(29), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
- { "b", D_OP(18), M_LI|M_AA|M_LK, F_LI, FL_AA|FL_LK },
- { "bc", D_OP(16), M_BO|M_BI|M_BD|M_AA|M_LK, F_BCx, FL_AA|FL_LK },
- { "bcctr", D_OP(19)|D_XO(528), M_BO|M_BI|M_LK, F_BO_BI, FL_LK },
- { "bclr", D_OP(19)|D_XO(16), M_BO|M_BI|M_LK, F_BO_BI, FL_LK|FL_SO },
- { "cmp", D_OP(31)|D_XO(0), M_CRFD|M_RA|M_RB, F_CMP, 0 },
- { "cmpd", D_OP(31)|D_XO(0)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0 },
- { "cmpi", D_OP(11), M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0 },
- { "cmpdi", D_OP(11)|M_L, M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0 },
- { "cmpl", D_OP(31)|D_XO(32), M_CRFD|M_RA|M_RB, F_CMP, 0 },
- { "cmpld", D_OP(31)|D_XO(32)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0 },
- { "cmpli", D_OP(10), M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0 },
- { "cmpldi", D_OP(10)|M_L, M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0 },
- { "cntlzw", D_OP(31)|D_XO(26), M_RT|M_RA|M_RC, F_RA_RT, FL_RC },
- { "crand", D_OP(19)|D_XO(257), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "crandc", D_OP(19)|D_XO(129), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "creqv", D_OP(19)|D_XO(289), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "crnand", D_OP(19)|D_XO(225), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "crnor", D_OP(19)|D_XO(33), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "cror", D_OP(19)|D_XO(449), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "crorc", D_OP(19)|D_XO(417), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "crxor", D_OP(19)|D_XO(193), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
- { "dcba", D_OP(31)|D_XO(758), M_RA|M_RB, F_RA_0_RB, 0 },
- { "dcbf", D_OP(31)|D_XO(86), M_RA|M_RB, F_RA_0_RB, 0 },
- { "dcbi", D_OP(31)|D_XO(470), M_RA|M_RB, F_RA_0_RB, 0 },
- { "dcbst", D_OP(31)|D_XO(54), M_RA|M_RB, F_RA_0_RB, 0 },
- { "dcbt", D_OP(31)|D_XO(278), M_RA|M_RB, F_RA_0_RB, 0 },
- { "dcbtst", D_OP(31)|D_XO(246), M_RA|M_RB, F_RA_0_RB, 0 },
- { "dcbz", D_OP(31)|D_XO(1014),M_RA|M_RB, F_RA_0_RB, 0 },
- { "dccci", D_OP(31)|D_XO(454), M_RA|M_RB, F_RA_0_RB, 0 },
- { "dcread", D_OP(31)|D_XO(486), M_RA|M_RB, F_RT_RA_RB, 0 },
- { "divw", D_OP(31)|D_XO(491), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "divwu", D_OP(31)|D_XO(459), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "dsa", D_OP(31)|D_XO(628), 0, 0, 0 },
- { "eciwx", D_OP(31)|D_XO(310), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "ecowx", D_OP(31)|D_XO(438), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "eieio", D_OP(31)|D_XO(854), 0, F_NONE, 0 },
- { "eqv", D_OP(31)|D_XO(284), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "esa", D_OP(31)|D_XO(596), 0, 0, 0 },
- { "extsb", D_OP(31)|D_XO(954), M_RT|M_RA|M_RC, F_RA_RT, FL_RC },
- { "extsh", D_OP(31)|D_XO(922), M_RT|M_RA|M_RC, F_RA_RT, FL_RC },
- { "fabs", D_OP(63)|D_XO(264), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fadd", D_OP(63)|D_XO(21), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
- { "fadds", D_OP(59)|D_XO(21), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
- { "fcmpo", D_OP(63)|D_XO(32), M_CRFD|M_RA|M_RB, F_FCMP, 0 },
- { "fcmpu", D_OP(63)|D_XO(0), M_CRFD|M_RA|M_RB, F_FCMP, 0 },
- { "fctiw", D_OP(63)|D_XO(14), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fctiwz", D_OP(63)|D_XO(15), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fdiv", D_OP(63)|D_XO(18), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
- { "fdivs", D_OP(59)|D_XO(18), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
- { "fmadd", D_OP(63)|D_XO(29), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fmadds", D_OP(59)|D_XO(29), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fmr", D_OP(63)|D_XO(72), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fmsub", D_OP(63)|D_XO(28), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fmsubs", D_OP(59)|D_XO(28), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fmul", D_OP(63)|D_XO(25), M_RT|M_RA|M_REGC|M_RC, F_FRT_FRA_FRC, FL_RC },
- { "fmuls", D_OP(59)|D_XO(25), M_RT|M_RA|M_REGC|M_RC, F_FRT_FRA_FRC, FL_RC },
- { "fnabs", D_OP(63)|D_XO(136), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fneg", D_OP(63)|D_XO(40), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fnmadd", D_OP(63)|D_XO(31), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fnmadds",D_OP(59)|D_XO(31), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fnmsub", D_OP(63)|D_XO(30), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fnmsubs",D_OP(59)|D_XO(30), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fres", D_OP(59)|D_XO(24), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "frsp", D_OP(63)|D_XO(12), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "frsqrte",D_OP(63)|D_XO(26), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fsel", D_OP(63)|D_XO(23), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
- { "fsqrt", D_OP(63)|D_XO(22), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fsqrts", D_OP(59)|D_XO(22), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
- { "fsub", D_OP(63)|D_XO(20), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
- { "fsubs", D_OP(59)|D_XO(20), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
- { "icbi", D_OP(31)|D_XO(982), M_RA|M_RB, F_RA_0_RB, 0 },
- { "icbt", D_OP(31)|D_XO(262), M_RA|M_RB, F_RA_0_RB, 0 },
- { "iccci", D_OP(31)|D_XO(966), M_RA|M_RB, F_RA_0_RB, 0 },
- { "icread", D_OP(31)|D_XO(998), M_RA|M_RB, F_RA_0_RB, 0 },
- { "isync", D_OP(19)|D_XO(150), 0, F_NONE, 0 },
- { "lbz", D_OP(34), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "lbzu", D_OP(35), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
- { "lbzux", D_OP(31)|D_XO(119), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
- { "lbzx", D_OP(31)|D_XO(87), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "lfd", D_OP(50), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
- { "lfdu", D_OP(51), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
- { "lfdux", D_OP(31)|D_XO(631), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
- { "lfdx", D_OP(31)|D_XO(599), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
- { "lfs", D_OP(48), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
- { "lfsu", D_OP(49), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
- { "lfsux", D_OP(31)|D_XO(567), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
- { "lfsx", D_OP(31)|D_XO(535), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
- { "lha", D_OP(42), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "lhau", D_OP(43), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
- { "lhaux", D_OP(31)|D_XO(375), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
- { "lhax", D_OP(31)|D_XO(343), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "lhbrx", D_OP(31)|D_XO(790), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "lhz", D_OP(40), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "lhzu", D_OP(41), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
- { "lhzux", D_OP(31)|D_XO(311), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
- { "lhzx", D_OP(31)|D_XO(279), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "lmw", D_OP(46), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "lswi", D_OP(31)|D_XO(597), M_RT|M_RA|M_NB, F_RT_RA_0_NB, FL_CHECK_LSWI },
- { "lswx", D_OP(31)|D_XO(533), M_RT|M_RA|M_RB, F_RT_RA_0_RB, FL_CHECK_LSWX },
- { "lwarx", D_OP(31)|D_XO(20), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "lwbrx", D_OP(31)|D_XO(534), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "lwz", D_OP(32), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "lwzu", D_OP(33), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
- { "lwzux", D_OP(31)|D_XO(55), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
- { "lwzx", D_OP(31)|D_XO(23), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "mcrf", D_OP(19)|D_XO(0), M_CRFD|M_CRFS, F_CRFD_CRFS, 0 },
- { "mcrfs", D_OP(63)|D_XO(64), M_CRFD|M_CRFS, F_CRFD_CRFS, 0 },
- { "mcrxr", D_OP(31)|D_XO(512), M_CRFD, F_MCRXR, 0 },
- { "mfcr", D_OP(31)|D_XO(19), M_RT, F_RT, 0 },
- { "mfdcr", D_OP(31)|D_XO(323), M_RT|M_DCR, F_RT_DCR, 0 },
- { "mffs", D_OP(63)|D_XO(583), M_RT|M_RC, F_MFFSx, FL_RC },
- { "mfmsr", D_OP(31)|D_XO(83), M_RT, F_RT, 0 },
- { "mfspr", D_OP(31)|D_XO(339), M_RT|M_SPR, F_RT_SPR, 0 },
- { "mfsr", D_OP(31)|D_XO(595), M_RT|M_SR, F_MFSR, 0 },
- { "mfsrin", D_OP(31)|D_XO(659), M_RT|M_RB, F_RT_RB, 0 },
- { "mftb", D_OP(31)|D_XO(371), M_RT|M_TBR, F_RT_SPR, 0 },
- { "mtcrf", D_OP(31)|D_XO(144), M_RT|M_CRM, F_MTCRF, 0 },
- { "mtdcr", D_OP(31)|D_XO(451), M_RT|M_DCR, F_MTDCR, 0 },
- { "mtfsb0", D_OP(63)|D_XO(70), M_CRBD|M_RC, F_FCRBD, FL_RC },
- { "mtfsb1", D_OP(63)|D_XO(38), M_CRBD|M_RC, F_FCRBD, FL_RC },
- { "mtfsf", D_OP(63)|D_XO(711), M_FM|M_RB|M_RC, F_MTFSFx, FL_RC },
- { "mtfsfi", D_OP(63)|D_XO(134), M_CRFD|M_IMM|M_RC, F_MTFSFIx, FL_RC },
- { "mtmsr", D_OP(31)|D_XO(146), M_RT, F_RT, 0 },
- { "mtspr", D_OP(31)|D_XO(467), M_RT|M_SPR, F_MTSPR, 0 },
- { "mtsr", D_OP(31)|D_XO(210), M_RT|M_SR, F_MTSR, 0 },
- { "mtsrin", D_OP(31)|D_XO(242), M_RT|M_RB, F_RT_RB, 0 },
- { "mulhw", D_OP(31)|D_XO(75), M_RT|M_RA|M_RB|M_RC, F_RT_RA_RB, FL_RC },
- { "mulhwu", D_OP(31)|D_XO(11), M_RT|M_RA|M_RB|M_RC, F_RT_RA_RB, FL_RC },
- { "mulli", D_OP(7), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
- { "mullw", D_OP(31)|D_XO(235), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "nand", D_OP(31)|D_XO(476), M_RA|M_RT|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "neg", D_OP(31)|D_XO(104), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
- { "nor", D_OP(31)|D_XO(124), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "or", D_OP(31)|D_XO(444), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "orc", D_OP(31)|D_XO(412), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "ori", D_OP(24), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
- { "oris", D_OP(25), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
- { "rfi", D_OP(19)|D_XO(50), 0, F_NONE, 0 },
- { "rfci", D_OP(19)|D_XO(51), 0, F_NONE, 0 },
- { "rlwimi", D_OP(20), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC },
- { "rlwinm", D_OP(21), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC },
- { "rlwnm", D_OP(23), M_RT|M_RA|M_RB|M_MB|M_ME|M_RC, F_RLWNMx, FL_RC },
- { "sc", D_OP(17)|2, 0, F_NONE, 0 },
- { "slw", D_OP(31)|D_XO(24), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "sraw", D_OP(31)|D_XO(792), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "srawi", D_OP(31)|D_XO(824), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC },
- { "srw", D_OP(31)|D_XO(536), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "stb", D_OP(38), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "stbu", D_OP(39), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA },
- { "stbux", D_OP(31)|D_XO(247), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA },
- { "stbx", D_OP(31)|D_XO(215), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "stfd", D_OP(54), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
- { "stfdu", D_OP(55), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
- { "stfdux", D_OP(31)|D_XO(759), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
- { "stfdx", D_OP(31)|D_XO(727), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
- { "stfiwx", D_OP(31)|D_XO(983), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
- { "stfs", D_OP(52), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
- { "stfsu", D_OP(53), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
- { "stfsux", D_OP(31)|D_XO(695), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
- { "stfsx", D_OP(31)|D_XO(663), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
- { "sth", D_OP(44), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "sthbrx", D_OP(31)|D_XO(918), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "sthu", D_OP(45), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA },
- { "sthux", D_OP(31)|D_XO(439), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA },
- { "sthx", D_OP(31)|D_XO(407), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "stmw", D_OP(47), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "stswi", D_OP(31)|D_XO(725), M_RT|M_RA|M_NB, F_RT_RA_0_NB, 0 },
- { "stswx", D_OP(31)|D_XO(661), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "stw", D_OP(36), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
- { "stwbrx", D_OP(31)|D_XO(662), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "stwcx.", D_OP(31)|D_XO(150)|1, M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "stwu", D_OP(37), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA },
- { "stwux", D_OP(31)|D_XO(183), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA },
- { "stwx", D_OP(31)|D_XO(151), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
- { "subf", D_OP(31)|D_XO(40), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "subfc", D_OP(31)|D_XO(8), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "subfe", D_OP(31)|D_XO(136), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
- { "subfic", D_OP(8), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
- { "subfme", D_OP(31)|D_XO(232), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
- { "subfze", D_OP(31)|D_XO(200), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
- { "sync", D_OP(31)|D_XO(598), 0, F_NONE, 0 },
- { "tlbia", D_OP(31)|D_XO(370), 0, F_NONE, 0 },
- { "tlbie", D_OP(31)|D_XO(306), M_RB, F_RB, 0 },
- { "tlbsync",D_OP(31)|D_XO(566), 0, F_NONE, 0 },
- { "tw", D_OP(31)|D_XO(4), M_TO|M_RA|M_RB, F_TW, 0 },
- { "twi", D_OP(3), M_TO|M_RA|M_SIMM, F_TWI, 0 },
- { "wrtee", D_OP(31)|D_XO(131), M_RT, F_RT, 0 },
- { "wrteei", D_OP(31)|D_XO(163), 0, 0, 0 },
- { "xor", D_OP(31)|D_XO(316), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
- { "xori", D_OP(26), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
- { "xoris", D_OP(27), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
+ { "a", D_OP(31)|D_XO(10), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "abs", D_OP(31)|D_XO(360), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWER },
+ { "add", D_OP(31)|D_XO(266), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "addc", D_OP(31)|D_XO(10), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "adde", D_OP(31)|D_XO(138), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "addi", D_OP(14), M_RT|M_RA|M_SIMM, F_RT_RA_0_SIMM, 0, I_POWERPC },
+ { "addic", D_OP(12), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWERPC },
+ { "addic.", D_OP(13), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWERPC },
+ { "addis", D_OP(15), M_RT|M_RA|M_SIMM, F_ADDIS, 0, I_POWERPC },
+ { "addme", D_OP(31)|D_XO(234), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWERPC },
+ { "addze", D_OP(31)|D_XO(202), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWERPC },
+ { "ae", D_OP(31)|D_XO(138), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "ai", D_OP(12), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWER },
+ { "ai.", D_OP(13), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWER },
+ { "ame", D_OP(31)|D_XO(234), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWER },
+ { "and", D_OP(31)|D_XO(28), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "andc", D_OP(31)|D_XO(60), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "andi.", D_OP(28), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWERPC },
+ { "andil.", D_OP(28), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWER },
+ { "andis.", D_OP(29), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWERPC },
+ { "andiu.", D_OP(29), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWER },
+ { "aze", D_OP(31)|D_XO(202), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWER },
+ { "b", D_OP(18), M_LI|M_AA|M_LK, F_LI, FL_AA|FL_LK, I_COMMON },
+ { "bc", D_OP(16), M_BO|M_BI|M_BD|M_AA|M_LK, F_BCx, FL_AA|FL_LK, I_COMMON },
+ { "bcc", D_OP(19)|D_XO(528), M_BO|M_BI|M_LK, F_BO_BI, FL_LK, I_POWER },
+ { "bcctr", D_OP(19)|D_XO(528), M_BO|M_BI|M_LK, F_BO_BI, FL_LK, I_POWERPC },
+ { "bclr", D_OP(19)|D_XO(16), M_BO|M_BI|M_LK, F_BO_BI, FL_LK|FL_SO, I_POWERPC },
+ { "bcr", D_OP(19)|D_XO(16), M_BO|M_BI|M_LK, F_BO_BI, FL_LK|FL_SO, I_POWER },
+ { "cal", D_OP(14), M_RT|M_RA|M_SIMM, F_RT_D_RA_0, 0, I_POWER },
+ { "cau", D_OP(15), M_RT|M_RA|M_SIMM, F_ADDIS, 0, I_POWER },
+ { "cax", D_OP(31)|D_XO(266), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "clcs", D_OP(31)|D_XO(531), M_RT|M_RA, F_RT_RA, 0, I_POWER },
+ { "clf", D_OP(31)|D_XO(118), M_RA|M_RB, F_RA_0_RB, 0, I_POWER },
+ { "cli", D_OP(31)|D_XO(502), M_RA|M_RB, F_RA_0_RB, 0, I_POWER },
+ { "cmp", D_OP(31)|D_XO(0), M_CRFD|M_RA|M_RB, F_CMP, 0, I_COMMON },
+ { "cmpd", D_OP(31)|D_XO(0)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0, I_POWERPC },
+ { "cmpi", D_OP(11), M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0, I_COMMON },
+ { "cmpdi", D_OP(11)|M_L, M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0, I_POWERPC },
+ { "cmpl", D_OP(31)|D_XO(32), M_CRFD|M_RA|M_RB, F_CMP, 0, I_COMMON },
+ { "cmpld", D_OP(31)|D_XO(32)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0, I_POWERPC },
+ { "cmpli", D_OP(10), M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0, I_COMMON },
+ { "cmpldi", D_OP(10)|M_L, M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0, I_POWERPC },
+ { "cntlz", D_OP(31)|D_XO(26), M_RT|M_RA|M_RC, F_RA_RT, FL_RC, I_POWER },
+ { "cntlzw", D_OP(31)|D_XO(26), M_RT|M_RA|M_RC, F_RA_RT, FL_RC, I_POWERPC },
+ { "crand", D_OP(19)|D_XO(257), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "crandc", D_OP(19)|D_XO(129), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "creqv", D_OP(19)|D_XO(289), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "crnand", D_OP(19)|D_XO(225), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "crnor", D_OP(19)|D_XO(33), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "cror", D_OP(19)|D_XO(449), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "crorc", D_OP(19)|D_XO(417), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "crxor", D_OP(19)|D_XO(193), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0, I_COMMON },
+ { "dcba", D_OP(31)|D_XO(758), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dcbf", D_OP(31)|D_XO(86), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dcbi", D_OP(31)|D_XO(470), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dcbst", D_OP(31)|D_XO(54), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dcbt", D_OP(31)|D_XO(278), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dcbtst", D_OP(31)|D_XO(246), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dcbz", D_OP(31)|D_XO(1014),M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dclst", D_OP(31)|D_XO(630), M_RA|M_RB, F_RA_0_RB, 0, I_POWER },
+ { "dclz", D_OP(31)|D_XO(1014),M_RA|M_RB, F_RA_0_RB, 0, I_POWER },
+ { "dcs", D_OP(31)|D_XO(598), 0, F_NONE, 0, I_POWER },
+ { "dccci", D_OP(31)|D_XO(454), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "dcread", D_OP(31)|D_XO(486), M_RA|M_RB, F_RT_RA_RB, 0, I_POWERPC },
+ { "div", D_OP(31)|D_XO(331), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "divs", D_OP(31)|D_XO(363), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "divw", D_OP(31)|D_XO(491), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "divwu", D_OP(31)|D_XO(459), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "doz", D_OP(31)|D_XO(264), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "dozi", D_OP(9), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWER },
+ { "dsa", D_OP(31)|D_XO(628), 0, 0, 0, I_POWERPC },
+ { "eciwx", D_OP(31)|D_XO(310), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "ecowx", D_OP(31)|D_XO(438), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "eieio", D_OP(31)|D_XO(854), 0, F_NONE, 0, I_POWERPC },
+ { "eqv", D_OP(31)|D_XO(284), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "esa", D_OP(31)|D_XO(596), 0, 0, 0, I_POWERPC },
+ { "exts", D_OP(31)|D_XO(922), M_RT|M_RA|M_RC, F_RA_RT, FL_RC, I_POWER },
+ { "extsb", D_OP(31)|D_XO(954), M_RT|M_RA|M_RC, F_RA_RT, FL_RC, I_POWERPC },
+ { "extsh", D_OP(31)|D_XO(922), M_RT|M_RA|M_RC, F_RA_RT, FL_RC, I_POWERPC },
+ { "fa", D_OP(63)|D_XO(21), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWER },
+ { "fabs", D_OP(63)|D_XO(264), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_COMMON },
+ { "fadd", D_OP(63)|D_XO(21), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWERPC },
+ { "fadds", D_OP(59)|D_XO(21), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWERPC },
+ { "fcir", D_OP(63)|D_XO(14), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWER },
+ { "fcirz", D_OP(63)|D_XO(15), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWER },
+ { "fcmpo", D_OP(63)|D_XO(32), M_CRFD|M_RA|M_RB, F_FCMP, 0, I_COMMON },
+ { "fcmpu", D_OP(63)|D_XO(0), M_CRFD|M_RA|M_RB, F_FCMP, 0, I_COMMON },
+ { "fctiw", D_OP(63)|D_XO(14), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWERPC },
+ { "fctiwz", D_OP(63)|D_XO(15), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWERPC },
+ { "fd", D_OP(63)|D_XO(18), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWER },
+ { "fdiv", D_OP(63)|D_XO(18), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWERPC },
+ { "fdivs", D_OP(59)|D_XO(18), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWERPC },
+ { "fm", D_OP(63)|D_XO(25), M_RT|M_RA|M_REGC|M_RC, F_FRT_FRA_FRC, FL_RC, I_POWER },
+ { "fma", D_OP(63)|D_XO(29), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWER },
+ { "fmadd", D_OP(63)|D_XO(29), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fmadds", D_OP(59)|D_XO(29), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fmr", D_OP(63)|D_XO(72), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_COMMON },
+ { "fms", D_OP(63)|D_XO(28), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWER },
+ { "fmsub", D_OP(63)|D_XO(28), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fmsubs", D_OP(59)|D_XO(28), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fmul", D_OP(63)|D_XO(25), M_RT|M_RA|M_REGC|M_RC, F_FRT_FRA_FRC, FL_RC, I_POWERPC },
+ { "fmuls", D_OP(59)|D_XO(25), M_RT|M_RA|M_REGC|M_RC, F_FRT_FRA_FRC, FL_RC, I_POWERPC },
+ { "fnabs", D_OP(63)|D_XO(136), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_COMMON },
+ { "fneg", D_OP(63)|D_XO(40), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_COMMON },
+ { "fnma", D_OP(63)|D_XO(31), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWER },
+ { "fnmadd", D_OP(63)|D_XO(31), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fnmadds",D_OP(59)|D_XO(31), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fnms", D_OP(63)|D_XO(30), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWER },
+ { "fnmsub", D_OP(63)|D_XO(30), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fnmsubs",D_OP(59)|D_XO(30), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fres", D_OP(59)|D_XO(24), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWERPC },
+ { "frsp", D_OP(63)|D_XO(12), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_COMMON },
+ { "frsqrte",D_OP(63)|D_XO(26), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWERPC },
+ { "fs", D_OP(63)|D_XO(20), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWER },
+ { "fsel", D_OP(63)|D_XO(23), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC, I_POWERPC },
+ { "fsqrt", D_OP(63)|D_XO(22), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWERPC },
+ { "fsqrts", D_OP(59)|D_XO(22), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC, I_POWERPC },
+ { "fsub", D_OP(63)|D_XO(20), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWERPC },
+ { "fsubs", D_OP(59)|D_XO(20), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC, I_POWERPC },
+ { "icbi", D_OP(31)|D_XO(982), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "icbt", D_OP(31)|D_XO(262), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "iccci", D_OP(31)|D_XO(966), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "icread", D_OP(31)|D_XO(998), M_RA|M_RB, F_RA_0_RB, 0, I_POWERPC },
+ { "ics", D_OP(19)|D_XO(150), 0, F_NONE, 0, I_POWER },
+ { "isync", D_OP(19)|D_XO(150), 0, F_NONE, 0, I_POWERPC },
+ { "l", D_OP(32), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWER },
+ { "lbz", D_OP(34), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_COMMON },
+ { "lbzu", D_OP(35), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT, I_COMMON },
+ { "lbzux", D_OP(31)|D_XO(119), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT, I_COMMON },
+ { "lbzx", D_OP(31)|D_XO(87), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_COMMON },
+ { "lfd", D_OP(50), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_COMMON },
+ { "lfdu", D_OP(51), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA, I_COMMON },
+ { "lfdux", D_OP(31)|D_XO(631), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA, I_COMMON },
+ { "lfdx", D_OP(31)|D_XO(599), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_COMMON },
+ { "lfs", D_OP(48), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_COMMON },
+ { "lfsu", D_OP(49), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA, I_COMMON },
+ { "lfsux", D_OP(31)|D_XO(567), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA, I_COMMON },
+ { "lfsx", D_OP(31)|D_XO(535), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_COMMON },
+ { "lha", D_OP(42), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_COMMON },
+ { "lhau", D_OP(43), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT, I_COMMON },
+ { "lhaux", D_OP(31)|D_XO(375), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT, I_COMMON },
+ { "lhax", D_OP(31)|D_XO(343), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_COMMON },
+ { "lhbrx", D_OP(31)|D_XO(790), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_COMMON },
+ { "lhz", D_OP(40), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_COMMON },
+ { "lhzu", D_OP(41), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT, I_COMMON },
+ { "lhzux", D_OP(31)|D_XO(311), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT, I_COMMON },
+ { "lhzx", D_OP(31)|D_XO(279), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_COMMON },
+ { "lm", D_OP(46), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWER },
+ { "lmw", D_OP(46), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWERPC },
+ { "lscbx", D_OP(31)|D_XO(277), M_RT|M_RA|M_RB|M_RC, F_RT_RA_0_RB, FL_RC, I_POWER },
+ { "lsi", D_OP(31)|D_XO(597), M_RT|M_RA|M_NB, F_RT_RA_0_NB, FL_CHECK_LSWI, I_POWER },
+ { "lswi", D_OP(31)|D_XO(597), M_RT|M_RA|M_NB, F_RT_RA_0_NB, FL_CHECK_LSWI, I_POWERPC },
+ { "lswx", D_OP(31)|D_XO(533), M_RT|M_RA|M_RB, F_RT_RA_0_RB, FL_CHECK_LSWX, I_POWERPC },
+ { "lsx", D_OP(31)|D_XO(533), M_RT|M_RA|M_RB, F_RT_RA_0_RB, FL_CHECK_LSWX, I_POWER },
+ { "lu", D_OP(33), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT, I_POWER },
+ { "lux", D_OP(31)|D_XO(55), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT, I_POWER },
+ { "lwarx", D_OP(31)|D_XO(20), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "lwbrx", D_OP(31)|D_XO(534), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "lwz", D_OP(32), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWERPC },
+ { "lwzu", D_OP(33), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT, I_POWERPC },
+ { "lwzux", D_OP(31)|D_XO(55), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT, I_POWERPC },
+ { "lwzx", D_OP(31)|D_XO(23), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "lx", D_OP(31)|D_XO(23), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWER },
+ { "maskg", D_OP(31)|D_XO(29), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "maskir", D_OP(31)|D_XO(541), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "mcrf", D_OP(19)|D_XO(0), M_CRFD|M_CRFS, F_CRFD_CRFS, 0, I_COMMON },
+ { "mcrfs", D_OP(63)|D_XO(64), M_CRFD|M_CRFS, F_CRFD_CRFS, 0, I_COMMON },
+ { "mcrxr", D_OP(31)|D_XO(512), M_CRFD, F_MCRXR, 0, I_COMMON },
+ { "mfcr", D_OP(31)|D_XO(19), M_RT, F_RT, 0, I_COMMON },
+ { "mfdcr", D_OP(31)|D_XO(323), M_RT|M_DCR, F_RT_DCR, 0, I_POWERPC },
+ { "mffs", D_OP(63)|D_XO(583), M_RT|M_RC, F_MFFSx, FL_RC, I_COMMON },
+ { "mfmsr", D_OP(31)|D_XO(83), M_RT, F_RT, 0, I_COMMON },
+ { "mfspr", D_OP(31)|D_XO(339), M_RT|M_SPR, F_RT_SPR, 0, I_COMMON },
+ { "mfsr", D_OP(31)|D_XO(595), M_RT|M_SR, F_MFSR, 0, I_COMMON },
+ { "mfsri", D_OP(31)|D_XO(627), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWER },
+ { "mfsrin", D_OP(31)|D_XO(659), M_RT|M_RB, F_RT_RB, 0, I_POWERPC },
+ { "mftb", D_OP(31)|D_XO(371), M_RT|M_TBR, F_RT_SPR, 0, I_POWERPC },
+ { "mtcrf", D_OP(31)|D_XO(144), M_RT|M_CRM, F_MTCRF, 0, I_COMMON },
+ { "mtdcr", D_OP(31)|D_XO(451), M_RT|M_DCR, F_MTDCR, 0, I_POWERPC },
+ { "mtfsb0", D_OP(63)|D_XO(70), M_CRBD|M_RC, F_FCRBD, FL_RC, I_COMMON },
+ { "mtfsb1", D_OP(63)|D_XO(38), M_CRBD|M_RC, F_FCRBD, FL_RC, I_COMMON },
+ { "mtfsf", D_OP(63)|D_XO(711), M_FM|M_RB|M_RC, F_MTFSFx, FL_RC, I_COMMON },
+ { "mtfsfi", D_OP(63)|D_XO(134), M_CRFD|M_IMM|M_RC, F_MTFSFIx, FL_RC, I_COMMON },
+ { "mtmsr", D_OP(31)|D_XO(146), M_RT, F_RT, 0, I_COMMON },
+ { "mtspr", D_OP(31)|D_XO(467), M_RT|M_SPR, F_MTSPR, 0, I_COMMON },
+ { "mtsr", D_OP(31)|D_XO(210), M_RT|M_SR, F_MTSR, 0, I_COMMON },
+ { "mtsri", D_OP(31)|D_XO(242), M_RT|M_RB, F_RT_RB, 0, I_POWER },
+ { "mtsrin", D_OP(31)|D_XO(242), M_RT|M_RB, F_RT_RB, 0, I_POWERPC },
+ { "mul", D_OP(31)|D_XO(107), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "mulhw", D_OP(31)|D_XO(75), M_RT|M_RA|M_RB|M_RC, F_RT_RA_RB, FL_RC, I_POWERPC },
+ { "mulhwu", D_OP(31)|D_XO(11), M_RT|M_RA|M_RB|M_RC, F_RT_RA_RB, FL_RC, I_POWERPC },
+ { "muli", D_OP(7), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWER },
+ { "mulli", D_OP(7), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWERPC },
+ { "mullw", D_OP(31)|D_XO(235), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "muls", D_OP(31)|D_XO(235), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "nabs", D_OP(31)|D_XO(488), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWER },
+ { "nand", D_OP(31)|D_XO(476), M_RA|M_RT|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "neg", D_OP(31)|D_XO(104), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_COMMON },
+ { "nor", D_OP(31)|D_XO(124), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "or", D_OP(31)|D_XO(444), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "orc", D_OP(31)|D_XO(412), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "ori", D_OP(24), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWERPC },
+ { "oril", D_OP(24), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWER },
+ { "oris", D_OP(25), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWERPC },
+ { "oriu", D_OP(25), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWER },
+ { "rac", D_OP(31)|D_XO(818), M_RT|M_RA|M_RB|M_RC, F_RT_RA_0_RB, FL_RC, I_POWER },
+ { "rfi", D_OP(19)|D_XO(50), 0, F_NONE, FL_SO, I_COMMON },
+ { "rfci", D_OP(19)|D_XO(51), 0, F_NONE, FL_SO, I_POWERPC },
+ { "rfsvc", D_OP(19)|D_XO(82), M_LK, F_NONE, FL_LK|FL_SO, I_POWER },
+ { "rlimi", D_OP(20), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC, I_POWER },
+ { "rlinm", D_OP(21), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC, I_POWER },
+ { "rlmi", D_OP(22), M_RT|M_RA|M_RB|M_MB|M_ME|M_RC, F_RA_RT_RB_MB_ME, FL_RC, I_POWER },
+ { "rlnm", D_OP(23), M_RT|M_RA|M_RB|M_MB|M_ME|M_RC, F_RA_RT_RB_MB_ME, FL_RC, I_POWER },
+ { "rlwimi", D_OP(20), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC, I_POWERPC },
+ { "rlwinm", D_OP(21), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC, I_POWERPC },
+ { "rlwnm", D_OP(23), M_RT|M_RA|M_RB|M_MB|M_ME|M_RC, F_RA_RT_RB_MB_ME, FL_RC, I_POWERPC },
+ { "rrib", D_OP(31)|D_XO(537), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sc", D_OP(17)|2, 0, F_NONE, 0, I_POWERPC },
+ { "sf", D_OP(31)|D_XO(8), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "sfe", D_OP(31)|D_XO(136), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWER },
+ { "sfi", D_OP(8), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWER },
+ { "sfme", D_OP(31)|D_XO(232), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWER },
+ { "sfze", D_OP(31)|D_XO(200), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWER },
+ { "sl", D_OP(31)|D_XO(24), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sle", D_OP(31)|D_XO(153), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sleq", D_OP(31)|D_XO(217), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sliq", D_OP(31)|D_XO(184), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC, I_POWER },
+ { "slliq", D_OP(31)|D_XO(248), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC, I_POWER },
+ { "sllq", D_OP(31)|D_XO(216), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "slq", D_OP(31)|D_XO(152), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "slw", D_OP(31)|D_XO(24), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWERPC },
+ { "sr", D_OP(31)|D_XO(536), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sra", D_OP(31)|D_XO(792), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "srai", D_OP(31)|D_XO(824), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC, I_POWER },
+ { "sraiq", D_OP(31)|D_XO(952), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC, I_POWER },
+ { "sraq", D_OP(31)|D_XO(920), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sraw", D_OP(31)|D_XO(792), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWERPC },
+ { "srawi", D_OP(31)|D_XO(824), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC, I_POWERPC },
+ { "sre", D_OP(31)|D_XO(665), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "srea", D_OP(31)|D_XO(921), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sreq", D_OP(31)|D_XO(729), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "sriq", D_OP(31)|D_XO(696), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC, I_POWER },
+ { "srliq", D_OP(31)|D_XO(184), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC, I_POWER },
+ { "srlq", D_OP(31)|D_XO(728), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "srq", D_OP(31)|D_XO(664), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWER },
+ { "srw", D_OP(31)|D_XO(536), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_POWERPC },
+ { "st", D_OP(36), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWER },
+ { "stb", D_OP(38), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_COMMON },
+ { "stbrx", D_OP(31)|D_XO(662), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWER },
+ { "stbu", D_OP(39), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA, I_COMMON },
+ { "stbux", D_OP(31)|D_XO(247), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA, I_COMMON },
+ { "stbx", D_OP(31)|D_XO(215), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_COMMON },
+ { "stfd", D_OP(54), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_COMMON },
+ { "stfdu", D_OP(55), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA, I_COMMON },
+ { "stfdux", D_OP(31)|D_XO(759), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA, I_COMMON },
+ { "stfdx", D_OP(31)|D_XO(727), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_COMMON },
+ { "stfiwx", D_OP(31)|D_XO(983), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_POWERPC },
+ { "stfs", D_OP(52), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_COMMON },
+ { "stfsu", D_OP(53), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA, I_COMMON },
+ { "stfsux", D_OP(31)|D_XO(695), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA, I_COMMON },
+ { "stfsx", D_OP(31)|D_XO(663), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_COMMON },
+ { "sth", D_OP(44), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_COMMON },
+ { "sthbrx", D_OP(31)|D_XO(918), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_COMMON },
+ { "sthu", D_OP(45), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA, I_COMMON },
+ { "sthux", D_OP(31)|D_XO(439), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA, I_COMMON },
+ { "sthx", D_OP(31)|D_XO(407), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_COMMON },
+ { "stm", D_OP(47), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWER },
+ { "stmw", D_OP(47), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWERPC },
+ { "stsi", D_OP(31)|D_XO(725), M_RT|M_RA|M_NB, F_RT_RA_0_NB, 0, I_POWER },
+ { "stswi", D_OP(31)|D_XO(725), M_RT|M_RA|M_NB, F_RT_RA_0_NB, 0, I_POWERPC },
+ { "stswx", D_OP(31)|D_XO(661), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "stsx", D_OP(31)|D_XO(661), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWER },
+ { "stu", D_OP(37), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA, I_POWER },
+ { "stux", D_OP(31)|D_XO(183), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA, I_POWER },
+ { "stw", D_OP(36), M_RT|M_RA|M_D, F_RT_D_RA_0, 0, I_POWERPC },
+ { "stwbrx", D_OP(31)|D_XO(662), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "stwcx.", D_OP(31)|D_XO(150)|1, M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "stwu", D_OP(37), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA, I_POWERPC },
+ { "stwux", D_OP(31)|D_XO(183), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA, I_POWERPC },
+ { "stwx", D_OP(31)|D_XO(151), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWERPC },
+ { "stx", D_OP(31)|D_XO(151), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0, I_POWER },
+ { "subf", D_OP(31)|D_XO(40), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "subfc", D_OP(31)|D_XO(8), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "subfe", D_OP(31)|D_XO(136), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC, I_POWERPC },
+ { "subfic", D_OP(8), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0, I_POWERPC },
+ { "subfme", D_OP(31)|D_XO(232), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWERPC },
+ { "subfze", D_OP(31)|D_XO(200), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC, I_POWERPC },
+ { "svc", D_OP(17)|2, M_BD|M_AA|M_LK, F_SC, FL_AA|FL_LK, I_POWER },
+ { "sync", D_OP(31)|D_XO(598), 0, F_NONE, 0, I_POWERPC },
+ { "t", D_OP(31)|D_XO(4), M_TO|M_RA|M_RB, F_TW, 0, I_POWER },
+ { "ti", D_OP(3), M_TO|M_RA|M_SIMM, F_TWI, 0, I_POWER },
+ { "tlbi", D_OP(31)|D_XO(306), M_RB, F_RB, 0, I_POWER },
+ { "tlbia", D_OP(31)|D_XO(370), 0, F_NONE, 0, I_POWERPC },
+ { "tlbie", D_OP(31)|D_XO(306), M_RB, F_RB, 0, I_POWERPC },
+ { "tlbsync",D_OP(31)|D_XO(566), 0, F_NONE, 0, I_POWERPC },
+ { "tw", D_OP(31)|D_XO(4), M_TO|M_RA|M_RB, F_TW, 0, I_POWERPC },
+ { "twi", D_OP(3), M_TO|M_RA|M_SIMM, F_TWI, 0, I_POWERPC },
+ { "wrtee", D_OP(31)|D_XO(131), M_RT, F_RT, 0, I_POWERPC },
+ { "wrteei", D_OP(31)|D_XO(163), 0, 0, 0, I_POWERPC },
+ { "xor", D_OP(31)|D_XO(316), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC, I_COMMON },
+ { "xori", D_OP(26), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWERPC },
+ { "xoril", D_OP(26), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWER },
+ { "xoris", D_OP(27), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWERPC },
+ { "xoriu", D_OP(27), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0, I_POWER },
/*
* PowerPC 603e/EC603e-specific instructions
*/
- { "tlbld", D_OP(31)|D_XO(978), M_RB, F_RB, 0 },
- { "tlbli", D_OP(31)|D_XO(1010),M_RB, F_RB, 0 }
+ { "tlbld", D_OP(31)|D_XO(978), M_RB, F_RB, 0, I_POWERPC },
+ { "tlbli", D_OP(31)|D_XO(1010),M_RB, F_RB, 0, I_POWERPC },
+
+ // POWER2 instructions
+ { "lfq", D_OP(56), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_POWER },
+ { "lfqu", D_OP(57), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_POWER },
+ { "lfqux", D_OP(31)|D_XO(823), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_POWER },
+ { "lfqx", D_OP(31)|D_XO(791), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_POWER },
+ { "stfq", D_OP(60), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_POWER },
+ { "stfqu", D_OP(61), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0, I_POWER },
+ { "stfqux", D_OP(31)|D_XO(951), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_POWER },
+ { "stfqx", D_OP(31)|D_XO(919), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0, I_POWER },
};
/*
@@ -360,6 +472,12 @@ std::string powerpc_disassembler::SPR(int spr_field)
case SPR4XX_PBL2: return "pbl2";
case SPR4XX_PBU2: return "pbu2";
+ // POWER SPR indexes
+ case 0: return "mq";
+ case 4: return "rtcu";
+ case 5: return "rtcl";
+ case 6: return "dec";
+
default: return util::string_format("%d", spr);
}
}
@@ -441,8 +559,8 @@ std::string powerpc_disassembler::DecodeSigned16(uint32_t op, int do_unsigned)
int16_t s;
s = G_SIMM(op);
- if (do_unsigned) // sign extend to unsigned 32-bits
- return util::string_format("0x%04X", (uint32_t) s);
+ if (do_unsigned)
+ return util::string_format("0x%04X", (uint16_t) s);
else // print as signed 16 bits
{
if (s < 0)
@@ -461,24 +579,11 @@ std::string powerpc_disassembler::DecodeSigned16(uint32_t op, int do_unsigned)
* Generate a mask from bit MB through ME (PPC-style backwards bit numbering.)
*/
-uint32_t powerpc_disassembler::Mask(int mb, int me)
+uint32_t powerpc_disassembler::Mask(unsigned const mb, unsigned const me)
{
- uint32_t i, mask;
-
- mb &= 31;
- me &= 31;
-
- i = mb;
- mask = 0;
- while (1)
- {
- mask |= (1 << (31 - i));
- if (i == me)
- break;
- i = (i + 1) & 31;
- }
-
- return mask;
+ return (mb > me) ?
+ (0xffffffffU >> mb) | (0xffffffffU << (31 - me)) :
+ (0xffffffffU >> mb) & (0xffffffffU << (31 - me));
}
/*
@@ -488,7 +593,7 @@ uint32_t powerpc_disassembler::Mask(int mb, int me)
* otherwise false to indicate disassembly should carry on as normal.
*/
-bool powerpc_disassembler::Simplified(uint32_t op, uint32_t vpc, std::string &signed16, std::string &mnem, std::string &oprs)
+bool powerpc_disassembler::Simplified(uint32_t op, uint32_t vpc, std::string &signed16, std::string &mnem, std::string &oprs, offs_t &flags)
{
uint32_t value, disp;
@@ -558,35 +663,11 @@ bool powerpc_disassembler::Simplified(uint32_t op, uint32_t vpc, std::string &si
mnem += "xori"; // xoris rA,rT,UIMM -> xori rA,rT,UIMM<<16
oprs = util::string_format("r%d,r%d,0x%08X", G_RA(op), G_RT(op), G_UIMM(op) << 16);
}
- else if ((op & ~(M_RT|M_RA|M_SH|M_MB|M_ME|M_RC)) == D_OP(20))
- {
- value = Mask(G_MB(op), G_ME(op));
- mnem += "rlwimi"; // rlwimi[.] rA,rT,SH,MB,ME -> rlwimi[.] rA,rT,SH,MASK
- if (op & M_RC) mnem += ".";
- oprs = util::string_format("r%d,r%d,%d,0x%08X", G_RA(op), G_RT(op), G_SH(op), value);
- }
- else if ((op & ~(M_RT|M_RA|M_SH|M_MB|M_ME|M_RC)) == D_OP(21))
- {
- value = Mask(G_MB(op), G_ME(op));
- if (G_SH(op) == 0) // rlwinm[.] rA,rT,0,MB,ME -> and[.] rA,rT,MASK
- {
- mnem += "and";
- if (op & M_RC) mnem += ".";
- oprs = util::string_format("r%d,r%d,0x%08X", G_RA(op), G_RT(op), value);
- }
- else // rlwinm[.] rA,rT,SH,MASK
- {
- mnem += "rlwinm";
- if (op & M_RC) mnem += ".";
- oprs = util::string_format("r%d,r%d,%d,0x%08X", G_RA(op), G_RT(op), G_SH(op), value);
- }
- }
- else if ((op & ~(M_RT|M_RA|M_RB|M_MB|M_ME|M_RC)) == D_OP(23))
+ else if ((op & ~(M_RT|M_RA|M_SH|M_MB|M_ME|M_RC)) == D_OP(21) && G_SH(op) == 0)
{
- value = Mask(G_MB(op), G_ME(op));
- mnem += "rlwnm"; // rlwnm[.] rA,rT,SH,MB,ME -> rlwnm[.] rA,rT,SH,MASK
+ mnem += "and"; // rl[w]inm[.] rA,rT,0,MB,ME -> and[.] rA,rT,MASK
if (op & M_RC) mnem += ".";
- oprs = util::string_format("r%d,r%d,r%d,0x%08X", G_RA(op), G_RT(op), G_RB(op), value);
+ oprs = util::string_format("r%d,r%d,0x%08X", G_RA(op), G_RT(op), Mask(G_MB(op), G_ME(op)));
}
else if ((op & ~(M_BO|M_BI|M_BD|M_AA|M_LK)) == D_OP(16))
{
@@ -599,16 +680,20 @@ bool powerpc_disassembler::Simplified(uint32_t op, uint32_t vpc, std::string &si
case 0x04: case 0x05: case 0x06: case 0x07:
mnem += "b";
mnem += crnbit[G_BI(op) & 3];
+ flags |= STEP_COND;
break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
mnem += "b";
mnem += crbit[G_BI(op) & 3];
+ flags |= STEP_COND;
break;
case 0x10: case 0x11: case 0x18: case 0x19:
mnem += "bdnz";
+ flags |= STEP_COND;
break;
case 0x12: case 0x13: case 0x1a: case 0x1b:
mnem += "bdz";
+ flags |= STEP_COND;
break;
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
@@ -618,7 +703,11 @@ bool powerpc_disassembler::Simplified(uint32_t op, uint32_t vpc, std::string &si
return false;
}
- if (op & M_LK) mnem += "l";
+ if (op & M_LK)
+ {
+ mnem += "l";
+ flags |= STEP_OVER;
+ }
if (op & M_AA) mnem += "a";
if (!(G_BO(op) & 0x10) && G_BI(op) / 4 != 0)
@@ -633,16 +722,20 @@ bool powerpc_disassembler::Simplified(uint32_t op, uint32_t vpc, std::string &si
case 0x04: case 0x05: case 0x06: case 0x07:
mnem += "b";
mnem += crnbit[G_BI(op) & 3];
+ flags |= STEP_COND;
break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
mnem += "b";
mnem += crbit[G_BI(op) & 3];
+ flags |= STEP_COND;
break;
case 0x10: case 0x11: case 0x18: case 0x19:
mnem += "bdnz";
+ flags |= STEP_COND;
break;
case 0x12: case 0x13: case 0x1a: case 0x1b:
mnem += "bdz";
+ flags |= STEP_COND;
break;
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
@@ -652,8 +745,19 @@ bool powerpc_disassembler::Simplified(uint32_t op, uint32_t vpc, std::string &si
return false;
}
- mnem += (G_XO(op) == 528) ? "ctr" : "lr";
- if (op & M_LK) mnem += "l";
+ if (G_XO(op) == 528)
+ mnem += "ctr";
+ else
+ {
+ mnem += "lr";
+ if (!(op & M_LK))
+ flags |= STEP_OUT;
+ }
+ if (op & M_LK)
+ {
+ mnem += "l";
+ flags |= STEP_OVER;
+ }
if (op & M_AA) mnem += "a";
if (!(G_BO(op) & 0x10) && G_BI(op) / 4 != 0)
@@ -696,7 +800,7 @@ offs_t powerpc_disassembler::dasm_one(std::ostream &stream, uint32_t pc, uint32_
* Try simplified forms first, then real instructions
*/
- if( Simplified(op, pc, signed16, mnem, oprs) ) {
+ if( Simplified(op, pc, signed16, mnem, oprs, flags) ) {
util::stream_format(stream, "%s", mnem);
for( j = mnem.size(); j < 10; j++ ) {
util::stream_format(stream, " ");
@@ -711,7 +815,7 @@ offs_t powerpc_disassembler::dasm_one(std::ostream &stream, uint32_t pc, uint32_
for (i = 0; i < sizeof(itab) / sizeof(IDESCR); i++)
{
- if ((op & ~itab[i].mask) == itab[i].match) // check for match
+ if ((itab[i].implementation & m_implementation) && (op & ~itab[i].mask) == itab[i].match) // check for match
{
/*
* Base mnemonic followed be O, ., L, A
@@ -764,21 +868,19 @@ offs_t powerpc_disassembler::dasm_one(std::ostream &stream, uint32_t pc, uint32_
break;
case F_LI:
- disp = G_LI(op) * 4;
- if (disp & 0x02000000) // sign extend
- disp |= 0xfc000000;
+ disp = util::sext(G_LI(op) * 4, 26);
oprs = util::string_format("0x%08X", disp + ((op & M_AA) ? 0 : pc));
break;
case F_BCx:
- disp = G_BD(op) * 4;
- if (disp & 0x00008000)
- disp |= 0xffff0000;
+ disp = util::sext(G_BD(op) * 4, 16);
if (G_BO(op) & 0x10) // BI is ignored (don't print CR bit)
oprs = util::string_format("0x%02X,%d,0x%08X", G_BO(op), G_BI(op), disp + ((op & M_AA) ? 0 : pc));
else // BI gives us the condition bit
oprs = util::string_format("0x%02X,cr%d[%s],0x%08X", G_BO(op), G_BI(op) / 4, crbit[G_BI(op) & 3], disp + ((op & M_AA) ? 0 : pc));
+ if ((G_BO(op) & 0x14) != 0x14)
+ flags |= STEP_COND;
break;
case F_BO_BI:
@@ -786,6 +888,8 @@ offs_t powerpc_disassembler::dasm_one(std::ostream &stream, uint32_t pc, uint32_
oprs = util::string_format("0x%02X,%d", G_BO(op), G_BI(op));
else
oprs = util::string_format("0x%02X,cr%d[%s]", G_BO(op), G_BI(op) / 4, crbit[G_BI(op) & 3]);
+ if ((G_BO(op) & 0x14) != 0x14)
+ flags |= STEP_COND;
break;
case F_CMP:
@@ -958,11 +1062,11 @@ offs_t powerpc_disassembler::dasm_one(std::ostream &stream, uint32_t pc, uint32_
break;
case F_RA_RT_SH_MB_ME:
- oprs = util::string_format("r%d,r%d,%d,%d,%d", G_RA(op), G_RT(op), G_SH(op), G_MB(op), G_ME(op));
+ oprs = util::string_format("r%d,r%d,%d,0x%08X", G_RA(op), G_RT(op), G_SH(op), Mask(G_MB(op), G_ME(op)));
break;
- case F_RLWNMx:
- oprs = util::string_format("r%d,r%d,r%d,%d,%d", G_RA(op), G_RT(op), G_RB(op), G_MB(op), G_ME(op));
+ case F_RA_RT_RB_MB_ME:
+ oprs = util::string_format("r%d,r%d,r%d,0x%08X", G_RA(op), G_RT(op), G_RB(op), Mask(G_MB(op), G_ME(op)));
break;
case F_SRAWIx:
@@ -981,7 +1085,18 @@ offs_t powerpc_disassembler::dasm_one(std::ostream &stream, uint32_t pc, uint32_
oprs = util::string_format("%d,r%d,%s", G_TO(op), G_RA(op), signed16);
break;
+ case F_SC:
+ if (op & M_AA)
+ oprs = util::string_format("0x%04X", (op & 0x0000fffc) >> 2);
+ else
+ oprs = util::string_format("%d,%d,%d", (op & 0x00000fe0) >> 5, (op & 0x0000f000) >> 12, (op & 0x0000001c) >> 2);
+ break;
+
case F_NONE:
+ if ((op >> 26) == 17) // SC (PowerPC)
+ flags |= STEP_OVER;
+ [[fallthrough]];
+
default:
break;
}
diff --git a/src/devices/cpu/powerpc/ppc_dasm.h b/src/devices/cpu/powerpc/ppc_dasm.h
index 5fab7dfe074..1f5ff6dba00 100644
--- a/src/devices/cpu/powerpc/ppc_dasm.h
+++ b/src/devices/cpu/powerpc/ppc_dasm.h
@@ -20,15 +20,25 @@
#pragma once
+
class powerpc_disassembler : public util::disasm_interface
{
public:
- powerpc_disassembler() = default;
+ enum implementation : int
+ {
+ I_POWER = 1 << 0,
+ I_POWERPC = 1 << 1,
+ };
+
+ powerpc_disassembler(implementation impl = I_POWERPC)
+ : m_implementation(impl)
+ {
+ };
virtual ~powerpc_disassembler() = default;
virtual u32 opcode_alignment() const override;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
- static offs_t dasm_one(std::ostream &stream, uint32_t pc, uint32_t op);
+ offs_t dasm_one(std::ostream &stream, uint32_t pc, uint32_t op);
private:
/*
@@ -91,8 +101,9 @@ private:
F_FRT_FRA_FRB, // frT, frA, frB
F_FRT_FRA_FRC, // frT, frA, frC
F_RA_RT_SH_MB_ME, // rA, rT, SH, MB, ME
- F_RLWNMx, // rT, rA, rB, MB, ME only used by RLWNMx
- F_RT_RB // rT, rB
+ F_RA_RT_RB_MB_ME, // rA, rT, rB, MB, ME
+ F_RT_RB, // rT, rB
+ F_SC // LEV, FL1, FL2 or SV only used by SVC (POWER)
};
/*
@@ -126,6 +137,7 @@ private:
// bit pattern to determine a match)
int format; // operand format
int flags; // flags
+ int implementation;
};
static const IDESCR itab[];
@@ -135,8 +147,19 @@ private:
static std::string SPR(int spr_field);
static std::string DCR(int dcr_field);
static std::string DecodeSigned16(uint32_t op, int do_unsigned);
- static uint32_t Mask(int mb, int me);
- static bool Simplified(uint32_t op, uint32_t vpc, std::string &signed16, std::string &mnem, std::string &oprs);
+ static uint32_t Mask(unsigned const mb, unsigned const me);
+ bool Simplified(uint32_t op, uint32_t vpc, std::string &signed16, std::string &mnem, std::string &oprs, offs_t &flags);
+
+ implementation const m_implementation;
+};
+
+class power_disassembler : public powerpc_disassembler
+{
+public:
+ power_disassembler()
+ : powerpc_disassembler(implementation::I_POWER)
+ {
+ };
};
#endif
diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp
index 4a8a071f903..4e76a3efbb2 100644
--- a/src/devices/cpu/powerpc/ppccom.cpp
+++ b/src/devices/cpu/powerpc/ppccom.cpp
@@ -205,6 +205,8 @@ DEFINE_DEVICE_TYPE(MPC8240, mpc8240_device, "mpc8240", "IBM PowerPC MPC82
DEFINE_DEVICE_TYPE(PPC403GA, ppc403ga_device, "ppc403ga", "IBM PowerPC 403GA")
DEFINE_DEVICE_TYPE(PPC403GCX, ppc403gcx_device, "ppc403gcx", "IBM PowerPC 403GCX")
DEFINE_DEVICE_TYPE(PPC405GP, ppc405gp_device, "ppc405gp", "IBM PowerPC 405GP")
+DEFINE_DEVICE_TYPE(PPC740, ppc740_device, "ppc740", "IBM PowerPC 740")
+DEFINE_DEVICE_TYPE(PPC750, ppc750_device, "ppc750", "IBM PowerPC 750")
ppc_device::ppc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int address_bits, int data_bits, powerpc_flavor flavor, uint32_t cap, uint32_t tb_divisor, address_map_constructor internal_map)
@@ -212,15 +214,23 @@ ppc_device::ppc_device(const machine_config &mconfig, device_type type, const ch
, device_vtlb_interface(mconfig, *this, AS_PROGRAM)
, m_program_config("program", ENDIANNESS_BIG, data_bits, address_bits, 0, internal_map)
, c_bus_frequency(0)
+ , c_serial_clock(0)
, m_core(nullptr)
, m_bus_freq_multiplier(1)
, m_flavor(flavor)
, m_cap(cap)
, m_tb_divisor(tb_divisor)
+ , m_spu(*this)
+ , m_dcr_read_func(*this)
+ , m_dcr_write_func(*this)
+ , m_dcstore_cb(*this)
+ , m_ext_dma_read_cb(*this)
+ , m_ext_dma_write_cb(*this)
, m_cache(CACHE_SIZE + sizeof(internal_ppc_state))
, m_drcuml(nullptr)
, m_drcfe(nullptr)
, m_drcoptions(0)
+ , m_dasm(powerpc_disassembler())
{
m_program_config.m_logaddr_width = 32;
m_program_config.m_page_shift = POWERPC_MIN_PAGE_SHIFT;
@@ -271,15 +281,31 @@ mpc8240_device::mpc8240_device(const machine_config &mconfig, const char *tag, d
}
ppc601_device::ppc601_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : ppc_device(mconfig, PPC601, tag, owner, clock, 32, 64, PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_MFIOC | PPCCAP_601BAT, 0/* no TB */, address_map_constructor())
+ : ppc_device(mconfig, PPC601, tag, owner, clock, 32, 64, PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_MFIOC | PPCCAP_601BAT | PPCCAP_LEGACY_POWER, 0 /* no TB */, address_map_constructor())
{
}
+std::unique_ptr<util::disasm_interface> ppc601_device::create_disassembler()
+{
+ // 601 has both POWER and PowerPC instructions
+ return std::make_unique<powerpc_disassembler>((powerpc_disassembler::implementation)(powerpc_disassembler::I_POWER|powerpc_disassembler::I_POWERPC));
+}
+
ppc604_device::ppc604_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: ppc_device(mconfig, PPC604, tag, owner, clock, 32, 64, PPC_MODEL_604, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_604_MMU, 4, address_map_constructor())
{
}
+ppc740_device::ppc740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ppc_device(mconfig, PPC740, tag, owner, clock, 32, 64, PPC_MODEL_740, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_604_MMU | PPCCAP_750_TLB , 4, address_map_constructor())
+{
+}
+
+ppc750_device::ppc750_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ppc_device(mconfig, PPC750, tag, owner, clock, 32, 64, PPC_MODEL_750, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_604_MMU | PPCCAP_750_TLB, 4, address_map_constructor())
+{
+}
+
void ppc4xx_device::internal_ppc4xx(address_map &map)
{
map(0x40000000, 0x4000000f).rw(FUNC(ppc4xx_device::ppc4xx_spu_r), FUNC(ppc4xx_device::ppc4xx_spu_w));
@@ -326,9 +352,9 @@ device_memory_interface::space_config_vector ppc_device::memory_space_config() c
static inline bool page_access_allowed(int transtype, uint8_t key, uint8_t protbits)
{
if (key == 0)
- return (transtype == TRANSLATE_WRITE) ? (protbits != 3) : true;
+ return (transtype == device_memory_interface::TR_WRITE) ? (protbits != 3) : true;
else
- return (transtype == TRANSLATE_WRITE) ? (protbits == 2) : (protbits != 0);
+ return (transtype == device_memory_interface::TR_WRITE) ? (protbits == 2) : (protbits != 0);
}
@@ -449,9 +475,9 @@ inline void ppc_device::set_decrementer(uint32_t newdec)
if (PRINTF_DECREMENTER)
{
uint64_t total = total_cycles();
- osd_printf_debug("set_decrementer: olddec=%08X newdec=%08X divisor=%d totalcyc=%08X%08X timer=%08X%08X\n",
+ osd_printf_debug("set_decrementer: olddec=%08X newdec=%08X divisor=%d totalcyc=%016X timer=%016X\n",
curdec, newdec, m_tb_divisor,
- (uint32_t)(total >> 32), (uint32_t)total, (uint32_t)(cycles_until_done >> 32), (uint32_t)cycles_until_done);
+ total, cycles_until_done);
}
m_dec_zero_cycles = total_cycles() + cycles_until_done;
@@ -485,8 +511,7 @@ static inline int is_qnan_double(double x)
{
uint64_t xi = *(uint64_t*)&x;
return( ((xi & DOUBLE_EXP) == DOUBLE_EXP) &&
- ((xi & 0x0007fffffffffffU) == 0x000000000000000U) &&
- ((xi & 0x000800000000000U) == 0x000800000000000U) );
+ ((xi & 0x0008000000000000U) == 0x0008000000000000U) );
}
@@ -694,7 +719,7 @@ void ppc_device::device_start()
m_sebr = 0;
m_ser = 0;
- memset(&m_spu, 0, sizeof(m_spu));
+ m_spu.clear();
m_pit_reload = 0;
m_irqstate = 0;
memset(m_buffered_dma_rate, 0, sizeof(m_buffered_dma_rate));
@@ -702,6 +727,7 @@ void ppc_device::device_start()
m_cpu_clock = 0;
m_tb_zero_cycles = 0;
m_dec_zero_cycles = 0;
+ m_rtc_zero_cycles = 0;
m_arg1 = 0;
m_fastram_select = 0;
@@ -711,58 +737,64 @@ void ppc_device::device_start()
m_debugger_temp = 0;
+ m_serial_clock = 0;
+
m_cache_line_size = 32;
m_cpu_clock = clock();
m_program = &space(AS_PROGRAM);
if(m_cap & PPCCAP_4XX)
{
- auto cache = m_program->cache<2, 0, ENDIANNESS_BIG>();
- m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); };
- m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); };
+ m_program->cache(m_cache32);
+ m_pr32 = [this](offs_t address) -> u32 { return m_cache32.read_dword(address); };
+ m_prptr = [this](offs_t address) -> const void * { return m_cache32.read_ptr(address); };
}
else
{
- auto cache = m_program->cache<3, 0, ENDIANNESS_BIG>();
- m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); };
+ m_program->cache(m_cache64);
+ m_pr32 = [this](offs_t address) -> u32 { return m_cache64.read_dword(address); };
if(space_config()->m_endianness != ENDIANNESS_NATIVE)
- m_prptr = [cache](offs_t address) -> const void * {
- const u32 *ptr = static_cast<u32 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u32 *ptr = static_cast<u32 *>(m_cache64.read_ptr(address & ~7));
if(!(address & 4))
ptr++;
return ptr;
};
else
- m_prptr = [cache](offs_t address) -> const void * {
- const u32 *ptr = static_cast<u32 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u32 *ptr = static_cast<u32 *>(m_cache64.read_ptr(address & ~7));
if(address & 4)
ptr++;
return ptr;
};
}
m_system_clock = c_bus_frequency != 0 ? c_bus_frequency : clock();
- m_dcr_read_func = read32_delegate();
- m_dcr_write_func = write32_delegate();
+ m_dcr_read_func.set(nullptr);
+ m_dcr_write_func.set(nullptr);
m_tb_divisor = (m_tb_divisor * clock() + m_system_clock / 2 - 1) / m_system_clock;
+ m_serial_clock = c_serial_clock != 0 ? c_serial_clock : 3'686'400; // TODO: get rid of this hard-coded magic number
+ if (m_serial_clock > m_system_clock / 2)
+ fatalerror("%s: PPC: serial clock (%d) must not be more than half of the system clock (%d)\n", tag(), m_serial_clock, m_system_clock);
+
/* allocate a timer for the compare interrupt */
if ((m_cap & PPCCAP_OEA) && (m_tb_divisor))
- m_decrementer_int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::decrementer_int_callback), this));
+ m_decrementer_int_timer = timer_alloc(FUNC(ppc_device::decrementer_int_callback), this);
/* and for the 4XX interrupts if needed */
if (m_cap & PPCCAP_4XX)
{
- m_fit_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_fit_callback), this));
- m_pit_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_pit_callback), this));
- m_spu.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_spu_callback), this));
+ m_fit_timer = timer_alloc(FUNC(ppc_device::ppc4xx_fit_callback), this);
+ m_pit_timer = timer_alloc(FUNC(ppc_device::ppc4xx_pit_callback), this);
+ m_spu.timer = timer_alloc(FUNC(ppc_device::ppc4xx_spu_callback), this);
}
if (m_cap & PPCCAP_4XX)
{
- m_buffered_dma_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this));
- m_buffered_dma_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this));
- m_buffered_dma_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this));
- m_buffered_dma_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this));
+ m_buffered_dma_timer[0] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this);
+ m_buffered_dma_timer[1] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this);
+ m_buffered_dma_timer[2] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this);
+ m_buffered_dma_timer[3] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this);
m_buffered_dma_rate[0] = 10000;
m_buffered_dma_rate[1] = 10000;
@@ -806,6 +838,11 @@ void ppc_device::device_start()
state_add(PPC_PC, "PC", m_core->pc).formatstr("%08X");
state_add(PPC_MSR, "MSR", m_core->msr).formatstr("%08X");
state_add(PPC_CR, "CR", m_debugger_temp).callimport().callexport().formatstr("%08X");
+ // If the legacy POWER instructions exist, that implies MQ is used and should be shown
+ if (m_cap & PPCCAP_LEGACY_POWER)
+ {
+ state_add(PPC_MQ, "MQ", m_core->spr[SPR601_MQ]).formatstr("%08X");
+ }
state_add(PPC_LR, "LR", m_core->spr[SPR_LR]).formatstr("%08X");
state_add(PPC_CTR, "CTR", m_core->spr[SPR_CTR]).formatstr("%08X");
state_add(PPC_XER, "XER", m_debugger_temp).callimport().callexport().formatstr("%08X");
@@ -836,7 +873,6 @@ void ppc_device::device_start()
state_add(STATE_GENPC, "GENPC", m_core->pc).noshow();
state_add(STATE_GENPCBASE, "CURPC", m_core->pc).noshow();
- state_add(STATE_GENSP, "GENSP", m_core->r[31]).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).noshow().formatstr("%1s");
set_icountptr(m_core->icount);
@@ -851,15 +887,15 @@ void ppc_device::device_start()
for (int regnum = 0; regnum < 32; regnum++)
{
char buf[10];
- sprintf(buf, "r%d", regnum);
+ snprintf(buf, 10, "r%d", regnum);
m_drcuml->symbol_add(&m_core->r[regnum], sizeof(m_core->r[regnum]), buf);
- sprintf(buf, "fpr%d", regnum);
+ snprintf(buf, 10, "fpr%d", regnum);
m_drcuml->symbol_add(&m_core->f[regnum], sizeof(m_core->f[regnum]), buf);
}
for (int regnum = 0; regnum < 8; regnum++)
{
char buf[10];
- sprintf(buf, "cr%d", regnum);
+ snprintf(buf, 10, "cr%d", regnum);
m_drcuml->symbol_add(&m_core->cr[regnum], sizeof(m_core->cr[regnum]), buf);
}
m_drcuml->symbol_add(&m_core->xerso, sizeof(m_core->xerso), "xerso");
@@ -1144,7 +1180,7 @@ void ppc_device::device_reset()
m_dec_zero_cycles = total_cycles();
if (m_tb_divisor)
{
- decrementer_int_callback(nullptr, 0);
+ decrementer_int_callback(0);
}
}
@@ -1195,7 +1231,7 @@ void ppc_device::device_reset()
std::unique_ptr<util::disasm_interface> ppc_device::create_disassembler()
{
- return std::make_unique<powerpc_disassembler>();
+ return std::make_unique<powerpc_disassembler>(powerpc_disassembler::I_POWERPC);
}
@@ -1208,7 +1244,7 @@ void ppc_device::ppccom_dcstore_callback()
{
if (!m_dcstore_cb.isnull())
{
- m_dcstore_cb(*m_program, m_core->param0, 0, 0xffffffff);
+ m_dcstore_cb(m_core->param0, 0);
}
}
@@ -1224,10 +1260,10 @@ void ppc_device::ppccom_dcstore_callback()
filling
-------------------------------------------------*/
-uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &address)
+uint32_t ppc_device::ppccom_translate_address_internal(int intention, bool debug, offs_t &address)
{
- int transpriv = ((intention & TRANSLATE_USER_MASK) == 0); // 1 for supervisor, 0 for user
- int transtype = intention & TRANSLATE_TYPE_MASK;
+ int transpriv = ((intention & TR_USER) == 0); // 1 for supervisor, 0 for user
+ int transtype = intention & TR_TYPE;
offs_t hash, hashbase, hashmask;
int batbase, batnum, hashnum;
uint32_t segreg;
@@ -1240,7 +1276,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
fatalerror("MMU enabled but not supported!\n");
/* only check if PE is enabled */
- if (transtype == TRANSLATE_WRITE && (m_core->msr & MSR4XX_PE))
+ if (transtype == TR_WRITE && (m_core->msr & MSR4XX_PE))
{
/* are we within one of the protection ranges? */
int inrange1 = ((address >> 12) >= (m_core->spr[SPR4XX_PBL1] >> 12) && (address >> 12) < (m_core->spr[SPR4XX_PBU1] >> 12));
@@ -1259,7 +1295,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
return 0x001;
/* also no translation necessary if translation is disabled */
- if ((transtype == TRANSLATE_FETCH && (m_core->msr & MSROEA_IR) == 0) || (transtype != TRANSLATE_FETCH && (m_core->msr & MSROEA_DR) == 0))
+ if ((transtype == TR_FETCH && (m_core->msr & MSROEA_IR) == 0) || (transtype != TR_FETCH && (m_core->msr & MSROEA_DR) == 0))
return 0x001;
/* first scan the appropriate BAT */
@@ -1269,9 +1305,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
{
uint32_t upper = m_core->spr[SPROEA_IBAT0U + 2*batnum + 0];
uint32_t lower = m_core->spr[SPROEA_IBAT0U + 2*batnum + 1];
- int privbit = ((intention & TRANSLATE_USER_MASK) == 0) ? 3 : 2;
-
-// printf("bat %d upper = %08x privbit %d\n", batnum, upper, privbit);
+ int privbit = ((intention & TR_USER) == 0) ? 3 : 2;
// is this pair valid?
if (lower & 0x40)
@@ -1286,7 +1320,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
/* verify protection; if we fail, return false and indicate a protection violation */
if (!page_access_allowed(transtype, key, upper & 3))
{
- return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0);
}
/* otherwise we're good */
@@ -1299,7 +1333,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
}
else
{
- batbase = (transtype == TRANSLATE_FETCH) ? SPROEA_IBAT0U : SPROEA_DBAT0U;
+ batbase = (transtype == TR_FETCH) ? SPROEA_IBAT0U : SPROEA_DBAT0U;
for (batnum = 0; batnum < 4; batnum++)
{
@@ -1318,7 +1352,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
/* verify protection; if we fail, return false and indicate a protection violation */
if (!page_access_allowed(transtype, 1, lower & 3))
{
- return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0);
}
/* otherwise we're good */
@@ -1340,13 +1374,13 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
/* look up the segment register */
segreg = m_core->sr[address >> 28];
- if (transtype == TRANSLATE_FETCH && (segreg & 0x10000000))
- return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ if (transtype == TR_FETCH && (segreg & 0x10000000))
+ return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0);
/* check for memory-forced I/O */
if (m_cap & PPCCAP_MFIOC)
{
- if ((transtype != TRANSLATE_FETCH) && ((segreg & 0x87f00000) == 0x87f00000))
+ if ((transtype != TR_FETCH) && ((segreg & 0x87f00000) == 0x87f00000))
{
address = ((segreg & 0xf)<<28) | (address & 0x0fffffff);
return 1;
@@ -1369,12 +1403,12 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
m_core->mmu603_cmp = 0x80000000 | ((segreg & 0xffffff) << 7) | (0 << 6) | ((address >> 22) & 0x3f);
m_core->mmu603_hash[0] = hashbase | ((hash << 6) & hashmask);
m_core->mmu603_hash[1] = hashbase | ((~hash << 6) & hashmask);
- if ((entry & (VTLB_FLAG_FIXED | VTLB_FLAG_VALID)) == (VTLB_FLAG_FIXED | VTLB_FLAG_VALID))
+ if ((entry & (FLAG_FIXED | FLAG_VALID)) == (FLAG_FIXED | FLAG_VALID))
{
address = (entry & 0xfffff000) | (address & 0x00000fff);
return 0x001;
}
- return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ return DSISR_NOT_FOUND | ((transtype == TR_WRITE) ? DSISR_STORE : 0);
}
/* loop twice over hashes */
@@ -1397,13 +1431,13 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
/* verify protection; if we fail, return false and indicate a protection violation */
if (!page_access_allowed(transtype, (segreg >> (29 + transpriv)) & 1, pteglower & 3))
- return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0);
/* update page table bits */
- if (!(intention & TRANSLATE_DEBUG_MASK))
+ if (!debug)
{
pteglower |= 0x100;
- if (transtype == TRANSLATE_WRITE)
+ if (transtype == TR_WRITE)
pteglower |= 0x080;
ptegptr[BYTE_XOR_BE(ptenum * 2 + 1)] = pteglower;
}
@@ -1419,7 +1453,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
}
/* we failed to find any match: not found */
- return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ return DSISR_NOT_FOUND | ((transtype == TR_WRITE) ? DSISR_STORE : 0);
}
@@ -1428,14 +1462,16 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad
from logical to physical
-------------------------------------------------*/
-bool ppc_device::memory_translate(int spacenum, int intention, offs_t &address)
+bool ppc_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space)
{
+ target_space = &space(spacenum);
+
/* only applies to the program address space */
if (spacenum != AS_PROGRAM)
return true;
/* translation is successful if the internal routine returns 0 or 1 */
- return (ppccom_translate_address_internal(intention, address) <= 1);
+ return (ppccom_translate_address_internal(intention, true, address) <= 1);
}
@@ -1445,7 +1481,10 @@ bool ppc_device::memory_translate(int spacenum, int intention, offs_t &address)
void ppc_device::ppccom_tlb_fill()
{
- vtlb_fill(m_core->param0, m_core->param1);
+ offs_t address = m_core->param0;
+ if(ppccom_translate_address_internal(m_core->param1, false, address) > 1)
+ return;
+ vtlb_fill(m_core->param0, address, m_core->param1);
}
@@ -1476,14 +1515,14 @@ void ppc_device::ppccom_get_dsisr()
if (m_core->param1 & 1)
{
- intent = TRANSLATE_WRITE;
+ intent = TR_WRITE;
}
else
{
- intent = TRANSLATE_READ;
+ intent = TR_READ;
}
- m_core->param1 = ppccom_translate_address_internal(intent, m_core->param0);
+ m_core->param1 = ppccom_translate_address_internal(intent, false, m_core->param0);
}
/*-------------------------------------------------
@@ -1527,11 +1566,11 @@ void ppc_device::ppccom_execute_tlbl()
entrynum = ((address >> 12) & 0x1f) | (machine().rand() & 0x20) | (isitlb ? 0x40 : 0);
/* determine the flags */
- flags = VTLB_FLAG_VALID | VTLB_READ_ALLOWED | VTLB_FETCH_ALLOWED;
+ flags = FLAG_VALID | READ_ALLOWED | FETCH_ALLOWED;
if (m_core->spr[SPR603_RPA] & 0x80)
- flags |= VTLB_WRITE_ALLOWED;
+ flags |= WRITE_ALLOWED;
if (isitlb)
- flags |= VTLB_FETCH_ALLOWED;
+ flags |= FETCH_ALLOWED;
/* load the entry */
vtlb_load(entrynum, 1, address, (m_core->spr[SPR603_RPA] & 0xfffff000) | flags);
@@ -1604,6 +1643,29 @@ void ppc_device::ppccom_execute_mfspr()
}
}
+ /* handle 601 specific SPRs (POWER holdovers) */
+ if (m_flavor == PPC_MODEL_601)
+ {
+ switch (m_core->param0)
+ {
+ case SPR601_PWRDEC:
+ m_core->param1 = get_decrementer();
+ return;
+
+ case SPR601_RTCUR_PWR:
+ m_core->param1 = (total_cycles() - m_rtc_zero_cycles) / clock();
+ return;
+
+ case SPR601_RTCLR_PWR:
+ {
+ const uint64_t remainder = (total_cycles() - m_rtc_zero_cycles) % clock();
+ const double seconds = remainder / clock(); // get fractional seconds
+ m_core->param1 = (uint64_t)(seconds * 1'000'000'000); // and convert to nanoseconds
+ }
+ return;
+ }
+ }
+
/* handle 602 SPRs */
if (m_flavor == PPC_MODEL_602)
{ // TODO: Which are read/write only?
@@ -1747,6 +1809,21 @@ void ppc_device::ppccom_execute_mtspr()
}
}
+ /* handle 601 specific POWER-holdover SPRs */
+ if (m_flavor == PPC_MODEL_601)
+ {
+ switch (m_core->param0)
+ {
+ case SPR601_MQ:
+ m_core->spr[m_core->param0] = m_core->param1;
+ return;
+
+ case SPR601_RTCUW_PWR:
+ m_rtc_zero_cycles = total_cycles();
+ break;
+ }
+ }
+
/* handle 602 SPRs */
if (m_flavor == PPC_MODEL_602)
{
@@ -1828,9 +1905,9 @@ void ppc_device::ppccom_execute_mtspr()
case SPR4XX_TCR:
m_core->spr[SPR4XX_TCR] = m_core->param1 | (oldval & PPC4XX_TCR_WRC_MASK);
if ((oldval ^ m_core->spr[SPR4XX_TCR]) & PPC4XX_TCR_FIE)
- ppc4xx_fit_callback(nullptr, false);
+ ppc4xx_fit_callback(false);
if ((oldval ^ m_core->spr[SPR4XX_TCR]) & PPC4XX_TCR_PIE)
- ppc4xx_pit_callback(nullptr, false);
+ ppc4xx_pit_callback(false);
return;
/* timer status register */
@@ -1843,7 +1920,7 @@ void ppc_device::ppccom_execute_mtspr()
case SPR4XX_PIT:
m_core->spr[SPR4XX_PIT] = m_core->param1;
m_pit_reload = m_core->param1;
- ppc4xx_pit_callback(nullptr, false);
+ ppc4xx_pit_callback(false);
return;
/* timebase */
@@ -1913,12 +1990,12 @@ void ppc_device::ppccom_execute_mfdcr()
/* default handling */
if (m_dcr_read_func.isnull()) {
osd_printf_debug("DCR %03X read\n", m_core->param0);
- if (m_core->param0 < ARRAY_LENGTH(m_dcr))
+ if (m_core->param0 < std::size(m_dcr))
m_core->param1 = m_dcr[m_core->param0];
else
m_core->param1 = 0;
} else {
- m_core->param1 = m_dcr_read_func(*m_program,m_core->param0,0xffffffff);
+ m_core->param1 = m_dcr_read_func(m_core->param0);
}
}
@@ -2005,10 +2082,10 @@ void ppc_device::ppccom_execute_mtdcr()
/* default handling */
if (m_dcr_write_func.isnull()) {
osd_printf_debug("DCR %03X write = %08X\n", m_core->param0, m_core->param1);
- if (m_core->param0 < ARRAY_LENGTH(m_dcr))
+ if (m_core->param0 < std::size(m_dcr))
m_dcr[m_core->param0] = m_core->param1;
} else {
- m_dcr_write_func(*m_program,m_core->param0,m_core->param1,0xffffffff);
+ m_dcr_write_func(m_core->param0,m_core->param1);
}
}
@@ -2093,7 +2170,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::decrementer_int_callback )
for detecting datacache stores with dcbst
-------------------------------------------------*/
-void ppc_device::ppc_set_dcstore_callback(write32_delegate callback)
+void ppc_device::ppc_set_dcstore_callback(write32sm_delegate callback)
{
m_dcstore_cb = callback;
}
@@ -2365,7 +2442,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_buffered_dma_callback )
{
uint8_t data = m_program->read_byte(dmaregs[DCR4XX_DMADA0]);
if (!m_ext_dma_write_cb[dmachan].isnull())
- (m_ext_dma_write_cb[dmachan])(*m_program, 1, data, 0xffffffff);
+ (m_ext_dma_write_cb[dmachan])(1, data);
dmaregs[DCR4XX_DMADA0] += destinc;
} while (!ppc4xx_dma_decrement_count(dmachan));
break;
@@ -2376,7 +2453,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_buffered_dma_callback )
{
uint16_t data = m_program->read_word(dmaregs[DCR4XX_DMADA0]);
if (!m_ext_dma_write_cb[dmachan].isnull())
- (m_ext_dma_write_cb[dmachan])(*m_program, 2, data, 0xffffffff);
+ (m_ext_dma_write_cb[dmachan])(2, data);
dmaregs[DCR4XX_DMADA0] += destinc;
} while (!ppc4xx_dma_decrement_count(dmachan));
break;
@@ -2387,7 +2464,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_buffered_dma_callback )
{
uint32_t data = m_program->read_dword(dmaregs[DCR4XX_DMADA0]);
if (!m_ext_dma_write_cb[dmachan].isnull())
- (m_ext_dma_write_cb[dmachan])(*m_program, 4, data, 0xffffffff);
+ (m_ext_dma_write_cb[dmachan])(4, data);
dmaregs[DCR4XX_DMADA0] += destinc;
} while (!ppc4xx_dma_decrement_count(dmachan));
break;
@@ -2656,7 +2733,7 @@ void ppc_device::ppc4xx_spu_rx_data(uint8_t data)
uint32_t new_rxin;
/* fail if we are going to overflow */
- new_rxin = (m_spu.rxin + 1) % ARRAY_LENGTH(m_spu.rxbuffer);
+ new_rxin = (m_spu.rxin + 1) % std::size(m_spu.rxbuffer);
if (new_rxin == m_spu.rxout)
fatalerror("ppc4xx_spu_rx_data: buffer overrun!\n");
@@ -2678,7 +2755,7 @@ void ppc_device::ppc4xx_spu_timer_reset()
/* if we're enabled, reset at the current baud rate */
if (enabled)
{
- attotime clockperiod = attotime::from_hz((m_dcr[DCR4XX_IOCR] & 0x02) ? 3686400 : 33333333);
+ attotime clockperiod = attotime::from_hz((m_dcr[DCR4XX_IOCR] & 0x02) ? m_serial_clock : m_system_clock);
int divisor = ((m_spu.regs[SPU4XX_BAUD_DIVISOR_H] * 256 + m_spu.regs[SPU4XX_BAUD_DIVISOR_L]) & 0xfff) + 1;
int bpc = 7 + ((m_spu.regs[SPU4XX_CONTROL] & 8) >> 3) + 1 + (m_spu.regs[SPU4XX_CONTROL] & 1);
attotime charperiod = clockperiod * (divisor * 16 * bpc);
@@ -2710,7 +2787,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_spu_callback )
{
/* if we have a transmit handler, send it that way */
if (!m_spu.tx_cb.isnull())
- (m_spu.tx_cb)(*m_program, 0, m_spu.txbuf, 0xff);
+ (m_spu.tx_cb)(m_spu.txbuf);
/* indicate that we have moved it to the shift register */
m_spu.regs[SPU4XX_LINE_STATUS] |= 0x04;
@@ -2735,7 +2812,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_spu_callback )
/* consume the byte and advance the out pointer */
rxbyte = m_spu.rxbuffer[m_spu.rxout];
- m_spu.rxout = (m_spu.rxout + 1) % ARRAY_LENGTH(m_spu.rxbuffer);
+ m_spu.rxout = (m_spu.rxout + 1) % std::size(m_spu.rxbuffer);
/* if we're not full, copy data to the buffer and update the line status */
if (!(m_spu.regs[SPU4XX_LINE_STATUS] & 0x80))
@@ -2766,7 +2843,7 @@ updateirq:
ppc4xx_spu_r - serial port read handler
-------------------------------------------------*/
-READ8_MEMBER( ppc4xx_device::ppc4xx_spu_r )
+uint8_t ppc4xx_device::ppc4xx_spu_r(offs_t offset)
{
uint8_t result = 0xff;
@@ -2778,7 +2855,7 @@ READ8_MEMBER( ppc4xx_device::ppc4xx_spu_r )
break;
default:
- if (offset < ARRAY_LENGTH(m_spu.regs))
+ if (offset < std::size(m_spu.regs))
result = m_spu.regs[offset];
break;
}
@@ -2792,7 +2869,7 @@ READ8_MEMBER( ppc4xx_device::ppc4xx_spu_r )
ppc4xx_spu_w - serial port write handler
-------------------------------------------------*/
-WRITE8_MEMBER( ppc4xx_device::ppc4xx_spu_w )
+void ppc4xx_device::ppc4xx_spu_w(offs_t offset, uint8_t data)
{
uint8_t oldstate, newstate;
@@ -2842,7 +2919,7 @@ WRITE8_MEMBER( ppc4xx_device::ppc4xx_spu_w )
break;
default:
- if (offset < ARRAY_LENGTH(m_spu.regs))
+ if (offset < std::size(m_spu.regs))
m_spu.regs[offset] = data;
break;
}
@@ -2855,7 +2932,7 @@ WRITE8_MEMBER( ppc4xx_device::ppc4xx_spu_w )
specific TX handler configuration
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_spu_set_tx_handler(write8_delegate callback)
+void ppc4xx_device::ppc4xx_spu_set_tx_handler(write8smo_delegate callback)
{
m_spu.tx_cb = callback;
}
@@ -2887,7 +2964,7 @@ void ppc4xx_device::ppc4xx_set_dma_read_handler(int channel, read32_delegate cal
specific external DMA write handler configuration
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_set_dma_write_handler(int channel, write32_delegate callback, int rate)
+void ppc4xx_device::ppc4xx_set_dma_write_handler(int channel, write32sm_delegate callback, int rate)
{
m_ext_dma_write_cb[channel] = callback;
m_buffered_dma_rate[channel] = rate;
@@ -2897,7 +2974,7 @@ void ppc4xx_device::ppc4xx_set_dma_write_handler(int channel, write32_delegate c
ppc4xx_set_dcr_read_handler
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_set_dcr_read_handler(read32_delegate dcr_read_func)
+void ppc4xx_device::ppc4xx_set_dcr_read_handler(read32sm_delegate dcr_read_func)
{
m_dcr_read_func = dcr_read_func;
@@ -2907,7 +2984,7 @@ void ppc4xx_device::ppc4xx_set_dcr_read_handler(read32_delegate dcr_read_func)
ppc4xx_set_dcr_write_handler
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_set_dcr_write_handler(write32_delegate dcr_write_func)
+void ppc4xx_device::ppc4xx_set_dcr_write_handler(write32sm_delegate dcr_write_func)
{
m_dcr_write_func = dcr_write_func;
}
diff --git a/src/devices/cpu/powerpc/ppccom.h b/src/devices/cpu/powerpc/ppccom.h
index 918ca62a4c4..da12935a5cc 100644
--- a/src/devices/cpu/powerpc/ppccom.h
+++ b/src/devices/cpu/powerpc/ppccom.h
@@ -64,7 +64,8 @@
#define PPCCAP_MFIOC 0x40 /* TRUE if we have memory-forced I/O controller interface accesses */
#define PPCCAP_601BAT 0x80 /* TRUE if we're doing 601-style BATs (unified I/D, different bit layout) */
#define PPCCAP_604_MMU 0x100 /* TRUE if we have 604-class MMU features */
-
+#define PPCCAP_750_TLB 0x200 /* TRUE if we have the extended 740/750 series TLB */
+#define PPCCAP_LEGACY_POWER 0x400 /* TRUE if we support the legacy POWER instructions */
/* exception types */
enum
@@ -171,6 +172,14 @@ enum
SPR4XX_PBL2 = 0x3fe, /* R/W 403GA 406GA Protection Bound Lower 2 */
SPR4XX_PBU2 = 0x3ff, /* R/W 403GA 406GA Protection Bound Upper 2 */
+ /* PowerPC 601 POWER back compatibility SPR indexes */
+ SPR601_MQ = 0x000, /* R/W Muliplicand/Quotient for 601 POWER instructions */
+ SPR601_RTCUR_PWR = 0x004, /* R Counts up number set in SPR 20 once per second, POWER only */
+ SPR601_RTCLR_PWR = 0x005, /* R Number of nanoseconds between the seconds counted in SPR 4 */
+ SPR601_PWRDEC = 0x006, /* R Decrementer register mirror for POWER compatibilty */
+ SPR601_RTCUW_PWR = 0x014, /* W Seconds counter, set here and read SPR 4 */
+ SPR601_RTCLW_PWR = 0x015, /* W Nanoseconds counter, not clear what writing here does */
+
/* PowerPC 602 SPR register indexes */
SPR602_TCR = 0x3d8, /* 602 */
SPR602_IBR = 0x3da, /* 602 */
@@ -198,7 +207,6 @@ enum
SPR603_HID2 = 0x3f3 /* R/W 603 */
};
-
/* PowerPC 4XX DCR register indexes */
enum
{
diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp
index 120328a50a0..b9c7484f1f9 100644
--- a/src/devices/cpu/powerpc/ppcdrc.cpp
+++ b/src/devices/cpu/powerpc/ppcdrc.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- ppcdrc.c
+ ppcdrc.cpp
Universal machine language-based PowerPC emulator.
@@ -18,12 +18,10 @@
#include "ppc.h"
#include "ppccom.h"
#include "ppcfe.h"
-#include "ppc_dasm.h"
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "cpu/drcumlsh.h"
-#include "debugger.h"
@@ -118,7 +116,7 @@ inline void ppc_device::load_fast_iregs(drcuml_block &block)
{
int regnum;
- for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (regnum = 0; regnum < std::size(m_regmap); regnum++)
{
if (m_regmap[regnum].is_int_register())
{
@@ -137,7 +135,7 @@ void ppc_device::save_fast_iregs(drcuml_block &block)
{
int regnum;
- for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (regnum = 0; regnum < std::size(m_regmap); regnum++)
{
if (m_regmap[regnum].is_int_register())
{
@@ -149,7 +147,7 @@ void ppc_device::save_fast_iregs(drcuml_block &block)
inline void ppc_device::load_fast_fregs(drcuml_block &block)
{
- for (int regnum = 0; regnum < ARRAY_LENGTH(m_fdregmap); regnum++)
+ for (int regnum = 0; regnum < std::size(m_fdregmap); regnum++)
{
if (m_fdregmap[regnum].is_float_register())
{
@@ -160,7 +158,7 @@ inline void ppc_device::load_fast_fregs(drcuml_block &block)
void ppc_device::save_fast_fregs(drcuml_block &block)
{
- for (int regnum = 0; regnum < ARRAY_LENGTH(m_fdregmap); regnum++)
+ for (int regnum = 0; regnum < std::size(m_fdregmap); regnum++)
{
if (m_fdregmap[regnum].is_float_register())
{
@@ -268,7 +266,7 @@ void ppc_device::ppcdrc_set_options(uint32_t options)
void ppc_device::ppcdrc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base)
{
- if (m_fastram_select < ARRAY_LENGTH(m_fastram))
+ if (m_fastram_select < std::size(m_fastram))
{
m_fastram[m_fastram_select].start = start;
m_fastram[m_fastram_select].end = end;
@@ -285,7 +283,7 @@ void ppc_device::ppcdrc_add_fastram(offs_t start, offs_t end, uint8_t readonly,
void ppc_device::ppcdrc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles)
{
- if (m_hotspot_select < ARRAY_LENGTH(m_hotspot))
+ if (m_hotspot_select < std::size(m_hotspot))
{
m_hotspot[m_hotspot_select].pc = pc;
m_hotspot[m_hotspot_select].opcode = opcode;
@@ -383,7 +381,7 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc)
const opcode_desc *desclist;
bool override = false;
- g_profiler.start(PROFILER_DRC_COMPILE);
+ auto profile = g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
desclist = m_drcfe->describe_code(pc);
@@ -467,7 +465,6 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc)
/* end the sequence */
block.end();
- g_profiler.stop();
succeeded = true;
}
catch (drcuml_block::abort_compilation &)
@@ -778,11 +775,11 @@ void ppc_device::static_generate_tlb_mismatch()
UML_SHR(block, I1, I0, 12); // shr i1,i0,12
UML_LOAD(block, I2, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i2,[vtlb],i1,dword
UML_MOV(block, mem(&m_core->param0), I0); // mov [param0],i0
- UML_MOV(block, mem(&m_core->param1), TRANSLATE_FETCH); // mov [param1],TRANSLATE_FETCH
+ UML_MOV(block, mem(&m_core->param1), TR_FETCH); // mov [param1],TR_FETCH
UML_CALLC(block, (c_function)cfunc_ppccom_mismatch, this);
UML_CALLC(block, (c_function)cfunc_ppccom_tlb_fill, this); // callc tlbfill,ppc
UML_LOAD(block, I1, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i1,[vtlb],i1,dword
- UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED
+ UML_TEST(block, I1, FETCH_ALLOWED); // test i1,FETCH_ALLOWED
UML_JMPc(block, COND_Z, isi = label++); // jmp isi,z
UML_CMP(block, I2, 0); // cmp i2,0
UML_JMPc(block, COND_NZ, exit = label++); // jmp exit,nz
@@ -1010,9 +1007,9 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
int ramnum;
if (mode & MODE_USER)
- translate_type = iswrite ? TRANSLATE_WRITE_USER : TRANSLATE_READ_USER;
+ translate_type = iswrite ? TR_UWRITE : TR_UREAD;
else
- translate_type = iswrite ? TRANSLATE_WRITE : TRANSLATE_READ;
+ translate_type = iswrite ? TR_WRITE : TR_READ;
/* begin generating */
drcuml_block &block(m_drcuml->begin_block(1024));
@@ -1024,32 +1021,30 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
/* check for unaligned accesses and break into two */
if (!ismasked && size != 1)
{
- /* in little-endian mode, anything misaligned generates an exception */
if ((mode & MODE_LITTLE_ENDIAN) || masked == nullptr || !(m_cap & PPCCAP_MISALIGNED))
{
+ /* in little-endian mode, anything misaligned generates an exception */
UML_TEST(block, I0, size - 1); // test i0,size-1
- UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
}
-
- /* in big-endian mode, it's more complicated */
else
{
- /* 8-byte accesses must be word-aligned */
+ /* in big-endian mode, it's more complicated */
if (size == 8)
{
+ /* 8-byte accesses must be word-aligned */
UML_TEST(block, I0, 3); // test i0,3
- UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
/* word aligned accesses need to be broken up */
UML_TEST(block, I0, 4); // test i0,4
UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned, nz
}
-
- /* unaligned 2 and 4 byte accesses need to be broken up */
else
{
+ /* unaligned 2 and 4 byte accesses need to be broken up */
UML_TEST(block, I0, size - 1); // test i0,size-1
- UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned,nz
+ UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned,nz
}
}
}
@@ -1057,18 +1052,18 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
/* general case: assume paging and perform a translation */
if (((m_cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION)) || (iswrite && (m_cap & PPCCAP_4XX) && (mode & MODE_PROTECTION)))
{
- UML_SHR(block, I3, I0, 12); // shr i3,i0,12
- UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword
- UML_TEST(block, I3, (uint64_t)1 << translate_type); // test i3,1 << translate_type
- UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
- UML_LABEL(block, tlbreturn = label++); // tlbreturn:
- UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
+ UML_SHR(block, I3, I0, 12); // shr i3,i0,12
+ UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4); // load i3,[vtlb],i3,dword
+ UML_TEST(block, I3, (uint64_t)1 << translate_type); // test i3,1 << translate_type
+ UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
+ UML_LABEL(block, tlbreturn = label++); // tlbreturn:
+ UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
}
else if (m_cap & PPCCAP_4XX)
UML_AND(block, I0, I0, 0x7fffffff); // and i0,i0,0x7fffffff
UML_XOR(block, I0, I0, (mode & MODE_LITTLE_ENDIAN) ? (8 - size) : 0); // xor i0,i0,8-size
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ if (!debugger_enabled())
for (ramnum = 0; ramnum < PPC_MAX_FASTRAM; ramnum++)
if (m_fastram[ramnum].base != nullptr && (!iswrite || !m_fastram[ramnum].readonly))
{
@@ -1468,7 +1463,7 @@ void ppc_device::static_generate_lsw_entries(int mode)
char temp[20];
/* allocate a handle */
- sprintf(temp, "lsw%d", regnum);
+ snprintf(temp, 20, "lsw%d", regnum);
alloc_handle(m_drcuml.get(), &m_lsw[mode][regnum], temp);
UML_HANDLE(block, *m_lsw[mode][regnum]); // handle lsw<regnum>
UML_LABEL(block, regnum); // regnum:
@@ -1520,7 +1515,7 @@ void ppc_device::static_generate_stsw_entries(int mode)
char temp[20];
/* allocate a handle */
- sprintf(temp, "stsw%d", regnum);
+ snprintf(temp, 20, "stsw%d", regnum);
alloc_handle(m_drcuml.get(), &m_stsw[mode][regnum], temp);
UML_HANDLE(block, *m_stsw[mode][regnum]); // handle stsw<regnum>
UML_LABEL(block, regnum); // regnum:
@@ -1716,7 +1711,7 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta
}
/* if we are debugging, call the debugger */
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
{
UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc
save_fast_iregs(block); // <save fastregs>
@@ -1739,25 +1734,31 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta
if (PRINTF_MMU)
{
const char *text = "Compiler page fault @ %08X\n";
- UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ if (sizeof(uintptr_t) == 8)
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ else
+ UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
UML_MOV(block, mem(&m_core->arg0), desc->pc); // mov [arg0],desc->pc
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
UML_EXH(block, *m_tlb_mismatch, 0); // exh tlb_mismatch,0
}
- /* validate our TLB entry at this PC; if we fail, we need to handle it */
- if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION))
+ // validate our TLB entry at this PC; if we fail, we need to handle it
+ // TODO: this code is highly sus based on the PPC architecture manual, but I'll only disable for 601 for now
+ if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION) && !(m_cap & PPCCAP_601BAT))
{
const vtlb_entry *tlbtable = vtlb_table();
- /* if we currently have a valid TLB read entry, we just verify */
if (tlbtable[desc->pc >> 12] != 0)
{
if (PRINTF_MMU)
{
const char *text = "Checking TLB at @ %08X\n";
- UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ if (sizeof(uintptr_t) == 8)
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ else
+ UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
UML_MOV(block, mem(&m_core->arg0), desc->pc); // mov [arg0],desc->pc
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
@@ -1772,7 +1773,10 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta
if (PRINTF_MMU)
{
const char *text = "No valid TLB @ %08X\n";
- UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ if (sizeof(uintptr_t) == 8)
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ else
+ UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
UML_MOV(block, mem(&m_core->arg0), desc->pc); // mov [arg0],desc->pc
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
@@ -2018,6 +2022,23 @@ bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler,
// muls rd,rd,ra,simm
return true;
+ case 0x9: /* DOZI (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_AND(block, I0, op, 0xffff);
+ UML_CMP(block, R32(G_RA(op)), I0); // cmp ra, I0
+ UML_JMPc(block, COND_B, compiler->labelnum); // bae 0:
+
+ UML_XOR(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RD(op))); // xor rd, rd, rd (rd = 0)
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), I0);
+ UML_ADD(block, R32(G_RD(op)), R32(G_RD(op)), 0x1);
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ return true;
+
case 0x0e: /* ADDI */
UML_ADD(block, R32(G_RD(op)), R32Z(G_RA(op)), (int16_t)G_SIMM(op)); // add rd,ra,simm
return true;
@@ -2250,12 +2271,15 @@ bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler,
case 0x2e: /* LMW */
UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
UML_MOV(block, mem(&m_core->tempaddr), R32Z(G_RA(op))); // mov [tempaddr],ra
+
for (int regnum = G_RD(op); regnum < 32; regnum++)
{
UML_ADD(block, I0, mem(&m_core->tempaddr), (int16_t)G_SIMM(op) + 4 * (regnum - G_RD(op)));
// add i0,[tempaddr],simm + 4*(regnum-rd)
UML_CALLH(block, *m_read32align[m_core->mode]); // callh read32align
- UML_MOV(block, R32(regnum), I0); // mov regnum,i0
+
+ if (regnum != G_RA(op) || ((m_cap & PPCCAP_4XX) && regnum == 31))
+ UML_MOV(block, R32(regnum), I0); // mov regnum,i0
}
generate_update_cycles(block, compiler, desc->pc + 4, true); // <update cycles>
return true;
@@ -2672,10 +2696,19 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
case 0x0eb: /* MULLWx */
case 0x2eb: /* MULLWOx */
- UML_MULS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // muls rd,rd,ra,rb
+ // The flags are calculated based on the resulting 32-bit value from the 32x32=32 multiplication
+ // reference: example 4 https://www.ibm.com/docs/en/aix/7.2?topic=set-mullw-muls-multiply-low-word-instruction
+ UML_MULSLW(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // mulslw rd,ra,rb
generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), false);// <update flags>
return true;
+ case 0x6b: /* MUL (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_MULU(block, SPR32(SPR601_MQ), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // mulu mq, rd, ra, rb
+ generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV | XER_SO : 0), false); // <update flags>
+ return true;
+
case 0x1cb: /* DIVWUx */
case 0x3cb: /* DIVWUOx */
UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
@@ -2703,6 +2736,68 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
UML_LABEL(block, compiler->labelnum++); // 1:
return true;
+ case 0x14b: /* DIV (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_MOV(block, I0, R32(G_RA(op)));
+ UML_MOV(block, I1, SPR32(SPR601_MQ));
+ UML_DSHL(block, I0, I0, 32); // I0 = RA << 32
+ UML_DOR(block, I0, I0, I1); // I0 |= MQ
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // bne 0:
+
+ UML_MOV(block, R32(G_RD(op)), 0x0); // mov rd, #0
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1
+ UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1
+ }
+ if (op & M_RC)
+ {
+ UML_MOV(block, CR32(0), 0x2); // CR = EQ
+ UML_AND(block, CR32(0), CR32(0), ~0x1);
+ UML_OR(block, CR32(0), CR32(0), XERSO32);
+ }
+
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++);
+ UML_MOV(block, I1, R32(G_RB(op)));
+ UML_DSEXT(block, I1, I1, SIZE_DWORD);
+ UML_DDIVS(block, I0, I1, I0, I1);
+ UML_MOV(block, R32(G_RD(op)), I0);
+ UML_MOV(block, SPR32(SPR601_MQ), I1);
+ generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV | XER_SO : 0), false); // <update flags>
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ return true;
+
+ case 0x16b: /* DIVS (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // bne 0:
+
+ UML_MOV(block, R32(G_RD(op)), 0x0); // mov rd, #0
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1
+ UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1
+ }
+ if (op & M_RC)
+ {
+ UML_MOV(block, CR32(0), 0x2); // CR = EQ
+ UML_AND(block, CR32(0), CR32(0), ~0x1);
+ UML_OR(block, CR32(0), CR32(0), XERSO32);
+ }
+
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_DIVS(block, R32(G_RD(op)), SPR32(SPR601_MQ), R32(G_RA(op)), R32(G_RB(op))); // divs rd,mq,ra,rb
+ generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), false); // <update flags>
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ return true;
+
case 0x1eb: /* DIVWx */
case 0x3eb: /* DIVWOx */
UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
@@ -2756,6 +2851,78 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
UML_LABEL(block, compiler->labelnum++); // 3:
return true;
+ case 0x108: /* DOZ (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra, rb
+ UML_JMPc(block, COND_B, compiler->labelnum); // bae 0:
+
+ UML_XOR(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RD(op))); // xor rd, rd, rd (rd = 0)
+ UML_JMP(block, compiler->labelnum+1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)));
+ UML_ADD(block, R32(G_RD(op)), R32(G_RD(op)), 0x1);
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1
+ UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1
+ }
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RD(op)), ~0); // test rd,~0
+ generate_compute_flags(block, desc, op & M_RC, 0, false); // <update flags>
+ }
+ return true;
+
+ case 0x168: /* ABS (POWER) */
+ case 0x1e8: /* NABS (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ // is rA already the correct sign (positive for ABS, negative for NABS)?
+ UML_CMP(block, R32(G_RA(op)), 0);
+ if (op & 0x080)
+ {
+ UML_JMPc(block, COND_L, compiler->labelnum); // bl 0:
+ }
+ else
+ {
+ UML_JMPc(block, COND_GE, compiler->labelnum); // bge 0:
+ }
+
+ UML_SUB(block, I0, 0, R32(G_RA(op))); // sub 0, ra (make positive)
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_MOV(block, I0, R32(G_RA(op)));
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ UML_MOV(block, R32(G_RD(op)), I0); // mov rd, I0
+ if (op & M_RC)
+ {
+ UML_GETFLGS(block, I0, FLAG_Z | FLAG_V | FLAG_C | FLAG_S); // getflgs i0,zvcs
+ UML_LOAD(block, I0, m_cmp_cr_table, I0, SIZE_DWORD, SCALE_x4); // load i0,cmp_cr_table,i0,dword
+ }
+ if (op & M_OE)
+ {
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+ }
+ return true;
+
+ case 0x21d: /* MASKIR (POWER) */
+ UML_AND(block, I0, R32(G_RS(op)), R32(G_RB(op))); // and i0, rs, rb
+ UML_XOR(block, I1, R32(G_RB(op)), 0xffffffff); // xor i1, rb, 0xffffffff
+ UML_AND(block, I1, I1, R32(G_RA(op))); // and i1, i1, ra
+ UML_OR(block, R32(G_RA(op)), I0, I1); // or ra, i0, i1
+ if (op & M_RC)
+ {
+ UML_GETFLGS(block, R32(G_RA(op)), FLAG_Z | FLAG_V | FLAG_C | FLAG_S); // getflgs i0,zvcs
+ UML_LOAD(block, I0, m_cmp_cr_table, I0, SIZE_DWORD, SCALE_x4); // load i0,cmp_cr_table,i0,dword
+ }
+ return true;
+
case 0x01c: /* ANDx */
UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // and ra,rs,rb
generate_compute_flags(block, desc, op & M_RC, 0, false); // <update flags>
@@ -3066,9 +3233,11 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
case 0x215: /* LSWX */
UML_ADD(block, mem(&m_core->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
- UML_AND(block, mem(&m_core->swcount), SPR32(SPR_XER), 0x7f); // and [swcount],[xer],0x7f
- UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), mem(&m_core->swcount));// sub icount,icount,[swcount]
- UML_CALLHc(block, COND_NZ, *m_lsw[m_core->mode][G_RD(op)]); // call lsw[rd],nz
+ UML_AND(block, I0, SPR32(SPR_XER), 0x7f); // and i0,[xer],0x7f
+ UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I0);// sub icount,icount,i0
+ UML_MOV(block, mem(&m_core->swcount), I0); // mov [swcount],i0
+ UML_TEST(block, I0, I0); // test i0,i0
+ UML_CALLHc(block, COND_NZ, *m_lsw[m_core->mode][G_RD(op)]); // call lsw[rd]
generate_update_cycles(block, compiler, desc->pc + 4, true); // <update cycles>
return true;
@@ -3218,8 +3387,10 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
case 0x295: /* STSWX */
UML_ADD(block, mem(&m_core->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
- UML_AND(block, mem(&m_core->swcount), SPR32(SPR_XER), 0x7f); // and [swcount],[xer],0x7f
- UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), mem(&m_core->swcount));// sub icount,icount,[swcount]
+ UML_AND(block, I0, SPR32(SPR_XER), 0x7f); // and i0,[xer],0x7f
+ UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I0);// sub icount,icount,i0
+ UML_MOV(block, mem(&m_core->swcount), I0); // mov [swcount],i0
+ UML_TEST(block, I0, I0); // test i0,i0
UML_CALLHc(block, COND_NZ, *m_stsw[m_core->mode][G_RD(op)]); // call stsw[rd]
generate_update_cycles(block, compiler, desc->pc + 4, true); // <update cycles>
return true;
@@ -3405,7 +3576,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
return true;
case 0x200: /* MCRXR */
- UML_ROLAND(block, I0, SPR32(SPR_XER), 28, 0x0f); // roland i0,[xer],28,0x0f
+ UML_ROLAND(block, I0, SPR32(SPR_XER), 4, 0x0f); // roland i0,[xer],4,0x0f
UML_SHL(block, I1, XERSO32, 3); // shl i1,[xerso],3
UML_OR(block, CR32(G_CRFD(op)), I0, I1); // or [crd],i0,i1
UML_AND(block, SPR32(SPR_XER), SPR32(SPR_XER), ~0xf0000000); // and [xer],[xer],~0xf0000000
@@ -3793,7 +3964,7 @@ void ppc_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32
if (m_drcuml->logging())
{
std::ostringstream stream;
- powerpc_disassembler::dasm_one(stream, pc, op);
+ m_dasm.dasm_one(stream, pc, op);
block.append_comment("%08X: %s", pc, stream.str()); // comment
}
}
@@ -3982,7 +4153,7 @@ void ppc_device::log_opcode_desc(const opcode_desc *desclist, int indent)
if (desclist->flags & OPFLAG_VIRTUAL_NOOP)
buffer << "<virtual nop>";
else
- powerpc_disassembler::dasm_one(buffer, desclist->pc, desclist->opptr.l[0]);
+ m_dasm.dasm_one(buffer, desclist->pc, desclist->opptr.l[0]);
}
else
buffer << "???";
diff --git a/src/devices/cpu/powerpc/ppcfe.cpp b/src/devices/cpu/powerpc/ppcfe.cpp
index fbb6ae3a313..1e8fb105ee1 100644
--- a/src/devices/cpu/powerpc/ppcfe.cpp
+++ b/src/devices/cpu/powerpc/ppcfe.cpp
@@ -74,7 +74,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev)
int regnum;
// compute the physical PC
- if (!m_ppc.memory_translate(AS_PROGRAM, TRANSLATE_FETCH, desc.physpc))
+ if (m_ppc.ppccom_translate_address_internal(TR_FETCH, false, desc.physpc) > 1)
{
// uh-oh: a page fault; leave the description empty and just if this is the first instruction, leave it empty and
// mark as needing to validate; otherwise, just end the sequence here
@@ -119,6 +119,16 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev)
desc.cycles = 2; // ???
return true;
+ case 0x09: // DOZI (POWER)
+ if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER))
+ {
+ return false;
+ }
+
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ return true;
+
case 0x0e: // ADDI
case 0x0f: // ADDIS
GPR_USED_OR_ZERO(desc, G_RA(op));
@@ -289,8 +299,12 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev)
case 0x2e: // LMW
GPR_USED_OR_ZERO(desc, G_RA(op));
+
for (regnum = G_RD(op); regnum < 32; regnum++)
- GPR_MODIFIED(desc, regnum);
+ {
+ if (regnum != G_RA(op) || ((m_ppc.m_cap & PPCCAP_4XX) && regnum == 31))
+ GPR_MODIFIED(desc, regnum);
+ }
desc.flags |= OPFLAG_READS_MEMORY;
desc.cycles = 32 - G_RD(op);
return true;
@@ -711,6 +725,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc
case 0x136: // ECIWX
if (!(m_ppc.m_cap & PPCCAP_VEA))
return false;
+ [[fallthrough]];
case 0x014: // LWARX
case 0x017: // LWZX
case 0x057: // LBZX
@@ -920,6 +935,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc
case 0x1b6: // ECOWX
if (!(m_ppc.m_cap & PPCCAP_VEA))
return false;
+ [[fallthrough]];
case 0x096: // STWCX.
case 0x097: // STWX
case 0x0d7: // STBX
@@ -1150,6 +1166,81 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc
return false;
desc.flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE;
return true;
+
+ case 0x14b: // DIV (POWER)
+ case 0x16b: // DIVS (POWER)
+ if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER))
+ {
+ return false;
+ }
+
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x6b: // MUL (POWER)
+ if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER))
+ {
+ return false;
+ }
+
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x108: // DOZ (POWER)
+ if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER))
+ {
+ return false;
+ }
+
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x168: // ABS (POWER)
+ case 0x1e8: // NABS (POWER)
+ if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER))
+ {
+ return false;
+ }
+
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x21d: // MASKIR (POWER)
+ if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER))
+ {
+ return false;
+ }
+
+ GPR_USED(desc, G_RS(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
}
return false;
@@ -1339,6 +1430,7 @@ bool ppc_device::frontend::describe_3f(uint32_t op, opcode_desc &desc, const opc
case 0x00e: // FCTIWx
case 0x00f: // FCTIWZx
FPSCR_MODIFIED(desc, 4);
+ [[fallthrough]];
case 0x028: // FNEGx
case 0x048: // FMRx
case 0x088: // FNABSx