diff options
Diffstat (limited to 'src')
45 files changed, 4885 insertions, 2106 deletions
diff --git a/src/devices/bus/spectrum/d40.cpp b/src/devices/bus/spectrum/d40.cpp index 693eae074b0..de29396815b 100644 --- a/src/devices/bus/spectrum/d40.cpp +++ b/src/devices/bus/spectrum/d40.cpp @@ -3,7 +3,12 @@ /********************************************************************** Didaktik D40/D80 disk interface - (C) 1991 Didaktik Scalica + (C) 1991 Didaktik Skalica + + useful commands: + CAT - files list + LIST * - system information + LOAD *"filename" - load program **********************************************************************/ @@ -16,8 +21,9 @@ // DEVICE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(SPECTRUM_D40, spectrum_d40_device, "spectrum_d40", "Didaktik D40 disk interface") -DEFINE_DEVICE_TYPE(SPECTRUM_D80, spectrum_d80_device, "spectrum_d80", "Didaktik D80 disk interface") +DEFINE_DEVICE_TYPE(SPECTRUM_D40, spectrum_d40_device, "spectrum_d40", "Didaktik D40") +DEFINE_DEVICE_TYPE(SPECTRUM_D80, spectrum_d80_device, "spectrum_d80", "Didaktik D80 (MDOS 1, 2793 FDC)") +DEFINE_DEVICE_TYPE(SPECTRUM_D80V2, spectrum_d80v2_device, "spectrum_d80v2", "Didaktik D80 (MDOS 2, 8272 FDC)") //------------------------------------------------- // INPUT_PORTS @@ -25,14 +31,14 @@ DEFINE_DEVICE_TYPE(SPECTRUM_D80, spectrum_d80_device, "spectrum_d80", "Didaktik INPUT_PORTS_START(d40) PORT_START("BUTTON") - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_d40_device, snapshot_button, 0) + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_d40base_device, snapshot_button, 0) INPUT_PORTS_END //------------------------------------------------- // input_ports - device-specific input ports //------------------------------------------------- -ioport_constructor spectrum_d40_device::device_input_ports() const +ioport_constructor spectrum_d40base_device::device_input_ports() const { return INPUT_PORTS_NAME(d40); } @@ -51,8 +57,8 @@ static void didaktik_floppies(device_slot_interface &device) // floppy_format_type floppy_formats //------------------------------------------------- -FLOPPY_FORMATS_MEMBER(spectrum_d40_device::floppy_formats) - FLOPPY_D40D80_FORMAT +FLOPPY_FORMATS_MEMBER(spectrum_d40base_device::floppy_formats) + FLOPPY_PC_FORMAT FLOPPY_FORMATS_END //------------------------------------------------- @@ -64,10 +70,15 @@ ROM_START(d40) ROM_DEFAULT_BIOS("mdos11") ROM_SYSTEM_BIOS(0, "mdos11", "MDOS 1.0 (1991)") ROMX_LOAD("mdos10.bin", 0x0000, 0x4000, CRC(e6b70939) SHA1(308c4b5daf6bb1f05c68a447129d723da423326e), ROM_BIOS(0)) - ROM_SYSTEM_BIOS(1, "mdos12", "MDOS 1.0+ (1992)") + ROM_SYSTEM_BIOS(1, "mdos12", "MDOS 1.0+ (1992)") // possible unofficial modification ROMX_LOAD("mdos10p.bin", 0x0000, 0x4000, CRC(92c45741) SHA1(b8473235feecff4eccbace56a90cf1d8c79506eb), ROM_BIOS(1)) - ROM_SYSTEM_BIOS(2, "mdos2", "MDOS 2.0 (1993)") // doesn't work, from different board type with GM82C765B FDC - ROMX_LOAD("mdos20.bin", 0x0000, 0x4000, CRC(9e79d022) SHA1(e8d3355051fb287dd0dda34ba8824442130c8254), ROM_BIOS(2)) +ROM_END + +ROM_START(d80v2) + ROM_REGION(0x4000, "rom", 0) + ROM_DEFAULT_BIOS("mdos2") + ROM_SYSTEM_BIOS(0, "mdos2", "MDOS 2.0 (1993)") + ROMX_LOAD("mdos20.bin", 0x0000, 0x4000, CRC(9e79d022) SHA1(e8d3355051fb287dd0dda34ba8824442130c8254), ROM_BIOS(0)) ROM_END //------------------------------------------------- @@ -82,6 +93,8 @@ void spectrum_d40_device::device_add_mconfig(machine_config &config) FLOPPY_CONNECTOR(config, "fdc:0", didaktik_floppies, "525dd", spectrum_d40_device::floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "fdc:1", didaktik_floppies, "525dd", spectrum_d40_device::floppy_formats).enable_sound(true); + I8255(config, m_ppi); + /* software list */ //SOFTWARE_LIST(config, "flop_list").set_original("spectrum_d40_flop"); } @@ -94,6 +107,20 @@ void spectrum_d80_device::device_add_mconfig(machine_config &config) FLOPPY_CONNECTOR(config, "fdc:0", didaktik_floppies, "35dd", spectrum_d80_device::floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "fdc:1", didaktik_floppies, "35dd", spectrum_d80_device::floppy_formats).enable_sound(true); + I8255(config, m_ppi); + + /* software list */ + //SOFTWARE_LIST(config, "flop_list").set_original("spectrum_d40_flop"); +} + +void spectrum_d80v2_device::device_add_mconfig(machine_config &config) +{ + WD37C65C(config, m_fdc, 16_MHz_XTAL); // actually GM82C765B + FLOPPY_CONNECTOR(config, "fdc:0", didaktik_floppies, "35dd", spectrum_d80v2_device::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:1", didaktik_floppies, "35dd", spectrum_d80v2_device::floppy_formats).enable_sound(true); + + I8255(config, m_ppi); + /* software list */ //SOFTWARE_LIST(config, "flop_list").set_original("spectrum_d40_flop"); } @@ -103,25 +130,39 @@ const tiny_rom_entry *spectrum_d40_device::device_rom_region() const return ROM_NAME(d40); } +const tiny_rom_entry *spectrum_d80v2_device::device_rom_region() const +{ + return ROM_NAME(d80v2); +} + //************************************************************************** // LIVE DEVICE //************************************************************************** //------------------------------------------------- -// spectrum_d40_device - constructor +// spectrum_d40base_device - constructor //------------------------------------------------- -spectrum_d40_device::spectrum_d40_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) +spectrum_d40base_device::spectrum_d40base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) , device_spectrum_expansion_interface(mconfig, *this) , m_rom(*this, "rom") + , m_ppi(*this, "ppi") + , m_snap(*this, "BUTTON") +{ +} + +spectrum_d40_device::spectrum_d40_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : spectrum_d40base_device(mconfig, SPECTRUM_D40, tag, owner, clock) , m_fdc(*this, "fdc") , m_floppy(*this, "fdc:%u", 0) { } -spectrum_d40_device::spectrum_d40_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : spectrum_d40_device(mconfig, SPECTRUM_D40, tag, owner, clock) +spectrum_d40_device::spectrum_d40_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + :spectrum_d40base_device(mconfig, type, tag, owner, clock) + , m_fdc(*this, "fdc") + , m_floppy(*this, "fdc:%u", 0) { } @@ -130,41 +171,50 @@ spectrum_d80_device::spectrum_d80_device(const machine_config &mconfig, const ch { } +spectrum_d80v2_device::spectrum_d80v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : spectrum_d40base_device(mconfig, SPECTRUM_D80V2, tag, owner, clock) + , m_fdc(*this, "fdc") + , m_floppy(*this, "fdc:%u", 0) +{ +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- -void spectrum_d40_device::device_start() +void spectrum_d40base_device::device_start() { std::fill(std::begin(m_ram), std::end(m_ram), 0); save_item(NAME(m_romcs)); save_item(NAME(m_ram)); - save_item(NAME(m_control)); save_item(NAME(m_snap_flag)); + save_item(NAME(m_8255_reset)); + save_item(NAME(m_8255_enable)); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- -void spectrum_d40_device::device_reset() +void spectrum_d40base_device::device_reset() { m_romcs = 0; - m_control = 0; m_snap_flag = 0; + m_8255_reset = 0; + m_8255_enable = 0; } //************************************************************************** -// IMPLEMENTATION spectrum_d40_device +// IMPLEMENTATION spectrum_d40base_device //************************************************************************** -READ_LINE_MEMBER(spectrum_d40_device::romcs) +READ_LINE_MEMBER(spectrum_d40base_device::romcs) { return m_romcs; } -void spectrum_d40_device::pre_opcode_fetch(offs_t offset) +void spectrum_d40base_device::pre_opcode_fetch(offs_t offset) { if (!machine().side_effects_disabled()) { @@ -173,72 +223,79 @@ void spectrum_d40_device::pre_opcode_fetch(offs_t offset) case 0x0000: case 0x0008: m_romcs = 1; + nmi_check(); break; case 0x0066: if (!m_romcs) { m_romcs = 1; m_snap_flag = 1; + nmi_check(); } break; case 0x1700: - m_romcs = 0; + if (!m_snap_flag) + m_romcs = 0; + nmi_check(); break; } } } -uint8_t spectrum_d40_device::iorq_r(offs_t offset) +uint8_t spectrum_d40base_device::iorq_r(offs_t offset) { uint8_t data = 0xff; switch (offset & 0xf9) { case 0x81: // FDC - data = m_fdc->read((offset >> 1) & 0x03); + data = fdc0_r(offset); + break; + case 0x89: // FDC + data = fdc1_r(offset); break; } + if (!BIT(offset, 7) && m_8255_enable) // 1F/3F/5F/7F + data = m_ppi->read((offset >> 5) & 3); + return data; } -void spectrum_d40_device::iorq_w(offs_t offset, uint8_t data) +void spectrum_d40base_device::iorq_w(offs_t offset, uint8_t data) { switch (offset & 0xf9) { case 0x81: // FDC - m_fdc->write((offset >> 1) & 0x03, data); + fdc0_w(offset, data); break; case 0x89: // control port - { - m_control = data; - - floppy_image_device* floppy = nullptr; - if (BIT(data, 0)) - floppy = m_floppy[0]->get_device(); - else if (BIT(data, 1)) - floppy = m_floppy[1]->get_device(); - m_fdc->set_floppy(floppy); - - m_floppy[0]->get_device()->mon_w(BIT(data, 2) ? 0 : 1); - m_floppy[1]->get_device()->mon_w(BIT(data, 3) ? 0 : 1); - } + fdc1_w(offset, data); break; case 0x91: // PPI reset - // TODO PPI + m_8255_reset = BIT(data, 5); + if (!m_8255_reset) + { + m_ppi->reset(); + m_8255_enable = 0; + } break; case 0x99: // PPI enable - // TODO PPI + if (m_8255_reset) + m_8255_enable = BIT(data, 4); break; } + + if (!BIT(offset, 7) && m_8255_enable) // 1F/3F/5F/7F + m_ppi->write((offset >> 5) & 3, data); } -uint8_t spectrum_d40_device::mreq_r(offs_t offset) +uint8_t spectrum_d40base_device::mreq_r(offs_t offset) { if (m_snap_flag && offset == 0x66) { - m_snap_flag = 0; - return 0xc7; + m_snap_flag = 0; // hacky, real hardware reset this latch by Z80 /WR line + return 0xc7; // RST 0 inject } uint8_t data = 0xff; @@ -254,7 +311,7 @@ uint8_t spectrum_d40_device::mreq_r(offs_t offset) return data; } -void spectrum_d40_device::mreq_w(offs_t offset, uint8_t data) +void spectrum_d40base_device::mreq_w(offs_t offset, uint8_t data) { if (m_romcs) { @@ -263,17 +320,152 @@ void spectrum_d40_device::mreq_w(offs_t offset, uint8_t data) } } -INPUT_CHANGED_MEMBER(spectrum_d40_device::snapshot_button) +INPUT_CHANGED_MEMBER(spectrum_d40base_device::snapshot_button) +{ + nmi_check(); +} + +void spectrum_d40base_device::nmi_check() +{ + int state = CLEAR_LINE; + + if (!m_romcs && m_snap->read()) + state = ASSERT_LINE; + + m_slot->nmi_w(state); +} + +//************************************************************************** +// IMPLEMENTATION spectrum_d40_device +//************************************************************************** + +void spectrum_d40_device::device_start() +{ + spectrum_d40base_device::device_start(); + save_item(NAME(m_control)); + save_item(NAME(m_intrq)); + save_item(NAME(m_drq)); +} + +void spectrum_d40_device::device_reset() { - m_slot->nmi_w((!newval && oldval && !m_romcs) ? ASSERT_LINE : CLEAR_LINE); + spectrum_d40base_device::device_reset(); + m_control = 0; + m_intrq = 0; + m_drq = 0; +} + +uint8_t spectrum_d40_device::fdc0_r(offs_t offset) +{ + return m_fdc->read((offset >> 1) & 0x03); +} + +void spectrum_d40_device::fdc0_w(offs_t offset, uint8_t data) +{ + m_fdc->write((offset >> 1) & 0x03, data); +} + +void spectrum_d40_device::fdc1_w(offs_t offset, uint8_t data) +{ + m_control = data; + + floppy_image_device* floppy = nullptr; + if (BIT(data, 0)) + floppy = m_floppy[0]->get_device(); + else if (BIT(data, 1)) + floppy = m_floppy[1]->get_device(); + m_fdc->set_floppy(floppy); + + m_floppy[0]->get_device()->mon_w(BIT(data, 2) ? 0 : 1); + m_floppy[1]->get_device()->mon_w(BIT(data, 3) ? 0 : 1); + + nmi_check(); } void spectrum_d40_device::fdc_intrq_w(int state) { - m_slot->nmi_w((state && BIT(m_control, 7)) ? ASSERT_LINE : CLEAR_LINE); + m_intrq = state; + nmi_check(); } void spectrum_d40_device::fdc_drq_w(int state) { - m_slot->nmi_w((state && BIT(m_control, 6)) ? ASSERT_LINE : CLEAR_LINE); + m_drq = state; + nmi_check(); +} + +void spectrum_d40_device::nmi_check() +{ + int state = CLEAR_LINE; + + if (!m_romcs && m_snap->read()) + state = ASSERT_LINE; + + if (m_intrq && BIT(m_control, 7)) + state = ASSERT_LINE; + + if (m_drq && BIT(m_control, 6)) + state = ASSERT_LINE; + + m_slot->nmi_w(state); +} + +//************************************************************************** +// IMPLEMENTATION spectrum_d80v2_device +//************************************************************************** + +void spectrum_d80v2_device::pre_opcode_fetch(offs_t offset) +{ + if (!machine().side_effects_disabled()) + { + switch (offset) + { + case 0x0000: + case 0x0008: + case 0x0066: + m_romcs = 1; + nmi_check(); + break; + case 0x1700: + m_romcs = 0; + nmi_check(); + break; + } + } +} + +uint8_t spectrum_d80v2_device::fdc0_r(offs_t offset) +{ + return BIT(offset, 2) ? m_fdc->fifo_r() : m_fdc->msr_r(); +} + +uint8_t spectrum_d80v2_device::fdc1_r(offs_t offset) +{ + return m_fdc->dor_r(); +} + +void spectrum_d80v2_device::fdc0_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 2)) + m_fdc->fifo_w(data); +} + +void spectrum_d80v2_device::fdc1_w(offs_t offset, uint8_t data) +{ + m_fdc->dor_w(data); +} + +uint8_t spectrum_d80v2_device::mreq_r(offs_t offset) +{ + uint8_t data = 0xff; + + if (m_romcs) + { + if (offset < 0x3800) + data = m_rom->base()[offset]; + else + data = m_ram[offset & 0x7ff]; + } + + return data; } diff --git a/src/devices/bus/spectrum/d40.h b/src/devices/bus/spectrum/d40.h index 42bd876bf0a..94be7b77084 100644 --- a/src/devices/bus/spectrum/d40.h +++ b/src/devices/bus/spectrum/d40.h @@ -15,32 +15,29 @@ //#include "softlist.h" #include "imagedev/floppy.h" #include "machine/wd_fdc.h" -#include "formats/d40_dsk.h" +#include "machine/upd765.h" +#include "machine/i8255.h" +#include "formats/pc_dsk.h" //************************************************************************** // TYPE DEFINITIONS //************************************************************************** -class spectrum_d40_device: public device_t, public device_spectrum_expansion_interface +class spectrum_d40base_device: public device_t, public device_spectrum_expansion_interface { public: - // construction/destruction - spectrum_d40_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - DECLARE_FLOPPY_FORMATS(floppy_formats); DECLARE_INPUT_CHANGED_MEMBER(snapshot_button); + DECLARE_FLOPPY_FORMATS(floppy_formats); protected: - spectrum_d40_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + spectrum_d40base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // device-level overrides virtual void device_start() override; virtual void device_reset() override; // optional information overrides - virtual void device_add_mconfig(machine_config &config) override; virtual ioport_constructor device_input_ports() const override; - virtual const tiny_rom_entry *device_rom_region() const override; virtual void pre_opcode_fetch(offs_t offset) override; virtual uint8_t mreq_r(offs_t offset) override; @@ -49,31 +46,87 @@ protected: virtual void iorq_w(offs_t offset, uint8_t data) override; virtual DECLARE_READ_LINE_MEMBER(romcs) override; - void fdc_intrq_w(int state); - void fdc_drq_w(int state); + virtual uint8_t fdc0_r(offs_t offset) { return 0xff; }; + virtual uint8_t fdc1_r(offs_t offset) { return 0xff; }; + virtual void fdc0_w(offs_t offset, uint8_t data) { }; + virtual void fdc1_w(offs_t offset, uint8_t data) { }; + virtual void nmi_check(); required_memory_region m_rom; - required_device<wd_fdc_device_base> m_fdc; - required_device_array<floppy_connector, 2> m_floppy; + required_device<i8255_device> m_ppi; + required_ioport m_snap; int m_romcs; uint8_t m_ram[2 * 1024]; - uint8_t m_control; int m_snap_flag; + int m_8255_reset; + int m_8255_enable; +}; + +class spectrum_d40_device : + public spectrum_d40base_device +{ +public: + spectrum_d40_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + spectrum_d40_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual void device_start() override; + virtual void device_reset() override; + + required_device<wd_fdc_device_base> m_fdc; + required_device_array<floppy_connector, 2> m_floppy; + + virtual uint8_t fdc0_r(offs_t offset) override; + virtual void fdc0_w(offs_t offset, uint8_t data) override; + virtual void fdc1_w(offs_t offset, uint8_t data) override; + void fdc_intrq_w(int state); + void fdc_drq_w(int state); + virtual void nmi_check() override; + + uint8_t m_control; + int m_intrq; + int m_drq; }; class spectrum_d80_device : public spectrum_d40_device { public: - // construction/destruction spectrum_d80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config &config) override; +}; + +class spectrum_d80v2_device : + public spectrum_d40base_device +{ +public: + spectrum_d80v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + protected: virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual void pre_opcode_fetch(offs_t offset) override; + virtual uint8_t mreq_r(offs_t offset) override; + + required_device<wd37c65c_device> m_fdc; + required_device_array<floppy_connector, 2> m_floppy; + + virtual uint8_t fdc0_r(offs_t offset) override; + virtual uint8_t fdc1_r(offs_t offset) override; + virtual void fdc0_w(offs_t offset, uint8_t data) override; + virtual void fdc1_w(offs_t offset, uint8_t data) override; }; // device type definition DECLARE_DEVICE_TYPE(SPECTRUM_D40, spectrum_d40_device) DECLARE_DEVICE_TYPE(SPECTRUM_D80, spectrum_d80_device) +DECLARE_DEVICE_TYPE(SPECTRUM_D80V2, spectrum_d80v2_device) #endif // MAME_BUS_SPECTRUM_D40_H diff --git a/src/devices/bus/spectrum/exp.cpp b/src/devices/bus/spectrum/exp.cpp index 10fac7b65d8..57b8bceaa8a 100644 --- a/src/devices/bus/spectrum/exp.cpp +++ b/src/devices/bus/spectrum/exp.cpp @@ -197,6 +197,7 @@ void spectrum_expansion_devices(device_slot_interface &device) device.option_add("plusd", SPECTRUM_PLUSD); device.option_add("d40", SPECTRUM_D40); device.option_add("d80", SPECTRUM_D80); + device.option_add("d80v2", SPECTRUM_D80V2); device.option_add("protek", SPECTRUM_PROTEK); device.option_add("specdrum", SPECTRUM_SPECDRUM); device.option_add("uslot", SPECTRUM_USLOT); @@ -216,8 +217,6 @@ void spec128_expansion_devices(device_slot_interface &device) device.option_add("mikroplus", SPECTRUM_MIKROPLUS); device.option_add("mprint", SPECTRUM_MPRINT); device.option_add("opus", SPECTRUM_OPUS); - //device.option_add("d40", SPECTRUM_D40); - //device.option_add("d80", SPECTRUM_D80); //device.option_add("plusd", SPECTRUM_PLUSD); device.option_add("plus2test", SPECTRUM_PLUS2TEST); device.option_add("protek", SPECTRUM_PROTEK); diff --git a/src/devices/bus/ti99/internal/992board.cpp b/src/devices/bus/ti99/internal/992board.cpp index 20b96f84186..031f82d7fe5 100644 --- a/src/devices/bus/ti99/internal/992board.cpp +++ b/src/devices/bus/ti99/internal/992board.cpp @@ -7,7 +7,12 @@ This component implements the custom video controller and interface chip from the TI-99/2 console. + Also, we emulate the expansion port at the backside of the console; there + are no known expansions except for a RAM expansion that is mentioned + in the specifications. + May 2018 + June 2020 ***************************************************************************/ @@ -20,8 +25,9 @@ #define LOG_HEXBUS (1U<<4) // Hexbus logging #define LOG_BANK (1U<<5) // Change ROM banks #define LOG_KEYBOARD (1U<<6) // Keyboard operation +#define LOG_EXPRAM (1U<<7) // Expansion RAM -#define VERBOSE ( LOG_WARN ) +#define VERBOSE ( LOG_GENERAL | LOG_WARN ) #include "logmacro.h" @@ -128,6 +134,8 @@ DEFINE_DEVICE_TYPE_NS(VIDEO99232, bus::ti99::internal, video992_32_device, "vide DEFINE_DEVICE_TYPE_NS(IO99224, bus::ti99::internal, io992_24_device, "io992_24", "TI-99/2 I/O controller 24K version") DEFINE_DEVICE_TYPE_NS(IO99232, bus::ti99::internal, io992_32_device, "io992_32", "TI-99/2 I/O controller 32K version") +DEFINE_DEVICE_TYPE_NS(TI992_EXPPORT, bus::ti99::internal, ti992_expport_device, "ti992_expport", "TI-99/2 Expansion Port") +DEFINE_DEVICE_TYPE_NS(TI992_RAM32K, bus::ti99::internal, ti992_expram_device, "ti992_ram32k", "TI-99/2 RAM Expansion 32K") namespace bus { namespace ti99 { namespace internal { @@ -596,6 +604,82 @@ ioport_constructor io992_device::device_input_ports() const return INPUT_PORTS_NAME( keys992 ); } +/******************************************************************** + Expansion port +********************************************************************/ + +ti992_expport_device::ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, TI992_EXPPORT, tag, owner, clock), + device_slot_interface(mconfig, *this), + m_connected(nullptr) +{ +} + +void ti992_expport_device::readz(offs_t offset, uint8_t *value) +{ + if (m_connected != nullptr) + m_connected->readz(offset, value); +} + +void ti992_expport_device::write(offs_t offset, uint8_t data) +{ + if (m_connected != nullptr) + m_connected->write(offset, data); +} + +void ti992_expport_device::device_config_complete() +{ + m_connected = static_cast<ti992_expport_attached_device*>(subdevices().first()); +} + +/* + 32K Expansion cartridge + Maps at 6000 - DFFF + This is the only known expansion device +*/ +ti992_expram_device::ti992_expram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + ti992_expport_attached_device(mconfig, TI992_RAM32K, tag, owner, clock), + m_ram(*this, "ram32k") +{ +} + +void ti992_expram_device::readz(offs_t offset, uint8_t *value) +{ + // 000 -> 100 100 -> 000 + // 001 -> 101 101 -> 001 + // 010 -> 110 110 -> 010 + // 011 -> 011 111 -> 111 + offs_t address = offset; + if ((offset & 0x6000) != 0x6000) address ^= 0x8000; + if ((address & 0x8000)==0) + { + *value = m_ram->read(address); + LOGMASKED(LOG_EXPRAM, "expram %04x -> %02x\n", offset, *value); + } +} + +void ti992_expram_device::write(offs_t offset, uint8_t value) +{ + offs_t address = offset; + if ((offset & 0x6000) != 0x6000) address ^= 0x8000; + if ((address & 0x8000)==0) + { + m_ram->write(address, value); + LOGMASKED(LOG_EXPRAM, "expram %04x <- %02x\n", offset, value); + } +} + +void ti992_expram_device::device_add_mconfig(machine_config &config) +{ + RAM(config, m_ram, 0); + m_ram->set_default_size("32k"); + m_ram->set_default_value(0); +} + } } } +void ti992_expport_options(device_slot_interface &device) +{ + device.option_add("ram32k", TI992_RAM32K); +} diff --git a/src/devices/bus/ti99/internal/992board.h b/src/devices/bus/ti99/internal/992board.h index 75849ce2aea..83f42035839 100644 --- a/src/devices/bus/ti99/internal/992board.h +++ b/src/devices/bus/ti99/internal/992board.h @@ -21,6 +21,7 @@ #include "screen.h" #include "bus/hexbus/hexbus.h" #include "imagedev/cassette.h" +#include "machine/ram.h" #define TI992_CASSETTE "cassette" #define TI992_VDC_TAG "vdc" @@ -149,11 +150,87 @@ public: io992_32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +/******************************************************************** + + Expansion port + This is modeled after the ioport connector of the TI-99/4A + + However, since there are basically no expansion cards available, + and only the memory expansion was described in the specs, we + only include the necessary connections. + +********************************************************************/ +#define TI992_EXPPORT_TAG "expport" + +class ti992_expport_attached_device : public device_t +{ +public: + ti992_expport_attached_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock) + { } + + // Methods called from the console + virtual void readz(offs_t offset, uint8_t *value) { } + virtual void write(offs_t offset, uint8_t data) { } +}; + +class ti992_expport_device : public device_t, public device_slot_interface +{ + friend class expport_attached_device; + +public: + template <typename U> + ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, U &&opts, const char *dflt) + : ti992_expport_device(mconfig, tag, owner, clock) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_fixed(false); + } + + ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // Methods called from the console + // More methods should be added, once we can find further 99/2 cartridges + void readz(offs_t offset, uint8_t *value); + void write(offs_t offset, uint8_t data); + +protected: + void device_start() override { }; + void device_config_complete() override; + +private: + ti992_expport_attached_device* m_connected; +}; + +// RAM expansion + +class ti992_expram_device : public ti992_expport_attached_device +{ +public: + ti992_expram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + void readz(offs_t offset, uint8_t *value) override; + void write(offs_t offset, uint8_t data) override; + +private: + void device_start() override {}; + void device_add_mconfig(machine_config &config) override; + required_device<ram_device> m_ram; +}; + + } } } // end namespace bus::ti99::internal +DECLARE_DEVICE_TYPE_NS(TI992_EXPPORT, bus::ti99::internal, ti992_expport_device) + +void ti992_expport_options(device_slot_interface &device); + DECLARE_DEVICE_TYPE_NS(VIDEO99224, bus::ti99::internal, video992_24_device) DECLARE_DEVICE_TYPE_NS(VIDEO99232, bus::ti99::internal, video992_32_device) DECLARE_DEVICE_TYPE_NS(IO99224, bus::ti99::internal, io992_24_device) DECLARE_DEVICE_TYPE_NS(IO99232, bus::ti99::internal, io992_32_device) +DECLARE_DEVICE_TYPE_NS(TI992_RAM32K, bus::ti99::internal, ti992_expram_device) + #endif // MAME_BUS_TI99_INTERNAL_992BOARD_H diff --git a/src/devices/cpu/arm7/arm7.cpp b/src/devices/cpu/arm7/arm7.cpp index d76a54a3c91..608d84a8612 100644 --- a/src/devices/cpu/arm7/arm7.cpp +++ b/src/devices/cpu/arm7/arm7.cpp @@ -66,7 +66,9 @@ DEFINE_DEVICE_TYPE(ARM920T, arm920t_cpu_device, "arm920t", "ARM92 DEFINE_DEVICE_TYPE(ARM946ES, arm946es_cpu_device, "arm946es", "ARM946ES") DEFINE_DEVICE_TYPE(ARM11, arm11_cpu_device, "arm11", "ARM11") DEFINE_DEVICE_TYPE(ARM1176JZF_S, arm1176jzf_s_cpu_device, "arm1176jzf_s", "ARM1176JZF-S") +DEFINE_DEVICE_TYPE(PXA250, pxa250_cpu_device, "pxa250", "Intel XScale PXA250") DEFINE_DEVICE_TYPE(PXA255, pxa255_cpu_device, "pxa255", "Intel XScale PXA255") +DEFINE_DEVICE_TYPE(PXA270, pxa270_cpu_device, "pxa270", "Intel XScale PXA270") DEFINE_DEVICE_TYPE(SA1110, sa1110_cpu_device, "sa1110", "Intel StrongARM SA-1110") DEFINE_DEVICE_TYPE(IGS036, igs036_cpu_device, "igs036", "IGS036") @@ -236,13 +238,30 @@ igs036_cpu_device::igs036_cpu_device(const machine_config &mconfig, const char * { } +pxa250_cpu_device::pxa250_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, PXA250, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E | ARCHFLAG_XSCALE, ENDIANNESS_LITTLE) +{ + m_copro_id = ARM9_COPRO_ID_MFR_INTEL + | ARM9_COPRO_ID_ARCH_V5TE + | ARM9_COPRO_ID_PART_PXA250 + | ARM9_COPRO_ID_STEP_PXA255_A0; +} + pxa255_cpu_device::pxa255_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : arm7_cpu_device(mconfig, PXA255, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E | ARCHFLAG_XSCALE, ENDIANNESS_LITTLE) { m_copro_id = ARM9_COPRO_ID_MFR_INTEL | ARM9_COPRO_ID_ARCH_V5TE - | ARM9_COPRO_ID_PXA255_CORE_GEN_XSCALE - | (3 << ARM9_COPRO_ID_PXA255_CORE_REV_SHIFT) + | ARM9_COPRO_ID_PART_PXA255 + | ARM9_COPRO_ID_STEP_PXA255_A0; +} + +pxa270_cpu_device::pxa270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, PXA270, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E | ARCHFLAG_XSCALE, ENDIANNESS_LITTLE) +{ + m_copro_id = ARM9_COPRO_ID_MFR_INTEL + | ARM9_COPRO_ID_ARCH_V5TE + | ARM9_COPRO_ID_PART_PXA270 | ARM9_COPRO_ID_STEP_PXA255_A0; } diff --git a/src/devices/cpu/arm7/arm7.h b/src/devices/cpu/arm7/arm7.h index 3f6f9c290a5..80757afe13b 100644 --- a/src/devices/cpu/arm7/arm7.h +++ b/src/devices/cpu/arm7/arm7.h @@ -89,10 +89,12 @@ protected: ARM9_COPRO_ID_PART_ARM946 = 0x946 << 4, ARM9_COPRO_ID_PART_ARM920 = 0x920 << 4, ARM9_COPRO_ID_PART_ARM710 = 0x710 << 4, + ARM9_COPRO_ID_PART_PXA250 = 0x200 << 4, + ARM9_COPRO_ID_PART_PXA255 = 0x2d0 << 4, + ARM9_COPRO_ID_PART_PXA270 = 0x411 << 4, ARM9_COPRO_ID_PART_GENERICARM7 = 0x700 << 4, ARM9_COPRO_ID_PXA255_CORE_REV_SHIFT = 10, - ARM9_COPRO_ID_PXA255_CORE_GEN_XSCALE = 0x01 << 13, ARM9_COPRO_ID_ARCH_V4 = 0x01 << 16, ARM9_COPRO_ID_ARCH_V4T = 0x02 << 16, @@ -691,6 +693,13 @@ public: igs036_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class pxa250_cpu_device : public arm7_cpu_device +{ +public: + // construction/destruction + pxa250_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + class pxa255_cpu_device : public arm7_cpu_device { public: @@ -698,6 +707,12 @@ public: pxa255_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class pxa270_cpu_device : public arm7_cpu_device +{ +public: + // construction/destruction + pxa270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; class sa1110_cpu_device : public arm7_cpu_device { @@ -716,7 +731,9 @@ DECLARE_DEVICE_TYPE(ARM920T, arm920t_cpu_device) DECLARE_DEVICE_TYPE(ARM946ES, arm946es_cpu_device) DECLARE_DEVICE_TYPE(ARM11, arm11_cpu_device) DECLARE_DEVICE_TYPE(ARM1176JZF_S, arm1176jzf_s_cpu_device) +DECLARE_DEVICE_TYPE(PXA250, pxa250_cpu_device) DECLARE_DEVICE_TYPE(PXA255, pxa255_cpu_device) +DECLARE_DEVICE_TYPE(PXA270, pxa270_cpu_device) DECLARE_DEVICE_TYPE(SA1110, sa1110_cpu_device) DECLARE_DEVICE_TYPE(IGS036, igs036_cpu_device) diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp index c6222d2050c..aa1860ba089 100644 --- a/src/devices/cpu/drcbex64.cpp +++ b/src/devices/cpu/drcbex64.cpp @@ -177,6 +177,28 @@ // and the x64 SDK declares ::REG_Exx and ::REG_Rxx namespace drc { using namespace uml; +using namespace x64emit; + +using x64emit::REG_EAX; +using x64emit::REG_ECX; +using x64emit::REG_EDX; +using x64emit::REG_RAX; +using x64emit::REG_RCX; +using x64emit::REG_RDX; +using x64emit::REG_RBX; +using x64emit::REG_RSP; +using x64emit::REG_RBP; +using x64emit::REG_RSI; +using x64emit::REG_RDI; + +using x64emit::REG_R8; +using x64emit::REG_R9; +using x64emit::REG_R10; +using x64emit::REG_R11; +using x64emit::REG_R12; +using x64emit::REG_R13; +using x64emit::REG_R14; +using x64emit::REG_R15; @@ -209,17 +231,17 @@ const uint32_t PTYPE_MF = PTYPE_M | PTYPE_F; #ifdef X64_WINDOWS_ABI -const uint32_t REG_PARAM1 = rcx.id(); -const uint32_t REG_PARAM2 = rdx.id(); -const uint32_t REG_PARAM3 = r8.id(); -const uint32_t REG_PARAM4 = r9.id(); +const int REG_PARAM1 = REG_RCX; +const int REG_PARAM2 = REG_RDX; +const int REG_PARAM3 = REG_R8; +const int REG_PARAM4 = REG_R9; #else -const uint32_t REG_PARAM1 = rdi.id(); -const uint32_t REG_PARAM2 = rsi.id(); -const uint32_t REG_PARAM3 = rdx.id(); -const uint32_t REG_PARAM4 = rcx.id(); +const int REG_PARAM1 = REG_RDI; +const int REG_PARAM2 = REG_RSI; +const int REG_PARAM3 = REG_RDX; +const int REG_PARAM4 = REG_RCX; #endif @@ -232,9 +254,9 @@ const uint32_t REG_PARAM4 = rcx.id(); #define X86_CONDITION(condition) (condition_map[condition - uml::COND_Z]) #define X86_NOT_CONDITION(condition) (condition_map[condition - uml::COND_Z] ^ 1) -inline Mem drcbe_x64::MABS(const void *ptr, const uint32_t size) +inline x86_memref drcbe_x64::MABS(const void *ptr) { - return Mem(rbp, offset_from_rbp(ptr), size); + return MBD(REG_BP, offset_from_rbp(ptr)); } #define assert_no_condition(inst) assert((inst).condition() == uml::COND_ALWAYS) @@ -254,45 +276,45 @@ drcbe_x64::opcode_generate_func drcbe_x64::s_opcode_table[OP_MAX]; //static const uint64_t size_to_mask[] = { 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0, 0xffffffffffffffffU }; // register mapping tables -static const uint32_t int_register_map[REG_I_COUNT] = +static const uint8_t int_register_map[REG_I_COUNT] = { #ifdef X64_WINDOWS_ABI - rbx.id(), rsi.id(), rdi.id(), r12.id(), r13.id(), r14.id(), r15.id(), + REG_RBX, REG_RSI, REG_RDI, REG_R12, REG_R13, REG_R14, REG_R15 #else - rbx.id(), r12.id(), r13.id(), r14.id(), r15.id() + REG_RBX, REG_R12, REG_R13, REG_R14, REG_R15 #endif }; -static uint32_t float_register_map[REG_F_COUNT] = +static uint8_t float_register_map[REG_F_COUNT] = { #ifdef X64_WINDOWS_ABI - xmm6.id(), xmm7.id(), xmm8.id(), xmm9.id(), xmm10.id(), xmm11.id(), xmm12.id(), xmm13.id(), xmm14.id(), xmm15.id() + REG_XMM6, REG_XMM7, REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15 #else // on AMD x64 ABI, XMM0-7 are FP function args. since this code has no args, and we // save/restore them around CALLC, they should be safe for our use. - xmm0.id(), xmm1.id(), xmm2.id(), xmm3.id(), xmm4.id(), xmm5.id(), xmm6.id(), xmm7.id() + REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7 #endif }; // condition mapping table -static const Condition::Code condition_map[uml::COND_MAX - uml::COND_Z] = -{ - Condition::Code::kZ, // COND_Z = 0x80, requires Z - Condition::Code::kNZ, // COND_NZ, requires Z - Condition::Code::kS, // COND_S, requires S - Condition::Code::kNS, // COND_NS, requires S - Condition::Code::kC, // COND_C, requires C - Condition::Code::kNC, // COND_NC, requires C - Condition::Code::kO, // COND_V, requires V - Condition::Code::kNO, // COND_NV, requires V - Condition::Code::kP, // COND_U, requires U - Condition::Code::kNP, // COND_NU, requires U - Condition::Code::kA, // COND_A, requires CZ - Condition::Code::kBE, // COND_BE, requires CZ - Condition::Code::kG, // COND_G, requires SVZ - Condition::Code::kLE, // COND_LE, requires SVZ - Condition::Code::kL, // COND_L, requires SV - Condition::Code::kGE, // COND_GE, requires SV +static const uint8_t condition_map[uml::COND_MAX - uml::COND_Z] = +{ + x64emit::COND_Z, // COND_Z = 0x80, requires Z + x64emit::COND_NZ, // COND_NZ, requires Z + x64emit::COND_S, // COND_S, requires S + x64emit::COND_NS, // COND_NS, requires S + x64emit::COND_C, // COND_C, requires C + x64emit::COND_NC, // COND_NC, requires C + x64emit::COND_O, // COND_V, requires V + x64emit::COND_NO, // COND_NV, requires V + x64emit::COND_P, // COND_U, requires U + x64emit::COND_NP, // COND_NU, requires U + x64emit::COND_A, // COND_A, requires CZ + x64emit::COND_BE, // COND_BE, requires CZ + x64emit::COND_G, // COND_G, requires SVZ + x64emit::COND_LE, // COND_LE, requires SVZ + x64emit::COND_L, // COND_L, requires SV + x64emit::COND_GE, // COND_GE, requires SV }; #if 0 @@ -371,13 +393,13 @@ const drcbe_x64::opcode_table_entry drcbe_x64::s_opcode_table_source[] = { uml::OP_LZCNT, &drcbe_x64::op_lzcnt }, // LZCNT dst,src[,f] { uml::OP_TZCNT, &drcbe_x64::op_tzcnt }, // TZCNT dst,src[,f] { uml::OP_BSWAP, &drcbe_x64::op_bswap }, // BSWAP dst,src - { uml::OP_SHL, &drcbe_x64::op_shift<Inst::kIdShl> }, // SHL dst,src,count[,f] - { uml::OP_SHR, &drcbe_x64::op_shift<Inst::kIdShr> }, // SHR dst,src,count[,f] - { uml::OP_SAR, &drcbe_x64::op_shift<Inst::kIdSar> }, // SAR dst,src,count[,f] - { uml::OP_ROL, &drcbe_x64::op_shift<Inst::kIdRol> }, // ROL dst,src,count[,f] - { uml::OP_ROLC, &drcbe_x64::op_shift<Inst::kIdRcl> }, // ROLC dst,src,count[,f] - { uml::OP_ROR, &drcbe_x64::op_shift<Inst::kIdRor> }, // ROR dst,src,count[,f] - { uml::OP_RORC, &drcbe_x64::op_shift<Inst::kIdRcr> }, // RORC dst,src,count[,f] + { uml::OP_SHL, &drcbe_x64::op_shl }, // SHL dst,src,count[,f] + { uml::OP_SHR, &drcbe_x64::op_shr }, // SHR dst,src,count[,f] + { uml::OP_SAR, &drcbe_x64::op_sar }, // SAR dst,src,count[,f] + { uml::OP_ROL, &drcbe_x64::op_rol }, // ROL dst,src,count[,f] + { uml::OP_ROLC, &drcbe_x64::op_rolc }, // ROLC dst,src,count[,f] + { uml::OP_ROR, &drcbe_x64::op_ror }, // ROR dst,src,count[,f] + { uml::OP_RORC, &drcbe_x64::op_rorc }, // RORC dst,src,count[,f] // Floating Point Operations { uml::OP_FLOAD, &drcbe_x64::op_fload }, // FLOAD dst,base,index @@ -467,28 +489,21 @@ drcbe_x64::be_parameter::be_parameter(drcbe_x64 &drcbe, const parameter ¶m, // checkparam //------------------------------------------------- -inline Gp drcbe_x64::be_parameter::select_register(Gp defreg) const +inline int drcbe_x64::be_parameter::select_register(int defreg) const { - if (m_type == PTYPE_INT_REGISTER) - return Gp::fromTypeAndId(defreg.type(), m_value); + if (m_type == PTYPE_INT_REGISTER || m_type == PTYPE_FLOAT_REGISTER || m_type == PTYPE_VECTOR_REGISTER) + return m_value; return defreg; } -inline Xmm drcbe_x64::be_parameter::select_register(Xmm defreg) const -{ - if (m_type == PTYPE_FLOAT_REGISTER) - return Xmm(m_value); - return defreg; -} - -template <typename T> T drcbe_x64::be_parameter::select_register(T defreg, const be_parameter &checkparam) const +inline int drcbe_x64::be_parameter::select_register(int defreg, const be_parameter &checkparam) const { if (*this == checkparam) return defreg; return select_register(defreg); } -template <typename T> T drcbe_x64::be_parameter::select_register(T defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const +inline int drcbe_x64::be_parameter::select_register(int defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const { if (*this == checkparam || *this == checkparam2) return defreg; @@ -542,18 +557,18 @@ inline int32_t drcbe_x64::offset_from_rbp(const void *ptr) // target address //------------------------------------------------- -inline Gp drcbe_x64::get_base_register_and_offset(Assembler &a, void *target, Gp reg, int32_t &offset) +inline int drcbe_x64::get_base_register_and_offset(x86code *&dst, void *target, uint8_t reg, int32_t &offset) { const int64_t delta = reinterpret_cast<uint8_t *>(target) - m_rbpvalue; if (short_immediate(delta)) { offset = delta; - return rbp; + return REG_RBP; } else { offset = 0; - emit_mov_r64_imm(a, reg, uintptr_t(target)); // mov reg,target + emit_mov_r64_imm(dst, reg, uintptr_t(target)); // mov reg,target return reg; } } @@ -564,15 +579,15 @@ inline Gp drcbe_x64::get_base_register_and_offset(Assembler &a, void *target, Gp // directly or via a call through pointer //------------------------------------------------- -inline void drcbe_x64::emit_smart_call_r64(Assembler &a, x86code *target, Gp reg) +inline void drcbe_x64::emit_smart_call_r64(x86code *&dst, x86code *target, uint8_t reg) { - const int64_t delta = target - (x86code *)(a.code()->baseAddress() + a.offset() + 5); + const int64_t delta = target - (dst + 5); if (short_immediate(delta)) - a.call(imm(target)); // call target + emit_call(dst, target); // call target else { - emit_mov_r64_imm(a, reg, uintptr_t(target)); // mov reg,target - a.call(reg); // call reg + emit_mov_r64_imm(dst, reg, uintptr_t(target)); // mov reg,target + emit_call_r64(dst, reg); // call reg } } @@ -582,13 +597,13 @@ inline void drcbe_x64::emit_smart_call_r64(Assembler &a, x86code *target, Gp reg // directly or via a call through pointer //------------------------------------------------- -inline void drcbe_x64::emit_smart_call_m64(Assembler &a, x86code **target) +inline void drcbe_x64::emit_smart_call_m64(x86code *&dst, x86code **target) { - const int64_t delta = *target - (x86code *)(a.code()->baseAddress() + a.offset() + 5); + const int64_t delta = *target - (dst + 5); if (short_immediate(delta)) - a.call(imm(*target)); // call *target + emit_call(dst, *target); // call *target else - a.call(MABS(target)); // call [target] + emit_call_m64(dst, MABS(target)); // call [target] } @@ -607,13 +622,15 @@ drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, u m_map(cache, 0xaaaaaaaa5555), m_labels(cache), m_log(nullptr), - m_log_asmjit(nullptr), + m_sse41(false), m_absmask32((uint32_t *)cache.alloc_near(16*2 + 15)), m_absmask64(nullptr), m_rbpvalue(cache.near() + 0x80), m_entry(nullptr), m_exit(nullptr), m_nocode(nullptr), + m_fixup_label(&drcbe_x64::fixup_label, this), + m_fixup_exception(&drcbe_x64::fixup_exception, this), m_near(*(near_state *)cache.alloc_near(sizeof(m_near))) { // build up necessary arrays @@ -676,7 +693,6 @@ drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, u { std::string filename = std::string("drcbex64_").append(device.shortname()).append(".asm"); m_log = x86log_create_context(filename.c_str()); - m_log_asmjit = fopen(std::string("drcbex64_asmjit_").append(device.shortname()).append(".asm").c_str(), "w"); } } @@ -690,39 +706,8 @@ drcbe_x64::~drcbe_x64() // free the log context if (m_log != nullptr) x86log_free_context(m_log); - - if (m_log_asmjit) - fclose(m_log_asmjit); } -size_t drcbe_x64::emit(CodeHolder &ch) -{ - Error err = ch.flatten(); - if (err) - throw emu_fatalerror("asmjit::CodeHolder::flatten() error %d", err); - - err = ch.resolveUnresolvedLinks(); - if (err) - throw emu_fatalerror("asmjit::CodeHolder::resolveUnresolvedLinks() error %d", err); - - size_t const alignment = ch.baseAddress() - uint64_t(m_cache.top()); - size_t const code_size = ch.codeSize(); - - // test if enough room remains in drc cache - drccodeptr *cachetop = m_cache.begin_codegen(alignment + code_size); - if (cachetop == nullptr) - throw emu_fatalerror("drc_cache::begin_codegen()"); - - err = ch.copyFlattenedData(drccodeptr(ch.baseAddress()), code_size, CodeHolder::kCopyWithPadding); - if (err) - throw emu_fatalerror("asmjit::CodeHolder::copyFlattenedData() error %d", err); - - // update the drc cache and end codegen - *cachetop += alignment + code_size; - m_cache.end_codegen(); - - return code_size; -} //------------------------------------------------- // reset - reset back-end specific state @@ -735,70 +720,70 @@ void drcbe_x64::reset() x86log_printf(m_log, "%s", "\n\n===========\nCACHE RESET\n===========\n\n"); // generate a little bit of glue code to set up the environment - x86code *dst = (x86code *)m_cache.top(); + drccodeptr *cachetop = m_cache.begin_codegen(500); + if (cachetop == nullptr) + fatalerror("Out of cache space after a reset!\n"); - CodeHolder ch; - ch.init(hostEnvironment(), uint64_t(dst)); + x86code *dst = (x86code *)*cachetop; - FileLogger logger(m_log_asmjit); - if (logger.file()) - { - logger.setFlags(FormatOptions::Flags::kFlagHexOffsets | FormatOptions::Flags::kFlagHexImms); - logger.setIndentation(FormatOptions::IndentationType::kIndentationCode, 4); - ch.setLogger(&logger); - } + // generate a simple CPUID stub + uint32_t (*cpuid_ecx_stub)(void) = (uint32_t (*)(void))dst; + emit_push_r64(dst, REG_RBX); // push rbx + emit_mov_r32_imm(dst, REG_EAX, 1); // mov eax,1 + emit_cpuid(dst); // cpuid + emit_mov_r32_r32(dst, REG_EAX, REG_ECX); // mov eax,ecx + emit_pop_r64(dst, REG_RBX); // pop rbx + emit_ret(dst); // ret - Assembler a(&ch); - if (logger.file()) - a.addValidationOptions(BaseEmitter::kValidationOptionIntermediate); + // call it to determine if we have SSE4.1 support + m_sse41 = (((*cpuid_ecx_stub)() & 0x80000) != 0); // generate an entry point m_entry = (x86_entry_point_func)dst; - a.bind(a.newNamedLabel("entry_point")); - - FuncDetail entry_point; - entry_point.init(FuncSignatureT<uint32_t, uint8_t *, x86code *>(CallConv::kIdHost), hostEnvironment()); - - FuncFrame frame; - frame.init(entry_point); - frame.addDirtyRegs(rbx, rbp, rsi, rdi, r12, r13, r14, r15); - FuncArgsAssignment args(&entry_point); - args.assignAll(rbp); - args.updateFuncFrame(frame); - frame.finalize(); - - a.emitProlog(frame); - a.emitArgsAssignment(frame, args); - - a.sub(rsp, 32); - a.mov(MABS(&m_near.hashstacksave), rsp); - a.sub(rsp, 8); - a.mov(MABS(&m_near.stacksave), rsp); - a.stmxcsr(MABS(&m_near.ssemode)); - a.jmp(Gpq(REG_PARAM2)); + emit_push_r64(dst, REG_RBX); // push rbx + emit_push_r64(dst, REG_RSI); // push rsi + emit_push_r64(dst, REG_RDI); // push rdi + emit_push_r64(dst, REG_RBP); // push rbp + emit_push_r64(dst, REG_R12); // push r12 + emit_push_r64(dst, REG_R13); // push r13 + emit_push_r64(dst, REG_R14); // push r14 + emit_push_r64(dst, REG_R15); // push r15 + emit_mov_r64_r64(dst, REG_RBP, REG_PARAM1); // mov rbp,param1 + emit_sub_r64_imm(dst, REG_RSP, 32); // sub rsp,32 + emit_mov_m64_r64(dst, MABS(&m_near.hashstacksave), REG_RSP); // mov [hashstacksave],rsp + emit_sub_r64_imm(dst, REG_RSP, 8); // sub rsp,8 + emit_mov_m64_r64(dst, MABS(&m_near.stacksave), REG_RSP); // mov [stacksave],rsp + emit_stmxcsr_m32(dst, MABS(&m_near.ssemode)); // stmxcsr [ssemode] + emit_jmp_r64(dst, REG_PARAM2); // jmp param2 + if (m_log != nullptr) + x86log_disasm_code_range(m_log, "entry_point", (x86code *)m_entry, dst); // generate an exit point - m_exit = dst + a.offset(); - a.bind(a.newNamedLabel("exit_point")); - a.ldmxcsr(MABS(&m_near.ssemode)); - a.mov(rsp, MABS(&m_near.hashstacksave)); - a.add(rsp, 32); - a.emitEpilog(frame); + m_exit = dst; + emit_ldmxcsr_m32(dst, MABS(&m_near.ssemode)); // ldmxcsr [ssemode] + emit_mov_r64_m64(dst, REG_RSP, MABS(&m_near.hashstacksave)); // mov rsp,[hashstacksave] + emit_add_r64_imm(dst, REG_RSP, 32); // add rsp,32 + emit_pop_r64(dst, REG_R15); // pop r15 + emit_pop_r64(dst, REG_R14); // pop r14 + emit_pop_r64(dst, REG_R13); // pop r13 + emit_pop_r64(dst, REG_R12); // pop r12 + emit_pop_r64(dst, REG_RBP); // pop rbp + emit_pop_r64(dst, REG_RDI); // pop rdi + emit_pop_r64(dst, REG_RSI); // pop rsi + emit_pop_r64(dst, REG_RBX); // pop rbx + emit_ret(dst); // ret + if (m_log != nullptr) + x86log_disasm_code_range(m_log, "exit_point", m_exit, dst); // generate a no code point - m_nocode = dst + a.offset(); - a.bind(a.newNamedLabel("nocode_point")); - a.ret(); - - // emit the generated code - size_t bytes = emit(ch); - + m_nocode = dst; + emit_ret(dst); // ret if (m_log != nullptr) - { - x86log_disasm_code_range(m_log, "entry_point", dst, m_exit); - x86log_disasm_code_range(m_log, "exit_point", m_exit, m_nocode); - x86log_disasm_code_range(m_log, "nocode_point", m_nocode, dst + bytes); - } + x86log_disasm_code_range(m_log, "nocode", m_nocode, dst); + + // finish up codegen + *cachetop = (drccodeptr)dst; + m_cache.end_codegen(); // reset our hash tables m_hash.reset(); @@ -829,25 +814,14 @@ void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, uint3 m_labels.block_begin(block); m_map.block_begin(block); - // compute the base by aligning the cache top to a cache line (assumed to be 64 bytes) - x86code *dst = (x86code *)(uint64_t(m_cache.top() + 63) & ~63); - - CodeHolder ch; - ch.init(hostEnvironment(), uint64_t(dst)); - ThrowableErrorHandler e; - ch.setErrorHandler(&e); - - FileLogger logger(m_log_asmjit); - if (logger.file()) - { - logger.setFlags(FormatOptions::Flags::kFlagHexOffsets | FormatOptions::Flags::kFlagHexImms | FormatOptions::Flags::kFlagMachineCode); - logger.setIndentation(FormatOptions::IndentationType::kIndentationCode, 4); - ch.setLogger(&logger); - } + // begin codegen; fail if we can't + drccodeptr *cachetop = m_cache.begin_codegen(numinst * 8 * 4); + if (cachetop == nullptr) + block.abort(); - Assembler a(&ch); - if (logger.file()) - a.addValidationOptions(BaseEmitter::kValidationOptionIntermediate); + // compute the base by aligning the cache top to a cache line (assumed to be 64 bytes) + x86code *base = (x86code *)(((uintptr_t)*cachetop + 63) & ~63); + x86code *dst = base; // generate code const char *blockname = nullptr; @@ -856,16 +830,11 @@ void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, uint3 const instruction &inst = instlist[inum]; assert(inst.opcode() < ARRAY_LENGTH(s_opcode_table)); - // must remain in scope until output - std::string dasm; - // add a comment if (m_log != nullptr) { - dasm = inst.disasm(&m_drcuml); - - x86log_add_comment(m_log, dst + a.offset(), "%s", dasm.c_str()); - a.setInlineComment(dasm.c_str()); + std::string dasm = inst.disasm(&m_drcuml); + x86log_add_comment(m_log, dst, "%s", dasm.c_str()); } // extract a blockname @@ -878,15 +847,16 @@ void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, uint3 } // generate code - (this->*s_opcode_table[inst.opcode()])(a, inst); + (this->*s_opcode_table[inst.opcode()])(dst, inst); } // complete codegen - size_t bytes = emit(ch); + *cachetop = (drccodeptr)dst; + m_cache.end_codegen(); // log it if (m_log != nullptr) - x86log_disasm_code_range(m_log, (blockname == nullptr) ? "Unknown block" : blockname, dst, dst + bytes); + x86log_disasm_code_range(m_log, (blockname == nullptr) ? "Unknown block" : blockname, base, m_cache.top()); // tell all of our utility objects that the block is finished m_hash.block_end(block); @@ -932,21 +902,21 @@ void drcbe_x64::get_info(drcbe_info &info) // into a register //------------------------------------------------- -void drcbe_x64::emit_mov_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m) +void drcbe_x64::emit_mov_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m) { if (param.is_immediate()) { if (param.immediate() == 0) - a.xor_(reg, reg); // xor reg,reg + emit_xor_r32_r32(dst, reg, reg); // xor reg,reg else - a.mov(reg, param.immediate()); // mov reg,param + emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param } else if (param.is_memory()) - a.mov(reg, MABS(param.memory())); // mov reg,[param] + emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param] else if (param.is_int_register()) { - if (reg.id() != param.ireg()) - a.mov(reg, Gpd(param.ireg())); // mov reg,param + if (reg != param.ireg()) + emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param } } @@ -956,21 +926,21 @@ void drcbe_x64::emit_mov_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // sign-extended into a register //------------------------------------------------- -void drcbe_x64::emit_movsx_r64_p32(Assembler &a, Gp reg, const be_parameter ¶m) +void drcbe_x64::emit_movsx_r64_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m) { if (param.is_immediate()) { if (param.immediate() == 0) - a.xor_(reg.r32(), reg.r32()); // xor reg,reg + emit_xor_r32_r32(dst, reg, reg); // xor reg,reg else if ((int32_t)param.immediate() >= 0) - a.mov(reg.r32(), param.immediate()); // mov reg,param + emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param else - emit_mov_r64_imm(a, reg, int32_t(param.immediate())); // mov reg,param + emit_mov_r64_imm(dst, reg, (int32_t)param.immediate()); // mov reg,param } else if (param.is_memory()) - a.movsxd(reg, MABS(param.memory())); // movsxd reg,[param] + emit_movsxd_r64_m32(dst, reg, MABS(param.memory())); // movsxd reg,[param] else if (param.is_int_register()) - a.movsxd(reg, Gpd(param.ireg())); // movsxd reg,param + emit_movsxd_r64_r32(dst, reg, param.ireg()); // movsdx reg,param } @@ -980,16 +950,16 @@ void drcbe_x64::emit_movsx_r64_p32(Assembler &a, Gp reg, const be_parameter &par // any flags //------------------------------------------------- -void drcbe_x64::emit_mov_r32_p32_keepflags(Assembler &a, Gp reg, const be_parameter ¶m) +void drcbe_x64::emit_mov_r32_p32_keepflags(x86code *&dst, uint8_t reg, const be_parameter ¶m) { if (param.is_immediate()) - a.mov(reg, param.immediate()); // mov reg,param + emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param else if (param.is_memory()) - a.mov(reg, MABS(param.memory())); // mov reg,[param] + emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param] else if (param.is_int_register()) { - if (reg.id() != param.ireg()) - a.mov(reg, Gpd(param.ireg())); // mov reg,param + if (reg != param.ireg()) + emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param } } @@ -999,17 +969,17 @@ void drcbe_x64::emit_mov_r32_p32_keepflags(Assembler &a, Gp reg, const be_parame // into a memory location //------------------------------------------------- -void drcbe_x64::emit_mov_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m) +void drcbe_x64::emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m) { if (param.is_immediate()) - a.mov(memref, param.immediate()); // mov [mem],param + emit_mov_m32_imm(dst, memref, param.immediate()); // mov [mem],param else if (param.is_memory()) { - a.mov(eax, MABS(param.memory())); // mov eax,[param] - a.mov(memref, eax); // mov [mem],eax + emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory())); // mov eax,[param] + emit_mov_m32_r32(dst, memref, REG_EAX); // mov [mem],eax } else if (param.is_int_register()) - a.mov(memref, Gpd(param.ireg())); // mov [mem],param + emit_mov_m32_r32(dst, memref, param.ireg()); // mov [mem],param } @@ -1018,15 +988,15 @@ void drcbe_x64::emit_mov_m32_p32(Assembler &a, Mem memref, const be_parameter &p // 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_mov_p32_r32(Assembler &a, const be_parameter ¶m, Gp reg) +void drcbe_x64::emit_mov_p32_r32(x86code *&dst, const be_parameter ¶m, uint8_t reg) { assert(!param.is_immediate()); if (param.is_memory()) - a.mov(MABS(param.memory()), reg); // mov [param],reg + emit_mov_m32_r32(dst, MABS(param.memory()), reg); // mov [param],reg else if (param.is_int_register()) { - if (reg.id() != param.ireg()) - a.mov(Gpd(param.ireg()), reg); // mov param,reg + if (reg != param.ireg()) + emit_mov_r32_r32(dst, param.ireg(), reg); // mov param,reg } } @@ -1036,17 +1006,17 @@ void drcbe_x64::emit_mov_p32_r32(Assembler &a, const be_parameter ¶m, Gp reg // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_add_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_add_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) - a.add(reg, param.immediate()); // add reg,param + emit_add_r32_imm(dst, reg, param.immediate()); // add reg,param } else if (param.is_memory()) - a.add(reg, MABS(param.memory())); // add reg,[param] + emit_add_r32_m32(dst, reg, MABS(param.memory())); // add reg,[param] else if (param.is_int_register()) - a.add(reg, Gpd(param.ireg())); // add reg,param + emit_add_r32_r32(dst, reg, param.ireg()); // add reg,param } @@ -1055,18 +1025,18 @@ void drcbe_x64::emit_add_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_add_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) - a.add(memref, param.immediate()); // add [dest],param + emit_add_m32_imm(dst, memref, param.immediate()); // add [dest],param } else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32(a, reg, param); // mov reg,param - a.add(memref, reg); // add [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32(dst, reg, param); // mov reg,param + emit_add_m32_r32(dst, memref, reg); // add [dest],reg } } @@ -1076,14 +1046,14 @@ void drcbe_x64::emit_add_m32_p32(Assembler &a, Mem memref, const be_parameter &p // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_adc_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_adc_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.adc(reg, param.immediate()); // adc reg,param + emit_adc_r32_imm(dst, reg, param.immediate()); // adc reg,param else if (param.is_memory()) - a.adc(reg, MABS(param.memory())); // adc reg,[param] + emit_adc_r32_m32(dst, reg, MABS(param.memory())); // adc reg,[param] else if (param.is_int_register()) - a.adc(reg, Gpd(param.ireg())); // adc reg,param + emit_adc_r32_r32(dst, reg, param.ireg()); // adc reg,param } @@ -1092,15 +1062,15 @@ void drcbe_x64::emit_adc_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_adc_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.adc(memref, param.immediate()); // adc [dest],param + emit_adc_m32_imm(dst, memref, param.immediate()); // adc [dest],param else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32_keepflags(a, reg, param); // mov reg,param - a.adc(memref, reg); // adc [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param + emit_adc_m32_r32(dst, memref, reg); // adc [dest],reg } } @@ -1110,17 +1080,17 @@ void drcbe_x64::emit_adc_m32_p32(Assembler &a, Mem memref, const be_parameter &p // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sub_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sub_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) - a.sub(reg, param.immediate()); // sub reg,param + emit_sub_r32_imm(dst, reg, param.immediate()); // sub reg,param } else if (param.is_memory()) - a.sub(reg, MABS(param.memory())); // sub reg,[param] + emit_sub_r32_m32(dst, reg, MABS(param.memory())); // sub reg,[param] else if (param.is_int_register()) - a.sub(reg, Gpd(param.ireg())); // sub reg,param + emit_sub_r32_r32(dst, reg, param.ireg()); // sub reg,param } @@ -1129,18 +1099,18 @@ void drcbe_x64::emit_sub_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sub_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) - a.sub(memref, param.immediate()); // sub [dest],param + emit_sub_m32_imm(dst, memref, param.immediate()); // sub [dest],param } else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32(a, reg, param); // mov reg,param - a.sub(memref, reg); // sub [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32(dst, reg, param); // mov reg,param + emit_sub_m32_r32(dst, memref, reg); // sub [dest],reg } } @@ -1150,14 +1120,14 @@ void drcbe_x64::emit_sub_m32_p32(Assembler &a, Mem memref, const be_parameter &p // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sbb_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sbb_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.sbb(reg, param.immediate()); // sbb reg,param + emit_sbb_r32_imm(dst, reg, param.immediate()); // sbb reg,param else if (param.is_memory()) - a.sbb(reg, MABS(param.memory())); // sbb reg,[param] + emit_sbb_r32_m32(dst, reg, MABS(param.memory())); // sbb reg,[param] else if (param.is_int_register()) - a.sbb(reg, Gpd(param.ireg())); // sbb reg,param + emit_sbb_r32_r32(dst, reg, param.ireg()); // sbb reg,param } @@ -1166,15 +1136,15 @@ void drcbe_x64::emit_sbb_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sbb_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.sbb(memref, param.immediate()); // sbb [dest],param + emit_sbb_m32_imm(dst, memref, param.immediate()); // sbb [dest],param else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32_keepflags(a, reg, param); // mov reg,param - a.sbb(memref, reg); // sbb [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param + emit_sbb_m32_r32(dst, memref, reg); // sbb [dest],reg } } @@ -1184,14 +1154,14 @@ void drcbe_x64::emit_sbb_m32_p32(Assembler &a, Mem memref, const be_parameter &p // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_cmp_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_cmp_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.cmp(reg, param.immediate()); // cmp reg,param + emit_cmp_r32_imm(dst, reg, param.immediate()); // cmp reg,param else if (param.is_memory()) - a.cmp(reg, MABS(param.memory())); // cmp reg,[param] + emit_cmp_r32_m32(dst, reg, MABS(param.memory())); // cmp reg,[param] else if (param.is_int_register()) - a.cmp(reg, Gpd(param.ireg())); // cmp reg,param + emit_cmp_r32_r32(dst, reg, param.ireg()); // cmp reg,param } @@ -1200,15 +1170,15 @@ void drcbe_x64::emit_cmp_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_cmp_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.cmp(memref, param.immediate()); // cmp [dest],param + emit_cmp_m32_imm(dst, memref, param.immediate()); // cmp [dest],param else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32(a, reg, param); // mov reg,param - a.cmp(memref, reg); // cmp [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32(dst, reg, param); // mov reg,param + emit_cmp_m32_r32(dst, memref, reg); // cmp [dest],reg } } @@ -1218,21 +1188,21 @@ void drcbe_x64::emit_cmp_m32_p32(Assembler &a, Mem memref, const be_parameter &p // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_and_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_and_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() == 0 && (uint32_t)param.immediate() == 0xffffffff) ;// skip else if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) - a.xor_(reg, reg); // xor reg,reg + emit_xor_r32_r32(dst, reg, reg); // xor reg,reg else - a.and_(reg, param.immediate()); // and reg,param + emit_and_r32_imm(dst, reg, param.immediate()); // and reg,param } else if (param.is_memory()) - a.and_(reg, MABS(param.memory())); // and reg,[param] + emit_and_r32_m32(dst, reg, MABS(param.memory())); // and reg,[param] else if (param.is_int_register()) - a.and_(reg, Gpd(param.ireg())); // and reg,param + emit_and_r32_r32(dst, reg, param.ireg()); // and reg,param } @@ -1241,22 +1211,22 @@ void drcbe_x64::emit_and_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_and_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() == 0 && (uint32_t)param.immediate() == 0xffffffff) ;// skip else if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) - a.mov(memref, 0); // mov [dest],0 + emit_mov_m32_imm(dst, memref, 0); // mov [dest],0 else - a.and_(memref, param.immediate()); // and [dest],param + emit_and_m32_imm(dst, memref, param.immediate()); // and [dest],param } else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32(a, reg, param); // mov reg,param - a.and_(memref, reg); // and [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32(dst, reg, param); // mov reg,param + emit_and_m32_r32(dst, memref, reg); // and [dest],reg } } @@ -1266,14 +1236,14 @@ void drcbe_x64::emit_and_m32_p32(Assembler &a, Mem memref, const be_parameter &p // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_test_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_test_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.test(reg, param.immediate()); // test reg,param + emit_test_r32_imm(dst, reg, param.immediate()); // test reg,param else if (param.is_memory()) - a.test(MABS(param.memory()), reg); // test [param],reg + emit_test_m32_r32(dst, MABS(param.memory()), reg); // test [param],reg else if (param.is_int_register()) - a.test(reg, Gpd(param.ireg())); // test reg,param + emit_test_r32_r32(dst, reg, param.ireg()); // test reg,param } @@ -1282,17 +1252,17 @@ void drcbe_x64::emit_test_r32_p32(Assembler &a, Gp reg, const be_parameter ¶ // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_test_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) - a.test(memref, param.immediate()); // test [dest],param + emit_test_m32_imm(dst, memref, param.immediate()); // test [dest],param else if (param.is_memory()) { - a.mov(eax, MABS(param.memory())); // mov reg,param - a.test(memref, eax); // test [dest],reg + emit_mov_r32_p32(dst, REG_EAX, param); // mov reg,param + emit_test_m32_r32(dst, memref, REG_EAX); // test [dest],reg } else if (param.is_int_register()) - a.test(memref, Gpd(param.ireg())); // test [dest],param + emit_test_m32_r32(dst, memref, param.ireg()); // test [dest],param } @@ -1301,21 +1271,21 @@ void drcbe_x64::emit_test_m32_p32(Assembler &a, Mem memref, const be_parameter & // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_or_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_or_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) ;// skip else if (inst.flags() == 0 && (uint32_t)param.immediate() == 0xffffffff) - a.mov(reg, 0xffffffff); // mov reg,-1 + emit_mov_r32_imm(dst, reg, 0xffffffff); // mov reg,-1 else - a.or_(reg, param.immediate()); // or reg,param + emit_or_r32_imm(dst, reg, param.immediate()); // or reg,param } else if (param.is_memory()) - a.or_(reg, MABS(param.memory())); // or reg,[param] + emit_or_r32_m32(dst, reg, MABS(param.memory())); // or reg,[param] else if (param.is_int_register()) - a.or_(reg, Gpd(param.ireg())); // or reg,param + emit_or_r32_r32(dst, reg, param.ireg()); // or reg,param } @@ -1324,22 +1294,22 @@ void drcbe_x64::emit_or_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_or_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_or_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) ;// skip else if (inst.flags() == 0 && (uint32_t)param.immediate() == 0xffffffff) - a.mov(memref, 0xffffffff); // mov [dest],-1 + emit_mov_m32_imm(dst, memref, 0xffffffff); // mov [dest],-1 else - a.or_(memref, param.immediate()); // or [dest],param + emit_or_m32_imm(dst, memref, param.immediate()); // or [dest],param } else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32(a, reg, param); // mov reg,param - a.or_(memref, reg); // or [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32(dst, reg, param); // mov reg,param + emit_or_m32_r32(dst, memref, reg); // or [dest],reg } } @@ -1349,21 +1319,21 @@ void drcbe_x64::emit_or_m32_p32(Assembler &a, Mem memref, const be_parameter &pa // register from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_xor_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_xor_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) ;// skip else if (inst.flags() == 0 && (uint32_t)param.immediate() == 0xffffffff) - a.not_(reg); // not reg + emit_not_r32(dst, reg); // not reg else - a.xor_(reg, param.immediate()); // xor reg,param + emit_xor_r32_imm(dst, reg, param.immediate()); // xor reg,param } else if (param.is_memory()) - a.xor_(reg, MABS(param.memory())); // xor reg,[param] + emit_xor_r32_m32(dst, reg, MABS(param.memory())); // xor reg,[param] else if (param.is_int_register()) - a.xor_(reg, Gpd(param.ireg())); // xor reg,param + emit_xor_r32_r32(dst, reg, param.ireg()); // xor reg,param } @@ -1372,71 +1342,359 @@ void drcbe_x64::emit_xor_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_xor_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) ;// skip else if (inst.flags() == 0 && (uint32_t)param.immediate() == 0xffffffff) - a.not_(memref); // not [dest] + emit_not_m32(dst, memref); // not [dest] else - a.xor_(memref, param.immediate()); // xor [dest],param + emit_xor_m32_imm(dst, memref, param.immediate()); // xor [dest],param } else { - Gp reg = param.select_register(eax); - emit_mov_r32_p32(a, reg, param); // mov reg,param - a.xor_(memref, reg); // xor [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r32_p32(dst, reg, param); // mov reg,param + emit_xor_m32_r32(dst, memref, reg); // xor [dest],reg } } -void drcbe_x64::emit_shift_p32(Assembler &a, const Inst::Id opcode, Operand op1, const be_parameter ¶m) + +//------------------------------------------------- +// emit_shl_r32_p32 - shl operation to a 32-bit +// register from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shl_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { - Operand op2 = cl; if (param.is_immediate()) - op2 = imm(param.immediate()); + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_shl_r32_imm(dst, reg, param.immediate()); // shl reg,param + } else - emit_mov_r32_p32(a, ecx, param); + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_shl_r32_cl(dst, reg); // shl reg,cl + } +} + - a.emit(opcode, op1, op2); +//------------------------------------------------- +// emit_shl_m32_p32 - shl operation to a 32-bit +// memory location from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_shl_m32_imm(dst, memref, param.immediate()); // shl [dest],param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_shl_m32_cl(dst, memref); // shl [dest],cl + } } -/*************************************************************************** - EMITTERS FOR 64-BIT OPERATIONS WITH PARAMETERS -***************************************************************************/ +//------------------------------------------------- +// emit_shr_r32_p32 - shr operation to a 32-bit +// register from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shr_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_shr_r32_imm(dst, reg, param.immediate()); // shr reg,param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_shr_r32_cl(dst, reg); // shr reg,cl + } +} + + +//------------------------------------------------- +// emit_shr_m32_p32 - shr operation to a 32-bit +// memory location from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_shr_m32_imm(dst, memref, param.immediate()); // shr [dest],param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_shr_m32_cl(dst, memref); // shr [dest],cl + } +} + + +//------------------------------------------------- +// emit_sar_r32_p32 - sar operation to a 32-bit +// register from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_sar_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_sar_r32_imm(dst, reg, param.immediate()); // sar reg,param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_sar_r32_cl(dst, reg); // sar reg,cl + } +} + + +//------------------------------------------------- +// emit_sar_m32_p32 - sar operation to a 32-bit +// memory location from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_sar_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_sar_m32_imm(dst, memref, param.immediate()); // sar [dest],param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_sar_m32_cl(dst, memref); // sar [dest],cl + } +} + + +//------------------------------------------------- +// emit_rol_r32_p32 - rol operation to a 32-bit +// register from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rol_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rol_r32_imm(dst, reg, param.immediate()); // rol reg,param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_rol_r32_cl(dst, reg); // rol reg,cl + } +} + + +//------------------------------------------------- +// emit_rol_m32_p32 - rol operation to a 32-bit +// memory location from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rol_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rol_m32_imm(dst, memref, param.immediate()); // rol [dest],param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_rol_m32_cl(dst, memref); // rol [dest],cl + } +} + + +//------------------------------------------------- +// emit_ror_r32_p32 - ror operation to a 32-bit +// register from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_ror_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_ror_r32_imm(dst, reg, param.immediate()); // ror reg,param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_ror_r32_cl(dst, reg); // ror reg,cl + } +} + + +//------------------------------------------------- +// emit_ror_m32_p32 - ror operation to a 32-bit +// memory location from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_ror_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_ror_m32_imm(dst, memref, param.immediate()); // ror [dest],param + } + else + { + emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param + emit_ror_m32_cl(dst, memref); // ror [dest],cl + } +} + + +//------------------------------------------------- +// emit_rcl_r32_p32 - rcl operation to a 32-bit +// register from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rcl_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rcl_r32_imm(dst, reg, param.immediate()); // rcl reg,param + } + else + { + emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param + emit_rcl_r32_cl(dst, reg); // rcl reg,cl + } +} + + +//------------------------------------------------- +// emit_rcl_m32_p32 - rcl operation to a 32-bit +// memory location from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rcl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rcl_m32_imm(dst, memref, param.immediate()); // rcl [dest],param + } + else + { + emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param + emit_rcl_m32_cl(dst, memref); // rcl [dest],cl + } +} + + +//------------------------------------------------- +// emit_rcr_r32_p32 - rcr operation to a 32-bit +// register from a 32-bit parameter +//------------------------------------------------- -void drcbe_x64::emit_mov_r64_imm(Assembler &a, Gp reg, uint64_t imm) +void drcbe_x64::emit_rcr_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { - if (u32(imm) == imm) - a.mov(reg.r32(), imm); - else if (s32(imm) == imm) - a.mov(reg.r64(), s32(imm)); + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rcr_r32_imm(dst, reg, param.immediate()); // rcr reg,param + } else - a.mov(reg.r64(), imm); + { + emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param + emit_rcr_r32_cl(dst, reg); // rcr reg,cl + } } + +//------------------------------------------------- +// emit_rcr_m32_p32 - rcr operation to a 32-bit +// memory location from a 32-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rcr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rcr_m32_imm(dst, memref, param.immediate()); // rcr [dest],param + } + else + { + emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param + emit_rcr_m32_cl(dst, memref); // rcr [dest],cl + } +} + + + +/*************************************************************************** + EMITTERS FOR 64-BIT OPERATIONS WITH PARAMETERS +***************************************************************************/ + //------------------------------------------------- // emit_mov_r64_p64 - move a 64-bit parameter // into a register //------------------------------------------------- -void drcbe_x64::emit_mov_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m) +void drcbe_x64::emit_mov_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m) { if (param.is_immediate()) { if (param.immediate() == 0) - a.xor_(reg.r32(), reg.r32()); // xor reg,reg + emit_xor_r32_r32(dst, reg, reg); // xor reg,reg else - emit_mov_r64_imm(a, reg, param.immediate()); // mov reg,param + emit_mov_r64_imm(dst, reg, param.immediate()); // mov reg,param } else if (param.is_memory()) - a.mov(reg, MABS(param.memory())); // mov reg,[param] + emit_mov_r64_m64(dst, reg, MABS(param.memory())); // mov reg,[param] else if (param.is_int_register()) { - if (reg.id() != param.ireg()) - a.mov(reg, Gpq(param.ireg())); // mov reg,param + if (reg != param.ireg()) + emit_mov_r64_r64(dst, reg, param.ireg()); // mov reg,param } } @@ -1447,16 +1705,16 @@ void drcbe_x64::emit_mov_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // any flags //------------------------------------------------- -void drcbe_x64::emit_mov_r64_p64_keepflags(Assembler &a, Gp reg, const be_parameter ¶m) +void drcbe_x64::emit_mov_r64_p64_keepflags(x86code *&dst, uint8_t reg, const be_parameter ¶m) { if (param.is_immediate()) - emit_mov_r64_imm(a, reg, param.immediate()); // mov reg,param + emit_mov_r64_imm(dst, reg, param.immediate()); // mov reg,param else if (param.is_memory()) - a.mov(reg, MABS(param.memory())); // mov reg,[param] + emit_mov_r64_m64(dst, reg, MABS(param.memory())); // mov reg,[param] else if (param.is_int_register()) { - if (reg.id() != param.ireg()) - a.mov(reg, Gpq(param.ireg())); // mov reg,param + if (reg != param.ireg()) + emit_mov_r64_r64(dst, reg, param.ireg()); // mov reg,param } } @@ -1466,15 +1724,15 @@ void drcbe_x64::emit_mov_r64_p64_keepflags(Assembler &a, Gp reg, const be_parame // 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_mov_p64_r64(Assembler &a, const be_parameter ¶m, Gp reg) +void drcbe_x64::emit_mov_p64_r64(x86code *&dst, const be_parameter ¶m, uint8_t reg) { assert(!param.is_immediate()); if (param.is_memory()) - a.mov(MABS(param.memory()), reg); // mov [param],reg + emit_mov_m64_r64(dst, MABS(param.memory()), reg); // mov [param],reg else if (param.is_int_register()) { - if (reg.id() != param.ireg()) - a.mov(Gpq(param.ireg()), reg); // mov param,reg + if (reg != param.ireg()) + emit_mov_r64_r64(dst, param.ireg(), reg); // mov param,reg } } @@ -1484,25 +1742,25 @@ void drcbe_x64::emit_mov_p64_r64(Assembler &a, const be_parameter ¶m, Gp reg // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_add_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_add_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (short_immediate(param.immediate())) - a.add(reg, param.immediate()); // add reg,param + emit_add_r64_imm(dst, reg, param.immediate()); // add reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.add(reg, r11); // add reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_add_r64_r64(dst, reg, REG_R11); // add reg,r11 } } } else if (param.is_memory()) - a.add(reg, MABS(param.memory())); // add reg,[param] + emit_add_r64_m64(dst, reg, MABS(param.memory())); // add reg,[param] else if (param.is_int_register()) - a.add(reg, Gpq(param.ireg())); // add reg,param + emit_add_r64_r64(dst, reg, param.ireg()); // add reg,param } @@ -1511,26 +1769,26 @@ void drcbe_x64::emit_add_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_add_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (short_immediate(param.immediate())) - a.add(memref, param.immediate()); // add [mem],param + emit_add_m64_imm(dst, memref, param.immediate()); // add [mem],param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.add(memref, r11); // add [mem],r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_add_m64_r64(dst, memref, REG_R11); // add [mem],r11 } } } else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64(a, reg, param); // mov reg,param - a.add(memref, reg); // add [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64(dst, reg, param); // mov reg,param + emit_add_m64_r64(dst, memref, reg); // add [dest],reg } } @@ -1540,22 +1798,22 @@ void drcbe_x64::emit_add_m64_p64(Assembler &a, Mem memref, const be_parameter &p // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_adc_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_adc_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (short_immediate(param.immediate())) - a.adc(reg, param.immediate()); // adc reg,param + emit_adc_r64_imm(dst, reg, param.immediate()); // adc reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.adc(reg, r11); // adc reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_adc_r64_r64(dst, reg, REG_R11); // adc reg,r11 } } else if (param.is_memory()) - a.adc(reg, MABS(param.memory())); // adc reg,[param] + emit_adc_r64_m64(dst, reg, MABS(param.memory())); // adc reg,[param] else if (param.is_int_register()) - a.adc(reg, Gpq(param.ireg())); // adc reg,param + emit_adc_r64_r64(dst, reg, param.ireg()); // adc reg,param } @@ -1564,15 +1822,15 @@ void drcbe_x64::emit_adc_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // memory locaiton from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_adc_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate() && short_immediate(param.immediate())) - a.adc(memref, param.immediate()); // adc [mem],param + emit_adc_m64_imm(dst, memref, param.immediate()); // adc [mem],param else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64_keepflags(a, reg, param); // mov reg,param - a.adc(memref, reg); // adc [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64_keepflags(dst, reg, param); // mov reg,param + emit_adc_m64_r64(dst, memref, reg); // adc [dest],reg } } @@ -1582,25 +1840,25 @@ void drcbe_x64::emit_adc_m64_p64(Assembler &a, Mem memref, const be_parameter &p // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sub_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sub_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (short_immediate(param.immediate())) - a.sub(reg, param.immediate()); // sub reg,param + emit_sub_r64_imm(dst, reg, param.immediate()); // sub reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.sub(reg, r11); // sub reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_sub_r64_r64(dst, reg, REG_R11); // sub reg,r11 } } } else if (param.is_memory()) - a.sub(reg, MABS(param.memory())); // sub reg,[param] + emit_sub_r64_m64(dst, reg, MABS(param.memory())); // sub reg,[param] else if (param.is_int_register()) - a.sub(reg, Gpq(param.ireg())); // sub reg,param + emit_sub_r64_r64(dst, reg, param.ireg()); // sub reg,param } @@ -1609,26 +1867,26 @@ void drcbe_x64::emit_sub_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sub_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (short_immediate(param.immediate())) - a.sub(memref, param.immediate()); // sub [mem],param + emit_sub_m64_imm(dst, memref, param.immediate()); // sub [mem],param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.sub(memref, r11); // sub [mem],r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_sub_m64_r64(dst, memref, REG_R11); // sub [mem],r11 } } } else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64(a, reg, param); // mov reg,param - a.sub(memref, reg); // sub [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64(dst, reg, param); // mov reg,param + emit_sub_m64_r64(dst, memref, reg); // sub [dest],reg } } @@ -1638,22 +1896,22 @@ void drcbe_x64::emit_sub_m64_p64(Assembler &a, Mem memref, const be_parameter &p // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sbb_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sbb_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (short_immediate(param.immediate())) - a.sbb(reg, param.immediate()); // sbb reg,param + emit_sbb_r64_imm(dst, reg, param.immediate()); // sbb reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.sbb(reg, r11); // sbb reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_sbb_r64_r64(dst, reg, REG_R11); // sbb reg,r11 } } else if (param.is_memory()) - a.sbb(reg, MABS(param.memory())); // sbb reg,[param] + emit_sbb_r64_m64(dst, reg, MABS(param.memory())); // sbb reg,[param] else if (param.is_int_register()) - a.sbb(reg, Gpq(param.ireg())); // sbb reg,param + emit_sbb_r64_r64(dst, reg, param.ireg()); // sbb reg,param } @@ -1662,15 +1920,15 @@ void drcbe_x64::emit_sbb_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_sbb_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate() && short_immediate(param.immediate())) - a.sbb(memref, param.immediate()); // sbb [mem],param + emit_sbb_m64_imm(dst, memref, param.immediate()); // sbb [mem],param else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64_keepflags(a, reg, param); // mov reg,param - a.sbb(memref, reg); // sbb [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64_keepflags(dst, reg, param); // mov reg,param + emit_sbb_m64_r64(dst, memref, reg); // sbb [dest],reg } } @@ -1680,22 +1938,22 @@ void drcbe_x64::emit_sbb_m64_p64(Assembler &a, Mem memref, const be_parameter &p // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_cmp_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_cmp_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (short_immediate(param.immediate())) - a.cmp(reg, param.immediate()); // cmp reg,param + emit_cmp_r64_imm(dst, reg, param.immediate()); // cmp reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.cmp(reg, r11); // cmp reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_cmp_r64_r64(dst, reg, REG_R11); // cmp reg,r11 } } else if (param.is_memory()) - a.cmp(reg, MABS(param.memory())); // cmp reg,[param] + emit_cmp_r64_m64(dst, reg, MABS(param.memory())); // cmp reg,[param] else if (param.is_int_register()) - a.cmp(reg, Gpq(param.ireg())); // cmp reg,param + emit_cmp_r64_r64(dst, reg, param.ireg()); // cmp reg,param } @@ -1704,15 +1962,15 @@ void drcbe_x64::emit_cmp_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_cmp_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_cmp_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate() && short_immediate(param.immediate())) - a.cmp(memref, param.immediate()); // cmp [dest],param + emit_cmp_m64_imm(dst, memref, param.immediate()); // cmp [dest],param else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64(a, reg, param); // mov reg,param - a.cmp(memref, reg); // cmp [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64(dst, reg, param); // mov reg,param + emit_cmp_m64_r64(dst, memref, reg); // cmp [dest],reg } } @@ -1722,25 +1980,25 @@ void drcbe_x64::emit_cmp_m64_p64(Assembler &a, Mem memref, const be_parameter &p // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_and_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_and_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0xffffffffffffffffU) { if (short_immediate(param.immediate())) - a.and_(reg, param.immediate()); // and reg,param + emit_and_r64_imm(dst, reg, param.immediate()); // and reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.and_(reg, r11); // and reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_and_r64_r64(dst, reg, REG_R11); // and reg,r11 } } } else if (param.is_memory()) - a.and_(reg, MABS(param.memory())); // and reg,[param] + emit_and_r64_m64(dst, reg, MABS(param.memory())); // and reg,[param] else if (param.is_int_register()) - a.and_(reg, Gpq(param.ireg())); // and reg,param + emit_and_r64_r64(dst, reg, param.ireg()); // and reg,param } @@ -1749,26 +2007,26 @@ void drcbe_x64::emit_and_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_and_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0xffffffffffffffffU) { if (short_immediate(param.immediate())) - a.and_(memref, param.immediate()); // and [mem],param + emit_and_m64_imm(dst, memref, param.immediate()); // and [mem],param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.and_(memref, r11); // and [mem],r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_and_m64_r64(dst, memref, REG_R11); // and [mem],r11 } } } else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64(a, reg, param); // mov reg,param - a.and_(memref, reg); // and [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64(dst, reg, param); // mov reg,param + emit_and_m64_r64(dst, memref, reg); // and [dest],reg } } @@ -1778,22 +2036,22 @@ void drcbe_x64::emit_and_m64_p64(Assembler &a, Mem memref, const be_parameter &p // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_test_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_test_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (short_immediate(param.immediate())) - a.test(reg, param.immediate()); // test reg,param + emit_test_r64_imm(dst, reg, param.immediate()); // test reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.test(reg, r11); // test reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_test_r64_r64(dst, reg, REG_R11); // test reg,r11 } } else if (param.is_memory()) - a.test(MABS(param.memory()), reg); // test [param],reg + emit_test_m64_r64(dst, MABS(param.memory()), reg); // test [param],reg else if (param.is_int_register()) - a.test(reg, Gpq(param.ireg())); // test reg,param + emit_test_r64_r64(dst, reg, param.ireg()); // test reg,param } @@ -1802,17 +2060,17 @@ void drcbe_x64::emit_test_r64_p64(Assembler &a, Gp reg, const be_parameter ¶ // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_test_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate() && short_immediate(param.immediate())) - a.test(memref, param.immediate()); // test [dest],param + emit_test_m64_imm(dst, memref, param.immediate()); // test [dest],param else if (param.is_memory()) { - emit_mov_r64_p64(a, rax, param); // mov rax,param - a.test(memref, rax); // test [dest],rax + emit_mov_r64_p64(dst, REG_EAX, param); // mov reg,param + emit_test_m64_r64(dst, memref, REG_EAX); // test [dest],reg } else if (param.is_int_register()) - a.test(memref, Gpq(param.ireg())); // test [dest],param + emit_test_m64_r64(dst, memref, param.ireg()); // test [dest],param } @@ -1821,25 +2079,25 @@ void drcbe_x64::emit_test_m64_p64(Assembler &a, Mem memref, const be_parameter & // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_or_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_or_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (short_immediate(param.immediate())) - a.or_(reg, param.immediate()); // or reg,param + emit_or_r64_imm(dst, reg, param.immediate()); // or reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.or_(reg, r11); // or reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_or_r64_r64(dst, reg, REG_R11); // or reg,r11 } } } else if (param.is_memory()) - a.or_(reg, MABS(param.memory())); // or reg,[param] + emit_or_r64_m64(dst, reg, MABS(param.memory())); // or reg,[param] else if (param.is_int_register()) - a.or_(reg, Gpq(param.ireg())); // or reg,param + emit_or_r64_r64(dst, reg, param.ireg()); // or reg,param } @@ -1848,26 +2106,26 @@ void drcbe_x64::emit_or_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_or_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_or_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (short_immediate(param.immediate())) - a.or_(memref, param.immediate()); // or [mem],param + emit_or_m64_imm(dst, memref, param.immediate()); // or [mem],param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.or_(memref, r11); // or [mem],r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_or_m64_r64(dst, memref, REG_R11); // or [mem],r11 } } } else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64(a, reg, param); // mov reg,param - a.or_(memref, reg); // or [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64(dst, reg, param); // mov reg,param + emit_or_m64_r64(dst, memref, reg); // or [dest],reg } } @@ -1877,27 +2135,27 @@ void drcbe_x64::emit_or_m64_p64(Assembler &a, Mem memref, const be_parameter &pa // register from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_xor_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_xor_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (param.immediate() == 0xffffffffffffffffU) - a.not_(reg); // not reg + emit_not_r64(dst, reg); // not reg else if (short_immediate(param.immediate())) - a.xor_(reg, param.immediate()); // xor reg,param + emit_xor_r64_imm(dst, reg, param.immediate()); // xor reg,param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.xor_(reg, r11); // xor reg,r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_xor_r64_r64(dst, reg, REG_R11); // xor reg,r11 } } } else if (param.is_memory()) - a.xor_(reg, MABS(param.memory())); // xor reg,[param] + emit_xor_r64_m64(dst, reg, MABS(param.memory())); // xor reg,[param] else if (param.is_int_register()) - a.xor_(reg, Gpq(param.ireg())); // xor reg,param + emit_xor_r64_r64(dst, reg, param.ireg()); // xor reg,param } @@ -1906,43 +2164,341 @@ void drcbe_x64::emit_xor_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m // memory location from a 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_xor_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const instruction &inst) +void drcbe_x64::emit_xor_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) { if (param.is_immediate()) { if (inst.flags() != 0 || param.immediate() != 0) { if (param.immediate() == 0xffffffffffffffffU) - a.not_(memref); // not [mem] + emit_not_m64(dst, memref); // not [mem] else if (short_immediate(param.immediate())) - a.xor_(memref, param.immediate()); // xor [mem],param + emit_xor_m64_imm(dst, memref, param.immediate()); // xor [mem],param else { - emit_mov_r64_imm(a, r11, param.immediate()); // mov r11,param - a.xor_(memref, r11); // xor [mem],r11 + emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param + emit_xor_m64_r64(dst, memref, REG_R11); // xor [mem],r11 } } } else { - Gp reg = param.select_register(rax); - emit_mov_r64_p64(a, reg, param); // mov reg,param - a.xor_(memref, reg); // xor [dest],reg + int reg = param.select_register(REG_EAX); + emit_mov_r64_p64(dst, reg, param); // mov reg,param + emit_xor_m64_r64(dst, memref, reg); // xor [dest],reg + } +} + + +//------------------------------------------------- +// emit_shl_r64_p64 - shl operation to a 64-bit +// register from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shl_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_shl_r64_imm(dst, reg, param.immediate()); // shl reg,param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_shl_r64_cl(dst, reg); // shl reg,cl + } +} + + +//------------------------------------------------- +// emit_shl_m64_p64 - shl operation to a 64-bit +// memory location from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint64_t)param.immediate() == 0) + ;// skip + else + emit_shl_m64_imm(dst, memref, param.immediate()); // shl [dest],param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_shl_m64_cl(dst, memref); // shl [dest],cl + } +} + + +//------------------------------------------------- +// emit_shr_r64_p64 - shr operation to a 64-bit +// register from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shr_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_shr_r64_imm(dst, reg, param.immediate()); // shr reg,param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_shr_r64_cl(dst, reg); // shr reg,cl + } +} + + +//------------------------------------------------- +// emit_shr_m64_p64 - shr operation to a 64-bit +// memory location from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_shr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint64_t)param.immediate() == 0) + ;// skip + else + emit_shr_m64_imm(dst, memref, param.immediate()); // shr [dest],param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_shr_m64_cl(dst, memref); // shr [dest],cl + } +} + + +//------------------------------------------------- +// emit_sar_r64_p64 - sar operation to a 64-bit +// register from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_sar_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_sar_r64_imm(dst, reg, param.immediate()); // sar reg,param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_sar_r64_cl(dst, reg); // sar reg,cl + } +} + + +//------------------------------------------------- +// emit_sar_m64_p64 - sar operation to a 64-bit +// memory location from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_sar_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint64_t)param.immediate() == 0) + ;// skip + else + emit_sar_m64_imm(dst, memref, param.immediate()); // sar [dest],param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_sar_m64_cl(dst, memref); // sar [dest],cl } } -void drcbe_x64::emit_shift_p64(Assembler &a, const Inst::Id opcode, Operand op1, const be_parameter ¶m) + +//------------------------------------------------- +// emit_rol_r64_p64 - rol operation to a 64-bit +// register from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rol_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) { - Operand op2 = cl; if (param.is_immediate()) - op2 = imm(param.immediate()); + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rol_r64_imm(dst, reg, param.immediate()); // rol reg,param + } else - emit_mov_r64_p64(a, rcx, param); + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_rol_r64_cl(dst, reg); // rol reg,cl + } +} + + +//------------------------------------------------- +// emit_rol_m64_p64 - rol operation to a 64-bit +// memory location from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rol_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint64_t)param.immediate() == 0) + ;// skip + else + emit_rol_m64_imm(dst, memref, param.immediate()); // rol [dest],param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_rol_m64_cl(dst, memref); // rol [dest],cl + } +} + + +//------------------------------------------------- +// emit_ror_r64_p64 - ror operation to a 64-bit +// register from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_ror_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_ror_r64_imm(dst, reg, param.immediate()); // ror reg,param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_ror_r64_cl(dst, reg); // ror reg,cl + } +} + + +//------------------------------------------------- +// emit_ror_m64_p64 - ror operation to a 64-bit +// memory location from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_ror_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint64_t)param.immediate() == 0) + ;// skip + else + emit_ror_m64_imm(dst, memref, param.immediate()); // ror [dest],param + } + else + { + emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param + emit_ror_m64_cl(dst, memref); // ror [dest],cl + } +} + + +//------------------------------------------------- +// emit_rcl_r64_p64 - rcl operation to a 64-bit +// register from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rcl_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rcl_r64_imm(dst, reg, param.immediate()); // rcl reg,param + } + else + { + emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param + emit_rcl_r64_cl(dst, reg); // rcl reg,cl + } +} + + +//------------------------------------------------- +// emit_rcl_m64_p64 - rcl operation to a 64-bit +// memory location from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rcl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint64_t)param.immediate() == 0) + ;// skip + else + emit_rcl_m64_imm(dst, memref, param.immediate()); // rcl [dest],param + } + else + { + emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param + emit_rcl_m64_cl(dst, memref); // rcl [dest],cl + } +} + + +//------------------------------------------------- +// emit_rcr_r64_p64 - rcr operation to a 64-bit +// register from a 64-bit parameter +//------------------------------------------------- + +void drcbe_x64::emit_rcr_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint32_t)param.immediate() == 0) + ;// skip + else + emit_rcr_r64_imm(dst, reg, param.immediate()); // rcr reg,param + } + else + { + emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param + emit_rcr_r64_cl(dst, reg); // rcr reg,cl + } +} + + +//------------------------------------------------- +// emit_rcr_m64_p64 - rcr operation to a 64-bit +// memory location from a 64-bit parameter +//------------------------------------------------- - a.emit(opcode, op1, op2); +void drcbe_x64::emit_rcr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst) +{ + if (param.is_immediate()) + { + if (inst.flags() == 0 && (uint64_t)param.immediate() == 0) + ;// skip + else + emit_rcr_m64_imm(dst, memref, param.immediate()); // rcr [dest],param + } + else + { + emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param + emit_rcr_m64_cl(dst, memref); // rcr [dest],cl + } } + /*************************************************************************** EMITTERS FOR FLOATING POINT OPERATIONS WITH PARAMETERS ***************************************************************************/ @@ -1952,15 +2508,15 @@ void drcbe_x64::emit_shift_p64(Assembler &a, const Inst::Id opcode, Operand op1, // into a register //------------------------------------------------- -void drcbe_x64::emit_movss_r128_p32(Assembler &a, Xmm reg, const be_parameter ¶m) +void drcbe_x64::emit_movss_r128_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m) { assert(!param.is_immediate()); if (param.is_memory()) - a.movss(reg, MABS(param.memory(), 4)); // movss reg,[param] + emit_movss_r128_m32(dst, reg, MABS(param.memory())); // movss reg,[param] else if (param.is_float_register()) { - if (reg.id() != param.freg()) - a.movss(reg, Xmm(param.freg())); // movss reg,param + if (reg != param.freg()) + emit_movss_r128_r128(dst, reg, param.freg()); // movss reg,param } } @@ -1970,15 +2526,15 @@ void drcbe_x64::emit_movss_r128_p32(Assembler &a, Xmm reg, const be_parameter &p // 32-bit parameter //------------------------------------------------- -void drcbe_x64::emit_movss_p32_r128(Assembler &a, const be_parameter ¶m, Xmm reg) +void drcbe_x64::emit_movss_p32_r128(x86code *&dst, const be_parameter ¶m, uint8_t reg) { assert(!param.is_immediate()); if (param.is_memory()) - a.movss(MABS(param.memory(), 4), reg); // movss [param],reg + emit_movss_m32_r128(dst, MABS(param.memory()), reg); // movss [param],reg else if (param.is_float_register()) { - if (reg.id() != param.freg()) - a.movss(Xmm(param.freg()), reg); // movss param,reg + if (reg != param.freg()) + emit_movss_r128_r128(dst, param.freg(), reg); // movss param,reg } } @@ -1988,15 +2544,15 @@ void drcbe_x64::emit_movss_p32_r128(Assembler &a, const be_parameter ¶m, Xmm // into a register //------------------------------------------------- -void drcbe_x64::emit_movsd_r128_p64(Assembler &a, Xmm reg, const be_parameter ¶m) +void drcbe_x64::emit_movsd_r128_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m) { assert(!param.is_immediate()); if (param.is_memory()) - a.movsd(reg, MABS(param.memory(), 8)); // movsd reg,[param] + emit_movsd_r128_m64(dst, reg, MABS(param.memory())); // movsd reg,[param] else if (param.is_float_register()) { - if (reg.id() != param.freg()) - a.movsd(reg, Xmm(param.freg())); // movsd reg,param + if (reg != param.freg()) + emit_movsd_r128_r128(dst, reg, param.freg()); // movsd reg,param } } @@ -2006,20 +2562,89 @@ void drcbe_x64::emit_movsd_r128_p64(Assembler &a, Xmm reg, const be_parameter &p // 64-bit parameter //------------------------------------------------- -void drcbe_x64::emit_movsd_p64_r128(Assembler &a, const be_parameter ¶m, Xmm reg) +void drcbe_x64::emit_movsd_p64_r128(x86code *&dst, const be_parameter ¶m, uint8_t reg) { assert(!param.is_immediate()); if (param.is_memory()) - a.movsd(MABS(param.memory(), 8), reg); // movsd [param],reg + emit_movsd_m64_r128(dst, MABS(param.memory()), reg); // movsd [param],reg else if (param.is_float_register()) { - if (reg.id() != param.freg()) - a.movsd(Xmm(param.freg()), reg); // movsd param,reg + if (reg != param.freg()) + emit_movsd_r128_r128(dst, param.freg(), reg); // movsd param,reg } } +/*************************************************************************** + OUT-OF-BAND CODE FIXUP CALLBACKS +***************************************************************************/ + +//------------------------------------------------- +// fixup_label - callback to fixup forward- +// referenced labels +//------------------------------------------------- + +void drcbe_x64::fixup_label(void *parameter, drccodeptr labelcodeptr) +{ + drccodeptr src = (drccodeptr)parameter; + + // find the end of the instruction + if (src[0] == 0xe3) + { + src += 1 + 1; + src[-1] = labelcodeptr - src; + } + else if (src[0] == 0xe9) + { + src += 1 + 4; + ((uint32_t *)src)[-1] = labelcodeptr - src; + } + else if (src[0] == 0x0f && (src[1] & 0xf0) == 0x80) + { + src += 2 + 4; + ((uint32_t *)src)[-1] = labelcodeptr - src; + } + else + fatalerror("fixup_label called with invalid jmp source!\n"); +} + + +//------------------------------------------------- +// fixup_exception - callback to perform cleanup +// and jump to an exception handler +//------------------------------------------------- + +void drcbe_x64::fixup_exception(drccodeptr *codeptr, void *param1, void *param2) +{ + drccodeptr src = (drccodeptr)param1; + const instruction &inst = *(const instruction *)param2; + + // normalize parameters + const parameter &handp = inst.param(0); + assert(handp.is_code_handle()); + be_parameter exp(*this, inst.param(1), PTYPE_MRI); + + // look up the handle target + drccodeptr *targetptr = handp.handle().codeptr_addr(); + + // first fixup the jump to get us here + drccodeptr dst = *codeptr; + ((uint32_t *)src)[-1] = dst - src; + + // then store the exception parameter + emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp + + // push the original return address on the stack + emit_lea_r64_m64(dst, REG_RAX, MABS(src)); // lea rax,[return] + emit_push_r64(dst, REG_RAX); // push rax + if (*targetptr != nullptr) + emit_jmp(dst, *targetptr); // jmp *targetptr + else + emit_jmp_m64(dst, MABS(targetptr)); // jmp [targetptr] + + *codeptr = dst; +} @@ -2058,27 +2683,23 @@ void drcbe_x64::debug_log_hashjmp_fail() // op_handle - process a HANDLE opcode //------------------------------------------------- -void drcbe_x64::op_handle(Assembler &a, const instruction &inst) +void drcbe_x64::op_handle(x86code *&dst, const instruction &inst) { assert_no_condition(inst); assert_no_flags(inst); assert(inst.numparams() == 1); assert(inst.param(0).is_code_handle()); - // make a label for documentation - Label handle = a.newNamedLabel(inst.param(0).handle().string()); - a.bind(handle); - // emit a jump around the stack adjust in case code falls through here - Label skip = a.newLabel(); - a.short_().jmp(skip); // jmp skip + emit_link skip; + emit_jmp_short_link(dst, skip); // jmp skip // register the current pointer for the handle - inst.param(0).handle().set_codeptr(drccodeptr(a.code()->baseAddress() + a.offset())); + inst.param(0).handle().set_codeptr(dst); // by default, the handle points to prolog code that moves the stack pointer - a.lea(rsp, ptr(rsp, -40)); // lea rsp,[rsp-40] - a.bind(skip); // skip: + emit_lea_r64_m64(dst, REG_RSP, MBD(REG_RSP, -40)); // lea rsp,[rsp-40] + resolve_link(dst, skip); // skip: } @@ -2086,7 +2707,7 @@ void drcbe_x64::op_handle(Assembler &a, const instruction &inst) // op_hash - process a HASH opcode //------------------------------------------------- -void drcbe_x64::op_hash(Assembler &a, const instruction &inst) +void drcbe_x64::op_hash(x86code *&dst, const instruction &inst) { assert_no_condition(inst); assert_no_flags(inst); @@ -2095,7 +2716,7 @@ void drcbe_x64::op_hash(Assembler &a, const instruction &inst) assert(inst.param(1).is_immediate()); // register the current pointer for the mode/PC - m_hash.set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), drccodeptr(a.code()->baseAddress() + a.offset())); + m_hash.set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), dst); } @@ -2103,20 +2724,15 @@ void drcbe_x64::op_hash(Assembler &a, const instruction &inst) // op_label - process a LABEL opcode //------------------------------------------------- -void drcbe_x64::op_label(Assembler &a, const instruction &inst) +void drcbe_x64::op_label(x86code *&dst, const instruction &inst) { assert_no_condition(inst); assert_no_flags(inst); assert(inst.numparams() == 1); assert(inst.param(0).is_code_label()); - std::string labelName = util::string_format("L$%x", inst.param(0).label()); - Label label = a.labelByName(labelName.c_str()); - if (!label.isValid()) - label = a.newNamedLabel(labelName.c_str()); - // register the current pointer for the label - a.bind(label); + m_labels.set_codeptr(inst.param(0).label(), dst); } @@ -2124,7 +2740,7 @@ void drcbe_x64::op_label(Assembler &a, const instruction &inst) // op_comment - process a COMMENT opcode //------------------------------------------------- -void drcbe_x64::op_comment(Assembler &a, const instruction &inst) +void drcbe_x64::op_comment(x86code *&dst, const instruction &inst) { assert_no_condition(inst); assert_no_flags(inst); @@ -2139,7 +2755,7 @@ void drcbe_x64::op_comment(Assembler &a, const instruction &inst) // op_mapvar - process a MAPVAR opcode //------------------------------------------------- -void drcbe_x64::op_mapvar(Assembler &a, const instruction &inst) +void drcbe_x64::op_mapvar(x86code *&dst, const instruction &inst) { assert_no_condition(inst); assert_no_flags(inst); @@ -2148,7 +2764,7 @@ void drcbe_x64::op_mapvar(Assembler &a, const instruction &inst) assert(inst.param(1).is_immediate()); // set the value of the specified mapvar - m_map.set_value(drccodeptr(a.code()->baseAddress() + a.offset()), inst.param(0).mapvar(), inst.param(1).immediate()); + m_map.set_value(dst, inst.param(0).mapvar(), inst.param(1).immediate()); } @@ -2161,7 +2777,7 @@ void drcbe_x64::op_mapvar(Assembler &a, const instruction &inst) // op_nop - process a NOP opcode //------------------------------------------------- -void drcbe_x64::op_nop(Assembler &a, const instruction &inst) +void drcbe_x64::op_nop(x86code *&dst, const instruction &inst) { // nothing } @@ -2171,7 +2787,7 @@ void drcbe_x64::op_nop(Assembler &a, const instruction &inst) // op_debug - process a DEBUG opcode //------------------------------------------------- -void drcbe_x64::op_debug(Assembler &a, const instruction &inst) +void drcbe_x64::op_debug(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2184,17 +2800,17 @@ void drcbe_x64::op_debug(Assembler &a, const instruction &inst) be_parameter pcp(*this, inst.param(0), PTYPE_MRI); // test and branch - emit_mov_r64_imm(a, rax, (uintptr_t)&m_device.machine().debug_flags); // mov rax,&debug_flags - a.test(dword_ptr(rax), DEBUG_FLAG_CALL_HOOK); // test [debug_flags],DEBUG_FLAG_CALL_HOOK - Label skip = a.newLabel(); - a.short_().jz(skip); + emit_mov_r64_imm(dst, REG_RAX, (uintptr_t)&m_device.machine().debug_flags); // mov rax,&debug_flags + emit_test_m32_imm(dst, MBD(REG_RAX, 0), DEBUG_FLAG_CALL_HOOK); // test [debug_flags],DEBUG_FLAG_CALL_HOOK + emit_link skip = { nullptr }; + emit_jcc_short_link(dst, x64emit::COND_Z, skip); // jz skip // push the parameter - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_device.debug()); // mov param1,device.debug - emit_mov_r32_p32(a, Gpd(REG_PARAM2), pcp); // mov param2,pcp - emit_smart_call_m64(a, &m_near.debug_cpu_instruction_hook); // call debug_cpu_instruction_hook + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)m_device.debug()); // mov param1,device.debug + emit_mov_r32_p32(dst, REG_PARAM2, pcp); // mov param2,pcp + emit_smart_call_m64(dst, &m_near.debug_cpu_instruction_hook); // call debug_cpu_instruction_hook - a.bind(skip); + resolve_link(dst, skip); // skip: } } @@ -2203,7 +2819,7 @@ void drcbe_x64::op_debug(Assembler &a, const instruction &inst) // op_exit - process an EXIT opcode //------------------------------------------------- -void drcbe_x64::op_exit(Assembler &a, const instruction &inst) +void drcbe_x64::op_exit(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2214,11 +2830,11 @@ void drcbe_x64::op_exit(Assembler &a, const instruction &inst) be_parameter retp(*this, inst.param(0), PTYPE_MRI); // load the parameter into EAX - emit_mov_r32_p32(a, eax, retp); // mov eax,retp + emit_mov_r32_p32(dst, REG_EAX, retp); // mov eax,retp if (inst.condition() == uml::COND_ALWAYS) - a.jmp(imm(m_exit)); // jmp exit + emit_jmp(dst, m_exit); // jmp exit else - a.j(X86_CONDITION(inst.condition()), imm(m_exit)); // jcc exit + emit_jcc(dst, X86_CONDITION(inst.condition()), m_exit); // jcc exit } @@ -2226,7 +2842,7 @@ void drcbe_x64::op_exit(Assembler &a, const instruction &inst) // op_hashjmp - process a HASHJMP opcode //------------------------------------------------- -void drcbe_x64::op_hashjmp(Assembler &a, const instruction &inst) +void drcbe_x64::op_hashjmp(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2241,13 +2857,13 @@ void drcbe_x64::op_hashjmp(Assembler &a, const instruction &inst) if (LOG_HASHJMPS) { - emit_mov_r32_p32(a, Gpd(REG_PARAM1), pcp); - emit_mov_r32_p32(a, Gpd(REG_PARAM2), modep); - emit_smart_call_m64(a, &m_near.debug_log_hashjmp); + emit_mov_r32_p32(dst, REG_PARAM1, pcp); + emit_mov_r32_p32(dst, REG_PARAM2, modep); + emit_smart_call_m64(dst, &m_near.debug_log_hashjmp); } // load the stack base one word early so we end up at the right spot after our call below - a.mov(rsp, MABS(&m_near.hashstacksave)); // mov rsp,[hashstacksave] + emit_mov_r64_m64(dst, REG_RSP, MABS(&m_near.hashstacksave)); // mov rsp,[hashstacksave] // fixed mode cases if (modep.is_immediate() && m_hash.is_mode_populated(modep.immediate())) @@ -2257,56 +2873,58 @@ void drcbe_x64::op_hashjmp(Assembler &a, const instruction &inst) { uint32_t l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask(); uint32_t l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask(); - a.call(MABS(&m_hash.base()[modep.immediate()][l1val][l2val])); // call hash[modep][l1val][l2val] + emit_call_m64(dst, MABS(&m_hash.base()[modep.immediate()][l1val][l2val])); + // call hash[modep][l1val][l2val] } // a fixed mode but variable PC else { - emit_mov_r32_p32(a, eax, pcp); // mov eax,pcp - a.mov(edx, eax); // mov edx,eax - a.shr(edx, m_hash.l1shift()); // shr edx,l1shift - a.and_(eax, m_hash.l2mask() << m_hash.l2shift()); // and eax,l2mask << l2shift - a.mov(rdx, ptr(rbp, rdx, 3, offset_from_rbp(&m_hash.base()[modep.immediate()][0]))); + emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp + emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax + emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift + emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift()); // and eax,l2mask << l2shift + emit_mov_r64_m64(dst, REG_RDX, MBISD(REG_RBP, REG_RDX, 8, offset_from_rbp(&m_hash.base()[modep.immediate()][0]))); // mov rdx,hash[modep+edx*8] - a.call(ptr(rdx, rax, 3 - m_hash.l2shift())); // call [rdx+rax*shift] + emit_call_m64(dst, MBISD(REG_RDX, REG_RAX, 8 >> m_hash.l2shift(), 0)); // call [rdx+rax*shift] } } else { // variable mode - Gp modereg = modep.select_register(ecx); - emit_mov_r32_p32(a, modereg, modep); // mov modereg,modep - a.mov(rcx, ptr(rbp, modereg, 3, offset_from_rbp(m_hash.base()))); // mov rcx,hash[modereg*8] + int modereg = modep.select_register(REG_ECX); + emit_mov_r32_p32(dst, modereg, modep); // mov modereg,modep + emit_mov_r64_m64(dst, REG_RCX, MBISD(REG_RBP, modereg, 8, offset_from_rbp(m_hash.base()))); + // mov rcx,hash[modereg*8] // fixed PC if (pcp.is_immediate()) { uint32_t l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask(); uint32_t l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask(); - a.mov(rdx, ptr(rcx, l1val * 8)); // mov rdx,[rcx+l1val*8] - a.call(ptr(rdx, l2val * 8)); // call [l2val*8] + emit_mov_r64_m64(dst, REG_RDX, MBD(REG_RCX, l1val*8)); // mov rdx,[rcx+l1val*8] + emit_call_m64(dst, MBD(REG_RDX, l2val*8)); // call [l2val*8] } // variable PC else { - emit_mov_r32_p32(a, eax, pcp); // mov eax,pcp - a.mov(edx, eax); // mov edx,eax - a.shr(edx, m_hash.l1shift()); // shr edx,l1shift - a.mov(rdx, ptr(rcx, rdx, 3)); // mov rdx,[rcx+rdx*8] - a.and_(eax, m_hash.l2mask() << m_hash.l2shift()); // and eax,l2mask << l2shift - a.call(ptr(rdx, rax, 3 - m_hash.l2shift())); // call [rdx+rax*shift] + emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp + emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax + emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift + emit_mov_r64_m64(dst, REG_RDX, MBISD(REG_RCX, REG_RDX, 8, 0)); // mov rdx,[rcx+rdx*8] + emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift()); // and eax,l2mask << l2shift + emit_call_m64(dst, MBISD(REG_RDX, REG_RAX, 8 >> m_hash.l2shift(), 0)); // call [rdx+rax*shift] } } // in all cases, if there is no code, we return here to generate the exception if (LOG_HASHJMPS) - emit_smart_call_m64(a, &m_near.debug_log_hashjmp_fail); + emit_smart_call_m64(dst, &m_near.debug_log_hashjmp_fail); - emit_mov_m32_p32(a, MABS(&m_state.exp, 4), pcp); // mov [exp],param - a.sub(rsp, 8); // sub rsp,8 - a.call(MABS(exp.handle().codeptr_addr())); // call [exp] + emit_mov_m32_p32(dst, MABS(&m_state.exp), pcp); // mov [exp],param + emit_sub_r64_imm(dst, REG_RSP, 8); // sub rsp,8 + emit_call_m64(dst, MABS(exp.handle().codeptr_addr())); // call [exp] } @@ -2314,7 +2932,7 @@ void drcbe_x64::op_hashjmp(Assembler &a, const instruction &inst) // op_jmp - process a JMP opcode //------------------------------------------------- -void drcbe_x64::op_jmp(Assembler &a, const instruction &inst) +void drcbe_x64::op_jmp(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2325,15 +2943,14 @@ void drcbe_x64::op_jmp(Assembler &a, const instruction &inst) const parameter &labelp = inst.param(0); assert(labelp.is_code_label()); - std::string labelName = util::string_format("L$%x", labelp.label()); - Label jmptarget = a.labelByName(labelName.c_str()); - if (!jmptarget.isValid()) - jmptarget = a.newNamedLabel(labelName.c_str()); - + // look up the jump target and jump there + x86code *jmptarget = (x86code *)m_labels.get_codeptr(labelp.label(), m_fixup_label, dst); + if (jmptarget == nullptr) + jmptarget = dst + 0x7ffffff0; if (inst.condition() == uml::COND_ALWAYS) - a.jmp(jmptarget); // jmp target + emit_jmp(dst, jmptarget); // jmp target else - a.j(X86_CONDITION(inst.condition()), jmptarget); // jcc target + emit_jcc(dst, X86_CONDITION(inst.condition()), jmptarget); // jcc target } @@ -2342,7 +2959,7 @@ void drcbe_x64::op_jmp(Assembler &a, const instruction &inst) // op_exh - process an EXH opcode //------------------------------------------------- -void drcbe_x64::op_exh(Assembler &a, const instruction &inst) +void drcbe_x64::op_exh(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2357,17 +2974,22 @@ void drcbe_x64::op_exh(Assembler &a, const instruction &inst) // look up the handle target drccodeptr *targetptr = handp.handle().codeptr_addr(); - // perform the exception processing - Label no_exception = a.newLabel(); - if (inst.condition() != uml::COND_ALWAYS) - a.short_().j(X86_NOT_CONDITION(inst.condition()), no_exception); // jcc no_exception - emit_mov_m32_p32(a, MABS(&m_state.exp, 4), exp); // mov [exp],exp - if (*targetptr != nullptr) - a.call(imm(*targetptr)); // call *targetptr + // perform the exception processing inline if unconditional + if (inst.condition() == uml::COND_ALWAYS) + { + emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp + if (*targetptr != nullptr) + emit_call(dst, *targetptr); // call *targetptr + else + emit_call_m64(dst, MABS(targetptr)); // call [targetptr] + } + + // otherwise, jump to an out-of-band handler else - a.call(MABS(targetptr)); // call [targetptr] - if (inst.condition() != uml::COND_ALWAYS) - a.bind(no_exception); + { + emit_jcc(dst, X86_CONDITION(inst.condition()), dst + 0x7ffffff0); // jcc exception + m_cache.request_oob_codegen(m_fixup_exception, dst, &const_cast<instruction &>(inst)); + } } @@ -2375,7 +2997,7 @@ void drcbe_x64::op_exh(Assembler &a, const instruction &inst) // op_callh - process a CALLH opcode //------------------------------------------------- -void drcbe_x64::op_callh(Assembler &a, const instruction &inst) +void drcbe_x64::op_callh(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2390,19 +3012,19 @@ void drcbe_x64::op_callh(Assembler &a, const instruction &inst) drccodeptr *targetptr = handp.handle().codeptr_addr(); // skip if conditional - Label skip = a.newLabel(); + emit_link skip = { nullptr }; if (inst.condition() != uml::COND_ALWAYS) - a.short_().j(X86_NOT_CONDITION(inst.condition()), skip); // jcc skip + emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip // jump through the handle; directly if a normal jump if (*targetptr != nullptr) - a.call(imm(*targetptr)); // call *targetptr + emit_call(dst, *targetptr); // call *targetptr else - a.call(MABS(targetptr)); // call [targetptr] + emit_call_m64(dst, MABS(targetptr)); // call [targetptr] // resolve the conditional link if (inst.condition() != uml::COND_ALWAYS) - a.bind(skip); // skip: + resolve_link(dst, skip); // skip: } @@ -2410,7 +3032,7 @@ void drcbe_x64::op_callh(Assembler &a, const instruction &inst) // op_ret - process a RET opcode //------------------------------------------------- -void drcbe_x64::op_ret(Assembler &a, const instruction &inst) +void drcbe_x64::op_ret(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2419,17 +3041,17 @@ void drcbe_x64::op_ret(Assembler &a, const instruction &inst) assert(inst.numparams() == 0); // skip if conditional - Label skip = a.newLabel(); + emit_link skip = { nullptr }; if (inst.condition() != uml::COND_ALWAYS) - a.short_().j(X86_NOT_CONDITION(inst.condition()), skip); // jcc skip + emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip // return - a.lea(rsp, ptr(rsp, 40)); // lea rsp,[rsp+40] - a.ret(); // ret + emit_lea_r64_m64(dst, REG_RSP, MBD(REG_RSP, 40)); // lea rsp,[rsp+40] + emit_ret(dst); // ret // resolve the conditional link if (inst.condition() != uml::COND_ALWAYS) - a.bind(skip); // skip: + resolve_link(dst, skip); // skip: } @@ -2437,7 +3059,7 @@ void drcbe_x64::op_ret(Assembler &a, const instruction &inst) // op_callc - process a CALLC opcode //------------------------------------------------- -void drcbe_x64::op_callc(Assembler &a, const instruction &inst) +void drcbe_x64::op_callc(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2450,17 +3072,17 @@ void drcbe_x64::op_callc(Assembler &a, const instruction &inst) be_parameter paramp(*this, inst.param(1), PTYPE_M); // skip if conditional - Label skip = a.newLabel(); + emit_link skip = { nullptr }; if (inst.condition() != uml::COND_ALWAYS) - a.short_().j(X86_NOT_CONDITION(inst.condition()), skip); // jcc skip + emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip // perform the call - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)paramp.memory()); // mov param1,paramp - emit_smart_call_r64(a, (x86code *)(uintptr_t)funcp.cfunc(), rax); // call funcp + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)paramp.memory()); // mov param1,paramp + emit_smart_call_r64(dst, (x86code *)(uintptr_t)funcp.cfunc(), REG_RAX); // call funcp // resolve the conditional link if (inst.condition() != uml::COND_ALWAYS) - a.bind(skip); // skip: + resolve_link(dst, skip); // skip: } @@ -2468,7 +3090,7 @@ void drcbe_x64::op_callc(Assembler &a, const instruction &inst) // op_recover - process a RECOVER opcode //------------------------------------------------- -void drcbe_x64::op_recover(Assembler &a, const instruction &inst) +void drcbe_x64::op_recover(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2479,13 +3101,13 @@ void drcbe_x64::op_recover(Assembler &a, const instruction &inst) be_parameter dstp(*this, inst.param(0), PTYPE_MR); // call the recovery code - a.mov(rax, MABS(&m_near.stacksave)); // mov rax,stacksave - a.mov(rax, ptr(rax, -8)); // mov rax,[rax-8] - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)&m_map); // mov param1,m_map - a.lea(Gpq(REG_PARAM2), ptr(rax, -1)); // lea param2,[rax-1] - emit_mov_r64_imm(a, Gpq(REG_PARAM3), inst.param(1).mapvar()); // mov param3,param[1].value - emit_smart_call_m64(a, &m_near.drcmap_get_value); // call drcmap_get_value - emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax + emit_mov_r64_m64(dst, REG_RAX, MABS(&m_near.stacksave)); // mov rax,stacksave + emit_mov_r64_m64(dst, REG_RAX, MBD(REG_RAX, -8)); // mov rax,[rax-4] + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)&m_map); // mov param1,m_map + emit_lea_r64_m64(dst, REG_PARAM2, MBD(REG_RAX, -1)); // lea param2,[rax-1] + emit_mov_r64_imm(dst, REG_PARAM3, inst.param(1).mapvar()); // mov param3,param[1].value + emit_smart_call_m64(dst, &m_near.drcmap_get_value); // call drcmap_get_value + emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax } @@ -2499,7 +3121,7 @@ void drcbe_x64::op_recover(Assembler &a, const instruction &inst) // op_setfmod - process a SETFMOD opcode //------------------------------------------------- -void drcbe_x64::op_setfmod(Assembler &a, const instruction &inst) +void drcbe_x64::op_setfmod(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2513,17 +3135,18 @@ void drcbe_x64::op_setfmod(Assembler &a, const instruction &inst) if (srcp.is_immediate()) { int value = srcp.immediate() & 3; - a.mov(MABS(&m_state.fmod), value); // mov [fmod],srcp - a.ldmxcsr(MABS(&m_near.ssecontrol[value])); // ldmxcsr fp_control[srcp] + emit_mov_m8_imm(dst, MABS(&m_state.fmod), value); // mov [fmod],srcp + emit_ldmxcsr_m32(dst, MABS(&m_near.ssecontrol[value])); // ldmxcsr fp_control[srcp] } // register/memory case else { - emit_mov_r32_p32(a, eax, srcp); // mov eax,srcp - a.and_(eax, 3); // and eax,3 - a.mov(MABS(&m_state.fmod), al); // mov [fmod],al - a.ldmxcsr(ptr(rbp, rax, 2, offset_from_rbp(&m_near.ssecontrol[0]))); // ldmxcsr fp_control[eax] + emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp + emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3 + emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al + emit_ldmxcsr_m32(dst, MBISD(REG_RBP, REG_RAX, 4, offset_from_rbp(&m_near.ssecontrol[0]))); + // ldmxcsr fp_control[eax] } } @@ -2532,7 +3155,7 @@ void drcbe_x64::op_setfmod(Assembler &a, const instruction &inst) // op_getfmod - process a GETFMOD opcode //------------------------------------------------- -void drcbe_x64::op_getfmod(Assembler &a, const instruction &inst) +void drcbe_x64::op_getfmod(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2542,16 +3165,13 @@ void drcbe_x64::op_getfmod(Assembler &a, const instruction &inst) // normalize parameters be_parameter dstp(*this, inst.param(0), PTYPE_MR); - Mem fmod = MABS(&m_state.fmod); - fmod.setSize(1); - // fetch the current mode and store to the destination if (dstp.is_int_register()) - a.movzx(Gpd(dstp.ireg()), fmod); // movzx reg,[fmod] + emit_movzx_r32_m8(dst, dstp.ireg(), MABS(&m_state.fmod)); // movzx reg,[fmod] else { - a.movzx(eax, fmod); // movzx eax,[fmod] - a.mov(MABS(dstp.memory()), eax); // mov [dstp],eax + emit_movzx_r32_m8(dst, REG_EAX, MABS(&m_state.fmod)); // movzx eax,[fmod] + emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax } } @@ -2560,7 +3180,7 @@ void drcbe_x64::op_getfmod(Assembler &a, const instruction &inst) // op_getexp - process a GETEXP opcode //------------------------------------------------- -void drcbe_x64::op_getexp(Assembler &a, const instruction &inst) +void drcbe_x64::op_getexp(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2572,11 +3192,11 @@ void drcbe_x64::op_getexp(Assembler &a, const instruction &inst) // fetch the exception parameter and store to the destination if (dstp.is_int_register()) - a.mov(Gpd(dstp.ireg()), MABS(&m_state.exp)); // mov reg,[exp] + emit_mov_r32_m32(dst, dstp.ireg(), MABS(&m_state.exp)); // mov reg,[exp] else { - a.mov(eax, MABS(&m_state.exp)); // mov eax,[exp] - a.mov(MABS(dstp.memory()), eax); // mov [dstp],eax + emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp] + emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax } } @@ -2585,7 +3205,7 @@ void drcbe_x64::op_getexp(Assembler &a, const instruction &inst) // op_getflgs - process a GETFLGS opcode //------------------------------------------------- -void drcbe_x64::op_getflgs(Assembler &a, const instruction &inst) +void drcbe_x64::op_getflgs(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2597,7 +3217,7 @@ void drcbe_x64::op_getflgs(Assembler &a, const instruction &inst) be_parameter maskp(*this, inst.param(1), PTYPE_I); // pick a target register for the general case - Gp dstreg = dstp.select_register(eax); + int dstreg = dstp.select_register(REG_EAX); // compute mask for flags uint32_t flagmask = 0; @@ -2611,104 +3231,105 @@ void drcbe_x64::op_getflgs(Assembler &a, const instruction &inst) { // single flags only case FLAG_C: - a.setc(al); // setc al - a.movzx(dstreg, al); // movzx dstreg,al + emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al + emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al break; case FLAG_V: - a.seto(al); // seto al - a.movzx(dstreg, al); // movzx dstreg,al - a.shl(dstreg, 1); // shl dstreg,1 + emit_setcc_r8(dst, x64emit::COND_O, REG_AL); // seto al + emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al + emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1 break; case FLAG_Z: - a.setz(al); // setz al - a.movzx(dstreg, al); // movzx dstreg,al - a.shl(dstreg, 2); // shl dstreg,2 + emit_setcc_r8(dst, x64emit::COND_Z, REG_AL); // setz al + emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al + emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2 break; case FLAG_S: - a.sets(al); // sets al - a.movzx(dstreg, al); // movzx dstreg,al - a.shl(dstreg, 3); // shl dstreg,3 + emit_setcc_r8(dst, x64emit::COND_S, REG_AL); // sets al + emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al + emit_shl_r32_imm(dst, dstreg, 3); // shl dstreg,3 break; case FLAG_U: - a.setp(al); // setp al - a.movzx(dstreg, al); // movzx dstreg,al - a.shl(dstreg, 4); // shl dstreg,4 + emit_setcc_r8(dst, x64emit::COND_P, REG_AL); // setp al + emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al + emit_shl_r32_imm(dst, dstreg, 4); // shl dstreg,4 break; // carry plus another flag case FLAG_C | FLAG_V: - a.setc(al); // setc al - a.seto(cl); // seto cl - a.movzx(eax, al); // movzx eax,al - a.movzx(ecx, cl); // movzx ecx,cl - a.lea(dstreg, ptr(eax, ecx, 1)); // lea dstreg,[eax+ecx*2] + emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al + emit_setcc_r8(dst, x64emit::COND_O, REG_CL); // seto cl + emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al + emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,cl + emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2] break; case FLAG_C | FLAG_Z: - a.setc(al); // setc al - a.setz(cl); // setz cl - a.movzx(eax, al); // movzx eax,al - a.movzx(ecx, cl); // movzx ecx,cl - a.lea(dstreg, ptr(eax, ecx, 2)); // lea dstreg,[eax+ecx*4] + emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al + emit_setcc_r8(dst, x64emit::COND_Z, REG_CL); // setz cl + emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al + emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,cl + emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4] break; case FLAG_C | FLAG_S: - a.setc(al); // setc al - a.sets(cl); // sets cl - a.movzx(eax, al); // movzx eax,al - a.movzx(ecx, cl); // movzx ecx,cl - a.lea(dstreg, ptr(eax, ecx, 3)); // lea dstreg,[eax+ecx*8] + emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al + emit_setcc_r8(dst, x64emit::COND_S, REG_CL); // sets cl + emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al + emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,cl + emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 8, 0)); // lea dstreg,[eax+ecx*8] break; // overflow plus another flag case FLAG_V | FLAG_Z: - a.seto(al); // seto al - a.setz(cl); // setz cl - a.movzx(eax, al); // movzx eax,al - a.movzx(ecx, cl); // movzx ecx,cl - a.lea(dstreg, ptr(eax, ecx, 1)); // lea dstreg,[eax+ecx*2] - a.shl(dstreg, 1); // shl dstreg,1 + emit_setcc_r8(dst, x64emit::COND_O, REG_AL); // seto al + emit_setcc_r8(dst, x64emit::COND_Z, REG_CL); // setz cl + emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al + emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,cl + emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2] + emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1 break; case FLAG_V | FLAG_S: - a.seto(al); // seto al - a.sets(cl); // sets cl - a.movzx(eax, al); // movzx eax,al - a.movzx(ecx, cl); // movzx ecx,cl - a.lea(dstreg, ptr(eax, ecx, 2)); // lea dstreg,[eax+ecx*4] - a.shl(dstreg, 1); // shl dstreg,1 + emit_setcc_r8(dst, x64emit::COND_O, REG_AL); // seto al + emit_setcc_r8(dst, x64emit::COND_S, REG_CL); // sets cl + emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al + emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al + emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4] + emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1 break; // zero plus another flag case FLAG_Z | FLAG_S: - a.setz(al); // setz al - a.sets(cl); // sets cl - a.movzx(eax, al); // movzx eax,al - a.movzx(ecx, cl); // movzx ecx,cl - a.lea(dstreg, ptr(eax, ecx, 1)); // lea dstreg,[eax+ecx*2] - a.shl(dstreg, 2); // shl dstreg,2 + emit_setcc_r8(dst, x64emit::COND_Z, REG_AL); // setz al + emit_setcc_r8(dst, x64emit::COND_S, REG_CL); // sets cl + emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al + emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al + emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2] + emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2 break; // default cases default: - a.pushf(); // pushf - a.pop(eax); // pop eax - a.and_(eax, flagmask); // and eax,flagmask - a.movzx(dstreg, byte_ptr(rbp, rax, 0, offset_from_rbp(&m_near.flagsmap[0]))); // movzx dstreg,[flags_map] + emit_pushf(dst); // pushf + emit_pop_r64(dst, REG_EAX); // pop eax + emit_and_r32_imm(dst, REG_EAX, flagmask); // and eax,flagmask + emit_movzx_r32_m8(dst, dstreg, MBISD(REG_RBP, REG_RAX, 1, offset_from_rbp(&m_near.flagsmap[0]))); + // movzx dstreg,[flags_map] break; } // 32-bit form if (inst.size() == 4) - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg // 64-bit form else if (inst.size() == 8) - emit_mov_p64_r64(a, dstp, dstreg.r64()); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } @@ -2716,7 +3337,7 @@ void drcbe_x64::op_getflgs(Assembler &a, const instruction &inst) // op_save - process a SAVE opcode //------------------------------------------------- -void drcbe_x64::op_save(Assembler &a, const instruction &inst) +void drcbe_x64::op_save(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2727,31 +3348,32 @@ void drcbe_x64::op_save(Assembler &a, const instruction &inst) be_parameter dstp(*this, inst.param(0), PTYPE_M); // copy live state to the destination - emit_mov_r64_imm(a, rcx, (uintptr_t)dstp.memory()); // mov rcx,dstp + emit_mov_r64_imm(dst, REG_RCX, (uintptr_t)dstp.memory()); // mov rcx,dstp // copy flags - a.pushf(); // pushf - a.pop(rax); // pop rax - a.and_(eax, 0x8c5); // and eax,0x8c5 - a.mov(al, ptr(rbp, rax, 0, offset_from_rbp(&m_near.flagsmap[0]))); // mov al,[flags_map] - a.mov(ptr(rcx, offsetof(drcuml_machine_state, flags)), al); // mov state->flags,al + emit_pushf(dst); // pushf + emit_pop_r64(dst, REG_RAX); // pop rax + emit_and_r32_imm(dst, REG_EAX, 0x8c5); // and eax,0x8c5 + emit_mov_r8_m8(dst, REG_AL, MBISD(REG_RBP, REG_RAX, 1, offset_from_rbp(&m_near.flagsmap[0]))); + // mov al,[flags_map] + emit_mov_m8_r8(dst, MBD(REG_RCX, offsetof(drcuml_machine_state, flags)), REG_AL); // mov state->flags,al // copy fmod and exp - a.mov(al, MABS(&m_state.fmod)); // mov al,[fmod] - a.mov(ptr(rcx, offsetof(drcuml_machine_state, fmod)), al); // mov state->fmod,al - a.mov(eax, MABS(&m_state.exp)); // mov eax,[exp] - a.mov(ptr(rcx, offsetof(drcuml_machine_state, exp)), eax); // mov state->exp,eax + emit_mov_r8_m8(dst, REG_AL, MABS(&m_state.fmod)); // mov al,[fmod] + emit_mov_m8_r8(dst, MBD(REG_RCX, offsetof(drcuml_machine_state, fmod)), REG_AL); // mov state->fmod,al + emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp] + emit_mov_m32_r32(dst, MBD(REG_RCX, offsetof(drcuml_machine_state, exp)), REG_EAX); // mov state->exp,eax // copy integer registers int regoffs = offsetof(drcuml_machine_state, r); for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++) { if (int_register_map[regnum] != 0) - a.mov(ptr(rcx, regoffs + 8 * regnum), Gpq(regnum)); + emit_mov_m64_r64(dst, MBD(REG_RCX, regoffs + 8 * regnum), int_register_map[regnum]); else { - a.mov(rax, MABS(&m_state.r[regnum].d)); - a.mov(ptr(rcx, regoffs + 8 * regnum), rax); + emit_mov_r64_m64(dst, REG_RAX, MABS(&m_state.r[regnum].d)); + emit_mov_m64_r64(dst, MBD(REG_RCX, regoffs + 8 * regnum), REG_RAX); } } @@ -2760,11 +3382,11 @@ void drcbe_x64::op_save(Assembler &a, const instruction &inst) for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++) { if (float_register_map[regnum] != 0) - a.movsd(ptr(rcx, regoffs + 8 * regnum), Xmm(regnum)); + emit_movsd_m64_r128(dst, MBD(REG_RCX, regoffs + 8 * regnum), float_register_map[regnum]); else { - a.mov(rax, MABS(&m_state.f[regnum].d)); - a.mov(ptr(rcx, regoffs + 8 * regnum), rax); + emit_mov_r64_m64(dst, REG_RAX, MABS(&m_state.f[regnum].d)); + emit_mov_m64_r64(dst, MBD(REG_RCX, regoffs + 8 * regnum), REG_RAX); } } } @@ -2774,7 +3396,7 @@ void drcbe_x64::op_save(Assembler &a, const instruction &inst) // op_restore - process a RESTORE opcode //------------------------------------------------- -void drcbe_x64::op_restore(Assembler &a, const instruction &inst) +void drcbe_x64::op_restore(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4); @@ -2784,18 +3406,18 @@ void drcbe_x64::op_restore(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(0), PTYPE_M); // copy live state from the destination - emit_mov_r64_imm(a, rcx, (uintptr_t)srcp.memory()); // mov rcx,dstp + emit_mov_r64_imm(dst, REG_ECX, (uintptr_t)srcp.memory()); // mov rcx,dstp // copy integer registers int regoffs = offsetof(drcuml_machine_state, r); for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++) { if (int_register_map[regnum] != 0) - a.mov(Gpq(regnum), ptr(rcx, regoffs + 8 * regnum)); + emit_mov_r64_m64(dst, int_register_map[regnum], MBD(REG_RCX, regoffs + 8 * regnum)); else { - a.mov(rax, ptr(rcx, regoffs + 8 * regnum)); - a.mov(MABS(&m_state.r[regnum].d), rax); + emit_mov_r64_m64(dst, REG_RAX, MBD(REG_RCX, regoffs + 8 * regnum)); + emit_mov_m64_r64(dst, MABS(&m_state.r[regnum].d), REG_RAX); } } @@ -2804,29 +3426,27 @@ void drcbe_x64::op_restore(Assembler &a, const instruction &inst) for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++) { if (float_register_map[regnum] != 0) - a.movsd(Xmm(regnum), ptr(rcx, regoffs + 8 * regnum)); + emit_movsd_r128_m64(dst, float_register_map[regnum], MBD(REG_RCX, regoffs + 8 * regnum)); else { - a.mov(rax, ptr(rcx, regoffs + 8 * regnum)); - a.mov(MABS(&m_state.f[regnum].d), rax); + emit_mov_r64_m64(dst, REG_RAX, MBD(REG_RCX, regoffs + 8 * regnum)); + emit_mov_m64_r64(dst, MABS(&m_state.f[regnum].d), REG_RAX); } } - Mem fmod = MABS(&m_state.fmod); - fmod.setSize(1); - // copy fmod and exp - a.movzx(eax, byte_ptr(rcx, offsetof(drcuml_machine_state, fmod))); // movzx eax,state->fmod - a.and_(eax, 3); // and eax,3 - a.mov(MABS(&m_state.fmod), al); // mov [fmod],al - a.ldmxcsr(ptr(rbp, rax, 2, offset_from_rbp(&m_near.ssecontrol[0]))); // ldmxcsr fp_control[eax] - a.mov(eax, ptr(rcx, offsetof(drcuml_machine_state, exp))); // mov eax,state->exp - a.mov(MABS(&m_state.exp), eax); // mov [exp],eax + emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_RCX, offsetof(drcuml_machine_state, fmod)));// movzx eax,state->fmod + emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3 + emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al + emit_ldmxcsr_m32(dst, MBISD(REG_RBP, REG_RAX, 4, offset_from_rbp(&m_near.ssecontrol[0]))); + emit_mov_r32_m32(dst, REG_EAX, MBD(REG_RCX, offsetof(drcuml_machine_state, exp))); // mov eax,state->exp + emit_mov_m32_r32(dst, MABS(&m_state.exp), REG_EAX); // mov [exp],eax // copy flags - a.movzx(eax, byte_ptr(rcx, offsetof(drcuml_machine_state, flags))); // movzx eax,state->flags - a.push(ptr(rbp, rax, 3, offset_from_rbp(&m_near.flagsunmap[0]))); // push flags_unmap[eax*8] - a.popf(); // popf + emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_RCX, offsetof(drcuml_machine_state, flags)));// movzx eax,state->flags + emit_push_m64(dst, MBISD(REG_RBP, REG_RAX, 8, offset_from_rbp(&m_near.flagsunmap[0]))); + // push flags_unmap[eax*8] + emit_popf(dst); // popf } @@ -2839,7 +3459,7 @@ void drcbe_x64::op_restore(Assembler &a, const instruction &inst) // op_load - process a LOAD opcode //------------------------------------------------- -void drcbe_x64::op_load(Assembler &a, const instruction &inst) +void drcbe_x64::op_load(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -2852,50 +3472,49 @@ void drcbe_x64::op_load(Assembler &a, const instruction &inst) be_parameter indp(*this, inst.param(2), PTYPE_MRI); const parameter &scalesizep = inst.param(3); assert(scalesizep.is_size_scale()); + int scale = 1 << scalesizep.scale(); int size = scalesizep.size(); // determine the pointer base int32_t baseoffs; - Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs); + int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs); // pick a target register for the general case - Gp dstreg = dstp.select_register(eax); + int dstreg = dstp.select_register(REG_EAX); // immediate index if (indp.is_immediate()) { - s32 const offset = baseoffs + (s32(indp.immediate()) << scalesizep.scale()); - if (size == SIZE_BYTE) - a.movzx(dstreg, byte_ptr(basereg, offset)); // movzx dstreg,[basep + scale*indp] + emit_movzx_r32_m8(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) - a.movzx(dstreg, word_ptr(basereg, offset)); // movzx dstreg,[basep + scale*indp] + emit_movzx_r32_m16(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp] else if (size == SIZE_DWORD) - a.mov(dstreg, ptr(basereg, offset)); // mov dstreg,[basep + scale*indp] + emit_mov_r32_m32(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp] else if (size == SIZE_QWORD) - a.mov(dstreg.r64(), ptr(basereg, offset)); // mov dstreg,[basep + scale*indp] + emit_mov_r64_m64(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp] } // other index else { - Gp indreg = indp.select_register(rcx); - emit_movsx_r64_p32(a, indreg, indp); + int indreg = indp.select_register(REG_ECX); + emit_movsx_r64_p32(dst, indreg, indp); if (size == SIZE_BYTE) - a.movzx(dstreg, byte_ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movzx dstreg,[basep + scale*indp] + emit_movzx_r32_m8(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // movzx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) - a.movzx(dstreg, word_ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movzx dstreg,[basep + scale*indp] + emit_movzx_r32_m16(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // movzx dstreg,[basep + scale*indp] else if (size == SIZE_DWORD) - a.mov(dstreg, ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // mov dstreg,[basep + scale*indp] + emit_mov_r32_m32(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp] else if (size == SIZE_QWORD) - a.mov(dstreg.r64(), ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // mov dstreg,[basep + scale*indp] + emit_mov_r64_m64(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp] } // store result if (inst.size() == 4) - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg else - emit_mov_p64_r64(a, dstp, dstreg.r64()); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } @@ -2904,7 +3523,7 @@ void drcbe_x64::op_load(Assembler &a, const instruction &inst) // op_loads - process a LOADS opcode //------------------------------------------------- -void drcbe_x64::op_loads(Assembler &a, const instruction &inst) +void drcbe_x64::op_loads(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -2917,74 +3536,73 @@ void drcbe_x64::op_loads(Assembler &a, const instruction &inst) be_parameter indp(*this, inst.param(2), PTYPE_MRI); const parameter &scalesizep = inst.param(3); assert(scalesizep.is_size_scale()); + int scale = 1 << scalesizep.scale(); int size = scalesizep.size(); // determine the pointer base int32_t baseoffs; - Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs); + int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs); // pick a target register for the general case - Gp dstreg = dstp.select_register(eax); + int dstreg = dstp.select_register(REG_EAX); // immediate index if (indp.is_immediate()) { - s32 const offset = baseoffs + (s32(indp.immediate()) << scalesizep.scale()); - if (inst.size() == 4) { if (size == SIZE_BYTE) - a.movsx(dstreg, byte_ptr(basereg, offset)); // movsx dstreg,[basep + scale*indp] + emit_movsx_r32_m8(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movsx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) - a.movsx(dstreg, word_ptr(basereg, offset)); // movsx dstreg,[basep + scale*indp] + emit_movsx_r32_m16(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movsx dstreg,[basep + scale*indp] else if (size == SIZE_DWORD) - a.mov(dstreg, ptr(basereg, offset)); // mov dstreg,[basep + scale*indp] + emit_mov_r32_m32(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp] } else if (inst.size() == 8) { if (size == SIZE_BYTE) - a.movsx(dstreg.r64(), byte_ptr(basereg, offset)); // movzx dstreg,[basep + scale*indp] + emit_movsx_r64_m8(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) - a.movsx(dstreg.r64(), word_ptr(basereg, offset)); // movzx dstreg,[basep + scale*indp] + emit_movsx_r64_m16(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp] else if (size == SIZE_DWORD) - a.movsxd(dstreg.r64(), ptr(basereg, offset)); // movsxd dstreg,[basep + scale*indp] + emit_movsxd_r64_m32(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movsxd dstreg,[basep + scale*indp] else if (size == SIZE_QWORD) - a.mov(dstreg.r64(), ptr(basereg, offset)); // mov dstreg,[basep + scale*indp] + emit_mov_r64_m64(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp] } } // other index else { - Gp indreg = indp.select_register(rcx); - emit_movsx_r64_p32(a, indreg, indp); + int indreg = indp.select_register(REG_ECX); + emit_movsx_r64_p32(dst, indreg, indp); if (inst.size() == 4) { if (size == SIZE_BYTE) - a.movsx(dstreg, byte_ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movsx dstreg,[basep + scale*indp] + emit_movsx_r32_m8(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) - a.movsx(dstreg, word_ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movsx dstreg,[basep + scale*indp] + emit_movsx_r32_m16(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp] else if (size == SIZE_DWORD) - a.mov(dstreg, ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // mov dstreg,[basep + scale*indp] + emit_mov_r32_m32(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp] } else if (inst.size() == 8) { if (size == SIZE_BYTE) - a.movsx(dstreg.r64(), byte_ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movsx dstreg,[basep + scale*indp] + emit_movsx_r64_m8(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) - a.movsx(dstreg.r64(), word_ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movsx dstreg,[basep + scale*indp] + emit_movsx_r64_m16(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp] else if (size == SIZE_DWORD) - a.movsxd(dstreg.r64(), ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movsxd dstreg,[basep + scale*indp] + emit_movsxd_r64_m32(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsxd dstreg,[basep + scale*indp] else if (size == SIZE_QWORD) - a.mov(dstreg.r64(), ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // mov dstreg,[basep + scale*indp] + emit_mov_r64_m64(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp] } } // store result if (inst.size() == 4) - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg else - emit_mov_p64_r64(a, dstp, dstreg.r64()); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } @@ -2993,7 +3611,7 @@ void drcbe_x64::op_loads(Assembler &a, const instruction &inst) // op_store - process a STORE opcode //------------------------------------------------- -void drcbe_x64::op_store(Assembler &a, const instruction &inst) +void drcbe_x64::op_store(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3005,93 +3623,102 @@ void drcbe_x64::op_store(Assembler &a, const instruction &inst) be_parameter indp(*this, inst.param(1), PTYPE_MRI); be_parameter srcp(*this, inst.param(2), PTYPE_MRI); const parameter &scalesizep = inst.param(3); + int scale = 1 << (scalesizep.scale()); int size = scalesizep.size(); // determine the pointer base int32_t baseoffs; - Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs); + int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs); // pick a source register for the general case - Gp srcreg = srcp.select_register(rax); + int srcreg = srcp.select_register(REG_EAX); // degenerate case: constant index if (indp.is_immediate()) { - s32 const offset = baseoffs + (s32(indp.immediate()) << scalesizep.scale()); - // immediate source if (srcp.is_immediate()) { - if (size == SIZE_QWORD) + if (size == SIZE_BYTE) + emit_mov_m8_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp + else if (size == SIZE_WORD) + emit_mov_m16_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp + else if (size == SIZE_DWORD) + emit_mov_m32_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp + else if (size == SIZE_QWORD) { if (short_immediate(srcp.immediate())) - a.mov(qword_ptr(basereg, offset), s32(srcp.immediate())); // mov [basep + scale*indp],srcp + emit_mov_m64_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp else { - a.mov(ptr(basereg, offset + 0), u32(srcp.immediate() >> 0)); // mov [basep + scale*indp],srcp - a.mov(ptr(basereg, offset + 4), u32(srcp.immediate() >> 32)); // mov [basep + scale*indp + 4],srcp >> 32 + emit_mov_m32_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp + emit_mov_m32_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate() + 4), srcp.immediate() >> 32); + // mov [basep + scale*indp + 4],srcp >> 32 } } - else - a.mov(ptr(basereg, offset, 1 << size), srcp.immediate()); // mov [basep + scale*indp],srcp } // variable source else { if (size != SIZE_QWORD) - emit_mov_r32_p32(a, srcreg.r32(), srcp); // mov srcreg,srcp + emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp else - emit_mov_r64_p64(a, srcreg.r64(), srcp); // mov srcreg,srcp + emit_mov_r64_p64(dst, srcreg, srcp); // mov srcreg,srcp if (size == SIZE_BYTE) - a.mov(ptr(basereg, offset), srcreg.r8()); // mov [basep + scale*indp],srcreg + emit_mov_m8_r8(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg else if (size == SIZE_WORD) - a.mov(ptr(basereg, offset), srcreg.r16()); // mov [basep + scale*indp],srcreg + emit_mov_m16_r16(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg else if (size == SIZE_DWORD) - a.mov(ptr(basereg, offset), srcreg.r32()); // mov [basep + scale*indp],srcreg + emit_mov_m32_r32(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg else if (size == SIZE_QWORD) - a.mov(ptr(basereg, offset), srcreg.r64()); // mov [basep + scale*indp],srcreg + emit_mov_m64_r64(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg } } // normal case: variable index else { - Gp indreg = indp.select_register(rcx); - emit_movsx_r64_p32(a, indreg, indp); // mov indreg,indp + int indreg = indp.select_register(REG_ECX); + emit_movsx_r64_p32(dst, indreg, indp); // mov indreg,indp // immediate source if (srcp.is_immediate()) { - if (size == SIZE_QWORD) + if (size == SIZE_BYTE) + emit_mov_m8_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp + else if (size == SIZE_WORD) + emit_mov_m16_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp + else if (size == SIZE_DWORD) + emit_mov_m32_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp + else if (size == SIZE_QWORD) { if (short_immediate(srcp.immediate())) - a.mov(qword_ptr(basereg, indreg, scalesizep.scale(), baseoffs), s32(srcp.immediate())); // mov [basep + scale*indp],srcp + emit_mov_m64_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*indp],srcp else { - a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs + 0), u32(srcp.immediate() >> 0)); // mov [basep + scale*ecx],srcp - a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs + 4), u32(srcp.immediate() >> 32)); // mov [basep + scale*ecx + 4],srcp >> 32 + emit_mov_m32_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp + emit_mov_m32_imm(dst, MBISD(basereg, indreg, scale, baseoffs + 4), srcp.immediate() >> 32); + // mov [basep + scale*ecx + 4],srcp >> 32 } } - else - a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs, 1 << size), srcp.immediate()); // mov [basep + scale*ecx],srcp } // variable source else { if (size != SIZE_QWORD) - emit_mov_r32_p32(a, srcreg.r32(), srcp); // mov srcreg,srcp + emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp else - emit_mov_r64_p64(a, srcreg.r64(), srcp); // mov edx:srcreg,srcp + emit_mov_r64_p64(dst, srcreg, srcp); // mov edx:srcreg,srcp if (size == SIZE_BYTE) - a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs), srcreg.r8()); // mov [basep + scale*ecx],srcreg + emit_mov_m8_r8(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg else if (size == SIZE_WORD) - a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs), srcreg.r16());// mov [basep + scale*ecx],srcreg + emit_mov_m16_r16(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg else if (size == SIZE_DWORD) - a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs), srcreg.r32());// mov [basep + scale*ecx],srcreg + emit_mov_m32_r32(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg else if (size == SIZE_QWORD) - a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs), srcreg.r64());// mov [basep + scale*ecx],srcreg + emit_mov_m64_r64(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg } } } @@ -3101,7 +3728,7 @@ void drcbe_x64::op_store(Assembler &a, const instruction &inst) // op_read - process a READ opcode //------------------------------------------------- -void drcbe_x64::op_read(Assembler &a, const instruction &inst) +void drcbe_x64::op_read(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3115,43 +3742,43 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst) assert(spacesizep.is_size_space()); // pick a target register for the general case - Gp dstreg = dstp.select_register(eax); + int dstreg = dstp.select_register(REG_EAX); // set up a call to the read byte handler - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_space[spacesizep.space()]); // mov param1,space - emit_mov_r32_p32(a, Gpd(REG_PARAM2), addrp); // mov param2,addrp + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)(m_space[spacesizep.space()])); // mov param1,space + emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp if (spacesizep.size() == SIZE_BYTE) { - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].read_byte); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_byte); // call read_byte - a.movzx(dstreg, al); // movzx dstreg,al + emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al } else if (spacesizep.size() == SIZE_WORD) { - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].read_word); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_word); // call read_word - a.movzx(dstreg, ax); // movzx dstreg,ax + emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax } else if (spacesizep.size() == SIZE_DWORD) { - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].read_dword); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_dword); // call read_dword - if (dstreg != eax || inst.size() == 8) - a.mov(dstreg, eax); // mov dstreg,eax + if (dstreg != REG_EAX || inst.size() == 8) + emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax } else if (spacesizep.size() == SIZE_QWORD) { - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].read_qword); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_qword); // call read_qword - if (dstreg != eax) - a.mov(dstreg.r64(), rax); // mov dstreg,rax + if (dstreg != REG_RAX) + emit_mov_r64_r64(dst, dstreg, REG_RAX); // mov dstreg,rax } // store result if (inst.size() == 4) - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg else - emit_mov_p64_r64(a, dstp, dstreg.r64()); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } @@ -3159,7 +3786,7 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst) // op_readm - process a READM opcode //------------------------------------------------- -void drcbe_x64::op_readm(Assembler &a, const instruction &inst) +void drcbe_x64::op_readm(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3174,41 +3801,41 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst) assert(spacesizep.is_size_space()); // pick a target register for the general case - Gp dstreg = dstp.select_register(eax); + int dstreg = dstp.select_register(REG_EAX); // set up a call to the read byte handler - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_space[spacesizep.space()]); // mov param1,space - emit_mov_r32_p32(a, Gpd(REG_PARAM2), addrp); // mov param2,addrp + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)(m_space[spacesizep.space()])); // mov param1,space + emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp if (spacesizep.size() != SIZE_QWORD) - emit_mov_r32_p32(a, Gpd(REG_PARAM3), maskp); // mov param3,maskp + emit_mov_r32_p32(dst, REG_PARAM3, maskp); // mov param3,maskp else - emit_mov_r64_p64(a, Gpq(REG_PARAM3), maskp); // mov param3,maskp + emit_mov_r64_p64(dst, REG_PARAM3, maskp); // mov param3,maskp if (spacesizep.size() == SIZE_WORD) { - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].read_word_masked); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_word_masked); // call read_word_masked - a.movzx(dstreg, ax); // movzx dstreg,ax + emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax } else if (spacesizep.size() == SIZE_DWORD) { - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].read_dword_masked); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_dword_masked); // call read_dword_masked - if (dstreg != eax || inst.size() == 8) - a.mov(dstreg, eax); // mov dstreg,eax + if (dstreg != REG_EAX || inst.size() == 8) + emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax } else if (spacesizep.size() == SIZE_QWORD) { - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].read_qword_masked); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_qword_masked); // call read_qword_masked - if (dstreg != eax) - a.mov(dstreg.r64(), rax); // mov dstreg,rax + if (dstreg != REG_RAX) + emit_mov_r64_r64(dst, dstreg, REG_RAX); // mov dstreg,rax } // store result if (inst.size() == 4) - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg else - emit_mov_p64_r64(a, dstp, dstreg.r64()); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } @@ -3216,7 +3843,7 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst) // op_write - process a WRITE opcode //------------------------------------------------- -void drcbe_x64::op_write(Assembler &a, const instruction &inst) +void drcbe_x64::op_write(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3230,23 +3857,23 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst) assert(spacesizep.is_size_space()); // set up a call to the write byte handler - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_space[spacesizep.space()]); // mov param1,space - emit_mov_r32_p32(a, Gpd(REG_PARAM2), addrp); // mov param2,addrp + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)(m_space[spacesizep.space()])); // mov param1,space + emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp if (spacesizep.size() != SIZE_QWORD) - emit_mov_r32_p32(a, Gpd(REG_PARAM3), srcp); // mov param3,srcp + emit_mov_r32_p32(dst, REG_PARAM3, srcp); // mov param3,srcp else - emit_mov_r64_p64(a, Gpq(REG_PARAM3), srcp); // mov param3,srcp + emit_mov_r64_p64(dst, REG_PARAM3, srcp); // mov param3,srcp if (spacesizep.size() == SIZE_BYTE) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].write_byte); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_byte); // call write_byte else if (spacesizep.size() == SIZE_WORD) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].write_word); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_word); // call write_word else if (spacesizep.size() == SIZE_DWORD) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].write_dword); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_dword); // call write_dword else if (spacesizep.size() == SIZE_QWORD) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].write_qword); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_qword); // call write_qword } @@ -3255,7 +3882,7 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst) // op_writem - process a WRITEM opcode //------------------------------------------------- -void drcbe_x64::op_writem(Assembler &a, const instruction &inst) +void drcbe_x64::op_writem(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3270,26 +3897,26 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst) assert(spacesizep.is_size_space()); // set up a call to the write byte handler - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_space[spacesizep.space()]); // mov param1,space - emit_mov_r32_p32(a, Gpd(REG_PARAM2), addrp); // mov param2,addrp + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)(m_space[spacesizep.space()])); // mov param1,space + emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp if (spacesizep.size() != SIZE_QWORD) { - emit_mov_r32_p32(a, Gpd(REG_PARAM3), srcp); // mov param3,srcp - emit_mov_r32_p32(a, Gpd(REG_PARAM4), maskp); // mov param4,maskp + emit_mov_r32_p32(dst, REG_PARAM3, srcp); // mov param3,srcp + emit_mov_r32_p32(dst, REG_PARAM4, maskp); // mov param4,maskp } else { - emit_mov_r64_p64(a, Gpq(REG_PARAM3), srcp); // mov param3,srcp - emit_mov_r64_p64(a, Gpq(REG_PARAM4), maskp); // mov param4,maskp + emit_mov_r64_p64(dst, REG_PARAM3, srcp); // mov param3,srcp + emit_mov_r64_p64(dst, REG_PARAM4, maskp); // mov param4,maskp } if (spacesizep.size() == SIZE_WORD) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].write_word_masked); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_word_masked); // call write_word_masked else if (spacesizep.size() == SIZE_DWORD) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].write_dword_masked); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_dword_masked); // call write_dword_masked else if (spacesizep.size() == SIZE_QWORD) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacesizep.space()].write_qword_masked); + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_qword_masked); // call write_qword_masked } @@ -3298,7 +3925,7 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst) // op_carry - process a CARRY opcode //------------------------------------------------- -void drcbe_x64::op_carry(Assembler &a, const instruction &inst) +void drcbe_x64::op_carry(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3313,16 +3940,16 @@ void drcbe_x64::op_carry(Assembler &a, const instruction &inst) if (srcp.is_immediate() && bitp.is_immediate()) { if (srcp.immediate() & ((uint64_t)1 << bitp.immediate())) - a.stc(); + emit_stc(dst); else - a.clc(); - } + emit_clc(dst); + } // load non-immediate bit numbers into a register if (!bitp.is_immediate()) { - emit_mov_r32_p32(a, ecx, bitp); - a.and_(ecx, inst.size() * 8 - 1); + emit_mov_r32_p32(dst, REG_ECX, bitp); + emit_and_r32_imm(dst, REG_ECX, inst.size() * 8 - 1); } // 32-bit form @@ -3331,16 +3958,16 @@ void drcbe_x64::op_carry(Assembler &a, const instruction &inst) if (bitp.is_immediate()) { if (srcp.is_memory()) - a.bt(MABS(srcp.memory(), inst.size()), bitp.immediate()); // bt [srcp],bitp + emit_bt_m32_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp else if (srcp.is_int_register()) - a.bt(Gpd(srcp.ireg()), bitp.immediate()); // bt srcp,bitp + emit_bt_r32_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp } else { if (srcp.is_memory()) - a.bt(MABS(srcp.memory(), inst.size()), ecx); // bt [srcp],ecx + emit_bt_m32_r32(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx else if (srcp.is_int_register()) - a.bt(Gpd(srcp.ireg()), ecx); // bt srcp,ecx + emit_bt_r32_r32(dst, srcp.ireg(), REG_ECX); // bt srcp,ecx } } @@ -3350,16 +3977,16 @@ void drcbe_x64::op_carry(Assembler &a, const instruction &inst) if (bitp.is_immediate()) { if (srcp.is_memory()) - a.bt(MABS(srcp.memory(), inst.size()), bitp.immediate()); // bt [srcp],bitp + emit_bt_m64_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp else if (srcp.is_int_register()) - a.bt(Gpq(srcp.ireg()), bitp.immediate()); // bt srcp,bitp + emit_bt_r64_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp } else { if (srcp.is_memory()) - a.bt(MABS(srcp.memory(), inst.size()), rcx); // bt [srcp],rcx + emit_bt_m64_r64(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx else if (srcp.is_int_register()) - a.bt(Gpq(srcp.ireg()), rcx); // bt srcp,rcx + emit_bt_r64_r64(dst, srcp.ireg(), REG_ECX); // bt srcp,ecx } } } @@ -3369,7 +3996,7 @@ void drcbe_x64::op_carry(Assembler &a, const instruction &inst) // op_set - process a SET opcode //------------------------------------------------- -void drcbe_x64::op_set(Assembler &a, const instruction &inst) +void drcbe_x64::op_set(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3380,19 +4007,19 @@ void drcbe_x64::op_set(Assembler &a, const instruction &inst) be_parameter dstp(*this, inst.param(0), PTYPE_MR); // pick a target register for the general case - Gp dstreg = dstp.select_register(eax); + int dstreg = dstp.select_register(REG_EAX); // set to AL - a.set(X86_CONDITION(inst.condition()), al); // setcc al - a.movzx(dstreg, al); // movzx dstreg,al + emit_setcc_r8(dst, X86_CONDITION(inst.condition()), REG_AL); // setcc al + emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al // 32-bit form if (inst.size() == 4) - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg // 64-bit form else if (inst.size() == 8) - emit_mov_p64_r64(a, dstp, dstreg.r64()); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } @@ -3401,8 +4028,10 @@ void drcbe_x64::op_set(Assembler &a, const instruction &inst) // op_mov - process a MOV opcode //------------------------------------------------- -void drcbe_x64::op_mov(Assembler &a, const instruction &inst) +void drcbe_x64::op_mov(x86code *&dst, const instruction &inst) { + x86code *savedst = dst; + // validate instruction assert(inst.size() == 4 || inst.size() == 8); assert_any_condition(inst); @@ -3412,41 +4041,48 @@ void drcbe_x64::op_mov(Assembler &a, const instruction &inst) be_parameter dstp(*this, inst.param(0), PTYPE_MR); be_parameter srcp(*this, inst.param(1), PTYPE_MRI); - // add a conditional branch unless a conditional move is possible - Label skip = a.newLabel(); - if (inst.condition() != uml::COND_ALWAYS && !(dstp.is_int_register() && !srcp.is_immediate())) - a.short_().j(X86_NOT_CONDITION(inst.condition()), skip); // jcc skip + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX); + + // always start with a jmp + emit_link skip = { nullptr }; + if (inst.condition() != uml::COND_ALWAYS) + emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip // 32-bit form if (inst.size() == 4) { // register to memory if (dstp.is_memory() && srcp.is_int_register()) - a.mov(MABS(dstp.memory()), Gpd(srcp.ireg())); // mov [dstp],srcp + emit_mov_m32_r32(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp // immediate to memory else if (dstp.is_memory() && srcp.is_immediate()) - a.mov(MABS(dstp.memory(), 4), u32(srcp.immediate())); // mov [dstp],srcp + emit_mov_m32_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp // conditional memory to register else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_memory()) { - a.cmov(X86_CONDITION(inst.condition()), Gpd(dstp.ireg()), MABS(srcp.memory())); // cmovcc dstp,[srcp] + dst = savedst; + skip.target = nullptr; + emit_cmovcc_r32_m32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), MABS(srcp.memory())); + // cmovcc dstp,[srcp] } // conditional register to register else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_int_register()) { - a.cmov(X86_CONDITION(inst.condition()), Gpd(dstp.ireg()), Gpd(srcp.ireg())); // cmovcc dstp,srcp + dst = savedst; + skip.target = nullptr; + emit_cmovcc_r32_r32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), srcp.ireg()); + // cmovcc dstp,srcp } // general case else { - Gp dstreg = dstp.select_register(eax); - - emit_mov_r32_p32_keepflags(a, dstreg, srcp); // mov dstreg,srcp - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32_keepflags(dst, dstreg, srcp); // mov dstreg,srcp + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -3455,39 +4091,41 @@ void drcbe_x64::op_mov(Assembler &a, const instruction &inst) { // register to memory if (dstp.is_memory() && srcp.is_int_register()) - a.mov(MABS(dstp.memory()), Gpq(srcp.ireg())); // mov [dstp],srcp + emit_mov_m64_r64(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp // immediate to memory else if (dstp.is_memory() && srcp.is_immediate() && short_immediate(srcp.immediate())) - a.mov(MABS(dstp.memory(), 8), srcp.immediate()); // mov [dstp],srcp + emit_mov_m64_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp // conditional memory to register else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_memory()) { - a.cmov(X86_CONDITION(inst.condition()), Gpq(dstp.ireg()), MABS(srcp.memory())); + dst = savedst; + skip.target = nullptr; + emit_cmovcc_r64_m64(dst, X86_CONDITION(inst.condition()), dstp.ireg(), MABS(srcp.memory())); // cmovcc dstp,[srcp] } // conditional register to register else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_int_register()) { - a.cmov(X86_CONDITION(inst.condition()), Gpq(dstp.ireg()), Gpq(srcp.ireg())); + dst = savedst; + skip.target = nullptr; + emit_cmovcc_r64_r64(dst, X86_CONDITION(inst.condition()), dstp.ireg(), srcp.ireg()); // cmovcc dstp,srcp } // general case else { - Gp dstreg = dstp.select_register(rax); - - emit_mov_r64_p64_keepflags(a, dstreg, srcp); // mov dstreg,srcp - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64_keepflags(dst, dstreg, srcp); // mov dstreg,srcp + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } // resolve the jump - if (inst.condition() != uml::COND_ALWAYS && !(dstp.is_int_register() && !srcp.is_immediate())) - a.bind(skip); + if (skip.target != nullptr) + resolve_link(dst, skip); } @@ -3495,7 +4133,7 @@ void drcbe_x64::op_mov(Assembler &a, const instruction &inst) // op_sext - process a SEXT opcode //------------------------------------------------- -void drcbe_x64::op_sext(Assembler &a, const instruction &inst) +void drcbe_x64::op_sext(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3508,33 +4146,34 @@ void drcbe_x64::op_sext(Assembler &a, const instruction &inst) const parameter &sizep = inst.param(2); assert(sizep.is_size()); - Gp dstreg = dstp.select_register(rax); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX); // 32-bit form if (inst.size() == 4) { - dstreg = dstreg.r32(); - // general case if (srcp.is_memory()) { if (sizep.size() == SIZE_BYTE) - a.movsx(dstreg, MABS(srcp.memory(), 1)); // movsx dstreg,[srcp] + emit_movsx_r32_m8(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp] else if (sizep.size() == SIZE_WORD) - a.movsx(dstreg, MABS(srcp.memory(), 2)); // movsx dstreg,[srcp] + emit_movsx_r32_m16(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp] else if (sizep.size() == SIZE_DWORD) - a.mov(dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] + emit_mov_r32_m32(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] } else if (srcp.is_int_register()) { if (sizep.size() == SIZE_BYTE) - a.movsx(dstreg, GpbLo(srcp.ireg())); // movsx dstreg,srcp + emit_movsx_r32_r8(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp else if (sizep.size() == SIZE_WORD) - a.movsx(dstreg, Gpw(srcp.ireg())); // movsx dstreg,srcp + emit_movsx_r32_r16(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp else if (sizep.size() == SIZE_DWORD) - a.mov(dstreg, Gpd(srcp.ireg())); // mov dstreg,srcp + emit_mov_r32_r32(dst, dstreg, srcp.ireg()); // mov dstreg,srcp } - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + if (inst.flags() != 0) + emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg } // 64-bit form @@ -3544,30 +4183,29 @@ void drcbe_x64::op_sext(Assembler &a, const instruction &inst) if (srcp.is_memory()) { if (sizep.size() == SIZE_BYTE) - a.movsx(dstreg, MABS(srcp.memory(), 1)); // movsx dstreg,[srcp] + emit_movsx_r64_m8(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp] else if (sizep.size() == SIZE_WORD) - a.movsx(dstreg, MABS(srcp.memory(), 2)); // movsx dstreg,[srcp] + emit_movsx_r64_m16(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp] else if (sizep.size() == SIZE_DWORD) - a.movsxd(dstreg, MABS(srcp.memory(), 4)); // movsxd dstreg,[srcp] + emit_movsxd_r64_m32(dst, dstreg, MABS(srcp.memory())); // movsxd dstreg,[srcp] else if (sizep.size() == SIZE_QWORD) - a.mov(dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] + emit_mov_r64_m64(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] } else if (srcp.is_int_register()) { if (sizep.size() == SIZE_BYTE) - a.movsx(dstreg, GpbLo(srcp.ireg())); // movsx dstreg,srcp + emit_movsx_r64_r8(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp else if (sizep.size() == SIZE_WORD) - a.movsx(dstreg, Gpw(srcp.ireg())); // movsx dstreg,srcp + emit_movsx_r64_r16(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp else if (sizep.size() == SIZE_DWORD) - a.movsxd(dstreg, Gpd(srcp.ireg())); // movsxd dstreg,srcp + emit_movsxd_r64_r32(dst, dstreg, srcp.ireg()); // movsxd dstreg,srcp else if (sizep.size() == SIZE_QWORD) - a.mov(dstreg, Gpq(srcp.ireg())); // mov dstreg,srcp + emit_mov_r64_r64(dst, dstreg, srcp.ireg()); // mov dstreg,srcp } - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg + if (inst.flags() != 0) + emit_test_r64_r64(dst, dstreg, dstreg); // test dstreg,dstreg } - - if (inst.flags() != 0) - a.test(dstreg, dstreg); // test dstreg,dstreg } @@ -3575,7 +4213,7 @@ void drcbe_x64::op_sext(Assembler &a, const instruction &inst) // op_roland - process an ROLAND opcode //------------------------------------------------- -void drcbe_x64::op_roland(Assembler &a, const instruction &inst) +void drcbe_x64::op_roland(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3588,30 +4226,25 @@ void drcbe_x64::op_roland(Assembler &a, const instruction &inst) be_parameter shiftp(*this, inst.param(2), PTYPE_MRI); be_parameter maskp(*this, inst.param(3), PTYPE_MRI); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, shiftp, maskp); + // 32-bit form if (inst.size() == 4) { - // pick a target register - Gp dstreg = dstp.select_register(eax, shiftp, maskp); - - emit_mov_r32_p32(a, dstreg, srcp); // mov dstreg,srcp - if (!shiftp.is_immediate_value(0)) - emit_shift_p32(a, Inst::kIdRol, dstreg, shiftp); // rol dstreg,shiftp - emit_and_r32_p32(a, dstreg, maskp, inst); // and dstreg,maskp - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,srcp + emit_rol_r32_p32(dst, dstreg, shiftp, inst); // rol dstreg,shiftp + emit_and_r32_p32(dst, dstreg, maskp, inst); // and dstreg,maskp + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - // pick a target register - Gp dstreg = dstp.select_register(rax, shiftp, maskp); - - emit_mov_r64_p64(a, dstreg, srcp); // mov dstreg,srcp - if (!shiftp.is_immediate_value(0)) - emit_shift_p64(a, Inst::kIdRol, dstreg, shiftp); // rol dstreg,shiftp - emit_and_r64_p64(a, dstreg, maskp, inst); // and dstreg,maskp - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,srcp + emit_rol_r64_p64(dst, dstreg, shiftp, inst); // rol dstreg,shiftp + emit_and_r64_p64(dst, dstreg, maskp, inst); // and dstreg,maskp + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -3620,7 +4253,7 @@ void drcbe_x64::op_roland(Assembler &a, const instruction &inst) // op_rolins - process an ROLINS opcode //------------------------------------------------- -void drcbe_x64::op_rolins(Assembler &a, const instruction &inst) +void drcbe_x64::op_rolins(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3633,48 +4266,43 @@ void drcbe_x64::op_rolins(Assembler &a, const instruction &inst) be_parameter shiftp(*this, inst.param(2), PTYPE_MRI); be_parameter maskp(*this, inst.param(3), PTYPE_MRI); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_ECX, shiftp, maskp); + // 32-bit form if (inst.size() == 4) { - // pick a target register - Gp dstreg = dstp.select_register(ecx, shiftp, maskp); - - emit_mov_r32_p32(a, eax, srcp); // mov eax,srcp - if (!shiftp.is_immediate_value(0)) - emit_shift_p32(a, Inst::kIdRol, eax, shiftp); // rol eax,shiftp - emit_mov_r32_p32(a, dstreg, dstp); // mov dstreg,dstp + emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp + emit_rol_r32_p32(dst, REG_EAX, shiftp, inst); // rol eax,shiftp + emit_mov_r32_p32(dst, dstreg, dstp); // mov dstreg,dstp if (maskp.is_immediate()) { - a.and_(eax, maskp.immediate()); // and eax,maskp - a.and_(dstreg, ~maskp.immediate()); // and dstreg,~maskp + emit_and_r32_imm(dst, REG_EAX, maskp.immediate()); // and eax,maskp + emit_and_r32_imm(dst, dstreg, ~maskp.immediate()); // and dstreg,~maskp } else { - emit_mov_r32_p32(a, edx, maskp); // mov edx,maskp - a.and_(eax, edx); // and eax,edx - a.not_(edx); // not edx - a.and_(dstreg, edx); // and dstreg,edx + emit_mov_r32_p32(dst, REG_EDX, maskp); // mov edx,maskp + emit_and_r32_r32(dst, REG_EAX, REG_EDX); // and eax,edx + emit_not_r32(dst, REG_EDX); // not edx + emit_and_r32_r32(dst, dstreg, REG_EDX); // and dstreg,edx } - a.or_(dstreg, eax); // or dstreg,eax - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_or_r32_r32(dst, dstreg, REG_EAX); // or dstreg,eax + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - // pick a target register - Gp dstreg = dstp.select_register(rcx, shiftp, maskp); - - emit_mov_r64_p64(a, rax, srcp); // mov rax,srcp - emit_mov_r64_p64(a, rdx, maskp); // mov rdx,maskp - if (!shiftp.is_immediate_value(0)) - emit_shift_p64(a, Inst::kIdRol, rax, shiftp); // rol rax,shiftp - emit_mov_r64_p64(a, dstreg, dstp); // mov dstreg,dstp - a.and_(rax, rdx); // and eax,rdx - a.not_(rdx); // not rdx - a.and_(dstreg, rdx); // and dstreg,rdx - a.or_(dstreg, rax); // or dstreg,rax - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, REG_RAX, srcp); // mov rax,srcp + emit_mov_r64_p64(dst, REG_RDX, maskp); // mov rdx,maskp + emit_rol_r64_p64(dst, REG_RAX, shiftp, inst); // rol rax,shiftp + emit_mov_r64_p64(dst, dstreg, dstp); // mov dstreg,dstp + emit_and_r64_r64(dst, REG_RAX, REG_RDX); // and eax,rdx + emit_not_r64(dst, REG_RDX); // not rdx + emit_and_r64_r64(dst, dstreg, REG_RDX); // and dstreg,rdx + emit_or_r64_r64(dst, dstreg, REG_RAX); // or dstreg,rax + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -3683,7 +4311,7 @@ void drcbe_x64::op_rolins(Assembler &a, const instruction &inst) // op_add - process a ADD opcode //------------------------------------------------- -void drcbe_x64::op_add(Assembler &a, const instruction &inst) +void drcbe_x64::op_add(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3696,34 +4324,34 @@ void drcbe_x64::op_add(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(2), PTYPE_MRI); normalize_commutative(src1p, src2p); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + // 32-bit form if (inst.size() == 4) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_add_m32_p32(a, MABS(dstp.memory(), 4), src2p, inst); // add [dstp],src2p + emit_add_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_add_m32_p32(a, MABS(dstp.memory(), 4), src1p, inst); // add [dstp],src1p + emit_add_m32_p32(dst, MABS(dstp.memory()), src1p, inst); // add [dstp],src1p // reg = reg + imm else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0) - a.lea(Gpd(dstp.ireg()), ptr(Gpd(src1p.ireg()), src2p.immediate())); // lea dstp,[src1p+src2p] + emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), src2p.immediate())); // lea dstp,[src1p+src2p] // reg = reg + reg else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_int_register() && inst.flags() == 0) - a.lea(Gpd(dstp.ireg()), ptr(Gpd(src1p.ireg()), Gpd(src2p.ireg()))); // lea dstp,[src1p+src2p] + emit_lea_r32_m32(dst, dstp.ireg(), MBISD(src1p.ireg(), src2p.ireg(), 1, 0));// lea dstp,[src1p+src2p] // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(eax, src2p); - - emit_mov_r32_p32(a, dstreg, src1p); // mov dstreg,src1p - emit_add_r32_p32(a, dstreg, src2p, inst); // add dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_add_r32_p32(dst, dstreg, src2p, inst); // add dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -3732,29 +4360,26 @@ void drcbe_x64::op_add(Assembler &a, const instruction &inst) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_add_m64_p64(a, MABS(dstp.memory(), 8), src2p, inst); // add [dstp],src2p + emit_add_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_add_m64_p64(a, MABS(dstp.memory(), 8), src1p, inst); // add [dstp],src1p + emit_add_m64_p64(dst, MABS(dstp.memory()), src1p, inst); // add [dstp],src1p // reg = reg + imm else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && short_immediate(src2p.immediate()) && inst.flags() == 0) - a.lea(Gpq(dstp.ireg()), ptr(Gpq(src1p.ireg()), src2p.immediate())); // lea dstp,[src1p+src2p] + emit_lea_r64_m64(dst, dstp.ireg(), MBD(src1p.ireg(), src2p.immediate())); // lea dstp,[src1p+src2p] // reg = reg + reg else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_int_register() && inst.flags() == 0) - a.lea(Gpq(dstp.ireg()), ptr(Gpq(src1p.ireg()), Gpq(src2p.ireg()))); // lea dstp,[src1p+src2p] + emit_lea_r64_m64(dst, dstp.ireg(), MBISD(src1p.ireg(), src2p.ireg(), 1, 0));// lea dstp,[src1p+src2p] // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(rax, src2p); - - emit_mov_r64_p64(a, dstreg, src1p); // mov dstreg,src1p - emit_add_r64_p64(a, dstreg, src2p, inst); // add dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_add_r64_p64(dst, dstreg, src2p, inst); // add dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } @@ -3764,7 +4389,7 @@ void drcbe_x64::op_add(Assembler &a, const instruction &inst) // op_addc - process a ADDC opcode //------------------------------------------------- -void drcbe_x64::op_addc(Assembler &a, const instruction &inst) +void drcbe_x64::op_addc(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3777,22 +4402,22 @@ void drcbe_x64::op_addc(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(2), PTYPE_MRI); normalize_commutative(src1p, src2p); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + // 32-bit form if (inst.size() == 4) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_adc_m32_p32(a, MABS(dstp.memory(), 4), src2p, inst); // adc [dstp],src2p + emit_adc_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(eax, src2p); - - emit_mov_r32_p32_keepflags(a, dstreg, src1p); // mov dstreg,src1p - emit_adc_r32_p32(a, dstreg, src2p, inst); // adc dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_adc_r32_p32(dst, dstreg, src2p, inst); // adc dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -3801,17 +4426,14 @@ void drcbe_x64::op_addc(Assembler &a, const instruction &inst) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_adc_m64_p64(a, MABS(dstp.memory(), 8), src2p, inst); // adc [dstp],src2p + emit_adc_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(rax, src2p); - - emit_mov_r64_p64_keepflags(a, dstreg, src1p); // mov dstreg,src1p - emit_adc_r64_p64(a, dstreg, src2p, inst); // adc dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_adc_r64_p64(dst, dstreg, src2p, inst); // adc dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } @@ -3821,7 +4443,7 @@ void drcbe_x64::op_addc(Assembler &a, const instruction &inst) // op_sub - process a SUB opcode //------------------------------------------------- -void drcbe_x64::op_sub(Assembler &a, const instruction &inst) +void drcbe_x64::op_sub(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3833,26 +4455,26 @@ void drcbe_x64::op_sub(Assembler &a, const instruction &inst) be_parameter src1p(*this, inst.param(1), PTYPE_MRI); be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + // 32-bit form if (inst.size() == 4) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_sub_m32_p32(a, MABS(dstp.memory(), 4), src2p, inst); // sub [dstp],src2p + emit_sub_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p // reg = reg - imm else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0) - a.lea(Gpd(dstp.ireg()), ptr(Gpd(src1p.ireg()), -src2p.immediate())); // lea dstp,[src1p-src2p] + emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), -src2p.immediate())); // lea dstp,[src1p-src2p] // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(eax, src2p); - - emit_mov_r32_p32(a, dstreg, src1p); // mov dstreg,src1p - emit_sub_r32_p32(a, dstreg, src2p, inst); // sub dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_sub_r32_p32(dst, dstreg, src2p, inst); // sub dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -3861,21 +4483,18 @@ void drcbe_x64::op_sub(Assembler &a, const instruction &inst) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_sub_m64_p64(a, MABS(dstp.memory(), 8), src2p, inst); // sub [dstp],src2p + emit_sub_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p // reg = reg - imm else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && short_immediate(src2p.immediate()) && inst.flags() == 0) - a.lea(Gpq(dstp.ireg()), ptr(Gpq(src1p.ireg()), -src2p.immediate())); // lea dstp,[src1p-src2p] + emit_lea_r64_m64(dst, dstp.ireg(), MBD(src1p.ireg(), -src2p.immediate())); // lea dstp,[src1p-src2p] // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(rax, src2p); - - emit_mov_r64_p64(a, dstreg, src1p); // mov dstreg,src1p - emit_sub_r64_p64(a, dstreg, src2p, inst); // sub dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_sub_r64_p64(dst, dstreg, src2p, inst); // sub dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } @@ -3885,7 +4504,7 @@ void drcbe_x64::op_sub(Assembler &a, const instruction &inst) // op_subc - process a SUBC opcode //------------------------------------------------- -void drcbe_x64::op_subc(Assembler &a, const instruction &inst) +void drcbe_x64::op_subc(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3897,22 +4516,22 @@ void drcbe_x64::op_subc(Assembler &a, const instruction &inst) be_parameter src1p(*this, inst.param(1), PTYPE_MRI); be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + // 32-bit form if (inst.size() == 4) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_sbb_m32_p32(a, MABS(dstp.memory(), 4), src2p, inst); // sbb [dstp],src2p + emit_sbb_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(eax, src2p); - - emit_mov_r32_p32_keepflags(a, dstreg, src1p); // mov dstreg,src1p - emit_sbb_r32_p32(a, dstreg, src2p, inst); // sbb dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_sbb_r32_p32(dst, dstreg, src2p, inst); // sbb dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -3921,17 +4540,14 @@ void drcbe_x64::op_subc(Assembler &a, const instruction &inst) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_sbb_m64_p64(a, MABS(dstp.memory(), 8), src2p, inst); // sbb [dstp],src2p + emit_sbb_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(rax, src2p); - - emit_mov_r64_p64_keepflags(a, dstreg, src1p); // mov dstreg,src1p - emit_sbb_r64_p64(a, dstreg, src2p, inst); // sbb dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_sbb_r64_p64(dst, dstreg, src2p, inst); // sbb dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } @@ -3941,7 +4557,7 @@ void drcbe_x64::op_subc(Assembler &a, const instruction &inst) // op_cmp - process a CMP opcode //------------------------------------------------- -void drcbe_x64::op_cmp(Assembler &a, const instruction &inst) +void drcbe_x64::op_cmp(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -3952,22 +4568,22 @@ void drcbe_x64::op_cmp(Assembler &a, const instruction &inst) be_parameter src1p(*this, inst.param(0), PTYPE_MRI); be_parameter src2p(*this, inst.param(1), PTYPE_MRI); + // pick a target register for the general case + int src1reg = src1p.select_register(REG_EAX); + // 32-bit form if (inst.size() == 4) { // memory versus anything if (src1p.is_memory()) - emit_cmp_m32_p32(a, MABS(src1p.memory(), 4), src2p, inst); // cmp [dstp],src2p + emit_cmp_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // cmp [dstp],src2p // general case else { - // pick a target register for the general case - Gp src1reg = src1p.select_register(eax); - if (src1p.is_immediate()) - a.mov(src1reg, src1p.immediate()); // mov src1reg,imm - emit_cmp_r32_p32(a, src1reg, src2p, inst); // cmp src1reg,src2p + emit_mov_r32_imm(dst, src1reg, src1p.immediate()); // mov src1reg,imm + emit_cmp_r32_p32(dst, src1reg, src2p, inst); // cmp src1reg,src2p } } @@ -3976,17 +4592,14 @@ void drcbe_x64::op_cmp(Assembler &a, const instruction &inst) { // memory versus anything if (src1p.is_memory()) - emit_cmp_m64_p64(a, MABS(src1p.memory(), 8), src2p, inst); // cmp [dstp],src2p + emit_cmp_m64_p64(dst, MABS(src1p.memory()), src2p, inst); // cmp [dstp],src2p // general case else { - // pick a target register for the general case - Gp src1reg = src1p.select_register(rax); - if (src1p.is_immediate()) - emit_mov_r64_imm(a, src1reg, src1p.immediate()); // mov src1reg,imm - emit_cmp_r64_p64(a, src1reg, src2p, inst); // cmp src1reg,src2p + emit_mov_r64_imm(dst, src1reg, src1p.immediate()); // mov src1reg,imm + emit_cmp_r64_p64(dst, src1reg, src2p, inst); // cmp src1reg,src2p } } } @@ -3996,7 +4609,7 @@ void drcbe_x64::op_cmp(Assembler &a, const instruction &inst) // op_mulu - process a MULU opcode //------------------------------------------------- -void drcbe_x64::op_mulu(Assembler &a, const instruction &inst) +void drcbe_x64::op_mulu(x86code *&dst, const instruction &inst) { uint8_t zsflags = inst.flags() & (FLAG_Z | FLAG_S); uint8_t vflag = inst.flags() & FLAG_V; @@ -4018,19 +4631,19 @@ void drcbe_x64::op_mulu(Assembler &a, const instruction &inst) if (inst.size() == 4) { // general case - emit_mov_r32_p32(a, eax, src1p); // mov eax,src1p + emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p if (src2p.is_memory()) - a.mul(MABS(src2p.memory(), 4)); // mul [src2p] + emit_mul_m32(dst, MABS(src2p.memory())); // mul [src2p] else if (src2p.is_int_register()) - a.mul(Gpd(src2p.ireg())); // mul src2p + emit_mul_r32(dst, src2p.ireg()); // mul src2p else if (src2p.is_immediate()) { - a.mov(edx, src2p.immediate()); // mov edx,src2p - a.mul(edx); // mul edx + emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p + emit_mul_r32(dst, REG_EDX); // mul edx } - emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax + emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax if (compute_hi) - emit_mov_p32_r32(a, edstp, edx); // mov edstp,edx + emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx // compute flags if (inst.flags() != 0) @@ -4038,32 +4651,32 @@ void drcbe_x64::op_mulu(Assembler &a, const instruction &inst) if (zsflags != 0) { if (vflag) - a.pushf(); // pushf + emit_pushf(dst); // pushf if (compute_hi) { if (zsflags == FLAG_Z) - a.or_(edx, eax); // or edx,eax + emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax else if (zsflags == FLAG_S) - a.test(edx, edx); // test edx,edx + emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx else { - a.movzx(ecx, ax); // movzx ecx,ax - a.shr(eax, 16); // shr eax,16 - a.or_(edx, ecx); // or edx,ecx - a.or_(edx, eax); // or edx,eax + emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax + emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16 + emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx + emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax } } else - a.test(eax, eax); // test eax,eax + emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax // we rely on the fact that OF is cleared by all logical operations above if (vflag) { - a.pushf(); // pushf - a.pop(rax); // pop rax - a.and_(qword_ptr(rsp), ~0x84); // and [rsp],~0x84 - a.or_(ptr(rsp), rax); // or [rsp],rax - a.popf(); // popf + emit_pushf(dst); // pushf + emit_pop_r64(dst, REG_RAX); // pop rax + emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84 + emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax + emit_popf(dst); // popf } } } @@ -4073,19 +4686,19 @@ void drcbe_x64::op_mulu(Assembler &a, const instruction &inst) else if (inst.size() == 8) { // general case - emit_mov_r64_p64(a, rax, src1p); // mov rax,src1p + emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p if (src2p.is_memory()) - a.mul(MABS(src2p.memory(), 8)); // mul [src2p] + emit_mul_m64(dst, MABS(src2p.memory())); // mul [src2p] else if (src2p.is_int_register()) - a.mul(Gpq(src2p.ireg())); // mul src2p + emit_mul_r64(dst, src2p.ireg()); // mul src2p else if (src2p.is_immediate()) { - emit_mov_r64_imm(a, rdx, src2p.immediate()); // mov rdx,src2p - a.mul(rdx); // mul rdx + emit_mov_r64_imm(dst, REG_RDX, src2p.immediate()); // mov rdx,src2p + emit_mul_r64(dst, REG_RDX); // mul rdx } - emit_mov_p64_r64(a, dstp, rax); // mov dstp,rax + emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax if (compute_hi) - emit_mov_p64_r64(a, edstp, rdx); // mov edstp,rdx + emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx // compute flags if (inst.flags() != 0) @@ -4093,32 +4706,32 @@ void drcbe_x64::op_mulu(Assembler &a, const instruction &inst) if (zsflags != 0) { if (vflag) - a.pushf(); // pushf + emit_pushf(dst); // pushf if (compute_hi) { if (zsflags == FLAG_Z) - a.or_(rdx, rax); // or rdx,rax + emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax else if (zsflags == FLAG_S) - a.test(rdx, rdx); // test rdx,rdx + emit_test_r64_r64(dst, REG_RDX, REG_RDX); // test rdx,rdx else { - a.mov(ecx, eax); // mov ecx,eax - a.shr(rax, 32); // shr rax,32 - a.or_(rdx, rcx); // or rdx,rcx - a.or_(rdx, rax); // or rdx,rax + emit_mov_r32_r32(dst, REG_ECX, REG_EAX); // mov ecx,eax + emit_shr_r64_imm(dst, REG_RAX, 32); // shr rax,32 + emit_or_r64_r64(dst, REG_RDX, REG_RCX); // or rdx,rcx + emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax } } else - a.test(rax, rax); // test rax,rax + emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test rax,rax // we rely on the fact that OF is cleared by all logical operations above if (vflag) { - a.pushf(); // pushf - a.pop(rax); // pop rax - a.and_(qword_ptr(rsp), ~0x84); // and [rsp],~0x84 - a.or_(ptr(rsp), rax); // or [rsp],rax - a.popf(); // popf + emit_pushf(dst); // pushf + emit_pop_r64(dst, REG_RAX); // pop rax + emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84 + emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax + emit_popf(dst); // popf } } } @@ -4130,7 +4743,7 @@ void drcbe_x64::op_mulu(Assembler &a, const instruction &inst) // op_muls - process a MULS opcode //------------------------------------------------- -void drcbe_x64::op_muls(Assembler &a, const instruction &inst) +void drcbe_x64::op_muls(x86code *&dst, const instruction &inst) { uint8_t zsflags = inst.flags() & (FLAG_Z | FLAG_S); uint8_t vflag = inst.flags() & FLAG_V; @@ -4154,41 +4767,41 @@ void drcbe_x64::op_muls(Assembler &a, const instruction &inst) // 32-bit destination with memory/immediate or register/immediate if (!compute_hi && !src1p.is_immediate() && src2p.is_immediate()) { - Gp dstreg = dstp.is_int_register() ? Gpd(dstp.ireg()) : eax; + int dstreg = dstp.is_int_register() ? dstp.ireg() : REG_EAX; if (src1p.is_memory()) - a.imul(dstreg, MABS(src1p.memory()), src2p.immediate()); // imul dstreg,[src1p],src2p + emit_imul_r32_m32_imm(dst, dstreg, MABS(src1p.memory()), src2p.immediate()); // imul dstreg,[src1p],src2p else if (src1p.is_int_register()) - a.imul(dstreg, Gpd(src1p.ireg()), src2p.immediate()); // imul dstreg,src1p,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,eax + emit_imul_r32_r32_imm(dst, dstreg, src1p.ireg(), src2p.immediate()); // imul dstreg,src1p,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,eax } // 32-bit destination, general case else if (!compute_hi) { - Gp dstreg = dstp.is_int_register() ? Gpd(dstp.ireg()) : eax; - emit_mov_r32_p32(a, dstreg, src1p); // mov dstreg,src1p + int dstreg = dstp.is_int_register() ? dstp.ireg() : REG_EAX; + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p if (src2p.is_memory()) - a.imul(dstreg, MABS(src2p.memory())); // imul dstreg,[src2p] + emit_imul_r32_m32(dst, dstreg, MABS(src2p.memory())); // imul dstreg,[src2p] else if (src2p.is_int_register()) - a.imul(dstreg, Gpd(src2p.ireg())); // imul dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_imul_r32_r32(dst, dstreg, src2p.ireg()); // imul dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } // 64-bit destination, general case else { - emit_mov_r32_p32(a, eax, src1p); // mov eax,src1p + emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p if (src2p.is_memory()) - a.imul(MABS(src2p.memory(), 4)); // imul [src2p] + emit_imul_m32(dst, MABS(src2p.memory())); // imul [src2p] else if (src2p.is_int_register()) - a.imul(Gpd(src2p.ireg())); // imul src2p + emit_imul_r32(dst, src2p.ireg()); // imul src2p else if (src2p.is_immediate()) { - a.mov(edx, src2p.immediate()); // mov edx,src2p - a.imul(edx); // imul edx + emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p + emit_imul_r32(dst, REG_EDX); // imul edx } - emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax - emit_mov_p32_r32(a, edstp, edx); // mov edstp,edx + emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax + emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx } // compute flags @@ -4197,32 +4810,32 @@ void drcbe_x64::op_muls(Assembler &a, const instruction &inst) if (zsflags != 0) { if (vflag) - a.pushf(); // pushf + emit_pushf(dst); // pushf if (compute_hi) { if (zsflags == FLAG_Z) - a.or_(edx, eax); // or edx,eax + emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax else if (zsflags == FLAG_S) - a.test(edx, edx); // test edx,edx + emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx else { - a.movzx(ecx, ax); // movzx ecx,ax - a.shr(eax, 16); // shr eax,16 - a.or_(edx, ecx); // or edx,ecx - a.or_(edx, eax); // or edx,eax + emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax + emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16 + emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx + emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax } } else - a.test(eax, eax); // test eax,eax + emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax // we rely on the fact that OF is cleared by all logical operations above if (vflag) { - a.pushf(); // pushf - a.pop(rax); // pop rax - a.and_(qword_ptr(rsp), ~0x84); // and [rsp],~0x84 - a.or_(ptr(rsp), rax); // or [rsp],rax - a.popf(); // popf + emit_pushf(dst); // pushf + emit_pop_r64(dst, REG_RAX); // pop rax + emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84 + emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax + emit_popf(dst); // popf } } } @@ -4234,41 +4847,41 @@ void drcbe_x64::op_muls(Assembler &a, const instruction &inst) // 64-bit destination with memory/immediate or register/immediate if (!compute_hi && !src1p.is_immediate() && src2p.is_immediate() && short_immediate(src2p.immediate())) { - Gp dstreg = dstp.is_int_register() ? Gpq(dstp.ireg()) : rax; + int dstreg = dstp.is_int_register() ? dstp.ireg() : REG_RAX; if (src1p.is_memory()) - a.imul(dstreg, MABS(src1p.memory()), src2p.immediate()); // imul dstreg,[src1p],src2p + emit_imul_r64_m64_imm(dst, dstreg, MABS(src1p.memory()), src2p.immediate());// imul dstreg,[src1p],src2p else if (src1p.is_int_register()) - a.imul(dstreg, Gpq(src1p.ireg()), src2p.immediate()); // imul rax,src1p,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,rax + emit_imul_r64_r64_imm(dst, dstreg, src1p.ireg(), src2p.immediate()); // imul rax,src1p,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,rax } // 64-bit destination, general case else if (!compute_hi) { - Gp dstreg = dstp.is_int_register() ? Gpq(dstp.ireg()) : rax; - emit_mov_r64_p64(a, dstreg, src1p); // mov dstreg,src1p + int dstreg = dstp.is_int_register() ? dstp.ireg() : REG_RAX; + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p if (src2p.is_memory()) - a.imul(dstreg, MABS(src2p.memory())); // imul dstreg,[src2p] + emit_imul_r64_m64(dst, dstreg, MABS(src2p.memory())); // imul dstreg,[src2p] else if (src2p.is_int_register()) - a.imul(dstreg, Gpq(src2p.ireg())); // imul dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_imul_r64_r64(dst, dstreg, src2p.ireg()); // imul dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } // 128-bit destination, general case else { - emit_mov_r64_p64(a, rax, src1p); // mov rax,src1p + emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p if (src2p.is_memory()) - a.imul(MABS(src2p.memory(), 8)); // imul [src2p] + emit_imul_m64(dst, MABS(src2p.memory())); // imul [src2p] else if (src2p.is_int_register()) - a.imul(Gpq(src2p.ireg())); // imul src2p + emit_imul_r64(dst, src2p.ireg()); // imul src2p else if (src2p.is_immediate()) { - emit_mov_r64_imm(a, rdx, src2p.immediate()); // mov rdx,src2p - a.imul(rdx); // imul rdx + emit_mov_r64_imm(dst, REG_RDX, src2p.immediate()); // mov rdx,src2p + emit_imul_r64(dst, REG_RDX); // imul rdx } - emit_mov_p64_r64(a, dstp, rax); // mov dstp,rax - emit_mov_p64_r64(a, edstp, rdx); // mov edstp,rdx + emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax + emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx } // compute flags @@ -4277,32 +4890,32 @@ void drcbe_x64::op_muls(Assembler &a, const instruction &inst) if (zsflags != 0) { if (vflag) - a.pushf(); // pushf + emit_pushf(dst); // pushf if (compute_hi) { if (zsflags == FLAG_Z) - a.or_(rdx, rax); // or rdx,rax + emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax else if (zsflags == FLAG_S) - a.test(rdx, rdx); // test rdx,rdx + emit_test_r64_r64(dst, REG_RDX, REG_RDX); // test rdx,rdx else { - a.mov(ecx, eax); // mov ecx,eax - a.shr(rax, 32); // shr rax,32 - a.or_(rdx, rcx); // or rdx,rcx - a.or_(rdx, rax); // or rdx,rax + emit_mov_r32_r32(dst, REG_ECX, REG_EAX); // mov ecx,eax + emit_shr_r64_imm(dst, REG_RAX, 32); // shr rax,32 + emit_or_r64_r64(dst, REG_RDX, REG_RCX); // or rdx,rcx + emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax } } else - a.test(rax, rax); // test rax,rax + emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test rax,rax // we rely on the fact that OF is cleared by all logical operations above if (vflag) { - a.pushf(); // pushf - a.pop(rax); // pop rax - a.and_(qword_ptr(rsp), ~0x84); // and [rsp],~0x84 - a.or_(ptr(rsp), rax); // or [rsp],rax - a.popf(); // popf + emit_pushf(dst); // pushf + emit_pop_r64(dst, REG_RAX); // pop rax + emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84 + emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax + emit_popf(dst); // popf } } } @@ -4314,7 +4927,7 @@ void drcbe_x64::op_muls(Assembler &a, const instruction &inst) // op_divu - process a DIVU opcode //------------------------------------------------- -void drcbe_x64::op_divu(Assembler &a, const instruction &inst) +void drcbe_x64::op_divu(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4328,51 +4941,51 @@ void drcbe_x64::op_divu(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(3), PTYPE_MRI); bool compute_rem = (dstp != edstp); - Label skip = a.newLabel(); - // 32-bit form if (inst.size() == 4) { // general case - emit_mov_r32_p32(a, ecx, src2p); // mov ecx,src2p + emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p if (inst.flags() != 0) { - a.mov(eax, 0xa0000000); // mov eax,0xa0000000 - a.add(eax, eax); // add eax,eax + emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000 + emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax } - a.short_().jecxz(skip); // jecxz skip - emit_mov_r32_p32(a, eax, src1p); // mov eax,src1p - a.xor_(edx, edx); // xor edx,edx - a.div(ecx); // div ecx - emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax + emit_link skip; + emit_jecxz_link(dst, skip); // jecxz skip + emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p + emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx + emit_div_r32(dst, REG_ECX); // div ecx + emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax if (compute_rem) - emit_mov_p32_r32(a, edstp, edx); // mov edstp,edx + emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx if (inst.flags() != 0) - a.test(eax, eax); // test eax,eax + emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax + resolve_link(dst, skip); // skip: } // 64-bit form else if (inst.size() == 8) { // general case - emit_mov_r64_p64(a, rcx, src2p); // mov rcx,src2p + emit_mov_r64_p64(dst, REG_RCX, src2p); // mov rcx,src2p if (inst.flags() != 0) { - a.mov(eax, 0xa0000000); // mov eax,0xa0000000 - a.add(eax, eax); // add eax,eax + emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000 + emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax } - a.short_().jecxz(skip); // jrcxz skip - emit_mov_r64_p64(a, rax, src1p); // mov rax,src1p - a.xor_(edx, edx); // xor edx,edx - a.div(rcx); // div rcx - emit_mov_p64_r64(a, dstp, rax); // mov dstp,rax + emit_link skip; + emit_jrcxz_link(dst, skip); // jrcxz skip + emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p + emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx + emit_div_r64(dst, REG_RCX); // div rcx + emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax if (compute_rem) - emit_mov_p64_r64(a, edstp, rdx); // mov edstp,rdx + emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx if (inst.flags() != 0) - a.test(rax, rax); // test eax,eax + emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test eax,eax + resolve_link(dst, skip); // skip: } - - a.bind(skip); // skip: } @@ -4380,7 +4993,7 @@ void drcbe_x64::op_divu(Assembler &a, const instruction &inst) // op_divs - process a DIVS opcode //------------------------------------------------- -void drcbe_x64::op_divs(Assembler &a, const instruction &inst) +void drcbe_x64::op_divs(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4394,51 +5007,51 @@ void drcbe_x64::op_divs(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(3), PTYPE_MRI); bool compute_rem = (dstp != edstp); - Label skip = a.newLabel(); - // 32-bit form if (inst.size() == 4) { // general case - emit_mov_r32_p32(a, ecx, src2p); // mov ecx,src2p + emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p if (inst.flags() != 0) { - a.mov(eax, 0xa0000000); // mov eax,0xa0000000 - a.add(eax, eax); // add eax,eax + emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000 + emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax } - a.short_().jecxz(skip); // jecxz skip - emit_mov_r32_p32(a, eax, src1p); // mov eax,src1p - a.cdq(); // cdq - a.idiv(ecx); // idiv ecx - emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax + emit_link skip; + emit_jecxz_link(dst, skip); // jecxz skip + emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p + emit_cdq(dst); // cdq + emit_idiv_r32(dst, REG_ECX); // idiv ecx + emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax if (compute_rem) - emit_mov_p32_r32(a, edstp, edx); // mov edstp,edx + emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx if (inst.flags() != 0) - a.test(eax, eax); // test eax,eax + emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax + resolve_link(dst, skip); // skip: } // 64-bit form else if (inst.size() == 8) { // general case - emit_mov_r64_p64(a, rcx, src2p); // mov rcx,src2p + emit_mov_r64_p64(dst, REG_RCX, src2p); // mov rcx,src2p if (inst.flags() != 0) { - a.mov(eax, 0xa0000000); // mov eax,0xa0000000 - a.add(eax, eax); // add eax,eax + emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000 + emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax } - a.short_().jecxz(skip); // jrcxz skip - emit_mov_r64_p64(a, rax, src1p); // mov rax,src1p - a.cqo(); // cqo - a.idiv(rcx); // idiv rcx - emit_mov_p64_r64(a, dstp, rax); // mov dstp,rax + emit_link skip; + emit_jrcxz_link(dst, skip); // jrcxz skip + emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p + emit_cqo(dst); // cqo + emit_idiv_r64(dst, REG_RCX); // idiv rcx + emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax if (compute_rem) - emit_mov_p64_r64(a, edstp, rdx); // mov edstp,rdx + emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx if (inst.flags() != 0) - a.test(rax, rax); // test eax,eax + emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test eax,eax + resolve_link(dst, skip); // skip: } - - a.bind(skip); // skip: } @@ -4446,7 +5059,7 @@ void drcbe_x64::op_divs(Assembler &a, const instruction &inst) // op_and - process a AND opcode //------------------------------------------------- -void drcbe_x64::op_and(Assembler &a, const instruction &inst) +void drcbe_x64::op_and(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4459,101 +5072,98 @@ void drcbe_x64::op_and(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(2), PTYPE_MRI); normalize_commutative(src1p, src2p); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + // 32-bit form if (inst.size() == 4) { - // pick a target register - Gp dstreg = dstp.select_register(eax, src2p); - // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_and_m32_p32(a, MABS(dstp.memory(), 4), src2p, inst); // and [dstp],src2p + emit_and_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_and_m32_p32(a, MABS(dstp.memory(), 4), src1p, inst); // and [dstp],src1p + emit_and_m32_p32(dst, MABS(dstp.memory()), src1p, inst); // and [dstp],src1p // AND with immediate 0xff else if (src2p.is_immediate_value(0xff) && inst.flags() == 0) { if (src1p.is_int_register()) - a.movzx(dstreg, GpbLo(src1p.ireg())); // movzx dstreg,src1p + emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p else if (src1p.is_memory()) - a.movzx(dstreg, MABS(src1p.memory(), 1)); // movzx dstreg,[src1p] - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p] + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } // AND with immediate 0xffff else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0) { if (src1p.is_int_register()) - a.movzx(dstreg, Gpw(src1p.ireg())); // movzx dstreg,src1p + emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p else if (src1p.is_memory()) - a.movzx(dstreg, MABS(src1p.memory(), 2)); // movzx dstreg,[src1p] - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p] + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } // general case else { - emit_mov_r32_p32(a, dstreg, src1p); // mov dstreg,src1p - emit_and_r32_p32(a, dstreg, src2p, inst); // and dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_and_r32_p32(dst, dstreg, src2p, inst); // and dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } // 64-bit form else if (inst.size() == 8) { - // pick a target register - Gp dstreg = dstp.select_register(rax, src2p); - // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_and_m64_p64(a, MABS(dstp.memory(), 8), src2p, inst); // and [dstp],src2p + emit_and_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_and_m64_p64(a, MABS(dstp.memory(), 8), src1p, inst); // and [dstp],src1p + emit_and_m64_p64(dst, MABS(dstp.memory()), src1p, inst); // and [dstp],src1p // AND with immediate 0xff else if (src2p.is_immediate_value(0xff) && inst.flags() == 0) { if (src1p.is_int_register()) - a.movzx(dstreg, GpbLo(src1p.ireg())); // movzx dstreg,src1p + emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p else if (src1p.is_memory()) - a.movzx(dstreg, MABS(src1p.memory(), 1)); // movzx dstreg,[src1p] - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p] + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } // AND with immediate 0xffff else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0) { if (src1p.is_int_register()) - a.movzx(dstreg, Gpw(src1p.ireg())); // movzx dstreg,src1p + emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p else if (src1p.is_memory()) - a.movzx(dstreg, MABS(src1p.memory(), 2)); // movzx dstreg,[src1p] - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p] + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } // AND with immediate 0xffffffff else if (src2p.is_immediate_value(0xffffffff) && inst.flags() == 0) { if (dstp.is_int_register() && src1p == dstp) - a.mov(dstreg.r32(), dstreg.r32()); // mov dstreg,dstreg + emit_mov_r32_r32(dst, dstreg, dstreg); // mov dstreg,dstreg else { - emit_mov_r32_p32(a, dstreg.r32(), src1p); // mov dstreg,src1p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } // general case else { - emit_mov_r64_p64(a, dstreg, src1p); // mov dstreg,src1p - emit_and_r64_p64(a, dstreg, src2p, inst); // and dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_and_r64_p64(dst, dstreg, src2p, inst); // and dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } @@ -4563,7 +5173,7 @@ void drcbe_x64::op_and(Assembler &a, const instruction &inst) // op_test - process a TEST opcode //------------------------------------------------- -void drcbe_x64::op_test(Assembler &a, const instruction &inst) +void drcbe_x64::op_test(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4575,21 +5185,21 @@ void drcbe_x64::op_test(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(1), PTYPE_MRI); normalize_commutative(src1p, src2p); + // pick a target register for the general case + int src1reg = src1p.select_register(REG_EAX); + // 32-bit form if (inst.size() == 4) { // src1p in memory if (src1p.is_memory()) - emit_test_m32_p32(a, MABS(src1p.memory(), 4), src2p, inst); // test [src1p],src2p + emit_test_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // test [src1p],src2p // general case else { - // pick a target register for the general case - Gp src1reg = src1p.select_register(eax); - - emit_mov_r32_p32(a, src1reg, src1p); // mov src1reg,src1p - emit_test_r32_p32(a, src1reg, src2p, inst); // test src1reg,src2p + emit_mov_r32_p32(dst, src1reg, src1p); // mov src1reg,src1p + emit_test_r32_p32(dst, src1reg, src2p, inst); // test src1reg,src2p } } @@ -4598,16 +5208,13 @@ void drcbe_x64::op_test(Assembler &a, const instruction &inst) { // src1p in memory if (src1p.is_memory()) - emit_test_m64_p64(a, MABS(src1p.memory(), 8), src2p, inst); // test [src1p],src2p + emit_test_m64_p64(dst, MABS(src1p.memory()), src2p, inst); // test [src1p],src2p // general case else { - // pick a target register for the general case - Gp src1reg = src1p.select_register(rax); - - emit_mov_r64_p64(a, src1reg, src1p); // mov src1reg,src1p - emit_test_r64_p64(a, src1reg, src2p, inst); // test src1reg,src2p + emit_mov_r64_p64(dst, src1reg, src1p); // mov src1reg,src1p + emit_test_r64_p64(dst, src1reg, src2p, inst); // test src1reg,src2p } } } @@ -4617,7 +5224,7 @@ void drcbe_x64::op_test(Assembler &a, const instruction &inst) // op_or - process a OR opcode //------------------------------------------------- -void drcbe_x64::op_or(Assembler &a, const instruction &inst) +void drcbe_x64::op_or(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4630,26 +5237,26 @@ void drcbe_x64::op_or(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(2), PTYPE_MRI); normalize_commutative(src1p, src2p); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + // 32-bit form if (inst.size() == 4) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_or_m32_p32(a, MABS(dstp.memory(), 4), src2p, inst); // or [dstp],src2p + emit_or_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_or_m32_p32(a, MABS(dstp.memory(), 4), src1p, inst); // or [dstp],src1p + emit_or_m32_p32(dst, MABS(dstp.memory()), src1p, inst); // or [dstp],src1p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(eax, src2p); - - emit_mov_r32_p32(a, dstreg, src1p); // mov dstreg,src1p - emit_or_r32_p32(a, dstreg, src2p, inst); // or dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_or_r32_p32(dst, dstreg, src2p, inst); // or dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -4658,21 +5265,18 @@ void drcbe_x64::op_or(Assembler &a, const instruction &inst) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_or_m64_p64(a, MABS(dstp.memory(), 8), src2p, inst); // or [dstp],src2p + emit_or_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_or_m64_p64(a, MABS(dstp.memory(), 8), src1p, inst); // or [dstp],src1p + emit_or_m64_p64(dst, MABS(dstp.memory()), src1p, inst); // or [dstp],src1p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(rax, src2p); - - emit_mov_r64_p64(a, dstreg, src1p); // mov dstreg,src1p - emit_or_r64_p64(a, dstreg, src2p, inst); // or dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_or_r64_p64(dst, dstreg, src2p, inst); // or dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } @@ -4682,7 +5286,7 @@ void drcbe_x64::op_or(Assembler &a, const instruction &inst) // op_xor - process a XOR opcode //------------------------------------------------- -void drcbe_x64::op_xor(Assembler &a, const instruction &inst) +void drcbe_x64::op_xor(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4695,30 +5299,30 @@ void drcbe_x64::op_xor(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(2), PTYPE_MRI); normalize_commutative(src1p, src2p); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + // 32-bit form if (inst.size() == 4) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_xor_m32_p32(a, MABS(dstp.memory(), 4), src2p, inst); // xor [dstp],src2p + emit_xor_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_xor_m32_p32(a, MABS(dstp.memory(), 4), src1p, inst); // xor [dstp],src1p + emit_xor_m32_p32(dst, MABS(dstp.memory()), src1p, inst); // xor [dstp],src1p // dstp == src1p register else if (dstp.is_int_register() && dstp == src1p) - emit_xor_r32_p32(a, Gpd(dstp.ireg()), src2p, inst); // xor dstp,src2p + emit_xor_r32_p32(dst, dstp.ireg(), src2p, inst); // xor dstp,src2p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(eax, src2p); - - emit_mov_r32_p32(a, dstreg, src1p); // mov dstreg,src1p - emit_xor_r32_p32(a, dstreg, src2p, inst); // xor dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_xor_r32_p32(dst, dstreg, src2p, inst); // xor dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -4727,25 +5331,22 @@ void drcbe_x64::op_xor(Assembler &a, const instruction &inst) { // dstp == src1p in memory if (dstp.is_memory() && dstp == src1p) - emit_xor_m64_p64(a, MABS(dstp.memory(), 8), src2p, inst); // xor [dstp],src2p + emit_xor_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p // dstp == src2p in memory else if (dstp.is_memory() && dstp == src2p) - emit_xor_m64_p64(a, MABS(dstp.memory(), 8), src1p, inst); // xor [dstp],src1p + emit_xor_m64_p64(dst, MABS(dstp.memory()), src1p, inst); // xor [dstp],src1p // dstp == src1p register else if (dstp.is_int_register() && dstp == src1p) - emit_xor_r64_p64(a, Gpq(dstp.ireg()), src2p, inst); // xor dstp,src2p + emit_xor_r64_p64(dst, dstp.ireg(), src2p, inst); // xor dstp,src2p // general case else { - // pick a target register for the general case - Gp dstreg = dstp.select_register(rax, src2p); - - emit_mov_r64_p64(a, dstreg, src1p); // mov dstreg,src1p - emit_xor_r64_p64(a, dstreg, src2p, inst); // xor dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_xor_r64_p64(dst, dstreg, src2p, inst); // xor dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } @@ -4755,7 +5356,7 @@ void drcbe_x64::op_xor(Assembler &a, const instruction &inst) // op_lzcnt - process a LZCNT opcode //------------------------------------------------- -void drcbe_x64::op_lzcnt(Assembler &a, const instruction &inst) +void drcbe_x64::op_lzcnt(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4766,32 +5367,29 @@ void drcbe_x64::op_lzcnt(Assembler &a, const instruction &inst) be_parameter dstp(*this, inst.param(0), PTYPE_MR); be_parameter srcp(*this, inst.param(1), PTYPE_MRI); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX); + // 32-bit form if (inst.size() == 4) { - // pick a target register - Gp dstreg = dstp.select_register(eax); - - emit_mov_r32_p32(a, dstreg, srcp); // mov dstreg,src1p - a.mov(ecx, 32 ^ 31); // mov ecx,32 ^ 31 - a.bsr(dstreg, dstreg); // bsr dstreg,dstreg - a.cmovz(dstreg, ecx); // cmovz dstreg,ecx - a.xor_(dstreg, 31); // xor dstreg,31 - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p + emit_mov_r32_imm(dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31 + emit_bsr_r32_r32(dst, dstreg, dstreg); // bsr dstreg,dstreg + emit_cmovcc_r32_r32(dst, x64emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx + emit_xor_r32_imm(dst, dstreg, 31); // xor dstreg,31 + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - // pick a target register - Gp dstreg = dstp.select_register(rax); - - emit_mov_r64_p64(a, dstreg, srcp); // mov dstreg,src1p - a.mov(ecx, 64 ^ 63); // mov ecx,64 ^ 63 - a.bsr(dstreg, dstreg); // bsr dstreg,dstreg - a.cmovz(dstreg, rcx); // cmovz dstreg,rcx - a.xor_(dstreg, 63); // xor dstreg,63 - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,src1p + emit_mov_r64_imm(dst, REG_RCX, 64 ^ 63); // mov rcx,64 ^ 63 + emit_bsr_r64_r64(dst, dstreg, dstreg); // bsr dstreg,dstreg + emit_cmovcc_r64_r64(dst, x64emit::COND_Z, dstreg, REG_RCX); // cmovz dstreg,rcx + emit_xor_r32_imm(dst, dstreg, 63); // xor dstreg,63 + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -4800,7 +5398,7 @@ void drcbe_x64::op_lzcnt(Assembler &a, const instruction &inst) // op_tzcnt - process a TZCNT opcode //------------------------------------------------- -void drcbe_x64::op_tzcnt(Assembler &a, const instruction &inst) +void drcbe_x64::op_tzcnt(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4814,25 +5412,23 @@ void drcbe_x64::op_tzcnt(Assembler &a, const instruction &inst) // 32-bit form if (inst.size() == 4) { - Gp dstreg = dstp.select_register(eax); - - emit_mov_r32_p32(a, dstreg, srcp); // mov dstreg,srcp - a.mov(ecx, 32); // mov ecx,32 - a.bsf(dstreg, dstreg); // bsf dstreg,dstreg - a.cmovz(dstreg, ecx); // cmovz dstreg,ecx - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + int dstreg = dstp.select_register(REG_EAX); + emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,srcp + emit_mov_r32_imm(dst, REG_ECX, 32); // mov ecx,32 + emit_bsf_r32_r32(dst, dstreg, dstreg); // bsf dstreg,dstreg + emit_cmovcc_r32_r32(dst, x64emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - Gp dstreg = dstp.select_register(rax); - - emit_mov_r64_p64(a, dstreg, srcp); // mov dstreg,srcp - a.mov(ecx, 64); // mov ecx,64 - a.bsf(dstreg, dstreg); // bsf dstreg,dstreg - a.cmovz(dstreg, rcx); // cmovz dstreg,rcx - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + int dstreg = dstp.select_register(REG_RAX); + emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,srcp + emit_mov_r64_imm(dst, REG_RCX, 64); // mov rcx,64 + emit_bsf_r64_r64(dst, dstreg, dstreg); // bsf dstreg,dstreg + emit_cmovcc_r64_r64(dst, x64emit::COND_Z, dstreg, REG_RCX); // cmovz dstreg,rcx + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } @@ -4841,7 +5437,7 @@ void drcbe_x64::op_tzcnt(Assembler &a, const instruction &inst) // op_bswap - process a BSWAP opcode //------------------------------------------------- -void drcbe_x64::op_bswap(Assembler &a, const instruction &inst) +void drcbe_x64::op_bswap(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4852,34 +5448,89 @@ void drcbe_x64::op_bswap(Assembler &a, const instruction &inst) be_parameter dstp(*this, inst.param(0), PTYPE_MR); be_parameter srcp(*this, inst.param(1), PTYPE_MRI); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_RAX); + // 32-bit form if (inst.size() == 4) { - // pick a target register - Gp dstreg = dstp.select_register(eax); + emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p + emit_bswap_r32(dst, dstreg); // bswap dstreg + if (inst.flags() != 0) + emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } - emit_mov_r32_p32(a, dstreg, srcp); // mov dstreg,src1p - a.bswap(dstreg); // bswap dstreg + // 64-bit form + else if (inst.size() == 8) + { + emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,src1p + emit_bswap_r64(dst, dstreg); // bswap dstreg if (inst.flags() != 0) - a.test(dstreg, dstreg); // test dstreg,dstreg - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_test_r64_r64(dst, dstreg, dstreg); // test dstreg,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg + } +} + + +//------------------------------------------------- +// op_shl - process a SHL opcode +//------------------------------------------------- + +void drcbe_x64::op_shl(x86code *&dst, const instruction &inst) +{ + // validate instruction + assert(inst.size() == 4 || inst.size() == 8); + assert_no_condition(inst); + assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S); + + // normalize parameters + be_parameter dstp(*this, inst.param(0), PTYPE_MR); + be_parameter src1p(*this, inst.param(1), PTYPE_MRI); + be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + + // 32-bit form + if (inst.size() == 4) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_shl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shl [dstp],src2p + + // general case + else + { + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_shl_r32_p32(dst, dstreg, src2p, inst); // shl dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } } // 64-bit form else if (inst.size() == 8) { - // pick a target register - Gp dstreg = dstp.select_register(rax); + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_shl_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // shl [dstp],src2p - emit_mov_r64_p64(a, dstreg, srcp); // mov dstreg,src1p - a.bswap(dstreg); // bswap dstreg - if (inst.flags() != 0) - a.test(dstreg, dstreg); // test dstreg,dstreg - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + // general case + else + { + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_shl_r64_p64(dst, dstreg, src2p, inst); // shl dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg + } } } -template <Inst::Id Opcode> void drcbe_x64::op_shift(Assembler &a, const uml::instruction &inst) + +//------------------------------------------------- +// op_shr - process a SHR opcode +//------------------------------------------------- + +void drcbe_x64::op_shr(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4891,58 +5542,309 @@ template <Inst::Id Opcode> void drcbe_x64::op_shift(Assembler &a, const uml::ins be_parameter src1p(*this, inst.param(1), PTYPE_MRI); be_parameter src2p(*this, inst.param(2), PTYPE_MRI); - const bool carry = (Opcode == Inst::kIdRcl) || (Opcode == Inst::kIdRcr); + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); - // optimize immediate zero case - if (carry || inst.flags() || !src2p.is_immediate_value(0)) + // 32-bit form + if (inst.size() == 4) { - // 32-bit form - if (inst.size() == 4) + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_shr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shr [dstp],src2p + + // general case + else { - // dstp == src1p in memory - if (dstp.is_memory() && dstp == src1p) - emit_shift_p32(a, Opcode, MABS(dstp.memory(), inst.size()), src2p); // <op> [dstp],src2p + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_shr_r32_p32(dst, dstreg, src2p, inst); // shr dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } + } - // general case - else - { - // pick a target register - Gp dstreg = dstp.select_register(eax, src2p); + // 64-bit form + else if (inst.size() == 8) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_shr_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // shr [dstp],src2p - if (carry) - emit_mov_r32_p32_keepflags(a, dstreg, src1p); // mov dstreg,src1p - else - emit_mov_r32_p32(a, dstreg, src1p); // mov dstreg,src1p - emit_shift_p32(a, Opcode, dstreg, src2p); // <op> dstreg,src2p - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg - } + // general case + else + { + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_shr_r64_p64(dst, dstreg, src2p, inst); // shr dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } + } +} - // 64-bit form - else if (inst.size() == 8) + +//------------------------------------------------- +// op_sar - process a SAR opcode +//------------------------------------------------- + +void drcbe_x64::op_sar(x86code *&dst, const instruction &inst) +{ + // validate instruction + assert(inst.size() == 4 || inst.size() == 8); + assert_no_condition(inst); + assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S); + + // normalize parameters + be_parameter dstp(*this, inst.param(0), PTYPE_MR); + be_parameter src1p(*this, inst.param(1), PTYPE_MRI); + be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + + // 32-bit form + if (inst.size() == 4) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_sar_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sar [dstp],src2p + + // general case + else { - // dstp == src1p in memory - if (dstp.is_memory() && dstp == src1p) - emit_shift_p64(a, Opcode, MABS(dstp.memory(), inst.size()), src2p); // <op> [dstp],src2p + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_sar_r32_p32(dst, dstreg, src2p, inst); // sar dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } + } - // general case - else - { - // pick a target register - Gp dstreg = dstp.select_register(rax, src2p); + // 64-bit form + else if (inst.size() == 8) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_sar_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sar [dstp],src2p - if (carry) - emit_mov_r64_p64_keepflags(a, dstreg, src1p); // mov dstreg,src1p - else - emit_mov_r64_p64(a, dstreg, src1p); // mov dstreg,src1p - emit_shift_p64(a, Opcode, dstreg, src2p); // <op> dstreg,src2p - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg - } + // general case + else + { + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_sar_r64_p64(dst, dstreg, src2p, inst); // sar dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg + } + } +} + + +//------------------------------------------------- +// op_rol - process a rol opcode +//------------------------------------------------- + +void drcbe_x64::op_rol(x86code *&dst, const instruction &inst) +{ + // validate instruction + assert(inst.size() == 4 || inst.size() == 8); + assert_no_condition(inst); + assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S); + + // normalize parameters + be_parameter dstp(*this, inst.param(0), PTYPE_MR); + be_parameter src1p(*this, inst.param(1), PTYPE_MRI); + be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + + // 32-bit form + if (inst.size() == 4) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_rol_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rol [dstp],src2p + + // general case + else + { + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_rol_r32_p32(dst, dstreg, src2p, inst); // rol dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } + } + + // 64-bit form + else if (inst.size() == 8) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_rol_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // rol [dstp],src2p + + // general case + else + { + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_rol_r64_p64(dst, dstreg, src2p, inst); // rol dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg + } + } +} + + +//------------------------------------------------- +// op_ror - process a ROR opcode +//------------------------------------------------- + +void drcbe_x64::op_ror(x86code *&dst, const instruction &inst) +{ + // validate instruction + assert(inst.size() == 4 || inst.size() == 8); + assert_no_condition(inst); + assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S); + + // normalize parameters + be_parameter dstp(*this, inst.param(0), PTYPE_MR); + be_parameter src1p(*this, inst.param(1), PTYPE_MRI); + be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + + // 32-bit form + if (inst.size() == 4) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_ror_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // ror [dstp],src2p + + // general case + else + { + emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p + emit_ror_r32_p32(dst, dstreg, src2p, inst); // ror dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } + } + + // 64-bit form + else if (inst.size() == 8) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_ror_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // ror [dstp],src2p + + // general case + else + { + emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p + emit_ror_r64_p64(dst, dstreg, src2p, inst); // ror dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg + } + } +} + + +//------------------------------------------------- +// op_rolc - process a ROLC opcode +//------------------------------------------------- + +void drcbe_x64::op_rolc(x86code *&dst, const instruction &inst) +{ + // validate instruction + assert(inst.size() == 4 || inst.size() == 8); + assert_no_condition(inst); + assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S); + + // normalize parameters + be_parameter dstp(*this, inst.param(0), PTYPE_MR); + be_parameter src1p(*this, inst.param(1), PTYPE_MRI); + be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + + // 32-bit form + if (inst.size() == 4) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_rcl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcl [dstp],src2p + + // general case + else + { + emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_rcl_r32_p32(dst, dstreg, src2p, inst); // rcl dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } + } + + // 64-bit form + else if (inst.size() == 8) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_rcl_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // rcl [dstp],src2p + + // general case + else + { + emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_rcl_r64_p64(dst, dstreg, src2p, inst); // rcl dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } } } +//------------------------------------------------- +// op_rorc - process a RORC opcode +//------------------------------------------------- + +void drcbe_x64::op_rorc(x86code *&dst, const instruction &inst) +{ + // validate instruction + assert(inst.size() == 4 || inst.size() == 8); + assert_no_condition(inst); + assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S); + + // normalize parameters + be_parameter dstp(*this, inst.param(0), PTYPE_MR); + be_parameter src1p(*this, inst.param(1), PTYPE_MRI); + be_parameter src2p(*this, inst.param(2), PTYPE_MRI); + + // pick a target register for the general case + int dstreg = dstp.select_register(REG_EAX, src2p); + + // 32-bit form + if (inst.size() == 4) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_rcr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcr [dstp],src2p + + // general case + else + { + emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_rcr_r32_p32(dst, dstreg, src2p, inst); // rcr dstreg,src2p + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg + } + } + + // 64-bit form + else if (inst.size() == 8) + { + // dstp == src1p in memory + if (dstp.is_memory() && dstp == src1p) + emit_rcr_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // rcr [dstp],src2p + + // general case + else + { + emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p + emit_rcr_r64_p64(dst, dstreg, src2p, inst); // rcr dstreg,src2p + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg + } + } +} + + + /*************************************************************************** FLOATING POINT OPERATIONS ***************************************************************************/ @@ -4951,7 +5853,7 @@ template <Inst::Id Opcode> void drcbe_x64::op_shift(Assembler &a, const uml::ins // op_fload - process a FLOAD opcode //------------------------------------------------- -void drcbe_x64::op_fload(Assembler &a, const instruction &inst) +void drcbe_x64::op_fload(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -4964,38 +5866,38 @@ void drcbe_x64::op_fload(Assembler &a, const instruction &inst) be_parameter indp(*this, inst.param(2), PTYPE_MRI); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // determine the pointer base int32_t baseoffs; - Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs); + int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs); // 32-bit form if (inst.size() == 4) { if (indp.is_immediate()) - a.movss(dstreg, ptr(basereg, baseoffs + 4*indp.immediate())); // movss dstreg,[basep + 4*indp] + emit_movss_r128_m32(dst, dstreg, MBD(basereg, baseoffs + 4*indp.immediate())); // movss dstreg,[basep + 4*indp] else { - Gp indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); // mov indreg,indp - a.movss(dstreg, ptr(basereg, indreg, 2, baseoffs)); // movss dstreg,[basep + 4*indp] + int indreg = indp.select_register(REG_ECX); + emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp + emit_movss_r128_m32(dst, dstreg, MBISD(basereg, indreg, 4, baseoffs)); // movss dstreg,[basep + 4*indp] } - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { if (indp.is_immediate()) - a.movsd(dstreg, ptr(basereg, baseoffs + 8*indp.immediate())); // movsd dstreg,[basep + 8*indp] + emit_movsd_r128_m64(dst, dstreg, MBD(basereg, baseoffs + 8*indp.immediate())); // movsd dstreg,[basep + 8*indp] else { - Gp indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); // mov indreg,indp - a.movsd(dstreg, ptr(basereg, indreg, 3, baseoffs)); // movsd dstreg,[basep + 8*indp] + int indreg = indp.select_register(REG_ECX); + emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp + emit_movsd_r128_m64(dst, dstreg, MBISD(basereg, indreg, 8, baseoffs)); // movsd dstreg,[basep + 8*indp] } - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5004,7 +5906,7 @@ void drcbe_x64::op_fload(Assembler &a, const instruction &inst) // op_fstore - process a FSTORE opcode //------------------------------------------------- -void drcbe_x64::op_fstore(Assembler &a, const instruction &inst) +void drcbe_x64::op_fstore(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5017,37 +5919,37 @@ void drcbe_x64::op_fstore(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(2), PTYPE_MF); // pick a target register for the general case - Xmm srcreg = srcp.select_register(xmm0); + int srcreg = srcp.select_register(REG_XMM0); // determine the pointer base int32_t baseoffs; - Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs); + int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs); // 32-bit form if (inst.size() == 4) { - emit_movss_r128_p32(a, srcreg, srcp); // movss srcreg,srcp + emit_movss_r128_p32(dst, srcreg, srcp); // movss srcreg,srcp if (indp.is_immediate()) - a.movss(ptr(basereg, baseoffs + 4*indp.immediate()), srcreg); // movss [basep + 4*indp],srcreg + emit_movss_m32_r128(dst, MBD(basereg, baseoffs + 4*indp.immediate()), srcreg); // movss [basep + 4*indp],srcreg else { - Gp indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); // mov indreg,indp - a.movss(ptr(basereg, indreg, 2, baseoffs), srcreg); // movss [basep + 4*indp],srcreg + int indreg = indp.select_register(REG_ECX); + emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp + emit_movss_m32_r128(dst, MBISD(basereg, indreg, 4, baseoffs), srcreg); // movss [basep + 4*indp],srcreg } } // 64-bit form else if (inst.size() == 8) { - emit_movsd_r128_p64(a, srcreg, srcp); // movsd srcreg,srcp + emit_movsd_r128_p64(dst, srcreg, srcp); // movsd srcreg,srcp if (indp.is_immediate()) - a.movsd(ptr(basereg, baseoffs + 8*indp.immediate()), srcreg); // movsd [basep + 8*indp],srcreg + emit_movsd_m64_r128(dst, MBD(basereg, baseoffs + 8*indp.immediate()), srcreg); // movsd [basep + 8*indp],srcreg else { - Gp indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); // mov indreg,indp - a.movsd(ptr(basereg, indreg, 3, baseoffs), srcreg); // movsd [basep + 8*indp],srcreg + int indreg = indp.select_register(REG_ECX); + emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp + emit_movsd_m64_r128(dst, MBISD(basereg, indreg, 8, baseoffs), srcreg); // movsd [basep + 8*indp],srcreg } } } @@ -5057,7 +5959,7 @@ void drcbe_x64::op_fstore(Assembler &a, const instruction &inst) // op_fread - process a FREAD opcode //------------------------------------------------- -void drcbe_x64::op_fread(Assembler &a, const instruction &inst) +void drcbe_x64::op_fread(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5072,27 +5974,27 @@ void drcbe_x64::op_fread(Assembler &a, const instruction &inst) assert((1 << spacep.size()) == inst.size()); // set up a call to the read dword/qword handler - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_space[spacep.space()]); // mov param1,space - emit_mov_r32_p32(a, Gpd(REG_PARAM2), addrp); // mov param2,addrp + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)(m_space[spacep.space()])); // mov param1,space + emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp if (inst.size() == 4) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacep.space()].read_dword); // call read_dword + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].read_dword); // call read_dword else if (inst.size() == 8) - emit_smart_call_m64(a, (x86code **)&m_accessors[spacep.space()].read_qword); // call read_qword + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].read_qword); // call read_qword // store result if (inst.size() == 4) { if (dstp.is_memory()) - a.mov(MABS(dstp.memory()), eax); // mov [dstp],eax + emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax else if (dstp.is_float_register()) - a.movd(Xmm(dstp.freg()), eax); // movd dstp,eax + emit_movd_r128_r32(dst, dstp.freg(), REG_EAX); // movd dstp,eax } else if (inst.size() == 8) { if (dstp.is_memory()) - a.mov(MABS(dstp.memory()), rax); // mov [dstp],rax + emit_mov_m64_r64(dst, MABS(dstp.memory()), REG_RAX); // mov [dstp],rax else if (dstp.is_float_register()) - a.movq(Xmm(dstp.freg()), rax); // movq dstp,rax + emit_movq_r128_r64(dst, dstp.freg(), REG_RAX); // movq dstp,rax } } @@ -5101,7 +6003,7 @@ void drcbe_x64::op_fread(Assembler &a, const instruction &inst) // op_fwrite - process a FWRITE opcode //------------------------------------------------- -void drcbe_x64::op_fwrite(Assembler &a, const instruction &inst) +void drcbe_x64::op_fwrite(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5116,27 +6018,27 @@ void drcbe_x64::op_fwrite(Assembler &a, const instruction &inst) assert((1 << spacep.size()) == inst.size()); // general case - emit_mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_space[spacep.space()]); // mov param1,space - emit_mov_r32_p32(a, Gpd(REG_PARAM2), addrp); // mov param21,addrp + emit_mov_r64_imm(dst, REG_PARAM1, (uintptr_t)(m_space[spacep.space()])); // mov param1,space + emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param21,addrp // 32-bit form if (inst.size() == 4) { if (srcp.is_memory()) - a.mov(Gpd(REG_PARAM3), MABS(srcp.memory())); // mov param3,[srcp] + emit_mov_r32_m32(dst, REG_PARAM3, MABS(srcp.memory())); // mov param3,[srcp] else if (srcp.is_float_register()) - a.movd(Gpd(REG_PARAM3), Xmm(srcp.freg())); // movd param3,srcp - emit_smart_call_m64(a, (x86code **)&m_accessors[spacep.space()].write_dword); // call write_dword + emit_movd_r32_r128(dst, REG_PARAM3, srcp.freg()); // movd param3,srcp + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].write_dword); // call write_dword } // 64-bit form else if (inst.size() == 8) { if (srcp.is_memory()) - a.mov(Gpq(REG_PARAM3), MABS(srcp.memory())); // mov param3,[srcp] + emit_mov_r64_m64(dst, REG_PARAM3, MABS(srcp.memory())); // mov param3,[srcp] else if (srcp.is_float_register()) - a.movq(Gpq(REG_PARAM3), Xmm(srcp.freg())); // movq param3,srcp - emit_smart_call_m64(a, (x86code **)&m_accessors[spacep.space()].write_qword); // call write_qword + emit_movq_r64_r128(dst, REG_PARAM3, srcp.freg()); // movq param3,srcp + emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].write_qword); // call write_qword } } @@ -5145,7 +6047,7 @@ void drcbe_x64::op_fwrite(Assembler &a, const instruction &inst) // op_fmov - process a FMOV opcode //------------------------------------------------- -void drcbe_x64::op_fmov(Assembler &a, const instruction &inst) +void drcbe_x64::op_fmov(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5157,24 +6059,24 @@ void drcbe_x64::op_fmov(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // always start with a jmp - Label skip = a.newLabel(); + emit_link skip = { nullptr }; if (inst.condition() != uml::COND_ALWAYS) - a.short_().j(X86_NOT_CONDITION(inst.condition()), skip); // jcc skip + emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip // 32-bit form if (inst.size() == 4) { if (srcp.is_float_register()) { - emit_movss_p32_r128(a, dstp, Xmm(srcp.freg())); // movss dstp,srcp + emit_movss_p32_r128(dst, dstp, srcp.freg()); // movss dstp,srcp } else { - emit_movss_r128_p32(a, dstreg, srcp); // movss dstreg,srcp - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_movss_r128_p32(dst, dstreg, srcp); // movss dstreg,srcp + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } } @@ -5183,18 +6085,18 @@ void drcbe_x64::op_fmov(Assembler &a, const instruction &inst) { if (srcp.is_float_register()) { - emit_movsd_p64_r128(a, dstp, Xmm(srcp.freg())); // movsd dstp,srcp + emit_movsd_p64_r128(dst, dstp, srcp.freg()); // movsd dstp,srcp } else { - emit_movsd_r128_p64(a, dstreg, srcp); // movsd dstreg,srcp - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_movsd_r128_p64(dst, dstreg, srcp); // movsd dstreg,srcp + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } // resolve the jump if (inst.condition() != uml::COND_ALWAYS) - a.bind(skip); // skip: + resolve_link(dst, skip); // skip: } @@ -5202,7 +6104,7 @@ void drcbe_x64::op_fmov(Assembler &a, const instruction &inst) // op_ftoint - process a FTOINT opcode //------------------------------------------------- -void drcbe_x64::op_ftoint(Assembler &a, const instruction &inst) +void drcbe_x64::op_ftoint(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5218,66 +6120,108 @@ void drcbe_x64::op_ftoint(Assembler &a, const instruction &inst) assert(roundp.is_rounding()); // pick a target register for the general case - Gp dstreg = dstp.select_register(rax); - - // 32-bit integer source - if (sizep.size() == SIZE_DWORD) - dstreg = dstreg.r32(); + int dstreg = dstp.select_register(REG_EAX); // set rounding mode if necessary if (roundp.rounding() != ROUND_DEFAULT && roundp.rounding() != ROUND_TRUNC) { - a.stmxcsr(MABS(&m_near.ssemodesave)); // stmxcsr [ssemodesave] - a.ldmxcsr(MABS(&m_near.ssecontrol[roundp.rounding()])); // ldmxcsr fpcontrol[mode] + emit_stmxcsr_m32(dst, MABS(&m_near.ssemodesave)); // stmxcsr [ssemodesave] + emit_ldmxcsr_m32(dst, MABS(&m_near.ssecontrol[roundp.rounding()])); // ldmxcsr fpcontrol[mode] } // 32-bit form if (inst.size() == 4) { - if (srcp.is_memory()) + // 32-bit integer source + if (sizep.size() == SIZE_DWORD) { - if (roundp.rounding() != ROUND_TRUNC) - a.cvtss2si(dstreg, MABS(srcp.memory())); // cvtss2si dstreg,[srcp] - else - a.cvttss2si(dstreg, MABS(srcp.memory())); // cvttss2si dstreg,[srcp] + if (srcp.is_memory()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtss2si_r32_m32(dst, dstreg, MABS(srcp.memory())); // cvtss2si dstreg,[srcp] + else + emit_cvttss2si_r32_m32(dst, dstreg, MABS(srcp.memory())); // cvttss2si dstreg,[srcp] + } + else if (srcp.is_float_register()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtss2si_r32_r128(dst, dstreg, srcp.freg()); // cvtss2si dstreg,srcp + else + emit_cvttss2si_r32_r128(dst, dstreg, srcp.freg()); // cvttss2si dstreg,srcp + } } - else if (srcp.is_float_register()) + + // 64-bit integer source + else if (sizep.size() == SIZE_QWORD) { - if (roundp.rounding() != ROUND_TRUNC) - a.cvtss2si(dstreg, Xmm(srcp.freg())); // cvtss2si dstreg,srcp - else - a.cvttss2si(dstreg, Xmm(srcp.freg())); // cvttss2si dstreg,srcp + if (srcp.is_memory()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtss2si_r64_m32(dst, dstreg, MABS(srcp.memory())); // cvtss2si dstreg,[srcp] + else + emit_cvttss2si_r64_m32(dst, dstreg, MABS(srcp.memory())); // cvttss2si dstreg,[srcp] + } + else if (srcp.is_float_register()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtss2si_r64_r128(dst, dstreg, srcp.freg()); // cvtss2si dstreg,srcp + else + emit_cvttss2si_r64_r128(dst, dstreg, srcp.freg()); // cvttss2si dstreg,srcp + } } } // 64-bit form else if (inst.size() == 8) { - if (srcp.is_memory()) + // 32-bit integer source + if (sizep.size() == SIZE_DWORD) { - if (roundp.rounding() != ROUND_TRUNC) - a.cvtsd2si(dstreg, MABS(srcp.memory())); // cvtsd2si dstreg,[srcp] - else - a.cvttsd2si(dstreg, MABS(srcp.memory())); // cvttsd2si dstreg,[srcp] + if (srcp.is_memory()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtsd2si_r32_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2si dstreg,[srcp] + else + emit_cvttsd2si_r32_m64(dst, dstreg, MABS(srcp.memory())); // cvttsd2si dstreg,[srcp] + } + else if (srcp.is_float_register()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtsd2si_r32_r128(dst, dstreg, srcp.freg()); // cvtsd2si dstreg,srcp + else + emit_cvttsd2si_r32_r128(dst, dstreg, srcp.freg()); // cvttsd2si dstreg,srcp + } } - else if (srcp.is_float_register()) + + // 64-bit integer source + else if (sizep.size() == SIZE_QWORD) { - if (roundp.rounding() != ROUND_TRUNC) - a.cvtsd2si(dstreg, Xmm(srcp.freg())); // cvtsd2si dstreg,srcp - else - a.cvttsd2si(dstreg, Xmm(srcp.freg())); // cvttsd2si dstreg,srcp + if (srcp.is_memory()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtsd2si_r64_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2si dstreg,[srcp] + else + emit_cvttsd2si_r64_m64(dst, dstreg, MABS(srcp.memory())); // cvttsd2si dstreg,[srcp] + } + else if (srcp.is_float_register()) + { + if (roundp.rounding() != ROUND_TRUNC) + emit_cvtsd2si_r64_r128(dst, dstreg, srcp.freg()); // cvtsd2si dstreg,srcp + else + emit_cvttsd2si_r64_r128(dst, dstreg, srcp.freg()); // cvttsd2si dstreg,srcp + } } } // general case if (sizep.size() == SIZE_DWORD) - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg else - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg // restore rounding mode if (roundp.rounding() != ROUND_DEFAULT && roundp.rounding() != ROUND_TRUNC) - a.ldmxcsr(MABS(&m_near.ssemodesave)); // ldmxcsr [ssemodesave] + emit_ldmxcsr_m32(dst, MABS(&m_near.ssemodesave)); // ldmxcsr [ssemodesave] } @@ -5285,7 +6229,7 @@ void drcbe_x64::op_ftoint(Assembler &a, const instruction &inst) // op_ffrint - process a FFRINT opcode //------------------------------------------------- -void drcbe_x64::op_ffrint(Assembler &a, const instruction &inst) +void drcbe_x64::op_ffrint(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5299,7 +6243,7 @@ void drcbe_x64::op_ffrint(Assembler &a, const instruction &inst) assert(sizep.is_size()); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // 32-bit form if (inst.size() == 4) @@ -5308,12 +6252,12 @@ void drcbe_x64::op_ffrint(Assembler &a, const instruction &inst) if (sizep.size() == SIZE_DWORD) { if (srcp.is_memory()) - a.cvtsi2ss(dstreg, MABS(srcp.memory(), 4)); // cvtsi2ss dstreg,[srcp] + emit_cvtsi2ss_r128_m32(dst, dstreg, MABS(srcp.memory())); // cvtsi2ss dstreg,[srcp] else { - Gp srcreg = srcp.select_register(eax); - emit_mov_r32_p32(a, srcreg, srcp); // mov srcreg,srcp - a.cvtsi2ss(dstreg, srcreg); // cvtsi2ss dstreg,srcreg + int srcreg = srcp.select_register(REG_EAX); + emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp + emit_cvtsi2ss_r128_r32(dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg } } @@ -5321,15 +6265,15 @@ void drcbe_x64::op_ffrint(Assembler &a, const instruction &inst) else { if (srcp.is_memory()) - a.cvtsi2ss(dstreg, MABS(srcp.memory(), 8)); // cvtsi2ss dstreg,[srcp] + emit_cvtsi2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsi2ss dstreg,[srcp] else { - Gp srcreg = srcp.select_register(rax); - emit_mov_r64_p64(a, srcreg, srcp); // mov srcreg,srcp - a.cvtsi2ss(dstreg, srcreg); // cvtsi2ss dstreg,srcreg + int srcreg = srcp.select_register(REG_RAX); + emit_mov_r64_p64(dst, srcreg, srcp); // mov srcreg,srcp + emit_cvtsi2ss_r128_r64(dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg } } - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form @@ -5339,12 +6283,12 @@ void drcbe_x64::op_ffrint(Assembler &a, const instruction &inst) if (sizep.size() == SIZE_DWORD) { if (srcp.is_memory()) - a.cvtsi2sd(dstreg, MABS(srcp.memory(), 4)); // cvtsi2sd dstreg,[srcp] + emit_cvtsi2sd_r128_m32(dst, dstreg, MABS(srcp.memory())); // cvtsi2sd dstreg,[srcp] else { - Gp srcreg = srcp.select_register(eax); - emit_mov_r32_p32(a, srcreg, srcp); // mov srcreg,srcp - a.cvtsi2sd(dstreg, srcreg); // cvtsi2sd dstreg,srcreg + int srcreg = srcp.select_register(REG_EAX); + emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp + emit_cvtsi2sd_r128_r32(dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg } } @@ -5352,15 +6296,15 @@ void drcbe_x64::op_ffrint(Assembler &a, const instruction &inst) else { if (srcp.is_memory()) - a.cvtsi2sd(dstreg, MABS(srcp.memory(), 8)); // cvtsi2sd dstreg,[srcp] + emit_cvtsi2sd_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsi2sd dstreg,[srcp] else { - Gp srcreg = srcp.select_register(rax); - emit_mov_r64_p64(a, srcreg, srcp); // mov srcreg,srcp - a.cvtsi2sd(dstreg, srcreg); // cvtsi2sd dstreg,srcreg + int srcreg = srcp.select_register(REG_EAX); + emit_mov_r64_p64(dst, srcreg, srcp); // mov srcreg,srcp + emit_cvtsi2sd_r128_r64(dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg } } - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5369,7 +6313,7 @@ void drcbe_x64::op_ffrint(Assembler &a, const instruction &inst) // op_ffrflt - process a FFRFLT opcode //------------------------------------------------- -void drcbe_x64::op_ffrflt(Assembler &a, const instruction &inst) +void drcbe_x64::op_ffrflt(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5383,26 +6327,26 @@ void drcbe_x64::op_ffrflt(Assembler &a, const instruction &inst) assert(sizep.is_size()); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // single-to-double if (inst.size() == 8 && sizep.size() == SIZE_DWORD) { if (srcp.is_memory()) - a.cvtss2sd(dstreg, MABS(srcp.memory())); // cvtss2sd dstreg,[srcp] + emit_cvtss2sd_r128_m32(dst, dstreg, MABS(srcp.memory())); // cvtss2sd dstreg,[srcp] else if (srcp.is_float_register()) - a.cvtss2sd(dstreg, Xmm(srcp.freg())); // cvtss2sd dstreg,srcp - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_cvtss2sd_r128_r128(dst, dstreg, srcp.freg()); // cvtss2sd dstreg,srcp + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } // double-to-single else if (inst.size() == 4 && sizep.size() == SIZE_QWORD) { if (srcp.is_memory()) - a.cvtsd2ss(dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp] + emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp] else if (srcp.is_float_register()) - a.cvtsd2ss(dstreg, Xmm(srcp.freg())); // cvtsd2ss dstreg,srcp - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } } @@ -5411,7 +6355,7 @@ void drcbe_x64::op_ffrflt(Assembler &a, const instruction &inst) // op_frnds - process a FRNDS opcode //------------------------------------------------- -void drcbe_x64::op_frnds(Assembler &a, const instruction &inst) +void drcbe_x64::op_frnds(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 8); @@ -5423,15 +6367,15 @@ void drcbe_x64::op_frnds(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // 64-bit form if (srcp.is_memory()) - a.cvtsd2ss(dstreg, MABS(srcp.memory(), 8)); // cvtsd2ss dstreg,[srcp] + emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp] else if (srcp.is_float_register()) - a.cvtsd2ss(dstreg, Xmm(srcp.freg())); // cvtsd2ss dstreg,srcp - a.cvtss2sd(dstreg, dstreg); // cvtss2sd dstreg,dstreg - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp + emit_cvtss2sd_r128_r128(dst, dstreg, dstreg); // cvtss2sd dstreg,dstreg + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } @@ -5439,7 +6383,7 @@ void drcbe_x64::op_frnds(Assembler &a, const instruction &inst) // op_fadd - process a FADD opcode //------------------------------------------------- -void drcbe_x64::op_fadd(Assembler &a, const instruction &inst) +void drcbe_x64::op_fadd(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5453,28 +6397,28 @@ void drcbe_x64::op_fadd(Assembler &a, const instruction &inst) normalize_commutative(src1p, src2p); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0, src2p); + int dstreg = dstp.select_register(REG_XMM0, src2p); // 32-bit form if (inst.size() == 4) { - emit_movss_r128_p32(a, dstreg, src1p); // movss dstreg,src1p + emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p if (src2p.is_memory()) - a.addss(dstreg, MABS(src2p.memory())); // addss dstreg,[src2p] + emit_addss_r128_m32(dst, dstreg, MABS(src2p.memory())); // addss dstreg,[src2p] else if (src2p.is_float_register()) - a.addss(dstreg, Xmm(src2p.freg())); // addss dstreg,src2p - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_addss_r128_r128(dst, dstreg, src2p.freg()); // addss dstreg,src2p + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - emit_movsd_r128_p64(a, dstreg, src1p); // movsd dstreg,src1p + emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p if (src2p.is_memory()) - a.addsd(dstreg, MABS(src2p.memory())); // addsd dstreg,[src2p] + emit_addsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // addsd dstreg,[src2p] else if (src2p.is_float_register()) - a.addsd(dstreg, Xmm(src2p.freg())); // addsd dstreg,src2p - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_addsd_r128_r128(dst, dstreg, src2p.freg()); // addsd dstreg,src2p + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5483,7 +6427,7 @@ void drcbe_x64::op_fadd(Assembler &a, const instruction &inst) // op_fsub - process a FSUB opcode //------------------------------------------------- -void drcbe_x64::op_fsub(Assembler &a, const instruction &inst) +void drcbe_x64::op_fsub(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5496,28 +6440,28 @@ void drcbe_x64::op_fsub(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(2), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0, src2p); + int dstreg = dstp.select_register(REG_XMM0, src2p); // 32-bit form if (inst.size() == 4) { - emit_movss_r128_p32(a, dstreg, src1p); // movss dstreg,src1p + emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p if (src2p.is_memory()) - a.subss(dstreg, MABS(src2p.memory())); // subss dstreg,[src2p] + emit_subss_r128_m32(dst, dstreg, MABS(src2p.memory())); // subss dstreg,[src2p] else if (src2p.is_float_register()) - a.subss(dstreg, Xmm(src2p.freg())); // subss dstreg,src2p - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_subss_r128_r128(dst, dstreg, src2p.freg()); // subss dstreg,src2p + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - emit_movsd_r128_p64(a, dstreg, src1p); // movsd dstreg,src1p + emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p if (src2p.is_memory()) - a.subsd(dstreg, MABS(src2p.memory())); // subsd dstreg,[src2p] + emit_subsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // subsd dstreg,[src2p] else if (src2p.is_float_register()) - a.subsd(dstreg, Xmm(src2p.freg())); // subsd dstreg,src2p - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_subsd_r128_r128(dst, dstreg, src2p.freg()); // subsd dstreg,src2p + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5526,7 +6470,7 @@ void drcbe_x64::op_fsub(Assembler &a, const instruction &inst) // op_fcmp - process a FCMP opcode //------------------------------------------------- -void drcbe_x64::op_fcmp(Assembler &a, const instruction &inst) +void drcbe_x64::op_fcmp(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5538,26 +6482,26 @@ void drcbe_x64::op_fcmp(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm src1reg = src1p.select_register(xmm0); + int src1reg = src1p.select_register(REG_XMM0); // 32-bit form if (inst.size() == 4) { - emit_movss_r128_p32(a, src1reg, src1p); // movss src1reg,src1p + emit_movss_r128_p32(dst, src1reg, src1p); // movss src1reg,src1p if (src2p.is_memory()) - a.comiss(src1reg, MABS(src2p.memory())); // comiss src1reg,[src2p] + emit_comiss_r128_m32(dst, src1reg, MABS(src2p.memory())); // comiss src1reg,[src2p] else if (src2p.is_float_register()) - a.comiss(src1reg, Xmm(src2p.freg())); // comiss src1reg,src2p + emit_comiss_r128_r128(dst, src1reg, src2p.freg()); // comiss src1reg,src2p } // 64-bit form else if (inst.size() == 8) { - emit_movsd_r128_p64(a, src1reg, src1p); // movsd src1reg,src1p + emit_movsd_r128_p64(dst, src1reg, src1p); // movsd src1reg,src1p if (src2p.is_memory()) - a.comisd(src1reg, MABS(src2p.memory())); // comisd src1reg,[src2p] + emit_comisd_r128_m64(dst, src1reg, MABS(src2p.memory())); // comisd src1reg,[src2p] else if (src2p.is_float_register()) - a.comisd(src1reg, Xmm(src2p.freg())); // comisd src1reg,src2p + emit_comisd_r128_r128(dst, src1reg, src2p.freg()); // comisd src1reg,src2p } } @@ -5566,7 +6510,7 @@ void drcbe_x64::op_fcmp(Assembler &a, const instruction &inst) // op_fmul - process a FMUL opcode //------------------------------------------------- -void drcbe_x64::op_fmul(Assembler &a, const instruction &inst) +void drcbe_x64::op_fmul(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5580,28 +6524,28 @@ void drcbe_x64::op_fmul(Assembler &a, const instruction &inst) normalize_commutative(src1p, src2p); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0, src2p); + int dstreg = dstp.select_register(REG_XMM0, src2p); // 32-bit form if (inst.size() == 4) { - emit_movss_r128_p32(a, dstreg, src1p); // movss dstreg,src1p + emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p if (src2p.is_memory()) - a.mulss(dstreg, MABS(src2p.memory())); // mulss dstreg,[src2p] + emit_mulss_r128_m32(dst, dstreg, MABS(src2p.memory())); // mulss dstreg,[src2p] else if (src2p.is_float_register()) - a.mulss(dstreg, Xmm(src2p.freg())); // mulss dstreg,src2p - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_mulss_r128_r128(dst, dstreg, src2p.freg()); // mulss dstreg,src2p + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - emit_movsd_r128_p64(a, dstreg, src1p); // movsd dstreg,src1p + emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p if (src2p.is_memory()) - a.mulsd(dstreg, MABS(src2p.memory())); // mulsd dstreg,[src2p] + emit_mulsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // mulsd dstreg,[src2p] else if (src2p.is_float_register()) - a.mulsd(dstreg, Xmm(src2p.freg())); // mulsd dstreg,src2p - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_mulsd_r128_r128(dst, dstreg, src2p.freg()); // mulsd dstreg,src2p + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5610,7 +6554,7 @@ void drcbe_x64::op_fmul(Assembler &a, const instruction &inst) // op_fdiv - process a FDIV opcode //------------------------------------------------- -void drcbe_x64::op_fdiv(Assembler &a, const instruction &inst) +void drcbe_x64::op_fdiv(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5623,28 +6567,28 @@ void drcbe_x64::op_fdiv(Assembler &a, const instruction &inst) be_parameter src2p(*this, inst.param(2), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0, src2p); + int dstreg = dstp.select_register(REG_XMM0, src2p); // 32-bit form if (inst.size() == 4) { - emit_movss_r128_p32(a, dstreg, src1p); // movss dstreg,src1p + emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p if (src2p.is_memory()) - a.divss(dstreg, MABS(src2p.memory())); // divss dstreg,[src2p] + emit_divss_r128_m32(dst, dstreg, MABS(src2p.memory())); // divss dstreg,[src2p] else if (src2p.is_float_register()) - a.divss(dstreg, Xmm(src2p.freg())); // divss dstreg,src2p - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_divss_r128_r128(dst, dstreg, src2p.freg()); // divss dstreg,src2p + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - emit_movsd_r128_p64(a, dstreg, src1p); // movsd dstreg,src1p + emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p if (src2p.is_memory()) - a.divsd(dstreg, MABS(src2p.memory())); // divsd dstreg,[src2p] + emit_divsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // divsd dstreg,[src2p] else if (src2p.is_float_register()) - a.divsd(dstreg, Xmm(src2p.freg())); // divsd dstreg,src2p - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_divsd_r128_r128(dst, dstreg, src2p.freg()); // divsd dstreg,src2p + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5653,7 +6597,7 @@ void drcbe_x64::op_fdiv(Assembler &a, const instruction &inst) // op_fneg - process a FNEG opcode //------------------------------------------------- -void drcbe_x64::op_fneg(Assembler &a, const instruction &inst) +void drcbe_x64::op_fneg(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5665,28 +6609,28 @@ void drcbe_x64::op_fneg(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0, srcp); + int dstreg = dstp.select_register(REG_XMM0, srcp); // 32-bit form if (inst.size() == 4) { - a.xorps(dstreg, dstreg); // xorps dstreg,dstreg + emit_xorps_r128_r128(dst, dstreg, dstreg); // xorps dstreg,dstreg if (srcp.is_memory()) - a.subss(dstreg, MABS(srcp.memory())); // subss dstreg,[srcp] + emit_subss_r128_m32(dst, dstreg, MABS(srcp.memory())); // subss dstreg,[srcp] else if (srcp.is_float_register()) - a.subss(dstreg, Xmm(srcp.freg())); // subss dstreg,srcp - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_subss_r128_r128(dst, dstreg, srcp.freg()); // subss dstreg,srcp + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - a.xorpd(dstreg, dstreg); // xorpd dstreg,dstreg + emit_xorpd_r128_r128(dst, dstreg, dstreg); // xorpd dstreg,dstreg if (srcp.is_memory()) - a.subsd(dstreg, MABS(srcp.memory())); // subsd dstreg,[srcp] + emit_subsd_r128_m64(dst, dstreg, MABS(srcp.memory())); // subsd dstreg,[srcp] else if (srcp.is_float_register()) - a.subsd(dstreg, Xmm(srcp.freg())); // subsd dstreg,srcp - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_subsd_r128_r128(dst, dstreg, srcp.freg()); // subsd dstreg,srcp + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5695,7 +6639,7 @@ void drcbe_x64::op_fneg(Assembler &a, const instruction &inst) // op_fabs - process a FABS opcode //------------------------------------------------- -void drcbe_x64::op_fabs(Assembler &a, const instruction &inst) +void drcbe_x64::op_fabs(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5707,22 +6651,22 @@ void drcbe_x64::op_fabs(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0, srcp); + int dstreg = dstp.select_register(REG_XMM0, srcp); // 32-bit form if (inst.size() == 4) { - emit_movss_r128_p32(a, dstreg, srcp); // movss dstreg,srcp - a.andps(dstreg, MABS(m_absmask32)); // andps dstreg,[absmask32] - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_movss_r128_p32(dst, dstreg, srcp); // movss dstreg,srcp + emit_andps_r128_m128(dst, dstreg, MABS(m_absmask32)); // andps dstreg,[absmask32] + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { - emit_movsd_r128_p64(a, dstreg, srcp); // movsd dstreg,srcp - a.andpd(dstreg, MABS(m_absmask64)); // andpd dstreg,[absmask64] - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_movsd_r128_p64(dst, dstreg, srcp); // movsd dstreg,srcp + emit_andpd_r128_m128(dst, dstreg, MABS(m_absmask64)); // andpd dstreg,[absmask64] + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5731,7 +6675,7 @@ void drcbe_x64::op_fabs(Assembler &a, const instruction &inst) // op_fsqrt - process a FSQRT opcode //------------------------------------------------- -void drcbe_x64::op_fsqrt(Assembler &a, const instruction &inst) +void drcbe_x64::op_fsqrt(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5743,26 +6687,26 @@ void drcbe_x64::op_fsqrt(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // 32-bit form if (inst.size() == 4) { if (srcp.is_memory()) - a.sqrtss(dstreg, MABS(srcp.memory())); // sqrtss dstreg,[srcp] + emit_sqrtss_r128_m32(dst, dstreg, MABS(srcp.memory())); // sqrtss dstreg,[srcp] else if (srcp.is_float_register()) - a.sqrtss(dstreg, Xmm(srcp.freg())); // sqrtss dstreg,srcp - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_sqrtss_r128_r128(dst, dstreg, srcp.freg()); // sqrtss dstreg,srcp + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form else if (inst.size() == 8) { if (srcp.is_memory()) - a.sqrtsd(dstreg, MABS(srcp.memory())); // sqrtsd dstreg,[srcp] + emit_sqrtsd_r128_m64(dst, dstreg, MABS(srcp.memory())); // sqrtsd dstreg,[srcp] else if (srcp.is_float_register()) - a.sqrtsd(dstreg, Xmm(srcp.freg())); // sqrtsd dstreg,srcp - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_sqrtsd_r128_r128(dst, dstreg, srcp.freg()); // sqrtsd dstreg,srcp + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5771,7 +6715,7 @@ void drcbe_x64::op_fsqrt(Assembler &a, const instruction &inst) // op_frecip - process a FRECIP opcode //------------------------------------------------- -void drcbe_x64::op_frecip(Assembler &a, const instruction &inst) +void drcbe_x64::op_frecip(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5783,7 +6727,7 @@ void drcbe_x64::op_frecip(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // 32-bit form if (inst.size() == 4) @@ -5791,19 +6735,19 @@ void drcbe_x64::op_frecip(Assembler &a, const instruction &inst) if (USE_RCPSS_FOR_SINGLES) { if (srcp.is_memory()) - a.rcpss(dstreg, MABS(srcp.memory())); // rcpss dstreg,[srcp] + emit_rcpss_r128_m32(dst, dstreg, MABS(srcp.memory())); // rcpss dstreg,[srcp] else if (srcp.is_float_register()) - a.rcpss(dstreg, Xmm(srcp.freg())); // rcpss dstreg,srcp - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_rcpss_r128_r128(dst, dstreg, srcp.freg()); // rcpss dstreg,srcp + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } else { - a.movss(xmm1, MABS(&m_near.single1)); // movss xmm1,1.0 + emit_movss_r128_m32(dst, REG_XMM1, MABS(&m_near.single1)); // movss xmm1,1.0 if (srcp.is_memory()) - a.divss(xmm1, MABS(srcp.memory())); // divss xmm1,[srcp] + emit_divss_r128_m32(dst, REG_XMM1, MABS(srcp.memory())); // divss xmm1,[srcp] else if (srcp.is_float_register()) - a.divss(xmm1, Xmm(srcp.freg())); // divss xmm1,srcp - emit_movss_p32_r128(a, dstp, xmm1); // movss dstp,xmm1 + emit_divss_r128_r128(dst, REG_XMM1, srcp.freg()); // divss xmm1,srcp + emit_movss_p32_r128(dst, dstp, REG_XMM1); // movss dstp,xmm1 } } @@ -5813,21 +6757,21 @@ void drcbe_x64::op_frecip(Assembler &a, const instruction &inst) if (USE_RCPSS_FOR_DOUBLES) { if (srcp.is_memory()) - a.cvtsd2ss(dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp] + emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp] else if (srcp.is_float_register()) - a.cvtsd2ss(dstreg, Xmm(srcp.freg())); // cvtsd2ss dstreg,srcp - a.rcpss(dstreg, dstreg); // rcpss dstreg,dstreg - a.cvtss2sd(dstreg, dstreg); // cvtss2sd dstreg,dstreg - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp + emit_rcpss_r128_r128(dst, dstreg, dstreg); // rcpss dstreg,dstreg + emit_cvtss2sd_r128_r128(dst, dstreg, dstreg); // cvtss2sd dstreg,dstreg + emit_movsd_p64_r128(dst, dstp, REG_XMM1); // movsd dstp,dstreg } else { - a.movsd(xmm1, MABS(&m_near.double1)); // movsd xmm1,1.0 + emit_movsd_r128_m64(dst, REG_XMM1, MABS(&m_near.double1)); // movsd xmm1,1.0 if (srcp.is_memory()) - a.divsd(xmm1, MABS(srcp.memory())); // divsd xmm1,[srcp] + emit_divsd_r128_m64(dst, REG_XMM1, MABS(srcp.memory())); // divsd xmm1,[srcp] else if (srcp.is_float_register()) - a.divsd(xmm1, Xmm(srcp.freg())); // divsd xmm1,srcp - emit_movsd_p64_r128(a, dstp, xmm1); // movsd dstp,xmm1 + emit_divsd_r128_r128(dst, REG_XMM1, srcp.freg()); // divsd xmm1,srcp + emit_movsd_p64_r128(dst, dstp, REG_XMM1); // movsd dstp,xmm1 } } } @@ -5837,7 +6781,7 @@ void drcbe_x64::op_frecip(Assembler &a, const instruction &inst) // op_frsqrt - process a FRSQRT opcode //------------------------------------------------- -void drcbe_x64::op_frsqrt(Assembler &a, const instruction &inst) +void drcbe_x64::op_frsqrt(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5849,7 +6793,7 @@ void drcbe_x64::op_frsqrt(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MF); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // 32-bit form if (inst.size() == 4) @@ -5857,20 +6801,20 @@ void drcbe_x64::op_frsqrt(Assembler &a, const instruction &inst) if (USE_RSQRTSS_FOR_SINGLES) { if (srcp.is_memory()) - a.rsqrtss(dstreg, MABS(srcp.memory())); // rsqrtss dstreg,[srcp] + emit_rsqrtss_r128_m32(dst, dstreg, MABS(srcp.memory())); // rsqrtss dstreg,[srcp] else if (srcp.is_float_register()) - a.rsqrtss(dstreg, Xmm(srcp.freg())); // rsqrtss dstreg,srcp + emit_rsqrtss_r128_r128(dst, dstreg, srcp.freg()); // rsqrtss dstreg,srcp } else { if (srcp.is_memory()) - a.sqrtss(xmm1, MABS(srcp.memory())); // sqrtss xmm1,[srcp] + emit_sqrtss_r128_m32(dst, REG_XMM1, MABS(srcp.memory())); // sqrtss xmm1,[srcp] else if (srcp.is_float_register()) - a.sqrtss(xmm1, Xmm(srcp.freg())); // sqrtss xmm1,srcp - a.movss(dstreg, MABS(&m_near.single1)); // movss dstreg,1.0 - a.divss(dstreg, xmm1); // divss dstreg,xmm1 + emit_sqrtss_r128_r128(dst, REG_XMM1, srcp.freg()); // sqrtss xmm1,srcp + emit_movss_r128_m32(dst, dstreg, MABS(&m_near.single1)); // movss dstreg,1.0 + emit_divss_r128_r128(dst, dstreg, REG_XMM1); // divss dstreg,xmm1 } - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } // 64-bit form @@ -5879,22 +6823,22 @@ void drcbe_x64::op_frsqrt(Assembler &a, const instruction &inst) if (USE_RSQRTSS_FOR_DOUBLES) { if (srcp.is_memory()) - a.cvtsd2ss(dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp] + emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp] else if (srcp.is_float_register()) - a.cvtsd2ss(dstreg, Xmm(srcp.freg())); // cvtsd2ss dstreg,srcp - a.rsqrtss(dstreg, dstreg); // rsqrtss dstreg,dstreg - a.cvtss2sd(dstreg, dstreg); // cvtss2sd dstreg,dstreg + emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp + emit_rsqrtss_r128_r128(dst, dstreg, dstreg); // rsqrtss dstreg,dstreg + emit_cvtss2sd_r128_r128(dst, dstreg, dstreg); // cvtss2sd dstreg,dstreg } else { if (srcp.is_memory()) - a.sqrtsd(xmm1, MABS(srcp.memory())); // sqrtsd xmm1,[srcp] + emit_sqrtsd_r128_m64(dst, REG_XMM1, MABS(srcp.memory())); // sqrtsd xmm1,[srcp] else if (srcp.is_float_register()) - a.sqrtsd(xmm1, Xmm(srcp.freg())); // sqrtsd xmm1,srcp - a.movsd(dstreg, MABS(&m_near.double1)); // movsd dstreg,1.0 - a.divsd(dstreg, xmm1); // divsd dstreg,xmm1 + emit_sqrtsd_r128_r128(dst, REG_XMM1, srcp.freg()); // sqrtsd xmm1,srcp + emit_movsd_r128_m64(dst, dstreg, MABS(&m_near.double1)); // movsd dstreg,1.0 + emit_divsd_r128_r128(dst, dstreg, REG_XMM1); // divsd dstreg,xmm1 } - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5903,7 +6847,7 @@ void drcbe_x64::op_frsqrt(Assembler &a, const instruction &inst) // op_fcopyi - process a FCOPYI opcode //------------------------------------------------- -void drcbe_x64::op_fcopyi(Assembler &a, const instruction &inst) +void drcbe_x64::op_fcopyi(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5915,26 +6859,26 @@ void drcbe_x64::op_fcopyi(Assembler &a, const instruction &inst) be_parameter srcp(*this, inst.param(1), PTYPE_MR); // pick a target register for the general case - Xmm dstreg = dstp.select_register(xmm0); + int dstreg = dstp.select_register(REG_XMM0); // 32-bit form if (inst.size() == 4) { if (srcp.is_memory()) { - a.movd(dstreg, MABS(srcp.memory())); // movd dstreg,[srcp] - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_movd_r128_m32(dst, dstreg, MABS(srcp.memory())); // movd dstreg,[srcp] + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } else { if (dstp.is_memory()) { - emit_mov_p32_r32(a, dstp, Gpd(srcp.ireg())); // mov dstp,srcp + emit_mov_p32_r32(dst, dstp, srcp.ireg()); // mov dstp,srcp } else { - a.movd(dstreg, Gpd(srcp.ireg())); // movd dstreg,srcp - emit_movss_p32_r128(a, dstp, dstreg); // movss dstp,dstreg + emit_movd_r128_r32(dst, dstreg, srcp.ireg()); // movd dstreg,srcp + emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg } } @@ -5945,19 +6889,19 @@ void drcbe_x64::op_fcopyi(Assembler &a, const instruction &inst) { if (srcp.is_memory()) { - a.movq(dstreg, MABS(srcp.memory())); // movq dstreg,[srcp] - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_movq_r128_m64(dst, dstreg, MABS(srcp.memory())); // movq dstreg,[srcp] + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } else { if (dstp.is_memory()) { - emit_mov_p64_r64(a, dstp, Gpq(srcp.ireg())); // mov dstp,srcp + emit_mov_p64_r64(dst, dstp, srcp.ireg()); // mov dstp,srcp } else { - a.movq(dstreg, Gpq(srcp.ireg())); // movq dstreg,srcp - emit_movsd_p64_r128(a, dstp, dstreg); // movsd dstp,dstreg + emit_movq_r128_r64(dst, dstreg, srcp.ireg()); // movq dstreg,srcp + emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg } } @@ -5969,7 +6913,7 @@ void drcbe_x64::op_fcopyi(Assembler &a, const instruction &inst) // op_icopyf - process a ICOPYF opcode //------------------------------------------------- -void drcbe_x64::op_icopyf(Assembler &a, const instruction &inst) +void drcbe_x64::op_icopyf(x86code *&dst, const instruction &inst) { // validate instruction assert(inst.size() == 4 || inst.size() == 8); @@ -5985,19 +6929,19 @@ void drcbe_x64::op_icopyf(Assembler &a, const instruction &inst) { if (srcp.is_memory()) { - Gp dstreg = dstp.select_register(eax); - a.mov(dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] - emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg + int dstreg = dstp.select_register(REG_EAX); + emit_mov_r32_m32(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] + emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg } else { if (dstp.is_memory()) { - a.movd(MABS(dstp.memory()), Xmm(srcp.freg())); // movd dstp,srcp + emit_movd_m32_r128(dst, MABS(dstp.memory()), srcp.freg()); // movd dstp,srcp } else { - a.movd(Gpd(dstp.ireg()), Xmm(srcp.freg())); // movd dstp,srcp + emit_movd_r32_r128(dst, dstp.ireg(), srcp.freg()); // movd dstp,srcp } } } @@ -6007,19 +6951,19 @@ void drcbe_x64::op_icopyf(Assembler &a, const instruction &inst) { if (srcp.is_memory()) { - Gp dstreg = dstp.select_register(rax); - a.mov(dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] - emit_mov_p64_r64(a, dstp, dstreg); // mov dstp,dstreg + int dstreg = dstp.select_register(REG_RAX); + emit_mov_r64_m64(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp] + emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg } else { if (dstp.is_memory()) { - a.movq(MABS(dstp.memory()), Xmm(srcp.freg())); // movq dstp,srcp + emit_movq_m64_r128(dst, MABS(dstp.memory()), srcp.freg()); // movq dstp,srcp } else { - a.movq(Gpq(dstp.ireg()), Xmm(srcp.freg())); // movq dstp,srcp + emit_movq_r64_r128(dst, dstp.ireg(), srcp.freg()); // movq dstp,srcp } } } diff --git a/src/devices/cpu/drcbex64.h b/src/devices/cpu/drcbex64.h index a414ebd590a..d996c5db8c7 100644 --- a/src/devices/cpu/drcbex64.h +++ b/src/devices/cpu/drcbex64.h @@ -17,10 +17,9 @@ #include "drcbeut.h" #include "x86log.h" -#include "asmjit/src/asmjit/asmjit.h" +#define X86EMIT_SIZE 64 +#include "x86emit.h" -using namespace asmjit; -using namespace asmjit::x86; namespace drc { //************************************************************************** @@ -49,9 +48,6 @@ private: class be_parameter { public: - // HACK: leftover from x86emit - static int const REG_MAX = 16; - // parameter types enum be_parameter_type { @@ -74,8 +70,9 @@ private: be_parameter(drcbe_x64 &drcbe, const uml::parameter ¶m, uint32_t allowed); // creators for types that don't safely default - static inline be_parameter make_ireg(int regnum) { assert(regnum >= 0 && regnum < REG_MAX); return be_parameter(PTYPE_INT_REGISTER, regnum); } - static inline be_parameter make_freg(int regnum) { assert(regnum >= 0 && regnum < REG_MAX); return be_parameter(PTYPE_FLOAT_REGISTER, regnum); } + static inline be_parameter make_ireg(int regnum) { assert(regnum >= 0 && regnum < x64emit::REG_MAX); return be_parameter(PTYPE_INT_REGISTER, regnum); } + static inline be_parameter make_freg(int regnum) { assert(regnum >= 0 && regnum < x64emit::REG_MAX); return be_parameter(PTYPE_FLOAT_REGISTER, regnum); } + static inline be_parameter make_vreg(int regnum) { assert(regnum >= 0 && regnum < x64emit::REG_MAX); return be_parameter(PTYPE_VECTOR_REGISTER, regnum); } static inline be_parameter make_memory(void *base) { return be_parameter(PTYPE_MEMORY, reinterpret_cast<be_parameter_value>(base)); } static inline be_parameter make_memory(const void *base) { return be_parameter(PTYPE_MEMORY, reinterpret_cast<be_parameter_value>(const_cast<void *>(base))); } @@ -86,24 +83,25 @@ private: // getters be_parameter_type type() const { return m_type; } uint64_t immediate() const { assert(m_type == PTYPE_IMMEDIATE); return m_value; } - uint32_t ireg() const { assert(m_type == PTYPE_INT_REGISTER); assert(m_value < REG_MAX); return m_value; } - uint32_t freg() const { assert(m_type == PTYPE_FLOAT_REGISTER); assert(m_value < REG_MAX); return m_value; } + int ireg() const { assert(m_type == PTYPE_INT_REGISTER); assert(m_value < x64emit::REG_MAX); return m_value; } + int freg() const { assert(m_type == PTYPE_FLOAT_REGISTER); assert(m_value < x64emit::REG_MAX); return m_value; } + int vreg() const { assert(m_type == PTYPE_VECTOR_REGISTER); assert(m_value < x64emit::REG_MAX); return m_value; } void *memory() const { assert(m_type == PTYPE_MEMORY); return reinterpret_cast<void *>(m_value); } // type queries bool is_immediate() const { return (m_type == PTYPE_IMMEDIATE); } bool is_int_register() const { return (m_type == PTYPE_INT_REGISTER); } bool is_float_register() const { return (m_type == PTYPE_FLOAT_REGISTER); } + bool is_vector_register() const { return (m_type == PTYPE_VECTOR_REGISTER); } bool is_memory() const { return (m_type == PTYPE_MEMORY); } // other queries bool is_immediate_value(uint64_t value) const { return (m_type == PTYPE_IMMEDIATE && m_value == value); } // helpers - Gp select_register(Gp defreg) const; - Xmm select_register(Xmm defreg) const; - template <typename T> T select_register(T defreg, const be_parameter &checkparam) const; - template <typename T> T select_register(T defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const; + int select_register(int defreg) const; + int select_register(int defreg, const be_parameter &checkparam) const; + int select_register(int defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const; private: // private constructor @@ -115,160 +113,192 @@ private: }; // helpers - Mem MABS(const void *ptr, const uint32_t size = 0); + x86_memref MABS(const void *ptr); bool short_immediate(int64_t immediate) const { return (int32_t)immediate == immediate; } void normalize_commutative(be_parameter &inner, be_parameter &outer); int32_t offset_from_rbp(const void *ptr); - Gp get_base_register_and_offset(Assembler &a, void *target, Gp reg, int32_t &offset); - void emit_smart_call_r64(Assembler &a, x86code *target, Gp reg); - void emit_smart_call_m64(Assembler &a, x86code **target); + int get_base_register_and_offset(x86code *&dst, void *target, uint8_t reg, int32_t &offset); + void emit_smart_call_r64(x86code *&dst, x86code *target, uint8_t reg); + void emit_smart_call_m64(x86code *&dst, x86code **target); + + void fixup_label(void *parameter, drccodeptr labelcodeptr); + void fixup_exception(drccodeptr *codeptr, void *param1, void *param2); static void debug_log_hashjmp(offs_t pc, int mode); static void debug_log_hashjmp_fail(); // code generators - void op_handle(Assembler &a, const uml::instruction &inst); - void op_hash(Assembler &a, const uml::instruction &inst); - void op_label(Assembler &a, const uml::instruction &inst); - void op_comment(Assembler &a, const uml::instruction &inst); - void op_mapvar(Assembler &a, const uml::instruction &inst); - - void op_nop(Assembler &a, const uml::instruction &inst); - void op_debug(Assembler &a, const uml::instruction &inst); - void op_exit(Assembler &a, const uml::instruction &inst); - void op_hashjmp(Assembler &a, const uml::instruction &inst); - void op_jmp(Assembler &a, const uml::instruction &inst); - void op_exh(Assembler &a, const uml::instruction &inst); - void op_callh(Assembler &a, const uml::instruction &inst); - void op_ret(Assembler &a, const uml::instruction &inst); - void op_callc(Assembler &a, const uml::instruction &inst); - void op_recover(Assembler &a, const uml::instruction &inst); - - void op_setfmod(Assembler &a, const uml::instruction &inst); - void op_getfmod(Assembler &a, const uml::instruction &inst); - void op_getexp(Assembler &a, const uml::instruction &inst); - void op_getflgs(Assembler &a, const uml::instruction &inst); - void op_save(Assembler &a, const uml::instruction &inst); - void op_restore(Assembler &a, const uml::instruction &inst); - - void op_load(Assembler &a, const uml::instruction &inst); - void op_loads(Assembler &a, const uml::instruction &inst); - void op_store(Assembler &a, const uml::instruction &inst); - void op_read(Assembler &a, const uml::instruction &inst); - void op_readm(Assembler &a, const uml::instruction &inst); - void op_write(Assembler &a, const uml::instruction &inst); - void op_writem(Assembler &a, const uml::instruction &inst); - void op_carry(Assembler &a, const uml::instruction &inst); - void op_set(Assembler &a, const uml::instruction &inst); - void op_mov(Assembler &a, const uml::instruction &inst); - void op_sext(Assembler &a, const uml::instruction &inst); - void op_roland(Assembler &a, const uml::instruction &inst); - void op_rolins(Assembler &a, const uml::instruction &inst); - void op_add(Assembler &a, const uml::instruction &inst); - void op_addc(Assembler &a, const uml::instruction &inst); - void op_sub(Assembler &a, const uml::instruction &inst); - void op_subc(Assembler &a, const uml::instruction &inst); - void op_cmp(Assembler &a, const uml::instruction &inst); - void op_mulu(Assembler &a, const uml::instruction &inst); - void op_muls(Assembler &a, const uml::instruction &inst); - void op_divu(Assembler &a, const uml::instruction &inst); - void op_divs(Assembler &a, const uml::instruction &inst); - void op_and(Assembler &a, const uml::instruction &inst); - void op_test(Assembler &a, const uml::instruction &inst); - void op_or(Assembler &a, const uml::instruction &inst); - void op_xor(Assembler &a, const uml::instruction &inst); - void op_lzcnt(Assembler &a, const uml::instruction &inst); - void op_tzcnt(Assembler &a, const uml::instruction &inst); - void op_bswap(Assembler &a, const uml::instruction &inst); - template <Inst::Id Opcode> void op_shift(Assembler &a, const uml::instruction &inst); - - void op_fload(Assembler &a, const uml::instruction &inst); - void op_fstore(Assembler &a, const uml::instruction &inst); - void op_fread(Assembler &a, const uml::instruction &inst); - void op_fwrite(Assembler &a, const uml::instruction &inst); - void op_fmov(Assembler &a, const uml::instruction &inst); - void op_ftoint(Assembler &a, const uml::instruction &inst); - void op_ffrint(Assembler &a, const uml::instruction &inst); - void op_ffrflt(Assembler &a, const uml::instruction &inst); - void op_frnds(Assembler &a, const uml::instruction &inst); - void op_fadd(Assembler &a, const uml::instruction &inst); - void op_fsub(Assembler &a, const uml::instruction &inst); - void op_fcmp(Assembler &a, const uml::instruction &inst); - void op_fmul(Assembler &a, const uml::instruction &inst); - void op_fdiv(Assembler &a, const uml::instruction &inst); - void op_fneg(Assembler &a, const uml::instruction &inst); - void op_fabs(Assembler &a, const uml::instruction &inst); - void op_fsqrt(Assembler &a, const uml::instruction &inst); - void op_frecip(Assembler &a, const uml::instruction &inst); - void op_frsqrt(Assembler &a, const uml::instruction &inst); - void op_fcopyi(Assembler &a, const uml::instruction &inst); - void op_icopyf(Assembler &a, const uml::instruction &inst); + void op_handle(x86code *&dst, const uml::instruction &inst); + void op_hash(x86code *&dst, const uml::instruction &inst); + void op_label(x86code *&dst, const uml::instruction &inst); + void op_comment(x86code *&dst, const uml::instruction &inst); + void op_mapvar(x86code *&dst, const uml::instruction &inst); + + void op_nop(x86code *&dst, const uml::instruction &inst); + void op_debug(x86code *&dst, const uml::instruction &inst); + void op_exit(x86code *&dst, const uml::instruction &inst); + void op_hashjmp(x86code *&dst, const uml::instruction &inst); + void op_jmp(x86code *&dst, const uml::instruction &inst); + void op_exh(x86code *&dst, const uml::instruction &inst); + void op_callh(x86code *&dst, const uml::instruction &inst); + void op_ret(x86code *&dst, const uml::instruction &inst); + void op_callc(x86code *&dst, const uml::instruction &inst); + void op_recover(x86code *&dst, const uml::instruction &inst); + + void op_setfmod(x86code *&dst, const uml::instruction &inst); + void op_getfmod(x86code *&dst, const uml::instruction &inst); + void op_getexp(x86code *&dst, const uml::instruction &inst); + void op_getflgs(x86code *&dst, const uml::instruction &inst); + void op_save(x86code *&dst, const uml::instruction &inst); + void op_restore(x86code *&dst, const uml::instruction &inst); + + void op_load(x86code *&dst, const uml::instruction &inst); + void op_loads(x86code *&dst, const uml::instruction &inst); + void op_store(x86code *&dst, const uml::instruction &inst); + void op_read(x86code *&dst, const uml::instruction &inst); + void op_readm(x86code *&dst, const uml::instruction &inst); + void op_write(x86code *&dst, const uml::instruction &inst); + void op_writem(x86code *&dst, const uml::instruction &inst); + void op_carry(x86code *&dst, const uml::instruction &inst); + void op_set(x86code *&dst, const uml::instruction &inst); + void op_mov(x86code *&dst, const uml::instruction &inst); + void op_sext(x86code *&dst, const uml::instruction &inst); + void op_roland(x86code *&dst, const uml::instruction &inst); + void op_rolins(x86code *&dst, const uml::instruction &inst); + void op_add(x86code *&dst, const uml::instruction &inst); + void op_addc(x86code *&dst, const uml::instruction &inst); + void op_sub(x86code *&dst, const uml::instruction &inst); + void op_subc(x86code *&dst, const uml::instruction &inst); + void op_cmp(x86code *&dst, const uml::instruction &inst); + void op_mulu(x86code *&dst, const uml::instruction &inst); + void op_muls(x86code *&dst, const uml::instruction &inst); + void op_divu(x86code *&dst, const uml::instruction &inst); + void op_divs(x86code *&dst, const uml::instruction &inst); + void op_and(x86code *&dst, const uml::instruction &inst); + void op_test(x86code *&dst, const uml::instruction &inst); + void op_or(x86code *&dst, const uml::instruction &inst); + void op_xor(x86code *&dst, const uml::instruction &inst); + void op_lzcnt(x86code *&dst, const uml::instruction &inst); + void op_tzcnt(x86code *&dst, const uml::instruction &inst); + void op_bswap(x86code *&dst, const uml::instruction &inst); + void op_shl(x86code *&dst, const uml::instruction &inst); + void op_shr(x86code *&dst, const uml::instruction &inst); + void op_sar(x86code *&dst, const uml::instruction &inst); + void op_ror(x86code *&dst, const uml::instruction &inst); + void op_rol(x86code *&dst, const uml::instruction &inst); + void op_rorc(x86code *&dst, const uml::instruction &inst); + void op_rolc(x86code *&dst, const uml::instruction &inst); + + void op_fload(x86code *&dst, const uml::instruction &inst); + void op_fstore(x86code *&dst, const uml::instruction &inst); + void op_fread(x86code *&dst, const uml::instruction &inst); + void op_fwrite(x86code *&dst, const uml::instruction &inst); + void op_fmov(x86code *&dst, const uml::instruction &inst); + void op_ftoint(x86code *&dst, const uml::instruction &inst); + void op_ffrint(x86code *&dst, const uml::instruction &inst); + void op_ffrflt(x86code *&dst, const uml::instruction &inst); + void op_frnds(x86code *&dst, const uml::instruction &inst); + void op_fadd(x86code *&dst, const uml::instruction &inst); + void op_fsub(x86code *&dst, const uml::instruction &inst); + void op_fcmp(x86code *&dst, const uml::instruction &inst); + void op_fmul(x86code *&dst, const uml::instruction &inst); + void op_fdiv(x86code *&dst, const uml::instruction &inst); + void op_fneg(x86code *&dst, const uml::instruction &inst); + void op_fabs(x86code *&dst, const uml::instruction &inst); + void op_fsqrt(x86code *&dst, const uml::instruction &inst); + void op_frecip(x86code *&dst, const uml::instruction &inst); + void op_frsqrt(x86code *&dst, const uml::instruction &inst); + void op_fcopyi(x86code *&dst, const uml::instruction &inst); + void op_icopyf(x86code *&dst, const uml::instruction &inst); // 32-bit code emission helpers - void emit_mov_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m); - void emit_movsx_r64_p32(Assembler &a, Gp reg, const be_parameter ¶m); - void emit_mov_r32_p32_keepflags(Assembler &a, Gp reg, const be_parameter ¶m); - void emit_mov_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m); - void emit_mov_p32_r32(Assembler &a, const be_parameter ¶m, Gp reg); - void emit_add_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_add_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_adc_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_adc_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_sub_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_sub_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_sbb_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_sbb_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_cmp_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_cmp_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_and_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_and_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_test_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_test_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_or_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_or_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_xor_r32_p32(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_xor_m32_p32(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_shift_p32(Assembler &a, const Inst::Id opcode, Operand op1, const be_parameter ¶m); + void emit_mov_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m); + void emit_movsx_r64_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m); + void emit_mov_r32_p32_keepflags(x86code *&dst, uint8_t reg, const be_parameter ¶m); + void emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m); + void emit_mov_p32_r32(x86code *&dst, const be_parameter ¶m, uint8_t reg); + void emit_add_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_adc_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_sub_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_sbb_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_cmp_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_and_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_test_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_or_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_or_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_xor_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_shl_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_shl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_shr_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_shr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_sar_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_sar_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_rol_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_rol_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_ror_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_ror_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcl_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcr_r32_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); // 64-bit code emission helpers - void emit_mov_r64_imm(Assembler &a, Gp reg, uint64_t imm); - void emit_mov_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m); - void emit_mov_r64_p64_keepflags(Assembler &a, Gp reg, const be_parameter ¶m); - void emit_mov_p64_r64(Assembler &a, const be_parameter ¶m, Gp reg); - void emit_add_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_add_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_adc_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_adc_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_sub_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_sub_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_sbb_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_sbb_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_cmp_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_cmp_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_and_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_and_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_test_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_test_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_or_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_or_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_xor_r64_p64(Assembler &a, Gp reg, const be_parameter ¶m, const uml::instruction &inst); - void emit_xor_m64_p64(Assembler &a, Mem memref, const be_parameter ¶m, const uml::instruction &inst); - void emit_shift_p64(Assembler &a, const Inst::Id opcode, Operand op1, const be_parameter ¶m); + void emit_mov_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m); + void emit_mov_r64_p64_keepflags(x86code *&dst, uint8_t reg, const be_parameter ¶m); + void emit_mov_p64_r64(x86code *&dst, const be_parameter ¶m, uint8_t reg); + void emit_add_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_adc_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_sub_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_sbb_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_cmp_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_cmp_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_and_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_test_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_or_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_or_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_xor_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_xor_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_shl_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_shl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_shr_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_shr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_sar_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_sar_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_rol_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_rol_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_ror_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_ror_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcl_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcr_r64_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m, const uml::instruction &inst); + void emit_rcr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const uml::instruction &inst); // floating-point code emission helpers - void emit_movss_r128_p32(Assembler &a, Xmm reg, const be_parameter ¶m); - void emit_movss_p32_r128(Assembler &a, const be_parameter ¶m, Xmm reg); - void emit_movsd_r128_p64(Assembler &a, Xmm reg, const be_parameter ¶m); - void emit_movsd_p64_r128(Assembler &a, const be_parameter ¶m, Xmm reg); - - size_t emit(CodeHolder &ch); + void emit_movss_r128_p32(x86code *&dst, uint8_t reg, const be_parameter ¶m); + void emit_movss_p32_r128(x86code *&dst, const be_parameter ¶m, uint8_t reg); + void emit_movsd_r128_p64(x86code *&dst, uint8_t reg, const be_parameter ¶m); + void emit_movsd_p64_r128(x86code *&dst, const be_parameter ¶m, uint8_t reg); // internal state drc_hash_table m_hash; // hash table state drc_map_variables m_map; // code map drc_label_list m_labels; // label list x86log_context * m_log; // logging - FILE * m_log_asmjit; + bool m_sse41; // do we have SSE4.1 support? uint32_t * m_absmask32; // absolute value mask (32-bit) uint64_t * m_absmask64; // absolute value mask (32-bit) @@ -278,6 +308,9 @@ private: x86code * m_exit; // exit point x86code * m_nocode; // nocode handler + drc_label_fixup_delegate m_fixup_label; // precomputed delegate for fixups + drc_oob_delegate m_fixup_exception; // precomputed delegate for exception fixups + // state to live in the near cache struct near_state { @@ -301,7 +334,7 @@ private: near_state & m_near; // globals - typedef void (drcbe_x64::*opcode_generate_func)(Assembler &a, const uml::instruction &inst); + typedef void (drcbe_x64::*opcode_generate_func)(x86code *&dst, const uml::instruction &inst); struct opcode_table_entry { uml::opcode_t opcode; // opcode in question @@ -315,13 +348,5 @@ private: using drc::drcbe_x64; -class ThrowableErrorHandler : public ErrorHandler -{ -public: - void handleError(Error err, const char *message, BaseEmitter *origin) override - { - throw emu_fatalerror("asmjit error %d: %s", err, message); - } -}; #endif /* MAME_DEVICES_CPU_DRCBEX64_H */ diff --git a/src/devices/cpu/gigatron/gigatron.cpp b/src/devices/cpu/gigatron/gigatron.cpp index 6c25f4abd52..78e3a19afb2 100644 --- a/src/devices/cpu/gigatron/gigatron.cpp +++ b/src/devices/cpu/gigatron/gigatron.cpp @@ -13,7 +13,7 @@ #include "gigatrondasm.h" -DEFINE_DEVICE_TYPE(GTRON, gigatron_cpu_device, "gigatron_cpu", "Gigatron CPU") +DEFINE_DEVICE_TYPE(GTRON, gigatron_cpu_device, "gigatron_cpu", "Gigatron") /* FLAGS */ @@ -24,7 +24,6 @@ DEFINE_DEVICE_TYPE(GTRON, gigatron_cpu_device, "gigatron_cpu", "Gigatron CPU") #define C 0x10 #endif - #define gigatron_readop(A) m_program->read_word(A) #define gigatron_readmem16(A) m_data->read_dword(A) #define gigatron_readmem8(A) m_data->read_byte(A) @@ -52,7 +51,8 @@ void gigatron_cpu_device::execute_run() debugger_instruction_hook(m_pc); opcode = gigatron_readop(m_pc); - m_pc = m_npc++; + m_pc = m_npc; + m_npc = (m_pc + 1) & m_romMask; uint8_t op = (opcode >> 13) & 0x0007; uint8_t mode = (opcode >> 10) & 0x0007; @@ -98,7 +98,7 @@ void gigatron_cpu_device::init() m_x = 0; m_y = 0; m_pc = 0; - m_npc = (m_pc + 1); + m_npc = (m_pc + 1) & m_romMask; m_ppc = 0; m_inReg = 0xFF; @@ -109,6 +109,7 @@ void gigatron_cpu_device::init() state_add(GTRON_AC, "AC", m_ac); state_add(GTRON_X, "X", m_x); state_add(GTRON_Y, "Y", m_y); + state_add(GTRON_IREG, "IREG", m_inReg); set_icountptr(m_icount); @@ -121,6 +122,7 @@ void gigatron_cpu_device::init() save_item(NAME(m_pc)); m_outx_cb.resolve_safe(); + m_ir_cb.resolve_safe(0); } void gigatron_cpu_device::branchOp(uint8_t op, uint8_t mode, uint8_t bus, uint8_t d) @@ -131,29 +133,29 @@ void gigatron_cpu_device::branchOp(uint8_t op, uint8_t mode, uint8_t bus, uint8_ uint16_t base = m_pc & 0xff00; switch (mode) { - case 0: + case 0: //jmp c = true; base = m_y << 8; break; - case 1: + case 1: //bgt c = (ac2 > ZERO); break; - case 2: + case 2: //blt c = (ac2 < ZERO); break; - case 3: + case 3: //bne c = (ac2 != ZERO); break; - case 4: + case 4: //beq c = (ac2 == ZERO); break; - case 5: + case 5: //bge c = (ac2 >= ZERO); break; - case 6: + case 6: //ble c = (ac2 <= ZERO); break; - case 7: + case 7: //bra c = true; break; } @@ -219,7 +221,10 @@ void gigatron_cpu_device::aluOp(uint8_t op, uint8_t mode, uint8_t bus, uint8_t d case 7: uint16_t rising = ~(m_out & b); if (rising & 0x40) + { m_outx = m_ac; + m_outx_cb(0, m_outx, 0xFF); + } break; } } @@ -313,10 +318,12 @@ void gigatron_cpu_device::execute_set_input(int irqline, int state) gigatron_cpu_device::gigatron_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, GTRON, tag, owner, clock) - , m_ramMask(0x7fff) + , m_ramMask(0x7FFF) + , m_romMask(0xFFFF) , m_program_config("program", ENDIANNESS_BIG, 16, 14, -1) , m_data_config("data", ENDIANNESS_BIG, 8, 15, 0) , m_outx_cb(*this) + , m_ir_cb(*this) { } diff --git a/src/devices/cpu/gigatron/gigatron.h b/src/devices/cpu/gigatron/gigatron.h index 6cc1173d23c..50f359af21f 100644 --- a/src/devices/cpu/gigatron/gigatron.h +++ b/src/devices/cpu/gigatron/gigatron.h @@ -16,7 +16,7 @@ enum { GTRON_PC, GTRON_NPC, - GTRON_AC, GTRON_X, GTRON_Y + GTRON_AC, GTRON_X, GTRON_Y, GTRON_IREG }; @@ -26,6 +26,7 @@ public: // construction/destruction gigatron_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto outx_cb() { return m_outx_cb.bind(); } + auto ir_cb() { return m_ir_cb.bind(); } protected: // device-level overrides @@ -61,6 +62,7 @@ protected: uint16_t m_ppc; uint8_t m_inReg; uint16_t m_ramMask; + uint16_t m_romMask; uint16_t m_out; uint16_t m_outx; @@ -79,6 +81,7 @@ private: void gigatron_illegal(); devcb_write8 m_outx_cb; + devcb_read8 m_ir_cb; }; diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index 56d25c5f73a..34bb1a86741 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -5044,11 +5044,6 @@ void r5900le_device::handle_sdc2(uint32_t op) } } -void mips3_device::burn_cycles(int32_t cycles) -{ - execute_burn(cycles); -} - #if ENABLE_O2_DPRINTF #include "o2dprintf.hxx" #endif diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index 9a6be2c98f6..9478f6b39c7 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -310,7 +310,6 @@ public: void clear_fastram(uint32_t select_start); void mips3drc_set_options(uint32_t options); void mips3drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles); - void burn_cycles(int32_t cycles); protected: // device-level overrides @@ -324,7 +323,6 @@ protected: virtual uint32_t execute_input_lines() const noexcept override { return 6; } virtual void execute_run() override; virtual void execute_set_input(int inputnum, int state) override; - virtual void execute_burn(int32_t cycles) override { m_totalcycles += cycles; } // device_memory_interface overrides virtual space_config_vector memory_space_config() const override; diff --git a/src/devices/cpu/tlcs900/900tbl.hxx b/src/devices/cpu/tlcs900/900tbl.hxx index b6c2466655f..44099216fb9 100644 --- a/src/devices/cpu/tlcs900/900tbl.hxx +++ b/src/devices/cpu/tlcs900/900tbl.hxx @@ -2569,7 +2569,7 @@ void tlcs900_device::op_LINK() void tlcs900_device::op_MAX() { - m_sr.b.h |= 0x04; + m_sr.b.h |= 0x08; } diff --git a/src/devices/cpu/tlcs900/tmp96c141.cpp b/src/devices/cpu/tlcs900/tmp96c141.cpp new file mode 100644 index 00000000000..b5e64be8da3 --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp96c141.cpp @@ -0,0 +1,197 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/**************************************************************************** + + Toshiba TMP96C141 microcontroller + + TMP96CM40 is the same as TMP96C141 with the addition of 32K of on-chip + ROM. TMP96PM40 is similar but with 32K OTP. TMP96C041 is RAMless as well + as ROMless. + +****************************************************************************/ + +#include "emu.h" +#include "tmp96c141.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(TMP96C141, tmp96c141_device, "tmp96c141", "Toshiba TMP96C141") + + +//************************************************************************** +// DEVICE CONSTRUCTION AND INITIALIZATION +//************************************************************************** + +//------------------------------------------------- +// tmp96c141_device - constructor +//------------------------------------------------- + +tmp96c141_device::tmp96c141_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : tlcs900_device(mconfig, TMP96C141, tag, owner, clock) +{ +} + + +//------------------------------------------------- +// device_config_complete - device-specific startup +//------------------------------------------------- + +void tmp96c141_device::device_config_complete() +{ + if (m_am8_16 == 0) + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(tmp96c141_device::internal_mem), this)); + else + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor(FUNC(tmp96c141_device::internal_mem), this)); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void tmp96c141_device::device_start() +{ + tlcs900_device::device_start(); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void tmp96c141_device::device_reset() +{ + tlcs900_device::device_reset(); +} + + +//************************************************************************** +// INTERNAL REGISTERS +//************************************************************************** + +//------------------------------------------------- +// internal_mem - memory map for internal RAM and +// I/O registers +//------------------------------------------------- + +void tmp96c141_device::internal_mem(address_map &map) +{ + map(0x000000, 0x00007f).unmaprw(); + //map(0x000000, 0x000000).rw(FUNC(tmp96c141_device::p0_r), FUNC(tmp96c141_device::p0_w)); + //map(0x000001, 0x000001).rw(FUNC(tmp96c141_device::p1_r), FUNC(tmp96c141_device::p1_w)); + //map(0x000002, 0x000002).w(FUNC(tmp96c141_device::p0cr_w)); + //map(0x000004, 0x000004).w(FUNC(tmp96c141_device::p1cr_w)); + //map(0x000005, 0x000005).w(FUNC(tmp96c141_device::p1fc_w)); + //map(0x000006, 0x000006).rw(FUNC(tmp96c141_device::p2_r), FUNC(tmp96c141_device::p2_w)); + //map(0x000007, 0x000007).rw(FUNC(tmp96c141_device::p3_r), FUNC(tmp96c141_device::p3_w)); + //map(0x000008, 0x000008).w(FUNC(tmp96c141_device::p2cr_w)); + //map(0x000009, 0x000009).w(FUNC(tmp96c141_device::p2fc_w)); + //map(0x00000a, 0x00000a).w(FUNC(tmp96c141_device::p3cr_w)); + //map(0x00000b, 0x00000b).w(FUNC(tmp96c141_device::p3fc_w)); + //map(0x00000c, 0x00000c).rw(FUNC(tmp96c141_device::p4_r), FUNC(tmp96c141_device::p4_w)); + //map(0x00000d, 0x00000d).r(FUNC(tmp96c141_device::p5_r)); + //map(0x00000e, 0x00000e).w(FUNC(tmp96c141_device::p4cr_w)); + //map(0x000010, 0x000010).w(FUNC(tmp96c141_device::p4fc_w)); + //map(0x000012, 0x000012).rw(FUNC(tmp96c141_device::p6_r), FUNC(tmp96c141_device::p6_w)); + //map(0x000013, 0x000013).rw(FUNC(tmp96c141_device::p7_r), FUNC(tmp96c141_device::p7_w)); + //map(0x000014, 0x000014).w(FUNC(tmp96c141_device::p6cr_w)); + //map(0x000015, 0x000015).w(FUNC(tmp96c141_device::p6fc_w)); + //map(0x000016, 0x000016).w(FUNC(tmp96c141_device::p7cr_w)); + //map(0x000017, 0x000017).w(FUNC(tmp96c141_device::p7fc_w)); + //map(0x000018, 0x000018).rw(FUNC(tmp96c141_device::p8_r), FUNC(tmp96c141_device::p8_w)); + //map(0x000019, 0x000019).rw(FUNC(tmp96c141_device::p9_r), FUNC(tmp96c141_device::p9_w)); + //map(0x00001a, 0x00001a).w(FUNC(tmp96c141_device::p8cr_w)); + //map(0x00001b, 0x00001b).w(FUNC(tmp96c141_device::p8fc_w)); + //map(0x00001c, 0x00001c).w(FUNC(tmp96c141_device::p9cr_w)); + //map(0x00001d, 0x00001d).w(FUNC(tmp96c141_device::p9fc_w)); + //map(0x000020, 0x000020).rw(FUNC(tmp96c141_device::trun_r), FUNC(tmp96c141_device::trun_w)); + //map(0x000022, 0x000023).w(FUNC(tmp96c141_device::treg01_w)); + //map(0x000024, 0x000024).w(FUNC(tmp96c141_device::tmod_w)); + //map(0x000025, 0x000025).rw(FUNC(tmp96c141_device::tffcr_r), FUNC(tmp96c141_device::tffcr_w)); + //map(0x000026, 0x000027).rw(FUNC(tmp96c141_device::treg23_r), FUNC(tmp96c141_device::treg23_w)); + //map(0x000028, 0x000029).rw(FUNC(tmp96c141_device::pwmod_r), FUNC(tmp96c141_device::pwmod_w)); + //map(0x00002a, 0x00002a).rw(FUNC(tmp96c141_device::pffcr_r), FUNC(tmp96c141_device::pffcr_w)); + //map(0x000030, 0x000033).w(FUNC(tmp96c141_device::treg45_w)); + //map(0x000034, 0x000037).r(FUNC(tmp96c141_device::cap12_r)); + //map(0x000038, 0x000038).rw(FUNC(tmp96c141_device::t4mod_r), FUNC(tmp96c141_device::t4mod_w)); + //map(0x000039, 0x000039).rw(FUNC(tmp96c141_device::t4ffcr_r), FUNC(tmp96c141_device::t4ffcr_w)); + //map(0x00003a, 0x00003a).rw(FUNC(tmp96c141_device::t45cr_r), FUNC(tmp96c141_device::t45cr_w)); + //map(0x000040, 0x000043).w(FUNC(tmp96c141_device::treg67_w)); + //map(0x000044, 0x000047).r(FUNC(tmp96c141_device::cap34_r)); + //map(0x000048, 0x000048).rw(FUNC(tmp96c141_device::t5mod_r), FUNC(tmp96c141_device::t5mod_w)); + //map(0x000049, 0x000049).rw(FUNC(tmp96c141_device::t5ffcr_r), FUNC(tmp96c141_device::t5ffcr_w)); + //map(0x00004c, 0x00004d).rw(FUNC(tmp96c141_device::pgreg_r), FUNC(tmp96c141_device::pgreg_w)); + //map(0x00004e, 0x00004e).rw(FUNC(tmp96c141_device::pg01cr_r), FUNC(tmp96c141_device::pg01cr_w)); + //map(0x000050, 0x000050).rw(FUNC(tmp96c141_device::sc0buf_r), FUNC(tmp96c141_device::sc0buf_w)); + //map(0x000051, 0x000051).rw(FUNC(tmp96c141_device::sc0cr_r), FUNC(tmp96c141_device::sc0cr_w)); + //map(0x000052, 0x000052).rw(FUNC(tmp96c141_device::sc0mod_r), FUNC(tmp96c141_device::sc0mod_w)); + //map(0x000053, 0x000053).rw(FUNC(tmp96c141_device::br0cr_r), FUNC(tmp96c141_device::br0cr_w)); + //map(0x000054, 0x000054).rw(FUNC(tmp96c141_device::sc1buf_r), FUNC(tmp96c141_device::sc1buf_w)); + //map(0x000055, 0x000055).rw(FUNC(tmp96c141_device::sc1cr_r), FUNC(tmp96c141_device::sc1cr_w)); + //map(0x000056, 0x000056).rw(FUNC(tmp96c141_device::sc1mod_r), FUNC(tmp96c141_device::sc1mod_w)); + //map(0x000057, 0x000057).rw(FUNC(tmp96c141_device::br1cr_r), FUNC(tmp96c141_device::br1cr_w)); + //map(0x000058, 0x000058).rw(FUNC(tmp96c141_device::ode_r), FUNC(tmp96c141_device::ode_w)); + //map(0x00005c, 0x00005c).rw(FUNC(tmp96c141_device::wdmod_r), FUNC(tmp96c141_device::wdmod_w)); + //map(0x00005d, 0x00005d).w(FUNC(tmp96c141_device::wdcr_w)); + //map(0x00005e, 0x00005e).rw(FUNC(tmp96c141_device::admod_r), FUNC(tmp96c141_device::admod_w)); + //map(0x000060, 0x000067).r(FUNC(tmp96c141_device::adreg_r)); + //map(0x000068, 0x00006a).w(FUNC(tmp96c141_device::bcs_w)); + //map(0x000070, 0x000078).rw(FUNC(tmp96c141_device::inte_r), FUNC(tmp96c141_device::inte_w)); + //map(0x00007b, 0x00007b).w(FUNC(tmp96c141_device::iimc_w)); + //map(0x00007c, 0x00007f).w(FUNC(tmp96c141_device::dmav_w)); + map(0x000080, 0x00047f).ram(); +} + + +//************************************************************************** +// EXECUTION CALLBACKS +//************************************************************************** + +//------------------------------------------------- +// tlcs900_check_hdma - +//------------------------------------------------- + +void tmp96c141_device::tlcs900_check_hdma() +{ +} + + +//------------------------------------------------- +// tlcs900_check_irqs - +//------------------------------------------------- + +void tmp96c141_device::tlcs900_check_irqs() +{ +} + + +//------------------------------------------------- +// tlcs900_handle_ad - +//------------------------------------------------- + +void tmp96c141_device::tlcs900_handle_ad() +{ +} + + +//------------------------------------------------- +// tlcs900_handle_timers - +//------------------------------------------------- + +void tmp96c141_device::tlcs900_handle_timers() +{ +} + + +//------------------------------------------------- +// execute_set_input - called when a synchronized +// input is changed +//------------------------------------------------- + +void tmp96c141_device::execute_set_input(int inputnum, int state) +{ +} diff --git a/src/devices/cpu/tlcs900/tmp96c141.h b/src/devices/cpu/tlcs900/tmp96c141.h new file mode 100644 index 00000000000..973693a201b --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp96c141.h @@ -0,0 +1,98 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/**************************************************************************** + + Toshiba TMP96C141 microcontroller + +***************************************************************************** + + (AN0)PS0 73 ----------------+ +---------------- 72 P42(_CS2/_CAS2) + (AN1)PS1 74 --------------+ | | +-------------- 71 P41(_CS1/_CAS1) + (AN2)PS2 75 ------------+ | | | | +------------ 70 P40(_CS0/_CAS0) + (AN3)PS3 76 ----------+ | | | | | | +---------- 69 P37(_RAS) + VCC 77 --------+ | | | | | | | | +-------- 68 P36(R/_W) + VREF 78 ------+ | | | | | | | | | | +------ 67 P35(_BUSAK) + AGND 79 ----+ | | | | | | | | | | | | +---- 66 P34(_BUSRQ) + VSS 80 --+ | | | | | | | | | | | | | | +-- 65 P33(_WAIT) + _|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_ + (PG00)P60 1 | _ | 64 P32(_HWR) + (PG01)P61 2 | (_) | 63 P31(_WR) + (PG02)P62 3 | | 62 P30(_RD) + (PG03)P63 4 | | 61 P27(A7/A23) + (PG10)P64 5 | | 60 P26(A6/A22) + (PG11)P65 6 | | 59 P25(A5/A21) + (PG12)P66 7 | | 58 P24(A4/A20) + (PG13)P67 8 | | 57 P23(A3/A19) + (TI0)P70 9 | | 56 P22(A2/A18) + (TO1)P71 10 | | 55 P21(A1/A17) + (TO2)P72 11 | | 54 P20(A0/A16) + (TO3)P73 12 | TMP96C141AF | 53 VSS + (INT4/TI4)P80 13 | (QFP80) | 52 P17(AD15/A15) + (INT5/TI5)P81 14 | | 51 P16(AD14/A14) + (TO4)P82 15 | | 50 P15(AD13/A13) + (TO5)P83 16 | | 49 P14(AD12/A12) + (INT6/TI6)P84 17 | | 48 P13(AD11/A11) + (INT7/TI7)P85 18 | | 47 P12(AD10/A10) + (TO6)P86 19 | | 46 P11(AD9/A9) + (TO7)P87 20 | | 45 P10(AD8/A8) + _NMI 21 | | 44 P07(AD7) + _WDTOUT 22 | | 43 P06(AD6) + _RESET 23 | | 42 P05(AD5) + CLK 24 |_________________________________| 41 P04(AD4) + | | | | | | | | | | | | | | | | + VSS 25 --+ | | | | | | | | | | | | | | +-- 40 P03(AD3) + X1 26 ----+ | | | | | | | | | | | | +---- 39 P02(AD2) + X2 27 ------+ | | | | | | | | | | +------ 38 P01(AD1) + _EA 28 --------+ | | | | | | | | +-------- 37 P00(AD0) + (TXD0)P90 29 ----------+ | | | | | | +---------- 36 VCC + (RXD0)P91 30 ------------+ | | | | +------------ 35 ALE + (_CTS0)P92 31 --------------+ | | +-------------- 34 P95(SCLK1) + (TXD1)P93 32 ----------------+ +---------------- 33 P94(RXD1) + +****************************************************************************/ + +#ifndef MAME_CPU_TLCS900_TMP96C141_H +#define MAME_CPU_TLCS900_TMP96C141_H + +#pragma once + +#include "tlcs900.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> tmp96c141_device + +class tmp96c141_device : public tlcs900_device +{ +public: + // device type constructor + tmp96c141_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // TODO: configuration helpers + +protected: + // device-level overrides + virtual void device_config_complete() override; + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual void execute_set_input(int inputnum, int state) override; + + // tlcs900_device overrides + virtual void tlcs900_check_hdma() override; + virtual void tlcs900_check_irqs() override; + virtual void tlcs900_handle_ad() override; + virtual void tlcs900_handle_timers() override; + +private: + void internal_mem(address_map &map); +}; + +// device type declaration +DECLARE_DEVICE_TYPE(TMP96C141, tmp96c141_device) + +#endif // MAME_CPU_TLCS900_TMP96C141_H diff --git a/src/devices/machine/pxa255.cpp b/src/devices/machine/pxa255.cpp index 4c6c750afd3..7ab7457f757 100644 --- a/src/devices/machine/pxa255.cpp +++ b/src/devices/machine/pxa255.cpp @@ -23,9 +23,12 @@ #define LOG_GPIO (1 << 6) #define LOG_LCD_DMA (1 << 7) #define LOG_LCD (1 << 8) -#define LOG_ALL (LOG_UNKNOWN | LOG_I2S | LOG_DMA | LOG_OSTIMER | LOG_INTC | LOG_GPIO | LOG_LCD_DMA | LOG_LCD) +#define LOG_POWER (1 << 9) +#define LOG_RTC (1 << 10) +#define LOG_CLOCKS (1 << 11) +#define LOG_ALL (LOG_UNKNOWN | LOG_I2S | LOG_DMA | LOG_OSTIMER | LOG_INTC | LOG_GPIO | LOG_LCD_DMA | LOG_LCD | LOG_POWER | LOG_RTC | LOG_CLOCKS) -#define VERBOSE (0) +#define VERBOSE (LOG_ALL) #include "logmacro.h" DEFINE_DEVICE_TYPE(PXA255_PERIPHERALS, pxa255_periphs_device, "pxa255_periphs", "Intel XScale PXA255 Peripherals") @@ -198,14 +201,14 @@ void pxa255_periphs_device::dma_load_descriptor_and_start(int channel) m_dma_regs.dcsr[channel] &= ~PXA255_DCSR_STOPSTATE; } -TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end) +void pxa255_periphs_device::dma_end_tick(int channel) { - uint32_t sadr = m_dma_regs.dsadr[param]; - uint32_t tadr = m_dma_regs.dtadr[param]; - uint32_t count = m_dma_regs.dcmd[param] & 0x00001fff; + uint32_t sadr = m_dma_regs.dsadr[channel]; + uint32_t tadr = m_dma_regs.dtadr[channel]; + uint32_t count = m_dma_regs.dcmd[channel] & 0x00001fff; address_space &space = m_maincpu->space(AS_PROGRAM); - switch (param) + switch (channel) { case 3: for (uint32_t index = 0; index < count; index += 4) @@ -224,7 +227,7 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end) default: for (uint32_t index = 0; index < count;) { - switch (m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE) + switch (m_dma_regs.dcmd[channel] & PXA255_DCMD_SIZE) { case PXA255_DCMD_SIZE_8: space.write_byte(tadr, space.read_byte(sadr)); @@ -243,9 +246,9 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end) break; } - if (m_dma_regs.dcmd[param] & PXA255_DCMD_INCSRCADDR) + if (m_dma_regs.dcmd[channel] & PXA255_DCMD_INCSRCADDR) { - switch(m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE) + switch(m_dma_regs.dcmd[channel] & PXA255_DCMD_SIZE) { case PXA255_DCMD_SIZE_8: sadr++; @@ -260,9 +263,9 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end) break; } } - if(m_dma_regs.dcmd[param] & PXA255_DCMD_INCTRGADDR) + if(m_dma_regs.dcmd[channel] & PXA255_DCMD_INCTRGADDR) { - switch(m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE) + switch(m_dma_regs.dcmd[channel] & PXA255_DCMD_SIZE) { case PXA255_DCMD_SIZE_8: tadr++; @@ -281,27 +284,27 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end) break; } - if (m_dma_regs.dcmd[param] & PXA255_DCMD_ENDIRQEN) + if (m_dma_regs.dcmd[channel] & PXA255_DCMD_ENDIRQEN) { - m_dma_regs.dcsr[param] |= PXA255_DCSR_ENDINTR; + m_dma_regs.dcsr[channel] |= PXA255_DCSR_ENDINTR; } - if (!(m_dma_regs.ddadr[param] & PXA255_DDADR_STOP) && (m_dma_regs.dcsr[param] & PXA255_DCSR_RUN)) + if (!(m_dma_regs.ddadr[channel] & PXA255_DDADR_STOP) && (m_dma_regs.dcsr[channel] & PXA255_DCSR_RUN)) { - if (m_dma_regs.dcsr[param] & PXA255_DCSR_RUN) + if (m_dma_regs.dcsr[channel] & PXA255_DCSR_RUN) { - dma_load_descriptor_and_start(param); + dma_load_descriptor_and_start(channel); } else { - m_dma_regs.dcsr[param] &= ~PXA255_DCSR_RUN; - m_dma_regs.dcsr[param] |= PXA255_DCSR_STOPSTATE; + m_dma_regs.dcsr[channel] &= ~PXA255_DCSR_RUN; + m_dma_regs.dcsr[channel] |= PXA255_DCSR_STOPSTATE; } } else { - m_dma_regs.dcsr[param] &= ~PXA255_DCSR_RUN; - m_dma_regs.dcsr[param] |= PXA255_DCSR_STOPSTATE; + m_dma_regs.dcsr[channel] &= ~PXA255_DCSR_RUN; + m_dma_regs.dcsr[channel] |= PXA255_DCSR_STOPSTATE; } dma_irq_check(); @@ -446,6 +449,95 @@ void pxa255_periphs_device::dma_w(offs_t offset, uint32_t data, uint32_t mem_mas /* + PXA255 Real-Time Clock + + pg. 132 to 138, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +void pxa255_periphs_device::rtc_tick() +{ + m_rtc_regs.rcnr++; + if (BIT(m_rtc_regs.rtsr, 3)) + { + m_rtc_regs.rtsr |= (1 << 1); + set_irq_line(PXA255_INT_RTC_HZ, 1); + } + + if (m_rtc_regs.rcnr == m_rtc_regs.rtar) + { + if (BIT(m_rtc_regs.rtsr, 2)) + { + m_rtc_regs.rtsr |= (1 << 0); + set_irq_line(PXA255_INT_RTC_ALARM, 1); + } + } +} + +uint32_t pxa255_periphs_device::rtc_r(offs_t offset, uint32_t mem_mask) +{ + switch(PXA255_RTC_BASE_ADDR | (offset << 2)) + { + case PXA255_RCNR: + LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Counter Register: %08x\n", machine().describe_context(), m_rtc_regs.rcnr); + return m_rtc_regs.rcnr; + case PXA255_RTAR: + LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Alarm Register: %08x\n", machine().describe_context(), m_rtc_regs.rtar); + return m_rtc_regs.rtar; + case PXA255_RTSR: + LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Status Register: %08x\n", machine().describe_context(), m_rtc_regs.rtsr); + return m_rtc_regs.rtsr; + case PXA255_RTTR: + LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Trim Register: %08x\n", machine().describe_context(), m_rtc_regs.rttr); + return m_rtc_regs.rttr; + default: + LOGMASKED(LOG_RTC | LOG_UNKNOWN, "pxa255 rtc_r: Unknown address: %08x\n", PXA255_RTC_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +void pxa255_periphs_device::rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch(PXA255_RTC_BASE_ADDR | (offset << 2)) + { + case PXA255_RCNR: + LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Counter Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_rtc_regs.rcnr); + break; + case PXA255_RTAR: + LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Alarm Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_rtc_regs.rtar); + break; + case PXA255_RTSR: + { + LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Status Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + const uint32_t old = m_rtc_regs.rtsr; + m_rtc_regs.rtsr &= ~(data & 0x00000003); + m_rtc_regs.rtsr &= ~0x0000000c; + m_rtc_regs.rtsr |= data & 0x0000000c; + const uint32_t diff = old ^ m_rtc_regs.rtsr; + if (BIT(diff, 1)) + set_irq_line(PXA255_INT_RTC_HZ, 0); + if (BIT(diff, 0)) + set_irq_line(PXA255_INT_RTC_ALARM, 0); + break; + } + case PXA255_RTTR: + LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Trim Register (not yet implemented): %08x & %08x\n", machine().describe_context(), data, mem_mask); + if (!BIT(m_rtc_regs.rttr, 31)) + { + COMBINE_DATA(&m_rtc_regs.rttr); + } + break; + default: + LOGMASKED(LOG_RTC | LOG_UNKNOWN, "pxa255 rtc_w: Unknown address: %08x = %08x & %08x\n", PXA255_RTC_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + PXA255 OS Timer register pg. 138 to 142, PXA255 Processor Developers Manual [278693-002].pdf @@ -460,10 +552,10 @@ void pxa255_periphs_device::ostimer_irq_check() //set_irq_line(PXA255_INT_OSTIMER3, (m_ostimer_regs.oier & PXA255_OIER_E3) ? ((m_ostimer_regs.ossr & PXA255_OSSR_M3) ? 1 : 0) : 0); } -TIMER_CALLBACK_MEMBER(pxa255_periphs_device::ostimer_match) +void pxa255_periphs_device::ostimer_match_tick(int channel) { - m_ostimer_regs.ossr |= (1 << param); - m_ostimer_regs.oscr = m_ostimer_regs.osmr[param]; + m_ostimer_regs.ossr |= (1 << channel); + m_ostimer_regs.oscr = m_ostimer_regs.osmr[channel]; ostimer_irq_check(); } @@ -663,6 +755,77 @@ void pxa255_periphs_device::intc_w(offs_t offset, uint32_t data, uint32_t mem_ma */ +void pxa255_periphs_device::gpio_bit_w(offs_t offset, uint8_t data, uint8_t mem_mask) +{ + const uint32_t val = (data != 0 ? 1 : 0); + LOGMASKED(LOG_GPIO, "pxa255: GPIO%d written: %d\n", offset, val); + if (offset < 32) + { + const uint32_t old = m_gpio_regs.gplr0; + m_gpio_regs.gplr0 &= ~(1 << offset); + m_gpio_regs.gplr0 |= (val << offset); + + LOGMASKED(LOG_GPIO, "pxa255: Old GPLR0 %08x, New GPLR0 %08x\n", old, m_gpio_regs.gplr0); + + const uint32_t rising = ~old & m_gpio_regs.gplr0; + const uint32_t falling = old & ~m_gpio_regs.gplr0; + + LOGMASKED(LOG_GPIO, "pxa255: Rising %08x, Falling %08x\n", rising, falling); + + const uint32_t old_gedr = m_gpio_regs.gedr0; + m_gpio_regs.gedr0 |= (rising & m_gpio_regs.grer0); + m_gpio_regs.gedr0 |= (falling & m_gpio_regs.gfer0); + + LOGMASKED(LOG_GPIO, "pxa255: Old GEDR0 %08x, New GEDR0 %08x\n", old_gedr, m_gpio_regs.gedr0); + if (old_gedr != m_gpio_regs.gedr0) + { + LOGMASKED(LOG_GPIO, "pxa255: Edge detected on GPIO%d\n", offset); + if (offset > 1) + set_irq_line(PXA255_INT_GPIO84_2, 1); + else if (offset == 1) + set_irq_line(PXA255_INT_GPIO1, 1); + else + set_irq_line(PXA255_INT_GPIO0, 1); + } + } + else if (offset < 64) + { + const uint32_t old = m_gpio_regs.gplr1; + m_gpio_regs.gplr1 &= ~(1 << (offset - 32)); + m_gpio_regs.gplr1 |= ~(val << (offset - 32)); + + const uint32_t rising = ~old & m_gpio_regs.gplr1; + const uint32_t falling = old & ~m_gpio_regs.gplr1; + + const uint32_t old_gedr = m_gpio_regs.gedr1; + m_gpio_regs.gedr1 |= (rising & m_gpio_regs.grer1); + m_gpio_regs.gedr1 |= (falling & m_gpio_regs.gfer1); + if (old_gedr != m_gpio_regs.gedr1) + { + LOGMASKED(LOG_GPIO, "pxa255: Edge detected on GPIO%d\n", offset); + set_irq_line(PXA255_INT_GPIO84_2, 1); + } + } + else if (offset < 85) + { + const uint32_t old = m_gpio_regs.gplr2; + m_gpio_regs.gplr2 &= ~(1 << (offset - 64)); + m_gpio_regs.gplr2 |= ~(val << (offset - 64)); + + const uint32_t rising = ~old & m_gpio_regs.gplr2; + const uint32_t falling = old & ~m_gpio_regs.gplr2; + + const uint32_t old_gedr = m_gpio_regs.gedr2; + m_gpio_regs.gedr2 |= (rising & m_gpio_regs.grer2); + m_gpio_regs.gedr2 |= (falling & m_gpio_regs.gfer2); + if (old_gedr != m_gpio_regs.gedr2) + { + LOGMASKED(LOG_GPIO, "pxa255: Edge detected on GPIO%d\n", offset); + set_irq_line(PXA255_INT_GPIO84_2, 1); + } + } +} + uint32_t pxa255_periphs_device::gpio_r(offs_t offset, uint32_t mem_mask) { switch(PXA255_GPIO_BASE_ADDR | (offset << 2)) @@ -844,17 +1007,39 @@ void pxa255_periphs_device::gpio_w(offs_t offset, uint32_t data, uint32_t mem_ma m_gpio_regs.gfer2 = data; break; case PXA255_GEDR0: + { LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Edge Detect Status Register 0: %08x & %08x\n", m_gpio_regs.gedr0, mem_mask); + const uint32_t old = m_gpio_regs.gedr0; m_gpio_regs.gedr0 &= ~data; + const uint32_t lowered = old & ~m_gpio_regs.gedr0; + if (BIT(lowered, 0)) + set_irq_line(PXA255_INT_GPIO0, 0); + else if (BIT(lowered, 1)) + set_irq_line(PXA255_INT_GPIO1, 0); + else if ((lowered & 0xfffffffc) && !m_gpio_regs.gedr0 && !m_gpio_regs.gedr1 && !m_gpio_regs.gedr2) + set_irq_line(PXA255_INT_GPIO84_2, 0); break; + } case PXA255_GEDR1: + { LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Edge Detect Status Register 1: %08x & %08x\n", m_gpio_regs.gedr1, mem_mask); + const uint32_t old = m_gpio_regs.gedr1; m_gpio_regs.gedr1 &= ~data; + const uint32_t lowered = old & !m_gpio_regs.gedr1; + if (lowered && !m_gpio_regs.gedr0 && !m_gpio_regs.gedr1 && !m_gpio_regs.gedr2) + set_irq_line(PXA255_INT_GPIO84_2, 0); break; + } case PXA255_GEDR2: + { LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Edge Detect Status Register 2: %08x & %08x\n", m_gpio_regs.gedr2, mem_mask); + const uint32_t old = m_gpio_regs.gedr2; m_gpio_regs.gedr2 &= ~data; + const uint32_t lowered = old & !m_gpio_regs.gedr2; + if (lowered && !m_gpio_regs.gedr0 && !m_gpio_regs.gedr1 && !m_gpio_regs.gedr2) + set_irq_line(PXA255_INT_GPIO84_2, 0); break; + } case PXA255_GAFR0_L: LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Alternate Function Register 0 Lower: %08x & %08x\n", m_gpio_regs.gafr0l, mem_mask); m_gpio_regs.gafr0l = data; @@ -987,15 +1172,15 @@ void pxa255_periphs_device::lcd_check_load_next_branch(int channel) } } -TIMER_CALLBACK_MEMBER(pxa255_periphs_device::lcd_dma_eof) +void pxa255_periphs_device::lcd_dma_eof_tick(int channel) { LOGMASKED(LOG_LCD_DMA, "End of frame callback\n" ); - if(m_lcd_regs.dma[param].ldcmd & PXA255_LDCMD_EOFINT) + if(m_lcd_regs.dma[channel].ldcmd & PXA255_LDCMD_EOFINT) { - m_lcd_regs.liidr = m_lcd_regs.dma[param].fidr; + m_lcd_regs.liidr = m_lcd_regs.dma[channel].fidr; m_lcd_regs.lcsr |= PXA255_LCSR_EOF; } - lcd_check_load_next_branch(param); + lcd_check_load_next_branch(channel); lcd_irq_check(); } @@ -1168,20 +1353,182 @@ void pxa255_periphs_device::lcd_w(address_space &space, offs_t offset, uint32_t } } +uint32_t pxa255_periphs_device::power_r(offs_t offset, uint32_t mem_mask) +{ + switch(PXA255_POWER_BASE_ADDR | (offset << 2)) + { + case PXA255_PMCR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Control Register: %08x\n", machine().describe_context(), m_power_regs.pmcr); + return m_power_regs.pmcr; + case PXA255_PSSR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Sleep Status Register: %08x\n", machine().describe_context(), m_power_regs.pssr); + return m_power_regs.pssr; + case PXA255_PSPR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Scratch Pad Register: %08x\n", machine().describe_context(), m_power_regs.pspr); + return m_power_regs.pspr; + case PXA255_PWER: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Wake-up Enable Register: %08x\n", machine().describe_context(), m_power_regs.pwer); + return m_power_regs.pwer; + case PXA255_PRER: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Rising-Edge Detect Enable Register: %08x\n", machine().describe_context(), m_power_regs.prer); + return m_power_regs.prer; + case PXA255_PFER: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Falling-Edge Detect Enable Register: %08x\n", machine().describe_context(), m_power_regs.pfer); + return m_power_regs.pfer; + case PXA255_PEDR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Edge Detect Status Register: %08x\n", machine().describe_context(), m_power_regs.pedr); + return m_power_regs.pedr; + case PXA255_PCFR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager General Configuration Register: %08x\n", machine().describe_context(), m_power_regs.pcfr); + return m_power_regs.pcfr; + case PXA255_PGSR0: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Sleep State Register for GP[31-0]: %08x\n", machine().describe_context(), m_power_regs.pgsr0); + return m_power_regs.pgsr0; + case PXA255_PGSR1: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Sleep State Register for GP[63-32]: %08x\n", machine().describe_context(), m_power_regs.pgsr1); + return m_power_regs.pgsr1; + case PXA255_PGSR2: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Sleep State Register for GP[84-64]: %08x\n", machine().describe_context(), m_power_regs.pgsr2); + return m_power_regs.pgsr2; + case PXA255_RCSR: + LOGMASKED(LOG_POWER, "%s: power_r: Reset Controller Status Register: %08x\n", machine().describe_context(), m_power_regs.rcsr); + return m_power_regs.rcsr; + case PXA255_PMFW: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Fast Sleep Walk-Up Configuration Register: %08x\n", machine().describe_context(), m_power_regs.pmfw); + return m_power_regs.pmfw; + default: + LOGMASKED(LOG_POWER | LOG_UNKNOWN, "%s: power_r: Unknown address: %08x\n", machine().describe_context(), PXA255_POWER_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +void pxa255_periphs_device::power_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch(PXA255_POWER_BASE_ADDR | (offset << 2)) + { + case PXA255_PMCR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pmcr); + break; + case PXA255_PSSR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Sleep Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_power_regs.pssr &= ~(data & 0x00000037); + break; + case PXA255_PSPR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Scratch Pad Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pspr); + break; + case PXA255_PWER: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Wake-Up Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pwer); + break; + case PXA255_PRER: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Rising-Edge Detect Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.prer); + break; + case PXA255_PFER: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Falling-Edge Detect Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pfer); + break; + case PXA255_PEDR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Edge Detect Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_power_regs.pedr &= ~(data & 0x0000ffff); + break; + case PXA255_PCFR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager General Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pcfr); + break; + case PXA255_PGSR0: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Sleep State Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pgsr0); + break; + case PXA255_PGSR1: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Sleep State Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pgsr1); + break; + case PXA255_PGSR2: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Sleep State Register 2 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pgsr2); + break; + case PXA255_PMFW: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Fast Sleep Walk-Up Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pmfw); + break; + default: + LOGMASKED(LOG_POWER | LOG_UNKNOWN, "%s: power_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), PXA255_POWER_BASE_ADDR | (offset << 2), + data, mem_mask); + break; + } +} + +/* + PXA255 Clock controller + + pg. 96 to 100, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +uint32_t pxa255_periphs_device::clocks_r(offs_t offset, uint32_t mem_mask) +{ + switch(PXA255_CLOCKS_BASE_ADDR | (offset << 2)) + { + case PXA255_CCCR: + LOGMASKED(LOG_CLOCKS, "%s: clocks_r: Core Clock Configuration Register: %08x\n", machine().describe_context(), m_clocks_regs.cccr); + return m_clocks_regs.cccr; + case PXA255_CKEN: + LOGMASKED(LOG_CLOCKS, "%s: clocks_r: Clock Enable Register: %08x\n", machine().describe_context(), m_clocks_regs.cken); + return m_clocks_regs.cken; + case PXA255_OSCC: + LOGMASKED(LOG_CLOCKS, "%s: clocks_r: Oscillator Configuration Register: %08x\n", machine().describe_context(), m_clocks_regs.oscc); + return BIT(m_clocks_regs.oscc, 0); + default: + LOGMASKED(LOG_CLOCKS | LOG_UNKNOWN, "%s: clocks_r: Unknown address: %08x\n", machine().describe_context(), PXA255_CLOCKS_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +void pxa255_periphs_device::clocks_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch(PXA255_CLOCKS_BASE_ADDR | (offset << 2)) + { + case PXA255_CCCR: + LOGMASKED(LOG_CLOCKS, "%s: clocks_w: Core Clock Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_clocks_regs.cccr); + break; + case PXA255_CKEN: + LOGMASKED(LOG_CLOCKS, "%s: clocks_w: Clock Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_clocks_regs.cken); + break; + case PXA255_OSCC: + LOGMASKED(LOG_CLOCKS, "%s: clocks_w: Oscillator Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + if (BIT(data, 1)) + { + m_clocks_regs.oscc |= 0x00000003; + } + break; + default: + LOGMASKED(LOG_CLOCKS | LOG_UNKNOWN, "%s: clocks_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), PXA255_CLOCKS_BASE_ADDR | (offset << 2), + data, mem_mask); + break; + } +} + void pxa255_periphs_device::device_start() { for (int index = 0; index < 16; index++) { - m_dma_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::dma_dma_end),this)); + m_dma_regs.timer[index] = timer_alloc(TIMER_DMA0 + index); } for (int index = 0; index < 4; index++) { - m_ostimer_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::ostimer_match),this)); + m_ostimer_regs.timer[index] = timer_alloc(TIMER_OSTIMER0 + index); } - m_lcd_regs.dma[0].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::lcd_dma_eof),this)); - m_lcd_regs.dma[1].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::lcd_dma_eof),this)); + m_lcd_regs.dma[0].eof = timer_alloc(TIMER_LCD_EOF0); + m_lcd_regs.dma[1].eof = timer_alloc(TIMER_LCD_EOF0 + 1); m_lcd_palette = make_unique_clear<uint32_t[]>(0x100); m_lcd_framebuffer = make_unique_clear<uint8_t[]>(0x100000); @@ -1194,6 +1541,8 @@ void pxa255_periphs_device::device_start() m_gpio0_r.resolve_safe(0xffffffff); m_gpio1_r.resolve_safe(0xffffffff); m_gpio2_r.resolve_safe(0xffffffff); + + m_rtc_regs.timer = timer_alloc(TIMER_RTC); } void pxa255_periphs_device::device_reset() @@ -1203,10 +1552,31 @@ void pxa255_periphs_device::device_reset() m_dma_regs.dcsr[index] = 0x00000008; } + m_rtc_regs.rcnr = 0x00000000; + m_rtc_regs.rtar = 0x00000000; + m_rtc_regs.rtsr = 0x00000000; + m_rtc_regs.rttr = 0x00007fff; + m_rtc_regs.timer->adjust(attotime::from_hz(1)); + memset(&m_intc_regs, 0, sizeof(m_intc_regs)); m_lcd_regs.trgbr = 0x00aa5500; m_lcd_regs.tcr = 0x0000754f; + + memset(&m_power_regs, 0, sizeof(m_power_regs)); + memset(&m_clocks_regs, 0, sizeof(m_clocks_regs)); +} + +void pxa255_periphs_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id < TIMER_OSTIMER0) + dma_end_tick(id); + else if (id < TIMER_LCD_EOF0) + ostimer_match_tick(id - TIMER_OSTIMER0); + else if (id < TIMER_RTC) + lcd_dma_eof_tick(id - TIMER_LCD_EOF0); + else if (id == TIMER_RTC) + rtc_tick(); } uint32_t pxa255_periphs_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) diff --git a/src/devices/machine/pxa255.h b/src/devices/machine/pxa255.h index 8f1e90544fe..c90f676b5ee 100644 --- a/src/devices/machine/pxa255.h +++ b/src/devices/machine/pxa255.h @@ -37,25 +37,36 @@ public: auto gpio0_write() { return m_gpio0_w.bind(); } auto gpio0_read() { return m_gpio0_r.bind(); } - uint32_t i2s_r(offs_t offset, uint32_t mem_mask = ~0); - void i2s_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint32_t dma_r(offs_t offset, uint32_t mem_mask = ~0); void dma_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t i2s_r(offs_t offset, uint32_t mem_mask = ~0); + void i2s_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t rtc_r(offs_t offset, uint32_t mem_mask = ~0); + void rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint32_t ostimer_r(offs_t offset, uint32_t mem_mask = ~0); void ostimer_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint32_t intc_r(offs_t offset, uint32_t mem_mask = ~0); void intc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + void gpio_bit_w(offs_t offset, uint8_t data, uint8_t mem_mask = ~0); uint32_t gpio_r(offs_t offset, uint32_t mem_mask = ~0); void gpio_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint32_t lcd_r(offs_t offset, uint32_t mem_mask = ~0); void lcd_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - - void set_irq_line(uint32_t line, int state); + uint32_t power_r(offs_t offset, uint32_t mem_mask = ~0); + void power_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t clocks_r(offs_t offset, uint32_t mem_mask = ~0); + void clocks_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); protected: virtual void device_add_mconfig(machine_config &config) override; virtual void device_start() override; virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + static const device_timer_id TIMER_DMA0 = 0; + static const device_timer_id TIMER_OSTIMER0 = 16; + static const device_timer_id TIMER_LCD_EOF0 = 20; + static const device_timer_id TIMER_RTC = 22; void dma_irq_check(); void dma_load_descriptor_and_start(int channel); @@ -68,11 +79,14 @@ protected: uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - TIMER_CALLBACK_MEMBER(dma_dma_end); - TIMER_CALLBACK_MEMBER(ostimer_match); - TIMER_CALLBACK_MEMBER(lcd_dma_eof); + void dma_end_tick(int channel); + void ostimer_match_tick(int channel); + void lcd_dma_eof_tick(int channel); + void rtc_tick(); + + void set_irq_line(uint32_t line, int state); - struct dma_regs_t + struct dma_regs { uint32_t dcsr[16]; uint32_t pad0[44]; @@ -91,7 +105,7 @@ protected: emu_timer* timer[16]; }; - struct i2s_regs_t + struct i2s_regs { uint32_t sacr0; uint32_t sacr1; @@ -110,7 +124,16 @@ protected: uint32_t sadr; }; - struct ostmr_regs_t + struct rtc_regs + { + uint32_t rcnr; + uint32_t rtar; + uint32_t rtsr; + uint32_t rttr; + emu_timer *timer; + }; + + struct ostmr_regs { uint32_t osmr[4]; uint32_t oscr; @@ -121,7 +144,7 @@ protected: emu_timer* timer[4]; }; - struct intc_regs_t + struct intc_regs { uint32_t icip; uint32_t icmr; @@ -131,7 +154,7 @@ protected: uint32_t iccr; }; - struct gpio_regs_t + struct gpio_regs { uint32_t gplr0; // GPIO Pin-Level uint32_t gplr1; @@ -169,7 +192,7 @@ protected: uint32_t gafr2u; }; - struct lcd_dma_regs_t + struct lcd_dma_regs { uint32_t fdadr; uint32_t fsadr; @@ -178,32 +201,56 @@ protected: emu_timer *eof; }; - struct lcd_regs_t + struct lcd_regs { uint32_t lccr0; uint32_t lccr1; uint32_t lccr2; uint32_t lccr3; - uint32_t pad0[4]; uint32_t fbr[2]; - uint32_t pad1[4]; uint32_t lcsr; uint32_t liidr; uint32_t trgbr; uint32_t tcr; - uint32_t pad2[110]; - lcd_dma_regs_t dma[2]; + lcd_dma_regs dma[2]; + }; + + struct power_regs + { + uint32_t pmcr; + uint32_t pssr; + uint32_t pspr; + uint32_t pwer; + uint32_t prer; + uint32_t pfer; + uint32_t pedr; + uint32_t pcfr; + uint32_t pgsr0; + uint32_t pgsr1; + uint32_t pgsr2; + uint32_t rcsr; + uint32_t pmfw; + }; + + struct clocks_regs + { + uint32_t cccr; + uint32_t cken; + uint32_t oscc; }; - dma_regs_t m_dma_regs; - i2s_regs_t m_i2s_regs; - ostmr_regs_t m_ostimer_regs; - intc_regs_t m_intc_regs; - gpio_regs_t m_gpio_regs; - lcd_regs_t m_lcd_regs; + dma_regs m_dma_regs; + i2s_regs m_i2s_regs; + rtc_regs m_rtc_regs; + ostmr_regs m_ostimer_regs; + intc_regs m_intc_regs; + gpio_regs m_gpio_regs; + lcd_regs m_lcd_regs; + power_regs m_power_regs; + clocks_regs m_clocks_regs; devcb_write32 m_gpio0_w; devcb_write32 m_gpio1_w; diff --git a/src/devices/machine/pxa255defs.h b/src/devices/machine/pxa255defs.h index d2c38f474f1..b746f08d30a 100644 --- a/src/devices/machine/pxa255defs.h +++ b/src/devices/machine/pxa255defs.h @@ -214,6 +214,20 @@ /* + PXA255 Real-Time Clock + + pg. 132 to 138, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +#define PXA255_RTC_BASE_ADDR (0x40900000) +#define PXA255_RCNR (PXA255_RTC_BASE_ADDR + 0x00000000) +#define PXA255_RTAR (PXA255_RTC_BASE_ADDR + 0x00000004) +#define PXA255_RTSR (PXA255_RTC_BASE_ADDR + 0x00000008) +#define PXA255_RTTR (PXA255_RTC_BASE_ADDR + 0x0000000c) + +/* + PXA255 OS Timer register pg. 138 to 142, PXA255 Processor Developers Manual [278693-002].pdf @@ -376,4 +390,37 @@ #define PXA255_FIDR1 (PXA255_LCD_BASE_ADDR + 0x00000218) #define PXA255_LDCMD1 (PXA255_LCD_BASE_ADDR + 0x0000021c) +/* + PXA255 Power controller + + pg. 85 to 96, PXA255 Processor Developers Manual [278693-002].pdf +*/ + +#define PXA255_POWER_BASE_ADDR (0x40f00000) +#define PXA255_PMCR (PXA255_POWER_BASE_ADDR + 0x00000000) +#define PXA255_PSSR (PXA255_POWER_BASE_ADDR + 0x00000004) +#define PXA255_PSPR (PXA255_POWER_BASE_ADDR + 0x00000008) +#define PXA255_PWER (PXA255_POWER_BASE_ADDR + 0x0000000c) +#define PXA255_PRER (PXA255_POWER_BASE_ADDR + 0x00000010) +#define PXA255_PFER (PXA255_POWER_BASE_ADDR + 0x00000014) +#define PXA255_PEDR (PXA255_POWER_BASE_ADDR + 0x00000018) +#define PXA255_PCFR (PXA255_POWER_BASE_ADDR + 0x0000001c) +#define PXA255_PGSR0 (PXA255_POWER_BASE_ADDR + 0x00000020) +#define PXA255_PGSR1 (PXA255_POWER_BASE_ADDR + 0x00000024) +#define PXA255_PGSR2 (PXA255_POWER_BASE_ADDR + 0x00000028) +#define PXA255_RCSR (PXA255_POWER_BASE_ADDR + 0x00000030) +#define PXA255_PMFW (PXA255_POWER_BASE_ADDR + 0x00000034) + +/* + PXA255 Clock controller + + pg. 96 to 100, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +#define PXA255_CLOCKS_BASE_ADDR (0x41300000) +#define PXA255_CCCR (PXA255_CLOCKS_BASE_ADDR + 0x00000000) +#define PXA255_CKEN (PXA255_CLOCKS_BASE_ADDR + 0x00000004) +#define PXA255_OSCC (PXA255_CLOCKS_BASE_ADDR + 0x00000008) + #endif // MAME_MACHINE_PXA255DEFS diff --git a/src/devices/machine/sa1110.cpp b/src/devices/machine/sa1110.cpp new file mode 100644 index 00000000000..ae75340f2ce --- /dev/null +++ b/src/devices/machine/sa1110.cpp @@ -0,0 +1,227 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/************************************************************************** + * + * Intel XScale SA1110 peripheral emulation + * + **************************************************************************/ + +#include "emu.h" +#include "sa1110.h" + +#define LOG_UNKNOWN (1 << 1) +#define LOG_INTC (1 << 2) +#define LOG_POWER (1 << 3) +#define LOG_ALL (LOG_UNKNOWN | LOG_INTC | LOG_POWER) + +#define VERBOSE (LOG_ALL) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(SA1110_PERIPHERALS, sa1110_periphs_device, "sa1110_periphs", "Intel XScale SA1110 Peripherals") + +sa1110_periphs_device::sa1110_periphs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SA1110_PERIPHERALS, tag, owner, clock) + , m_maincpu(*this, finder_base::DUMMY_TAG) +{ +} + +/* + + Intel SA-1110 Interrupt Controller + + pg. 81 to 88 Intel StrongARM SA-1110 Microprocessor Developer's Manual + +*/ + +void sa1110_periphs_device::update_interrupts() +{ + m_intc_regs.icfp = (m_intc_regs.icpr & m_intc_regs.icmr) & m_intc_regs.iclr; + m_intc_regs.icip = (m_intc_regs.icpr & m_intc_regs.icmr) & (~m_intc_regs.iclr); + m_maincpu->set_input_line(ARM7_FIRQ_LINE, m_intc_regs.icfp ? ASSERT_LINE : CLEAR_LINE); + m_maincpu->set_input_line(ARM7_IRQ_LINE, m_intc_regs.icip ? ASSERT_LINE : CLEAR_LINE); +} + +void sa1110_periphs_device::set_irq_line(uint32_t line, int irq_state) +{ + m_intc_regs.icpr &= ~line; + m_intc_regs.icpr |= irq_state ? line : 0; + update_interrupts(); +} + +uint32_t sa1110_periphs_device::intc_r(offs_t offset, uint32_t mem_mask) +{ + switch (offset) + { + case REG_ICIP: + LOGMASKED(LOG_INTC, "sa1110 intc_r: Interrupt Controller IRQ Pending Register: %08x & %08x\n", m_intc_regs.icip, mem_mask); + return m_intc_regs.icip; + case REG_ICMR: + LOGMASKED(LOG_INTC, "sa1110 intc_r: Interrupt Controller Mask Register: %08x & %08x\n", m_intc_regs.icmr, mem_mask); + return m_intc_regs.icmr; + case REG_ICLR: + LOGMASKED(LOG_INTC, "sa1110 intc_r: Interrupt Controller Level Register: %08x & %08x\n", m_intc_regs.iclr, mem_mask); + return m_intc_regs.iclr; + case REG_ICFP: + LOGMASKED(LOG_INTC, "sa1110 intc_r: Interrupt Controller FIQ Pending Register: %08x & %08x\n", m_intc_regs.icfp, mem_mask); + return m_intc_regs.icfp; + case REG_ICPR: + LOGMASKED(LOG_INTC, "sa1110 intc_r: Interrupt Controller Pending Register: %08x & %08x\n", m_intc_regs.icpr, mem_mask); + return m_intc_regs.icpr; + case REG_ICCR: + LOGMASKED(LOG_INTC, "sa1110 intc_r: Interrupt Controller Control Register: %08x & %08x\n", m_intc_regs.iccr, mem_mask); + return m_intc_regs.iccr; + default: + LOGMASKED(LOG_INTC | LOG_UNKNOWN, "sa1110 intc_r: Unknown address: %08x\n", INTC_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +void sa1110_periphs_device::intc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset) + { + case REG_ICIP: + LOGMASKED(LOG_INTC, "sa1110 intc_w: (Invalid Write) Interrupt Controller IRQ Pending Register: %08x & %08x\n", data, mem_mask); + break; + case REG_ICMR: + LOGMASKED(LOG_INTC, "sa1110 intc_w: Interrupt Controller Mask Register: %08x & %08x\n", data, mem_mask); + COMBINE_DATA(&m_intc_regs.icmr); + break; + case REG_ICLR: + LOGMASKED(LOG_INTC, "sa1110 intc_w: Interrupt Controller Level Register: %08x & %08x\n", data, mem_mask); + COMBINE_DATA(&m_intc_regs.iclr); + break; + case REG_ICFP: + LOGMASKED(LOG_INTC, "sa1110 intc_w: (Invalid Write) Interrupt Controller FIQ Pending Register: %08x & %08x\n", data, mem_mask); + break; + case REG_ICPR: + LOGMASKED(LOG_INTC, "sa1110_intc_w: (Invalid Write) Interrupt Controller Pending Register: %08x & %08x\n", data, mem_mask); + break; + case REG_ICCR: + LOGMASKED(LOG_INTC, "sa1110 intc_w: Interrupt Controller Control Register: %08x & %08x\n", data, mem_mask); + m_intc_regs.iccr = BIT(data, 0); + break; + default: + LOGMASKED(LOG_INTC | LOG_UNKNOWN, "sa1110 intc_w: Unknown address: %08x = %08x & %08x\n", INTC_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + + Intel SA-1110 Power Controller + + pg. 104 to 111 Intel StrongARM SA-1110 Microprocessor Developer's Manual + +*/ + +uint32_t sa1110_periphs_device::power_r(offs_t offset, uint32_t mem_mask) +{ + switch (offset) + { + case REG_PMCR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Control Register: %08x\n", machine().describe_context(), m_power_regs.pmcr); + return m_power_regs.pmcr; + case REG_PSSR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Sleep Status Register: %08x\n", machine().describe_context(), m_power_regs.pssr); + return m_power_regs.pssr; + case REG_PSPR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Scratch Pad Register: %08x\n", machine().describe_context(), m_power_regs.pspr); + return m_power_regs.pspr; + case REG_PWER: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Wake-up Enable Register: %08x\n", machine().describe_context(), m_power_regs.pwer); + return m_power_regs.pwer; + case REG_PCFR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager General Configuration Register: %08x\n", machine().describe_context(), m_power_regs.pcfr); + return m_power_regs.pcfr; + case REG_PPCR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager PLL Configuration Register: %08x\n", machine().describe_context(), m_power_regs.ppcr); + return m_power_regs.ppcr; + case REG_PGSR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Sleep State Register: %08x\n", machine().describe_context(), m_power_regs.pgsr); + return m_power_regs.pgsr; + case REG_POSR: + LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Oscillator Status Register: %08x\n", machine().describe_context(), m_power_regs.posr); + return m_power_regs.posr; + default: + LOGMASKED(LOG_POWER | LOG_UNKNOWN, "%s: power_r: Unknown address: %08x\n", machine().describe_context(), POWER_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +void sa1110_periphs_device::power_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset) + { + case REG_PMCR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pmcr); + break; + case REG_PSSR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Sleep Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_power_regs.pssr &= ~(data & 0x0000001f); + break; + case REG_PSPR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Scratch Pad Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pspr); + break; + case REG_PWER: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Wake-Up Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pwer); + break; + case REG_PCFR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager General Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pcfr); + break; + case REG_PPCR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager PLL Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.ppcr); + break; + case REG_PGSR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Sleep State Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_power_regs.pgsr); + break; + case REG_POSR: + LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Oscillator Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + default: + LOGMASKED(LOG_POWER | LOG_UNKNOWN, "%s: power_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), POWER_BASE_ADDR | (offset << 2), + data, mem_mask); + break; + } +} + +void sa1110_periphs_device::device_start() +{ + save_item(NAME(m_intc_regs.icip), m_intc_regs.icip); + save_item(NAME(m_intc_regs.icmr), m_intc_regs.icmr); + save_item(NAME(m_intc_regs.iclr), m_intc_regs.iclr); + save_item(NAME(m_intc_regs.iccr), m_intc_regs.iccr); + save_item(NAME(m_intc_regs.icfp), m_intc_regs.icfp); + save_item(NAME(m_intc_regs.icpr), m_intc_regs.icpr); + + save_item(NAME(m_power_regs.pmcr), m_power_regs.pmcr); + save_item(NAME(m_power_regs.pssr), m_power_regs.pssr); + save_item(NAME(m_power_regs.pspr), m_power_regs.pspr); + save_item(NAME(m_power_regs.pwer), m_power_regs.pwer); + save_item(NAME(m_power_regs.pcfr), m_power_regs.pcfr); + save_item(NAME(m_power_regs.ppcr), m_power_regs.ppcr); + save_item(NAME(m_power_regs.pgsr), m_power_regs.pgsr); + save_item(NAME(m_power_regs.posr), m_power_regs.posr); +} + +void sa1110_periphs_device::device_reset() +{ + memset(&m_intc_regs, 0, sizeof(m_intc_regs)); + memset(&m_power_regs, 0, sizeof(m_power_regs)); +} + +void sa1110_periphs_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ +} + +void sa1110_periphs_device::device_add_mconfig(machine_config &config) +{ +} diff --git a/src/devices/machine/sa1110.h b/src/devices/machine/sa1110.h new file mode 100644 index 00000000000..0296ab1c2eb --- /dev/null +++ b/src/devices/machine/sa1110.h @@ -0,0 +1,96 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/************************************************************************** + * + * Intel XScale SA1110 peripheral emulation + * + **************************************************************************/ + +#ifndef MAME_MACHINE_SA1110 +#define MAME_MACHINE_SA1110 + +#pragma once + +#include "cpu/arm7/arm7.h" +#include "cpu/arm7/arm7core.h" +#include "sound/dmadac.h" +#include "emupal.h" + +class sa1110_periphs_device : public device_t +{ +public: + template <typename T> + sa1110_periphs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag) + : sa1110_periphs_device(mconfig, tag, owner, clock) + { + m_maincpu.set_tag(std::forward<T>(cpu_tag)); + } + + sa1110_periphs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint32_t intc_r(offs_t offset, uint32_t mem_mask = ~0); + void intc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t power_r(offs_t offset, uint32_t mem_mask = ~0); + void power_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + void update_interrupts(); + void set_irq_line(uint32_t line, int state); + + enum + { + INTC_BASE_ADDR = 0x90050000, + REG_ICIP = (0x00000000 >> 2), + REG_ICMR = (0x00000004 >> 2), + REG_ICLR = (0x00000008 >> 2), + REG_ICCR = (0x0000000c >> 2), + REG_ICFP = (0x00000010 >> 2), + REG_ICPR = (0x00000020 >> 2), + + POWER_BASE_ADDR = 0x90020000, + REG_PMCR = (0x00000000 >> 2), + REG_PSSR = (0x00000004 >> 2), + REG_PSPR = (0x00000008 >> 2), + REG_PWER = (0x0000000c >> 2), + REG_PCFR = (0x00000010 >> 2), + REG_PPCR = (0x00000014 >> 2), + REG_PGSR = (0x00000018 >> 2), + REG_POSR = (0x0000001c >> 2) + }; + + struct intc_regs + { + uint32_t icip; + uint32_t icmr; + uint32_t iclr; + uint32_t iccr; + uint32_t icfp; + uint32_t icpr; + }; + + struct power_regs + { + uint32_t pmcr; + uint32_t pssr; + uint32_t pspr; + uint32_t pwer; + uint32_t pcfr; + uint32_t ppcr; + uint32_t pgsr; + uint32_t posr; + }; + + intc_regs m_intc_regs; + power_regs m_power_regs; + + required_device<cpu_device> m_maincpu; +}; + +DECLARE_DEVICE_TYPE(SA1110_PERIPHERALS, sa1110_periphs_device) + +#endif // MAME_MACHINE_SA1110 diff --git a/src/devices/sound/k051649.cpp b/src/devices/sound/k051649.cpp index 29287ba63f9..07df808d42f 100644 --- a/src/devices/sound/k051649.cpp +++ b/src/devices/sound/k051649.cpp @@ -28,7 +28,6 @@ #include "k051649.h" #include <algorithm> -#define FREQ_BITS 16 #define DEF_GAIN 8 void k051649_device::scc_map(address_map &map) @@ -56,7 +55,6 @@ k051649_device::k051649_device(const machine_config &mconfig, const char *tag, d : device_t(mconfig, K051649, tag, owner, clock) , device_sound_interface(mconfig, *this) , m_stream(nullptr) - , m_mclock(0) , m_rate(0) , m_mixer_table(nullptr) , m_mixer_lookup(nullptr) @@ -74,7 +72,6 @@ void k051649_device::device_start() // get stream channels m_rate = clock()/16; m_stream = stream_alloc(0, 1, m_rate); - m_mclock = clock(); // allocate a buffer to mix into - 1 second's worth should be more than enough m_mixer_buffer.resize(2 * m_rate); @@ -83,14 +80,12 @@ void k051649_device::device_start() make_mixer_table(5); // save states - for (int voice = 0; voice < 5; voice++) - { - save_item(NAME(m_channel_list[voice].counter), voice); - save_item(NAME(m_channel_list[voice].frequency), voice); - save_item(NAME(m_channel_list[voice].volume), voice); - save_item(NAME(m_channel_list[voice].key), voice); - save_item(NAME(m_channel_list[voice].waveram), voice); - } + save_item(STRUCT_MEMBER(m_channel_list, counter)); + save_item(STRUCT_MEMBER(m_channel_list, clock)); + save_item(STRUCT_MEMBER(m_channel_list, frequency)); + save_item(STRUCT_MEMBER(m_channel_list, volume)); + save_item(STRUCT_MEMBER(m_channel_list, key)); + save_item(STRUCT_MEMBER(m_channel_list, waveram)); save_item(NAME(m_test)); } @@ -107,6 +102,7 @@ void k051649_device::device_reset() voice.frequency = 0; voice.volume = 0xf; voice.counter = 0; + voice.clock = 0; voice.key = false; } @@ -134,7 +130,6 @@ void k051649_device::device_clock_changed() { const u32 old_rate = m_rate; m_rate = clock()/16; - m_mclock = clock(); if (old_rate < m_rate) { @@ -159,19 +154,25 @@ void k051649_device::sound_stream_update(sound_stream &stream, stream_sample_t * if (voice.frequency > 8) { const int v = voice.volume * voice.key; - int c = voice.counter; - const int step = ((s64(m_mclock) << FREQ_BITS) / float((voice.frequency + 1) * 16 * (m_rate / 32))) + 0.5f; + int a = voice.counter; + int c = voice.clock; + const int step = voice.frequency; // add our contribution for (int i = 0; i < samples; i++) { - c += step; - const int offs = (c >> FREQ_BITS) & 0x1f; - m_mixer_buffer[i] += (voice.waveram[offs] * v) >> 3; + c += 32; + while (c > step) + { + a = (a + 1) & 0x1f; + c -= step+1; + } + m_mixer_buffer[i] += (voice.waveram[a] * v) >> 3; } // update the counter for this voice - voice.counter = c; + voice.counter = a; + voice.clock = c; } } @@ -212,9 +213,9 @@ u8 k051649_device::k051649_waveform_r(offs_t offset) m_stream->update(); if (offset >= 0x60) - offset += (m_channel_list[3 + (m_test >> 6 & 1)].counter >> FREQ_BITS); + offset += m_channel_list[3 + (m_test >> 6 & 1)].counter; else if (m_test & 0x40) - offset += (m_channel_list[offset >> 5].counter >> FREQ_BITS); + offset += m_channel_list[offset >> 5].counter; } return m_channel_list[offset >> 5].waveram[offset & 0x1f]; } @@ -237,7 +238,7 @@ u8 k051649_device::k052539_waveform_r(offs_t offset) if (m_test & 0x40) { m_stream->update(); - offset += (m_channel_list[offset >> 5].counter >> FREQ_BITS); + offset += m_channel_list[offset >> 5].counter; } return m_channel_list[offset >> 5].waveram[offset & 0x1f]; } @@ -259,9 +260,13 @@ void k051649_device::k051649_frequency_w(offs_t offset, u8 data) // test-register bit 5 resets the internal counter if (m_test & 0x20) - m_channel_list[offset].counter = ~0; + { + m_channel_list[offset].counter = 0; + m_channel_list[offset].clock = 0; + } + // TODO: correct? else if (m_channel_list[offset].frequency < 9) - m_channel_list[offset].counter |= ((1 << FREQ_BITS) - 1); + m_channel_list[offset].clock = 0; // update frequency if (freq_hi) diff --git a/src/devices/sound/k051649.h b/src/devices/sound/k051649.h index c8e3e31481e..f69ae00b707 100644 --- a/src/devices/sound/k051649.h +++ b/src/devices/sound/k051649.h @@ -46,6 +46,7 @@ private: { sound_channel() : counter(0), + clock(0), frequency(0), volume(0), key(false) @@ -53,11 +54,12 @@ private: std::fill(std::begin(waveram), std::end(waveram), 0); } - u64 counter; - int frequency; - int volume; - bool key; - s8 waveram[32]; + u8 counter; // address counter for wavetable + u32 clock; // internal clock + u16 frequency; // frequency; result: (input clock / (32 * (frequency + 1))) + int volume; // volume + bool key; // keyon/off + s8 waveram[32]; // 32 byte wavetable }; void make_mixer_table(int voices); @@ -66,7 +68,6 @@ private: /* global sound parameters */ sound_stream *m_stream; - int m_mclock; int m_rate; /* mixer tables and internal buffers */ diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index efdd93da307..eaa273ee886 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -233,11 +233,13 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu m_console.register_command("saved", CMDFLAG_NONE, AS_DATA, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2)); m_console.register_command("savei", CMDFLAG_NONE, AS_IO, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2)); m_console.register_command("saveo", CMDFLAG_NONE, AS_OPCODES, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2)); + m_console.register_command("saver", CMDFLAG_NONE, 0, 4, 4, std::bind(&debugger_commands::execute_saveregion, this, _1, _2)); m_console.register_command("load", CMDFLAG_NONE, AS_PROGRAM, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); m_console.register_command("loadd", CMDFLAG_NONE, AS_DATA, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); m_console.register_command("loadi", CMDFLAG_NONE, AS_IO, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); m_console.register_command("loado", CMDFLAG_NONE, AS_OPCODES, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); + m_console.register_command("loadr", CMDFLAG_NONE, 0, 4, 4, std::bind(&debugger_commands::execute_loadregion, this, _1, _2)); m_console.register_command("dump", CMDFLAG_NONE, AS_PROGRAM, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2)); m_console.register_command("dumpd", CMDFLAG_NONE, AS_DATA, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2)); @@ -530,6 +532,25 @@ bool debugger_commands::validate_cpu_space_parameter(const char *param, int spac /*------------------------------------------------- + validate_memory_region_parameter - validates + a parameter as a memory region name and + retrieves the given memory region +-------------------------------------------------*/ + +bool debugger_commands::validate_memory_region_parameter(const std::string ¶m, memory_region *&result) +{ + auto ®ions = m_machine.memory().regions(); + auto iter = regions.find(param); + if(iter == regions.end()) { + m_console.printf("No matching memory region found for '%s'\n", param); + return false; + } + result = iter->second.get(); + return true; +} + + +/*------------------------------------------------- debug_command_parameter_expression - validates an expression parameter -------------------------------------------------*/ @@ -1949,6 +1970,46 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa /*------------------------------------------------- + execute_saveregion - execute the save command on region memory +-------------------------------------------------*/ + +void debugger_commands::execute_saveregion(int ref, const std::vector<std::string> ¶ms) +{ + u64 offset, length; + memory_region *region; + FILE *f; + + /* validate parameters */ + if (!validate_number_parameter(params[1], offset)) + return; + if (!validate_number_parameter(params[2], length)) + return; + if (!validate_memory_region_parameter(params[3], region)) + return; + + /* open the file */ + f = fopen(params[0].c_str(), "wb"); + if (!f) { + m_console.printf("Error opening file '%s'\n", params[0].c_str()); + return; + } + + if(offset >= region->bytes()) { + m_console.printf("Invalide offset\n"); + return; + } + // get full length + if(length <= 0 || length + offset >= region->bytes()) { + length = region->bytes() - offset; + } + fwrite(region->base() + offset, 1, length, f); + + fclose(f); + m_console.printf("Data saved successfully\n"); +} + + +/*------------------------------------------------- execute_load - execute the load command -------------------------------------------------*/ @@ -2057,6 +2118,55 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa /*------------------------------------------------- + execute_saveregion - execute the save command on region memory +-------------------------------------------------*/ + +void debugger_commands::execute_loadregion(int ref, const std::vector<std::string> ¶ms) +{ + u64 offset, length; + memory_region *region; + FILE *f; + + /* validate parameters */ + if (!validate_number_parameter(params[1], offset)) + return; + if (!validate_number_parameter(params[2], length)) + return; + if (!validate_memory_region_parameter(params[3], region)) + return; + + /* open the file */ + f = fopen(params[0].c_str(), "rb"); + if (!f) { + m_console.printf("Error opening file '%s'\n", params[0].c_str()); + return; + } + + fseek(f, 0L, SEEK_END); + u64 size = ftell(f); + rewind(f); + + if(offset >= region->bytes()) { + m_console.printf("Invalide offset\n"); + return; + } + // get full length + if(length <= 0 || length + offset >= region->bytes()) { + length = region->bytes() - offset; + } + // check file size + if(length >= size) { + length = size; + } + + fread(region->base() + offset, 1, length, f); + + fclose(f); + m_console.printf("Data loaded successfully to memory : 0x%X to 0x%X\n", offset, offset + length - 1); +} + + +/*------------------------------------------------- execute_dump - execute the dump command -------------------------------------------------*/ diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index a47378765ff..04f54a4d75d 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -34,6 +34,9 @@ public: /* validates a parameter as a cpu and retrieves the given address space */ bool validate_cpu_space_parameter(const char *param, int spacenum, address_space *&result); + /* validates a parameter as a memory region name and retrieves the given region */ + bool validate_memory_region_parameter(const std::string ¶m, memory_region *&result); + private: struct global_entry { @@ -139,7 +142,9 @@ private: void execute_stateload(int ref, const std::vector<std::string> ¶ms); void execute_rewind(int ref, const std::vector<std::string> ¶ms); void execute_save(int ref, const std::vector<std::string> ¶ms); + void execute_saveregion(int ref, const std::vector<std::string> ¶ms); void execute_load(int ref, const std::vector<std::string> ¶ms); + void execute_loadregion(int ref, const std::vector<std::string> ¶ms); void execute_dump(int ref, const std::vector<std::string> ¶ms); void execute_cheatinit(int ref, const std::vector<std::string> ¶ms); void execute_cheatnext(int ref, const std::vector<std::string> ¶ms); diff --git a/src/emu/diexec.h b/src/emu/diexec.h index 55dc3d473df..c661544ba73 100644 --- a/src/emu/diexec.h +++ b/src/emu/diexec.h @@ -317,9 +317,7 @@ private: s32 m_inttrigger; // interrupt trigger index // clock and timing information -protected: // FIXME: MIPS3 accesses m_totalcycles directly from execute_burn - devise a better solution u64 m_totalcycles; // total device cycles executed -private: attotime m_localtime; // local time, relative to the timer system's global time s32 m_divisor; // 32-bit attoseconds_per_cycle divisor u8 m_divshift; // right shift amount to fit the divisor into 32 bits diff --git a/src/lib/formats/d40_dsk.cpp b/src/lib/formats/d40_dsk.cpp deleted file mode 100644 index 868c36a7eef..00000000000 --- a/src/lib/formats/d40_dsk.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:MetalliC -/********************************************************************* - - formats/d40_dsk.c - - Didaktik D40/D80 disk images - -*********************************************************************/ - -#include <cassert> - -#include "formats/d40_dsk.h" - -d40_format::d40_format() : wd177x_format(formats) -{ -} - -const char *d40_format::name() const -{ - return "d40"; -} - -const char *d40_format::description() const -{ - return "Didaktik D40/D80 floppy disk image"; -} - -const char *d40_format::extensions() const -{ - return "d40,d80"; -} - -const d40_format::format d40_format::formats[] = { - { // 400K 5"25 double density, gaps unverified - floppy_image::FF_525, floppy_image::DSDD, floppy_image::MFM, - 2000, 10, 40, 2, 512, {}, 1, {}, 50, 22, 36 - }, - { // 720K 3'5 double density, gaps unverified - floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM, - 2000, 9, 80, 2, 512, {}, 1, {}, 50, 22, 80 - }, - {} -}; - -const floppy_format_type FLOPPY_D40D80_FORMAT = &floppy_image_format_creator<d40_format>; diff --git a/src/lib/formats/d40_dsk.h b/src/lib/formats/d40_dsk.h deleted file mode 100644 index 93aa08e46af..00000000000 --- a/src/lib/formats/d40_dsk.h +++ /dev/null @@ -1,31 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:MetalliC -/********************************************************************* - - formats/d40_dsk.h - - Didaktik D40/D80 disk images - -*********************************************************************/ -#ifndef MAME_FORMATS_D40_DSK_H -#define MAME_FORMATS_D40_DSK_H - -#pragma once - -#include "wd177x_dsk.h" - -class d40_format : public wd177x_format { -public: - d40_format(); - - virtual const char *name() const override; - virtual const char *description() const override; - virtual const char *extensions() const override; - -private: - static const format formats[]; -}; - -extern const floppy_format_type FLOPPY_D40D80_FORMAT; - -#endif // MAME_FORMATS_D40_DSK_H diff --git a/src/mame/drivers/armedf.cpp b/src/mame/drivers/armedf.cpp index 5f61f9c4097..f64ed231a64 100644 --- a/src/mame/drivers/armedf.cpp +++ b/src/mame/drivers/armedf.cpp @@ -1032,13 +1032,13 @@ static INPUT_PORTS_START( bigfghtr ) PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:5") PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:6") + PORT_DIPNAME( 0x20, 0x20, "Debug 2 (requires Debug On) (P2 Start skip stage, Invulnerability)" ) PORT_DIPLOCATION("DSW1:6") PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x40, 0x40, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("DSW1:7") PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:8") + PORT_DIPNAME( 0x80, 0x80, "Debug (P1 Start to pause)" ) PORT_DIPLOCATION("DSW1:8") PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) INPUT_PORTS_END diff --git a/src/mame/drivers/braiplus.cpp b/src/mame/drivers/braiplus.cpp index 8ea6ac83db0..2e684f282b7 100644 --- a/src/mame/drivers/braiplus.cpp +++ b/src/mame/drivers/braiplus.cpp @@ -4,6 +4,22 @@ Skeleton driver for BraiLab Plus talking computer. + (from a document translated from Hungarian) +In addition to the Z80 microprocessor on the two-sided printed circuit board, +there are 256 Kbytes of dynamic RAM, 16 Kbytes of EPROM, 2 Z80PIOs, 4 Kbytes +of static RAM, a character generator EPROM, a WD2793 floppy disk controller, +a I8251 PUSART and a MEA-8000 speech synthesizer. + +180 Kbytes of 256 Kbytes of RAM is handled as a fixed RAM disk under the +CP/M operating system. Memory management supports the use of a dynamic RAM +fixed disk, provides the appropriate address space for the operating system, +and flips between them and between EPROMs. The two Z80PIOs perform centronics +interface, system clock interrupt handling, and serial programming of the +baud rate with serial interface I8251 and HD-4702. + +The increased size of 4 Kbytes memory enabled 25x80 character screen. +Floppy disk holds 792kb (formatted). + ***************************************************************************/ #include "emu.h" diff --git a/src/mame/drivers/ddenlovr.cpp b/src/mame/drivers/ddenlovr.cpp index 1dcca59af8d..e6fae1c1a76 100644 --- a/src/mame/drivers/ddenlovr.cpp +++ b/src/mame/drivers/ddenlovr.cpp @@ -5294,8 +5294,8 @@ static INPUT_PORTS_START( mmpanic ) PORT_DIPSETTING( 0x10, "3" ) PORT_DIPSETTING( 0x0c, "4" ) PORT_DIPSETTING( 0x08, "5" ) -// PORT_DIPSETTING( 0x04, "5" ) -// PORT_DIPSETTING( 0x00, "5" ) + PORT_DIPSETTING( 0x04, "5 (duplicate 1)" ) + PORT_DIPSETTING( 0x00, "5 (duplicate 2)" ) PORT_DIPNAME( 0x20, 0x20, "Linked Cabinets" ) PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) @@ -5378,79 +5378,69 @@ static INPUT_PORTS_START( animaljr ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("6") PORT_CODE(KEYCODE_6_PAD) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) + // dipswitches are 2 banks of 10 PORT_START("DSW1") - PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ) ) + PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ) ) PORT_DIPLOCATION("DSWA:1,2") PORT_DIPSETTING( 0x00, DEF_STR( 3C_1C ) ) PORT_DIPSETTING( 0x02, DEF_STR( 2C_1C ) ) PORT_DIPSETTING( 0x03, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0x01, DEF_STR( 1C_2C ) ) - PORT_DIPNAME( 0x04, 0x04, "Unknown 1-2" ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x08, "Unknown 1-3" ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x10, "Unknown 1-4" ) - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0xe0, 0x80, "Difficulty?" ) - PORT_DIPSETTING( 0xe0, "0" ) - PORT_DIPSETTING( 0xc0, "1" ) - PORT_DIPSETTING( 0xa0, "2" ) - PORT_DIPSETTING( 0x80, "3" ) - PORT_DIPSETTING( 0x60, "4" ) - PORT_DIPSETTING( 0x40, "5" ) - PORT_DIPSETTING( 0x20, "6" ) - PORT_DIPSETTING( 0x00, "7" ) + PORT_DIPNAME( 0x1c, 0x1c, "Difficulty" ) PORT_DIPLOCATION("DSWA:3,4,5") // manual lists 6 valid settings + PORT_DIPSETTING( 0x08, "Level 1" ) + PORT_DIPSETTING( 0x18, "Level 2" ) + PORT_DIPSETTING( 0x14, "Level 3" ) + PORT_DIPSETTING( 0x1c, "Level 4" ) + PORT_DIPSETTING( 0x0c, "Level 5" ) + PORT_DIPSETTING( 0x04, "Level 6" ) + PORT_DIPSETTING( 0x00, "unknown Level (00)" ) + PORT_DIPSETTING( 0x10, "unknown Level (10)" ) + PORT_DIPNAME( 0xe0, 0xe0, "Game Hit Probability" ) PORT_DIPLOCATION("DSWA:6,7,8") // manual lists 6 valid settings + PORT_DIPSETTING( 0x40, "1/15" ) + PORT_DIPSETTING( 0x60, "1/10" ) + PORT_DIPSETTING( 0x80, "1/7" ) + PORT_DIPSETTING( 0xe0, "1/5" ) + PORT_DIPSETTING( 0xa0, "1/4" ) + PORT_DIPSETTING( 0xc0, "1/3" ) + PORT_DIPSETTING( 0x00, "unknown Probability (00)" ) + PORT_DIPSETTING( 0x20, "unknown Probability (20)" ) PORT_START("DSW2") - PORT_DIPNAME( 0x01, 0x01, DEF_STR( Flip_Screen ) ) + PORT_DIPNAME( 0x01, 0x01, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("DSWB:1") PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Demo_Sounds ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("DSWB:2") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, "Unknown 2-2*" ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x18, 0x18, "Unknown 2-3&4" ) // used ? -// PORT_DIPSETTING( 0x10, "0" ) - PORT_DIPSETTING( 0x00, "0" ) - PORT_DIPSETTING( 0x18, "1" ) - PORT_DIPSETTING( 0x08, "2" ) - PORT_DIPNAME( 0x20, 0x20, "Unknown 2-5" ) + PORT_DIPNAME( 0x04, 0x04, "Attract Sound Type" ) PORT_DIPLOCATION("DSWB:3") + PORT_DIPSETTING( 0x04, "Type 1" ) + PORT_DIPSETTING( 0x00, "Type 2" ) + PORT_DIPNAME( 0x18, 0x18, "Bonus Game Type" ) PORT_DIPLOCATION("DSWB:4,5") + PORT_DIPSETTING( 0x18, "Type 1" ) + PORT_DIPSETTING( 0x10, "Type 2" ) + PORT_DIPSETTING( 0x08, "Without" ) + PORT_DIPSETTING( 0x00, "Type 2 (duplicate)" ) + PORT_DIPNAME( 0x20, 0x20, "Unknown B-6 (debug?)" ) PORT_DIPLOCATION("DSWB:6") // manual lists 'unused, should remain OFF' PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "Pirate Fight" ) + PORT_DIPNAME( 0x40, 0x40, "Pirate Fight (debug?)" ) PORT_DIPLOCATION("DSWB:7") // manual lists 'unused, should remain OFF' PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, "Taito Copyright" ) + PORT_DIPNAME( 0x80, 0x80, "Taito Copyright (debug?)" ) PORT_DIPLOCATION("DSWB:8") // manual lists 'unused, should remain OFF' PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x80, DEF_STR( On ) ) PORT_START("DSW3") - PORT_DIPNAME( 0x01, 0x01, "Unknown 3-0*" ) + PORT_DIPNAME( 0x01, 0x01, "Unknown A-9 (debug?)" ) PORT_DIPLOCATION("DSWA:9") // manual lists 'unused, MUST remain OFF' PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, "Tickets" ) + PORT_DIPNAME( 0x02, 0x02, "Tickets" ) PORT_DIPLOCATION("DSWA:10") PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, "Unknown 3-2*" ) + PORT_DIPNAME( 0x04, 0x04, "Unknown B-9 (debug?)" ) PORT_DIPLOCATION("DSWB:9") // manual lists 'unused, should remain OFF' PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_SERVICE( 0x08, IP_ACTIVE_LOW ) - PORT_DIPNAME( 0x10, 0x10, "Unknown 3-4" ) - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, "Unknown 3-5" ) - PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, "Unknown 3-6" ) - PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, "Unknown 3-7" ) - PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_SERVICE( 0x08, IP_ACTIVE_LOW ) PORT_DIPLOCATION("DSWB:10") + PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNKNOWN ) INPUT_PORTS_END @@ -13025,50 +13015,82 @@ ROM_START( htengoku ) ROM_END GAME( 1992, htengoku, 0, htengoku, htengoku, ddenlovr_state, empty_init, ROT180, "Dynax", "Hanafuda Hana Tengoku [BET] (Japan)", 0) + GAME( 1992, mmpanic, 0, mmpanic, mmpanic, ddenlovr_state, empty_init, ROT0, "Nakanihon / East Technology (Taito license)", "Monkey Mole Panic (USA)", MACHINE_NO_COCKTAIL ) +// "Waiwai Animal Land" (without the Jr.) should be the original Japanese version of Monkey Mole Panic + GAME( 1993, mjmyorn2, 0, mjmyornt, mjmyorn2, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong The Mysterious Orient Part 2 ~ Exotic Dream ~ [BET] (Japan, v1.00)", MACHINE_NO_COCKTAIL ) // no copyright warning, assume Japan from game strings GAME( 1992, mjmyornt, mjmyorn2, mjmyornt, mjmyornt, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong The Mysterious Orient [BET] (Japan, v1.00)", MACHINE_NO_COCKTAIL ) // no copyright warning, assume Japan from game strings + GAME( 1993, funkyfig, 0, funkyfig, funkyfig, ddenlovr_state, empty_init, ROT0, "Nakanihon / East Technology (Taito license)", "The First Funky Fighter (USA, Canada, Mexico / Japan, set 1)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS ) // scrolling, priority? GAME( 1993, funkyfiga, funkyfig, funkyfig, funkyfig, ddenlovr_state, empty_init, ROT0, "Nakanihon / East Technology (Taito license)", "The First Funky Fighter (USA, Canada, Mexico / Japan, set 2)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS ) // "" + GAME( 1993, quizchq, 0, quizchq, quizchq, ddenlovr_state, empty_init, ROT0, "Nakanihon", "Quiz Channel Question (Japan, Ver 1.00)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) GAME( 1993, quizchql, quizchq, quizchq, quizchq, ddenlovr_state, empty_init, ROT0, "Nakanihon (Laxan license)", "Quiz Channel Question (Taiwan?, Ver 1.23)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) + GAME( 1993, animaljr, 0, mmpanic, animaljr, ddenlovr_state, empty_init, ROT0, "Nakanihon / East Technology (Taito license)", "Exciting Animal Land Jr. (USA, Canada, Mexico)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_SOUND ) GAME( 1993, animaljrs, animaljr, mmpanic, animaljr, ddenlovr_state, empty_init, ROT0, "Nakanihon / East Technology (Taito license)", "Animalandia Jr. (Spanish)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_SOUND ) GAME( 1993, animaljrj, animaljr, mmpanic, animaljr, ddenlovr_state, empty_init, ROT0, "Nakanihon / East Technology (Taito license)", "Waiwai Animal Land Jr. (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1994, mjmyster, 0, mjmyster, mjmyster, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong The Mysterious World [BET] (Japan, set 1)", MACHINE_NO_COCKTAIL ) GAME( 1994, mjmywrld, mjmyster, mjmywrld, mjmyster, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong The Mysterious World [BET] (Japan, set 2)", MACHINE_NO_COCKTAIL ) + GAME( 1994, hginga, 0, hginga, hginga, ddenlovr_state, empty_init, ROT0, "Dynax", "Hanafuda Hana Ginga [BET] (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1994, mjmyuniv, 0, mjmyuniv, mjmyster, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong The Mysterious Universe [BET] (Japan, D85)", MACHINE_NO_COCKTAIL ) + GAME( 1994, quiz365, 0, quiz365, quiz365, ddenlovr_state, empty_init, ROT0, "Nakanihon", "Quiz 365 (Japan)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS | MACHINE_UNEMULATED_PROTECTION ) GAME( 1994, quiz365t, quiz365, quiz365, quiz365, ddenlovr_state, empty_init, ROT0, "Nakanihon / Taito", "Quiz 365 (Hong Kong & Taiwan)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS | MACHINE_UNEMULATED_PROTECTION ) + GAME( 1994, rongrong, 0, rongrong, rongrong, ddenlovr_state, init_rongrong, ROT0, "Nakanihon (Activision license)", "Puzzle Game Rong Rong (Europe)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_COLORS ) GAME( 1994, rongrongj, rongrong, rongrong, rongrong, ddenlovr_state, init_rongrong, ROT0, "Nakanihon (Activision license)", "Puzzle Game Rong Rong (Japan)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_COLORS ) GAME( 1994, rongrongg, rongrong, rongrong, rongrong, ddenlovr_state, init_rongrong, ROT0, "Nakanihon (Activision license)", "Puzzle Game Rong Rong (Germany)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_COLORS ) + GAME( 1994, hparadis, 0, hparadis, hparadis, ddenlovr_state, empty_init, ROT0, "Dynax", "Super Hana Paradise (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1995, hgokou, 0, hgokou, hgokou, ddenlovr_state, empty_init, ROT0, "Dynax (Alba license)", "Hanafuda Hana Gokou [BET] (Japan)", MACHINE_NO_COCKTAIL ) GAME( 1995, hgokbang, hgokou, hgokbang, hgokou, ddenlovr_state, empty_init, ROT0, "Dynax", "Hanafuda Hana Gokou Bangaihen [BET] (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1995, mjdchuka, 0, mjchuuka, mjchuuka, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong The Dai Chuuka Ken [BET] (China, D111)", MACHINE_NO_COCKTAIL ) + GAME( 1995, mjschuka, 0, mjschuka, mjschuka, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong Super Dai Chuuka Ken [BET] (Japan, D115)", MACHINE_NO_COCKTAIL ) + GAME( 1995, nettoqc, 0, nettoqc, nettoqc, ddenlovr_state, empty_init, ROT0, "Nakanihon", "Nettoh Quiz Champion (Japan)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_COLORS ) GAME( 1995, ultrchmp, nettoqc, ultrchmp, ultrchmp, ddenlovr_state, empty_init, ROT0, "Nakanihon", "Se Gye Hweng Dan Ultra Champion (Korea)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_COLORS ) GAME( 1995, ultrchmph, nettoqc, ultrchmp, ultrchmp, ddenlovr_state, empty_init, ROT0, "Nakanihon", "Cheng Ba Shi Jie - Chao Shi Kong Guan Jun (Taiwan)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_COLORS ) + GAME( 1995, ddenlovj, 0, ddenlovj, ddenlovj, ddenlovr_state, empty_init, ROT0, "Dynax", "Don Den Lover Vol. 1 - Shiro Kuro Tsukeyo! (Japan)", MACHINE_NO_COCKTAIL ) GAME( 1995, ddenlovrk, ddenlovj, ddenlovrk, ddenlovr, ddenlovr_state, empty_init, ROT0, "Dynax", "Don Den Lover Vol. 1 - Heukbaeg-euro Jeonghaja (Korea)", MACHINE_NO_COCKTAIL ) GAME( 1995, ddenlovrb, ddenlovj, ddenlovr, ddenlovr, ddenlovr_state, empty_init, ROT0, "bootleg", "Don Den Lover Vol. 1 - Heukbaeg-euro Jeonghaja (Korea, bootleg)", MACHINE_NO_COCKTAIL ) GAME( 1996, ddenlovr, ddenlovj, ddenlovr, ddenlovr, ddenlovr_state, empty_init, ROT0, "Dynax", "Don Den Lover Vol. 1 (Hong Kong)", MACHINE_NO_COCKTAIL ) + GAME( 1996, hanakanz, 0, hanakanz, hanakanz, ddenlovr_state, empty_init, ROT0, "Dynax", "Hana Kanzashi (Japan)", MACHINE_NO_COCKTAIL ) GAME( 1997, kotbinyo, hanakanz, kotbinyo, kotbinyo, ddenlovr_state, empty_init, ROT0, "Dynax / Shinwhajin", "Kkot Bi Nyo (Korea)", MACHINE_NO_COCKTAIL ) + GAME( 1997, kotbinsp, 0, kotbinsp, kotbinsp, ddenlovr_state, empty_init, ROT0, "Dynax / Shinwhajin", "Kkot Bi Nyo Special (Korea)", MACHINE_NO_COCKTAIL ) + GAME( 1996, akamaru, 0, akamaru, akamaru, ddenlovr_state, empty_init, ROT0, "Dynax (Nakanihon license)", "Panel & Variety Akamaru Q Jousyou Dont-R", MACHINE_NO_COCKTAIL ) + GAME( 1996, janshinp, 0, janshinp, janshinp, ddenlovr_state, empty_init, ROT0, "Dynax / Sigma", "Mahjong Janshin Plus [BET] (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1996, dtoyoken, 0, dtoyoken, dtoyoken, ddenlovr_state, empty_init, ROT0, "Dynax / Sigma", "Mahjong Dai Touyouken [BET] (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1996, sryudens, 0, sryudens, sryudens, ddenlovr_state, empty_init, ROT0, "Dynax / Face", "Mahjong Seiryu Densetsu [BET] (Japan, NM502)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS ) + GAME( 1996, seljan2, 0, seljan2, seljan2, ddenlovr_state, empty_init, ROT0, "Dynax / Face", "Return Of Sel Jan II [BET] (Japan, NM557)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS ) + GAME( 1996, mjflove, 0, mjflove, mjflove, ddenlovr_state, empty_init, ROT0, "Nakanihon", "Mahjong Fantasic Love (Japan)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS ) + GAME( 1997, hkagerou, 0, hkagerou, hkagerou, ddenlovr_state, empty_init, ROT0, "Nakanihon / Dynax", "Hana Kagerou [BET] (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1998, mjchuuka, 0, mjchuuka, mjchuuka, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong Chuukanejyo [BET] (China)", MACHINE_NO_COCKTAIL ) + GAME( 1998, mjreach1, 0, mjreach1, mjreach1, ddenlovr_state, empty_init, ROT0, "Nihon System", "Mahjong Reach Ippatsu [BET] (Japan)", MACHINE_NO_COCKTAIL ) + GAME( 1999, jongtei, 0, jongtei, jongtei, ddenlovr_state, empty_init, ROT0, "Dynax", "Mahjong Jong-Tei [BET] (Japan, NM532-01)", MACHINE_NO_COCKTAIL ) + GAME( 2000, mjgnight, 0, mjgnight, mjgnight, ddenlovr_state, empty_init, ROT0, "Techno-Top", "Mahjong Gorgeous Night [BET] (Japan, TSM003-01)", MACHINE_NO_COCKTAIL ) + GAME( 2002, daimyojn, 0, daimyojn, daimyojn, ddenlovr_state, empty_init, ROT0, "Dynax / Techno-Top / Techno-Planning", "Mahjong Daimyojin [BET] (Japan, T017-PB-00)", MACHINE_NO_COCKTAIL ) + GAME( 2004, momotaro, 0, daimyojn, daimyojn, ddenlovr_state, init_momotaro, ROT0, "Techno-Top", "Mahjong Momotarou [BET] (Japan, T027-RB-01)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) diff --git a/src/mame/drivers/fidel_elite.cpp b/src/mame/drivers/fidel_elite.cpp index 21cfee30381..f39022001cd 100644 --- a/src/mame/drivers/fidel_elite.cpp +++ b/src/mame/drivers/fidel_elite.cpp @@ -10,7 +10,7 @@ TODO: - add feas (original program) BTANB: -- feasglaa locks up at boot if it was powered off in the middle of the game. +- feasglab locks up at boot if it was powered off in the middle of the game. To resolve this, hold the Game Control button while booting to clear nvram. The ROM dump was verified from 2 chesscomputers. @@ -570,6 +570,42 @@ ROM_END ROM_START( feasglaa ) ROM_REGION( 0x10000, "mainmap", 0 ) + ROM_LOAD("orange", 0x8000, 0x0800, CRC(32784e2d) SHA1(dae060a5c49cc1993a78db293cd80464adfd892d) ) + ROM_CONTINUE( 0x9000, 0x0800 ) + ROM_CONTINUE( 0x8800, 0x0800 ) + ROM_CONTINUE( 0x9800, 0x0800 ) + ROM_LOAD("black", 0xc000, 0x0800, CRC(3f0b01b6) SHA1(fe8d214f1678e000ba945e2f6dc3438af97c6f33) ) // only 2 bytes different + ROM_CONTINUE( 0xd000, 0x0800 ) + ROM_CONTINUE( 0xc800, 0x0800 ) + ROM_CONTINUE( 0xd800, 0x0800 ) + ROM_LOAD("green", 0xe000, 0x0800, CRC(62a5305a) SHA1(a361bd9a54b903d7b0fbacabe55ea5ccbbc1dc51) ) + ROM_CONTINUE( 0xf000, 0x0800 ) + ROM_CONTINUE( 0xe800, 0x0800 ) + ROM_CONTINUE( 0xf800, 0x0800 ) + + // speech ROM + ROM_DEFAULT_BIOS("en") + ROM_SYSTEM_BIOS(0, "en", "English") + ROM_SYSTEM_BIOS(1, "de", "German") + ROM_SYSTEM_BIOS(2, "fr", "French") + ROM_SYSTEM_BIOS(3, "sp", "Spanish") + + ROM_REGION( 1, "language", 0 ) + ROMX_FILL(0, 1, 3, ROM_BIOS(0) ) + ROMX_FILL(0, 1, 2, ROM_BIOS(1) ) + ROMX_FILL(0, 1, 1, ROM_BIOS(2) ) + ROMX_FILL(0, 1, 0, ROM_BIOS(3) ) + + ROM_REGION( 0x2000, "speech", 0 ) + ROMX_LOAD("101-32107", 0x0000, 0x1000, CRC(f35784f9) SHA1(348e54a7fa1e8091f89ac656b4da22f28ca2e44d), ROM_BIOS(0) ) + ROM_RELOAD( 0x1000, 0x1000) + ROMX_LOAD("101-64101", 0x0000, 0x2000, CRC(6c85e310) SHA1(20d1d6543c1e6a1f04184a2df2a468f33faec3ff), ROM_BIOS(1) ) + ROMX_LOAD("101-64105", 0x0000, 0x2000, CRC(fe8c5c18) SHA1(2b64279ab3747ee81c86963c13e78321c6cfa3a3), ROM_BIOS(2) ) + ROMX_LOAD("101-64106", 0x0000, 0x2000, CRC(8766e128) SHA1(78c7413bf240159720b131ab70bfbdf4e86eb1e9), ROM_BIOS(3) ) +ROM_END + +ROM_START( feasglab ) + ROM_REGION( 0x10000, "mainmap", 0 ) ROM_LOAD("6a", 0x8000, 0x0800, CRC(2fdddb4f) SHA1(6da0a328a45462f285ae6a0756f97c5a43148f97) ) ROM_CONTINUE( 0x9000, 0x0800 ) ROM_CONTINUE( 0x8800, 0x0800 ) @@ -761,6 +797,7 @@ ROM_END CONS( 1983, feasbu, 0, 0, eas, eas, elite_state, empty_init, "Fidelity Electronics", "Elite A/S Challenger (Budapest program)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_TIMING ) CONS( 1984, feasgla, feasbu, 0, eas, eas, elite_state, empty_init, "Fidelity Electronics", "Elite A/S Challenger (Glasgow program, set 1)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_TIMING ) CONS( 1984, feasglaa, feasbu, 0, eas, eas, elite_state, empty_init, "Fidelity Electronics", "Elite A/S Challenger (Glasgow program, set 2)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_TIMING ) +CONS( 1984, feasglab, feasbu, 0, eas, eas, elite_state, empty_init, "Fidelity Electronics", "Elite A/S Challenger (Glasgow program, set 3)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_TIMING ) CONS( 1982, fpres, 0, 0, pc, pc, elite_state, empty_init, "Fidelity Electronics", "Prestige Challenger (original program)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_TIMING ) CONS( 1983, fpresbu, fpres, 0, pc, pc, elite_state, empty_init, "Fidelity Electronics", "Prestige Challenger (Budapest program)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_TIMING ) diff --git a/src/mame/drivers/gigatron.cpp b/src/mame/drivers/gigatron.cpp index e589c88f201..30590ebc4a2 100644 --- a/src/mame/drivers/gigatron.cpp +++ b/src/mame/drivers/gigatron.cpp @@ -48,6 +48,7 @@ private: } void blinkenlights(uint8_t data); + uint8_t inputs(); required_device<gigatron_cpu_device> m_maincpu; required_ioport m_io_inputs; @@ -82,6 +83,11 @@ void gigatron_state::blinkenlights(uint8_t data) lights_changed ^= light; } +uint8_t gigatron_state::inputs() +{ + return m_io_inputs->read() ^ 0xFF; +} + static INPUT_PORTS_START(gigatron) PORT_START("GAMEPAD") PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) @@ -100,6 +106,7 @@ void gigatron_state::gigatron(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &gigatron_state::prog_map); m_maincpu->set_addrmap(AS_DATA, &gigatron_state::data_map); m_maincpu->outx_cb().set(FUNC(gigatron_state::blinkenlights)); + m_maincpu->ir_cb().set(FUNC(gigatron_state::inputs)); /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); diff --git a/src/mame/drivers/hh_sm510.cpp b/src/mame/drivers/hh_sm510.cpp index 582c9038c3c..14fb751f7d5 100644 --- a/src/mame/drivers/hh_sm510.cpp +++ b/src/mame/drivers/hh_sm510.cpp @@ -4245,7 +4245,7 @@ static INPUT_PORTS_START( gnw_dkong3 ) PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_CHANGED_CB(acl_button) PORT_NAME("ACL") PORT_START("B") - PORT_CONFNAME( 0x01, 0x01, "P1 Infinite Health (Cheat)") // " + PORT_CONFNAME( 0x01, 0x01, "P1 Infinite Lives (Cheat)") // factory test, unpopulated on PCB PORT_CONFSETTING( 0x01, DEF_STR( Off ) ) PORT_CONFSETTING( 0x00, DEF_STR( On ) ) INPUT_PORTS_END diff --git a/src/mame/drivers/kawai_ksp10.cpp b/src/mame/drivers/kawai_ksp10.cpp new file mode 100644 index 00000000000..ce117e7a229 --- /dev/null +++ b/src/mame/drivers/kawai_ksp10.cpp @@ -0,0 +1,54 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/**************************************************************************** + + Skeleton driver for Kawai KSP10 digital piano. + +****************************************************************************/ + +#include "emu.h" +#include "cpu/tlcs900/tmp96c141.h" + +class kawai_ksp10_state : public driver_device +{ +public: + kawai_ksp10_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + { + } + + void ksp10(machine_config &config); + +private: + void mem_map(address_map &map); + + required_device<tmp96c141_device> m_maincpu; +}; + + +void kawai_ksp10_state::mem_map(address_map &map) +{ + map(0x000000, 0x07ffff).rom().region("firmware", 0); + map(0x400000, 0x407fff).ram(); // NVRAM? +} + + +static INPUT_PORTS_START(ksp10) +INPUT_PORTS_END + +void kawai_ksp10_state::ksp10(machine_config &config) +{ + TMP96C141(config, m_maincpu, 10'000'000); // clock unknown + m_maincpu->set_addrmap(AS_PROGRAM, &kawai_ksp10_state::mem_map); +} + +ROM_START(ksp10) + ROM_REGION16_LE(0x80000, "firmware", 0) + ROM_LOAD("u3_hp041b_e8dp_tms27c240.bin", 0x00000, 0x80000, CRC(b64e7a97) SHA1(bac0f345d0a039a3315883a6ca8eefe659709a26)) + + ROM_REGION16_LE(0x40000, "samples", 0) + ROM_LOAD("u21_hp042a_e7dp_mbm27c2048.bin", 0x00000, 0x40000, CRC(e21b1141) SHA1(181c2beed18da2efa2f0e45cb3233adf6b932127)) +ROM_END + +SYST(199?, ksp10, 0, 0, ksp10, ksp10, kawai_ksp10_state, empty_init, "Kawai Musical Instruments Manufacturing", "KSP10 Digital Piano", MACHINE_IS_SKELETON) diff --git a/src/mame/drivers/microkorg.cpp b/src/mame/drivers/microkorg.cpp new file mode 100644 index 00000000000..7f57f2d1912 --- /dev/null +++ b/src/mame/drivers/microkorg.cpp @@ -0,0 +1,61 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/**************************************************************************** + + Skeleton driver for Korg microKORG compact synthesizer/vocoder. + + The MS2000 Analog Modeling Synthesizer runs on similar hardware. + +****************************************************************************/ + +#include "emu.h" +#include "cpu/h8/h8s2320.h" +#include "machine/intelfsh.h" + +class microkorg_state : public driver_device +{ +public: + microkorg_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + { + } + + void microkorg(machine_config &config); + +private: + void mem_map(address_map &map); + + required_device<h8s2320_device> m_maincpu; +}; + + +void microkorg_state::mem_map(address_map &map) +{ + map(0x000000, 0x0fffff).rw("flash", FUNC(intelfsh16_device::read), FUNC(intelfsh16_device::write)); + map(0x400000, 0x47ffff).ram(); +} + + +static INPUT_PORTS_START(microkorg) +INPUT_PORTS_END + +void microkorg_state::microkorg(machine_config &config) +{ + H8S2320(config, m_maincpu, 10_MHz_XTAL); // HD6412320VF25 (or HD6412324SVF25) + m_maincpu->set_addrmap(AS_PROGRAM, µkorg_state::mem_map); + // TODO: serial channel 0 is SPI link to DSP; serial channel 1 is MIDI + + FUJITSU_29LV800B(config, "flash"); // MBM29LV800BA-90PFTN + + //DSP56362(config, "dsp", 12.288_MHz_XTAL / 4); // DSPB56362PV100 + + //AK4522(config, "codec", 12.288_MHz_XTAL); // AK4522VF +} + +ROM_START(microkorg) + ROM_REGION16_LE(0x100000, "flash", 0) + ROM_LOAD("korg_microkorg_v1.03_29lv800b.ic20", 0x000000, 0x100000, CRC(607ada7e) SHA1(4a6e2f4068cac7493484af2a8c1d1db7d8bd7a17)) +ROM_END + +SYST(2002, microkorg, 0, 0, microkorg, microkorg, microkorg_state, empty_init, "Korg", "microKORG Synthesizer/Vocoder", MACHINE_IS_SKELETON) diff --git a/src/mame/drivers/nes_vt.cpp b/src/mame/drivers/nes_vt.cpp index 2d128fb9c35..653ef17ac1c 100644 --- a/src/mame/drivers/nes_vt.cpp +++ b/src/mame/drivers/nes_vt.cpp @@ -1985,7 +1985,7 @@ CONS( 200?, megapad, 0, 0, nes_vt_waixing_2mb, nes_vt, nes_vt_waixing_ CONS( 2006, ablmini, 0, 0, nes_vt_waixing_alt_pal_8mb, nes_vt, nes_vt_waixing_alt_state, empty_init, "Advance Bright Ltd", "Double Players Mini Joystick 80-in-1 (MJ8500, ABL TV Game)", MACHINE_IMPERFECT_GRAPHICS ) // silver 'N64' type controller design -CONS( 200?, zudugo, 0, 0, nes_vt_waixing_alt_4mb, nes_vt, nes_vt_waixing_alt_state, empty_init, "<unknown>", "Zudu-go / 2udu-go", MACHINE_IMPERFECT_GRAPHICS ) // the styling on the box looks like a '2' in places, a 'Z' in others. +CONS( 200?, zudugo, 0, 0, nes_vt_waixing_alt_4mb, nes_vt, nes_vt_waixing_alt_state, empty_init, "Macro Winners / Waixing", "Zudu-go / 2udu-go", MACHINE_IMPERFECT_GRAPHICS ) // the styling on the box looks like a '2' in places, a 'Z' in others. // needs PCM samples, Y button is not mapped (not used by any of the games?) CONS( 200?, timetp36, 0, 0, nes_vt_pal_4mb, timetp36, nes_vt_timetp36_state, empty_init, "TimeTop", "Super Game 36-in-1 (TimeTop SuperGame) (PAL)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) diff --git a/src/mame/drivers/startouch.cpp b/src/mame/drivers/startouch.cpp index 6f6708b9a04..2d3a3d5c1f7 100644 --- a/src/mame/drivers/startouch.cpp +++ b/src/mame/drivers/startouch.cpp @@ -62,20 +62,25 @@ void startouch_state::europl01(machine_config &config) } ROM_START(europl01) + + // Sleic used different motherboards for this machine. By now, we're adding the all the known BIOSes here ROM_REGION(0x20000, "mb_bios", 0) - ROM_LOAD( "award_pci-pnp_586_222951562_v4.51pg.u2", 0x00000, 0x20000, CRC(5bb1bcbc) SHA1(6e2a7b5b3fc892ed20d0b12a1a533231c8953177) ) + ROM_SYSTEM_BIOS(0, "soyo_m5eh_aw4_52", "Soyo M5EH with Award 4.51pg BIOS") // Soyo M5EH V1.2 (1MB cache) + ROMX_LOAD("award_pci-pnp_586_222951562_v4.51pg.u2", 0x00000, 0x20000, CRC(5bb1bcbc) SHA1(6e2a7b5b3fc892ed20d0b12a1a533231c8953177), ROM_BIOS(0)) + ROM_SYSTEM_BIOS(1, "bst_m5atd_aw4_52", "Biostar M5ATD with Award 4.51pg BIOS") // Biostar M5ATD V1.2 (ALi M5819P + ALi M1543 B1 + ALi M1531 B1 + UMC UM61L6464F-6) + ROMX_LOAD("award_pci_pnp_586_w29c011a.u11", 0x00000, 0x20000, CRC(1ec5749b) SHA1(3dd1dac852b00c8108aaf9c89f47ae1922d645f0), ROM_BIOS(1)) ROM_REGION(0x8000, "vga_bios", 0) - ROM_LOAD( "s3_86c775-86c785_video_bios_v1.01.04.u5", 0x0000, 0x8000, CRC(e718418f) SHA1(1288ce51bb732a346eb7c61d5bdf80ea22454d45) ) + ROM_LOAD("s3_86c775-86c785_video_bios_v1.01.04.u5", 0x0000, 0x8000, CRC(e718418f) SHA1(1288ce51bb732a346eb7c61d5bdf80ea22454d45)) ROM_REGION(0x20000, "hd_firmware", 0) - ROM_LOAD( "jk200-35.bin", 0x00000, 0x20000, CRC(601fa709) SHA1(13ded4826a64209faac8bc81708172b81195ab96) ) + ROM_LOAD("jk200-35.bin", 0x00000, 0x20000, CRC(601fa709) SHA1(13ded4826a64209faac8bc81708172b81195ab96)) ROM_REGION(0x66da4, "dongle", 0) - ROM_LOAD( "9b91f19d.hsp", 0x00000, 0x66da4, CRC(0cf78908) SHA1(c596f415accd6b91be85ea8c1b89ea380d0dc6c8) ) + ROM_LOAD("9b91f19d.hsp", 0x00000, 0x66da4, CRC(0cf78908) SHA1(c596f415accd6b91be85ea8c1b89ea380d0dc6c8)) DISK_REGION( "ide:0:hdd:image" ) - DISK_IMAGE( "sleic-petaco_startouch_2001_v2.0", 0, SHA1(3164a5786d6b9bb0dd9910b4d27a77a6b746dedf) ) // labeled startouch_2001 but when run game title is EuroPlay 2001 + DISK_IMAGE("sleic-petaco_startouch_2001_v2.0", 0, SHA1(3164a5786d6b9bb0dd9910b4d27a77a6b746dedf)) // labeled startouch_2001 but when run game title is EuroPlay 2001 ROM_END diff --git a/src/mame/drivers/ti99_2.cpp b/src/mame/drivers/ti99_2.cpp index faf077a3dba..4bd2a136bf4 100644 --- a/src/mame/drivers/ti99_2.cpp +++ b/src/mame/drivers/ti99_2.cpp @@ -193,6 +193,7 @@ public: m_io992(*this, TI992_IO_TAG), m_cassette(*this, TI992_CASSETTE), m_ram(*this, TI992_RAM_TAG), + m_expport(*this, TI992_EXPPORT_TAG), m_otherbank(false), m_rom(nullptr), m_ram_start(0xf000), @@ -230,6 +231,8 @@ private: required_device<cassette_image_device> m_cassette; required_device<ram_device> m_ram; + required_device<bus::ti99::internal::ti992_expport_device> m_expport; + bool m_otherbank; uint8_t* m_rom; @@ -322,6 +325,7 @@ void ti99_2_state::intflag_write(offs_t offset, uint8_t data) */ uint8_t ti99_2_state::mem_read(offs_t offset) { + uint8_t value = 0; if (m_maincpu->is_onchip(offset)) return m_maincpu->debug_read_onchip_memory(offset&0xff); int page = offset >> 12; @@ -329,22 +333,23 @@ uint8_t ti99_2_state::mem_read(offs_t offset) if (page>=0 && page<4) { // ROM, unbanked - return m_rom[offset]; + value = m_rom[offset]; } if (page>=4 && page<6) { // ROM, banked on 32K version if (m_otherbank) offset = (offset & 0x1fff) | 0x10000; - return m_rom[offset]; + value = m_rom[offset]; } if ((page >= m_first_ram_page) && (page < 15)) { - return m_ram->pointer()[offset - m_ram_start]; + value = m_ram->pointer()[offset - m_ram_start]; } - LOGMASKED(LOG_WARN, "Unmapped read access at %04x\n", offset); - return 0; + m_expport->readz(offset, &value); + + return value; } void ti99_2_state::mem_write(offs_t offset, uint8_t data) @@ -370,7 +375,7 @@ void ti99_2_state::mem_write(offs_t offset, uint8_t data) return; } - LOGMASKED(LOG_WARN, "Unmapped write access at %04x\n", offset); + m_expport->write(offset, data); } /* @@ -470,6 +475,9 @@ void ti99_2_state::ti99_2(machine_config& config) // Hexbus HEXBUS(config, TI992_HEXBUS_TAG, 0, hexbus_options, nullptr); + + // Expansion port (backside) + TI992_EXPPORT(config, m_expport, 0, ti992_expport_options, nullptr); } /* diff --git a/src/mame/drivers/zaurus.cpp b/src/mame/drivers/zaurus.cpp index 4a1cac86b38..b8d80ce1aeb 100644 --- a/src/mame/drivers/zaurus.cpp +++ b/src/mame/drivers/zaurus.cpp @@ -5,10 +5,7 @@ Sharp Zaurus PDA skeleton driver (SL, ARM/Linux based, 4th generation) TODO: - - PXA-255 ID opcode fails on this - ARM TLB look-up errors? - - RTC IRQ doesn't fire? - - For whatever reason, after RTC check ARM executes invalid code at 0-0x200 - Dumps are questionable ========================================================================================================================================= @@ -1407,6 +1404,7 @@ Note: #include "cpu/arm7/arm7.h" #include "cpu/arm7/arm7core.h" #include "machine/pxa255.h" +#include "machine/sa1110.h" #include "machine/timer.h" #include "emupal.h" #include "screen.h" @@ -1423,121 +1421,133 @@ class zaurus_state : public driver_device public: zaurus_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) - , m_pxa_periphs(*this, "pxa_periphs") , m_maincpu(*this, "maincpu") , m_ram(*this, "ram") { } - void zaurus_base(machine_config &config); - void zaurus_sa1110(machine_config &config); - void zaurus_pxa250(machine_config &config); - void zaurus_pxa255(machine_config &config); - void zaurus_pxa270(machine_config &config); - -private: +protected: // driver_device overrides virtual void machine_start() override; virtual void machine_reset() override; - void zaurus_map(address_map &map); - // devices - required_device<pxa255_periphs_device> m_pxa_periphs; required_device<cpu_device> m_maincpu; required_shared_ptr<uint32_t> m_ram; - - uint8_t m_rtc_tick; - uint32_t rtc_r(offs_t offset); - void rtc_w(offs_t offset, uint32_t data); - TIMER_DEVICE_CALLBACK_MEMBER(rtc_irq_callback); }; +class zaurus_sa_state : public zaurus_state +{ +public: + zaurus_sa_state(const machine_config &mconfig, device_type type, const char *tag) + : zaurus_state(mconfig, type, tag) + , m_sa_periphs(*this, "sa_periphs") + { } -uint32_t zaurus_state::rtc_r(offs_t offset) + void zaurus_sa1110(machine_config &config); + +private: + void main_map(address_map &map); + + required_device<sa1110_periphs_device> m_sa_periphs; +}; + +class zaurus_pxa_state : public zaurus_state { - osd_printf_debug("%08x\n", offset << 2); +public: + zaurus_pxa_state(const machine_config &mconfig, device_type type, const char *tag) + : zaurus_state(mconfig, type, tag) + , m_pxa_periphs(*this, "pxa_periphs") + , m_power(*this, "PWR") + { } - return 0; -} + void zaurus_pxa_base(machine_config &config); + void zaurus_pxa250(machine_config &config); + void zaurus_pxa255(machine_config &config); + void zaurus_pxa270(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER( system_start ); + +private: + void main_map(address_map &map); + + required_device<pxa255_periphs_device> m_pxa_periphs; + required_ioport m_power; +}; -void zaurus_state::rtc_w(offs_t offset, uint32_t data) +void zaurus_sa_state::main_map(address_map &map) { - osd_printf_debug("%08x %08x\n", offset << 2, data); + map(0x00000000, 0x00ffffff).ram().region("firmware", 0); + map(0x90020000, 0x9002001f).rw(m_sa_periphs, FUNC(sa1110_periphs_device::power_r), FUNC(sa1110_periphs_device::power_w)); + map(0x90050000, 0x90050023).rw(m_sa_periphs, FUNC(sa1110_periphs_device::intc_r), FUNC(sa1110_periphs_device::intc_w)); + map(0xc0000000, 0xc07fffff).ram().share("ram"); } -void zaurus_state::zaurus_map(address_map &map) +void zaurus_pxa_state::main_map(address_map &map) { map(0x00000000, 0x001fffff).ram().region("firmware", 0); - map(0x40900000, 0x4090000f).rw(FUNC(zaurus_state::rtc_r), FUNC(zaurus_state::rtc_w)); map(0x40000000, 0x400002ff).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::dma_r), FUNC(pxa255_periphs_device::dma_w)); map(0x40400000, 0x40400083).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::i2s_r), FUNC(pxa255_periphs_device::i2s_w)); + map(0x40900000, 0x4090000f).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::rtc_r), FUNC(pxa255_periphs_device::rtc_w)); map(0x40a00000, 0x40a0001f).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::ostimer_r), FUNC(pxa255_periphs_device::ostimer_w)); map(0x40d00000, 0x40d00017).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::intc_r), FUNC(pxa255_periphs_device::intc_w)); map(0x40e00000, 0x40e0006b).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::gpio_r), FUNC(pxa255_periphs_device::gpio_w)); + map(0x40f00000, 0x40f00037).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::power_r), FUNC(pxa255_periphs_device::power_w)); + map(0x41300000, 0x4130000b).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::clocks_r), FUNC(pxa255_periphs_device::clocks_w)); map(0x44000000, 0x4400021f).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::lcd_r), FUNC(pxa255_periphs_device::lcd_w)); map(0xa0000000, 0xa07fffff).ram().share("ram"); } -static INPUT_PORTS_START( zaurus ) -INPUT_PORTS_END - -void zaurus_state::machine_start() +INPUT_CHANGED_MEMBER( zaurus_pxa_state::system_start ) { + m_pxa_periphs->gpio_bit_w(10, m_power->read()); } -void zaurus_state::machine_reset() -{ -} +static INPUT_PORTS_START( zaurus_sa ) +INPUT_PORTS_END +static INPUT_PORTS_START( zaurus_pxa ) + PORT_START("PWR") + PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_START1 ) PORT_NAME("Start System") PORT_CHANGED_MEMBER(DEVICE_SELF, zaurus_pxa_state, system_start, 0) +INPUT_PORTS_END -/* TODO: Hack */ -TIMER_DEVICE_CALLBACK_MEMBER(zaurus_state::rtc_irq_callback) +void zaurus_state::machine_start() { -#if 1 - m_rtc_tick++; - m_rtc_tick &= 1; - - if(m_rtc_tick & 1) - m_pxa_periphs->set_irq_line(PXA255_INT_RTC_HZ, 1); - else - m_pxa_periphs->set_irq_line(PXA255_INT_RTC_HZ, 0); -#else - (void)m_rtc_tick; -#endif } -void zaurus_state::zaurus_base(machine_config &config) +void zaurus_state::machine_reset() { - m_maincpu->set_addrmap(AS_PROGRAM, &zaurus_state::zaurus_map); - TIMER(config, "rtc_timer").configure_periodic(FUNC(zaurus_state::rtc_irq_callback), attotime::from_hz(XTAL(32'768))); } -void zaurus_state::zaurus_sa1110(machine_config &config) +void zaurus_sa_state::zaurus_sa1110(machine_config &config) { SA1110(config, m_maincpu, SA1110_CLOCK); - PXA255_PERIPHERALS(config, m_pxa_periphs, SA1110_CLOCK, m_maincpu); // TODO: Correct peripherals - zaurus_base(config); + m_maincpu->set_addrmap(AS_PROGRAM, &zaurus_sa_state::main_map); + + SA1110_PERIPHERALS(config, m_sa_periphs, SA1110_CLOCK, m_maincpu); } -void zaurus_state::zaurus_pxa250(machine_config &config) +void zaurus_pxa_state::zaurus_pxa250(machine_config &config) { - PXA255(config, m_maincpu, PXA250_CLOCK); // TODO: Correct CPU type - PXA255_PERIPHERALS(config, m_pxa_periphs, PXA250_CLOCK, m_maincpu); // TODO: Correct peripherals - zaurus_base(config); + PXA250(config, m_maincpu, PXA250_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &zaurus_pxa_state::main_map); + + PXA255_PERIPHERALS(config, m_pxa_periphs, PXA250_CLOCK, m_maincpu); } -void zaurus_state::zaurus_pxa255(machine_config &config) +void zaurus_pxa_state::zaurus_pxa255(machine_config &config) { PXA255(config, m_maincpu, PXA255_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &zaurus_pxa_state::main_map); + PXA255_PERIPHERALS(config, m_pxa_periphs, PXA255_CLOCK, m_maincpu); - zaurus_base(config); } -void zaurus_state::zaurus_pxa270(machine_config &config) +void zaurus_pxa_state::zaurus_pxa270(machine_config &config) { - PXA255(config, m_maincpu, PXA270_CLOCK); // TODO: Correct CPU type + PXA270(config, m_maincpu, PXA270_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &zaurus_pxa_state::main_map); + PXA255_PERIPHERALS(config, m_pxa_periphs, PXA270_CLOCK, m_maincpu); // TODO: Correct peripherals - zaurus_base(config); } /*************************************************************************** @@ -1546,8 +1556,16 @@ void zaurus_state::zaurus_pxa270(machine_config &config) ***************************************************************************/ -/* was labeled SL-C500 */ ROM_START( zsl5500 ) + ROM_REGION32_LE( 0x1000000, "firmware", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS( 0, "2.58", "OS Pack 2.58" ) \ + ROMX_LOAD( "ospack-2.58", 0x0000000, 0x1000000, CRC(31c4d3ef) SHA1(a3b67fb45160bdb990e34dca5c389ed345c000c6), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS( 1, "3.10", "OS Pack 3.10" ) \ + ROMX_LOAD( "ospack-3.10", 0x0000000, 0x1000000, CRC(12345678) SHA1(1234567812345678123456781234567812345678), ROM_BIOS(1) ) +ROM_END + +/* was labeled SL-C500 */ +ROM_START( zslc500 ) ROM_REGION32_LE( 0x200000, "firmware", ROMREGION_ERASE00 ) ROM_LOAD( "sl-c500 v1.20,zimage.bin", 0x000000, 0x13c000, BAD_DUMP CRC(dc1c259f) SHA1(8150744196a72821ae792462d0381182274c2ce0) ) ROM_END @@ -1577,9 +1595,10 @@ ROM_START( zslc1000 ) ROM_LOAD( "openzaurus 3.5.3 - zimage-sharp sl-c1000-20050427214434.bin", 0x000000, 0x128980, BAD_DUMP CRC(1e1a9279) SHA1(909ac3f00385eced55822d6a155b79d9d25f43b3) ) ROM_END -COMP( 2002, zsl5500, 0, 0, zaurus_sa1110, zaurus, zaurus_state, empty_init, "Sharp", "Zaurus SL-5500 \"Collie\"", MACHINE_IS_SKELETON ) -COMP( 2002, zsl5600, 0, 0, zaurus_pxa250, zaurus, zaurus_state, empty_init, "Sharp", "Zaurus SL-5600 / SL-B500 \"Poodle\"", MACHINE_IS_SKELETON ) -COMP( 2003, zslc750, 0, 0, zaurus_pxa255, zaurus, zaurus_state, empty_init, "Sharp", "Zaurus SL-C750 \"Shepherd\" (Japan)", MACHINE_IS_SKELETON ) -COMP( 2004, zslc760, 0, 0, zaurus_pxa255, zaurus, zaurus_state, empty_init, "Sharp", "Zaurus SL-C760 \"Husky\" (Japan)", MACHINE_IS_SKELETON ) -COMP( 200?, zslc3000, 0, 0, zaurus_pxa270, zaurus, zaurus_state, empty_init, "Sharp", "Zaurus SL-C3000 \"Spitz\" (Japan)", MACHINE_IS_SKELETON ) -COMP( 200?, zslc1000, 0, 0, zaurus_pxa270, zaurus, zaurus_state, empty_init, "Sharp", "Zaurus SL-C3000 \"Akita\" (Japan)", MACHINE_IS_SKELETON ) +COMP( 2002, zsl5500, 0, 0, zaurus_sa1110, zaurus_sa, zaurus_sa_state, empty_init, "Sharp", "Zaurus SL-5500 \"Collie\"", MACHINE_IS_SKELETON ) +COMP( 2002, zslc500, 0, 0, zaurus_pxa250, zaurus_pxa, zaurus_pxa_state, empty_init, "Sharp", "Zaurus SL-C500", MACHINE_IS_SKELETON ) +COMP( 2002, zsl5600, 0, 0, zaurus_pxa250, zaurus_pxa, zaurus_pxa_state, empty_init, "Sharp", "Zaurus SL-5600 / SL-B500 \"Poodle\"", MACHINE_IS_SKELETON ) +COMP( 2003, zslc750, 0, 0, zaurus_pxa255, zaurus_pxa, zaurus_pxa_state, empty_init, "Sharp", "Zaurus SL-C750 \"Shepherd\" (Japan)", MACHINE_IS_SKELETON ) +COMP( 2004, zslc760, 0, 0, zaurus_pxa255, zaurus_pxa, zaurus_pxa_state, empty_init, "Sharp", "Zaurus SL-C760 \"Husky\" (Japan)", MACHINE_IS_SKELETON ) +COMP( 200?, zslc3000, 0, 0, zaurus_pxa270, zaurus_pxa, zaurus_pxa_state, empty_init, "Sharp", "Zaurus SL-C3000 \"Spitz\" (Japan)", MACHINE_IS_SKELETON ) +COMP( 200?, zslc1000, 0, 0, zaurus_pxa270, zaurus_pxa, zaurus_pxa_state, empty_init, "Sharp", "Zaurus SL-C3000 \"Akita\" (Japan)", MACHINE_IS_SKELETON ) diff --git a/src/mame/machine/n64.cpp b/src/mame/machine/n64.cpp index 67b3cb5b2c8..d5395995f2d 100644 --- a/src/mame/machine/n64.cpp +++ b/src/mame/machine/n64.cpp @@ -1653,7 +1653,7 @@ uint32_t n64_periphs::ri_reg_r(offs_t offset, uint32_t mem_mask) time recommended for letting the SI devices settle after startup. This allows the initialization routines for the SI to see that a proper amount of time has passed since system startup. */ - m_vr4300->burn_cycles(93750000/2); + m_vr4300->adjust_icount(-93750000/2); } if(offset > 0x1c/4) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index ce4be0957ba..aa2ad377415 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -13550,6 +13550,7 @@ fex68km4 // feasbu // feasgla // feasglaa // +feasglab // feag // feag2100 // feag2100a // @@ -18663,6 +18664,9 @@ k4r // k5 // k5m // +@source:kawai_ksp10.cpp +ksp10 // + @source:kawai_r100.cpp r100 // @@ -22592,6 +22596,9 @@ md3 // @source:microkit.cpp microkit // +@source:microkorg.cpp +microkorg // + @source:micromon.cpp micromon7141 // @@ -42060,6 +42067,7 @@ zapcomp // (1981) ZAP computer - Z80 Applications Proces @source:zaurus.cpp zsl5500 // Sharp Zaurus SL-5500 "Collie" +zslc500 // Sharp Zaurus SL-C500 zsl5600 // Sharp Zaurus SL-5600 / SL-B500 "Poodle" zslc1000 // Sharp Zaurus SL-C1000 "Akita" zslc3000 // Sharp Zaurus SL-C3000 "Spitz" diff --git a/src/mame/mess.flt b/src/mame/mess.flt index 4e6cf7f5df8..91336316aaf 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -460,6 +460,7 @@ k8915.cpp kawai_k1.cpp kawai_k4.cpp kawai_k5.cpp +kawai_ksp10.cpp kawai_r100.cpp kaypro.cpp kc.cpp @@ -552,6 +553,7 @@ micro20.cpp microb.cpp microdec.cpp microkit.cpp +microkorg.cpp micromon.cpp micronic.cpp microtan.cpp diff --git a/src/mame/video/bbc.cpp b/src/mame/video/bbc.cpp index 4c49cd58e8f..d599169000a 100644 --- a/src/mame/video/bbc.cpp +++ b/src/mame/video/bbc.cpp @@ -320,7 +320,7 @@ MC6845_UPDATE_ROW( bbc_state::crtc_update_row ) for (int pixelno = 0; pixelno < m_pixels_per_byte; pixelno++) { - int col = !(ra & 0x08) ? m_vula_palette_lookup[m_pixel_bits[data]] : 7; + int col = !(ra & 0x08) ? m_vula_palette_lookup[m_pixel_bits[data]] : 0; col ^= ((cursor_x != -1 && x_pos >= cursor_x && x_pos < (cursor_x + m_cursor_size)) ? 7 : 0); diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index 23b212e71b5..74a60eb955a 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -209,6 +209,7 @@ bool renderer_d3d9::init(running_machine &machine) d3d9_create_fn d3d9_create_ptr = d3dintf->d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9"); if (d3d9_create_ptr == nullptr) { + global_free(d3dintf); osd_printf_verbose("Direct3D: Unable to find Direct3D 9 runtime library\n"); return true; } @@ -216,6 +217,7 @@ bool renderer_d3d9::init(running_machine &machine) d3dintf->d3dobj = (*d3d9_create_ptr)(D3D_SDK_VERSION); if (d3dintf->d3dobj == nullptr) { + global_free(d3dintf); osd_printf_verbose("Direct3D: Unable to initialize Direct3D 9\n"); return true; } @@ -971,6 +973,7 @@ void renderer_d3d9::exit() { d3dintf->d3dobj->Release(); global_free(d3dintf); + d3dintf = nullptr; } } |