summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2025-03-14 14:18:43 +1100
committer Vas Crabb <vas@vastheman.com>2025-03-14 14:18:43 +1100
commite75c7079cfd0984dc0af61fa6fc7b667baafd267 (patch)
tree12279992eda44b826ae8faea8e754aca199ad485 /src/devices
parent14d11c479ecd7fbc4bc833b9d8e6366557bba399 (diff)
-cpu/drcbearm64.cpp: More fixes and optimisations:
* Correctly identify valid immediate constants for add/sub/cmp (it was too conservative). * Don't unnecessarily copy UML register values kept in host registers for CMP. * Fixed detection of TST against immediate zero and optimised generated code. * Optimised TST against immediate with all bits set. -cpu/alto2: Follow the same pattern as the other things that have been altered to avoid problematic memsets in this device. -cpu/powerpc: Realigned some comments that had drifted.
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/cpu/alto2/a2disp.cpp2
-rw-r--r--src/devices/cpu/alto2/a2disp.h47
-rw-r--r--src/devices/cpu/drcbearm64.cpp69
-rw-r--r--src/devices/cpu/powerpc/ppcdrc.cpp28
4 files changed, 80 insertions, 66 deletions
diff --git a/src/devices/cpu/alto2/a2disp.cpp b/src/devices/cpu/alto2/a2disp.cpp
index c2e1c2455a0..5cc9e5cc300 100644
--- a/src/devices/cpu/alto2/a2disp.cpp
+++ b/src/devices/cpu/alto2/a2disp.cpp
@@ -499,7 +499,7 @@ void alto2_cpu_device::f2_late_evenfield()
*/
void alto2_cpu_device::init_disp()
{
- m_dsp.clear();
+ m_dsp = decltype(m_dsp)();
save_item(NAME(m_dsp.state));
save_item(NAME(m_dsp.hlc));
save_item(NAME(m_dsp.setmode));
diff --git a/src/devices/cpu/alto2/a2disp.h b/src/devices/cpu/alto2/a2disp.h
index ad9d1112c92..02c51435d5a 100644
--- a/src/devices/cpu/alto2/a2disp.h
+++ b/src/devices/cpu/alto2/a2disp.h
@@ -193,35 +193,24 @@
#ifndef MAME_CPU_ALTO2_A2DISP_H
#define MAME_CPU_ALTO2_A2DISP_H
struct {
-
- void clear()
- {
- state = hlc = setmode = inverse = scanline = 0;
- halfclock = vblank = false;
- std::fill(std::begin(fifo), std::end(fifo), 0);
- wa = ra = a63 = a66 = 0;
- dht_blocks = dwt_blocks = curt_blocks = curt_wakeup = false;
- xpreg = csr = 0;
- }
-
- uint32_t state; //!< current state of the display_state_machine()
- uint32_t hlc; //!< horizontal line counter
- uint32_t setmode; //!< value written by last SETMODE<-
- uint32_t inverse; //!< set to 0xffff if line is inverse, 0x0000 otherwise
- uint32_t scanline; //!< current scanline
- bool halfclock; //!< false for normal pixel clock, true for half pixel clock
- bool vblank; //!< true during vblank, false otherwise
- uint16_t fifo[A2_DISP_FIFO]; //!< display word fifo
- uint32_t wa; //!< fifo input pointer (write address; 4-bit)
- uint32_t ra; //!< fifo output pointer (read address; 4-bit)
- uint32_t a63; //!< most recent value read from the PROM a63
- uint32_t a66; //!< most recent value read from the PROM a66
- bool dht_blocks; //!< set true, if the DHT executed BLOCK
- bool dwt_blocks; //!< set true, if the DWT executed BLOCK
- bool curt_blocks; //!< set true, if the CURT executed BLOCK
- bool curt_wakeup; //!< set true, if CURT wakeups are generated
- uint32_t xpreg; //!< cursor cursor x position register (10-bit)
- uint32_t csr; //!< cursor shift register (16-bit)
+ uint32_t state = 0; //!< current state of the display_state_machine()
+ uint32_t hlc = 0; //!< horizontal line counter
+ uint32_t setmode = 0; //!< value written by last SETMODE<-
+ uint32_t inverse = 0; //!< set to 0xffff if line is inverse, 0x0000 otherwise
+ uint32_t scanline = 0; //!< current scanline
+ bool halfclock = false; //!< false for normal pixel clock, true for half pixel clock
+ bool vblank = false; //!< true during vblank, false otherwise
+ uint16_t fifo[A2_DISP_FIFO] = { }; //!< display word fifo
+ uint32_t wa = 0; //!< fifo input pointer (write address; 4-bit)
+ uint32_t ra = 0; //!< fifo output pointer (read address; 4-bit)
+ uint32_t a63 = 0; //!< most recent value read from the PROM a63
+ uint32_t a66 = 0; //!< most recent value read from the PROM a66
+ bool dht_blocks = false; //!< set true, if the DHT executed BLOCK
+ bool dwt_blocks = false; //!< set true, if the DWT executed BLOCK
+ bool curt_blocks = false; //!< set true, if the CURT executed BLOCK
+ bool curt_wakeup = false; //!< set true, if CURT wakeups are generated
+ uint32_t xpreg = 0; //!< cursor cursor x position register (10-bit)
+ uint32_t csr = 0; //!< cursor shift register (16-bit)
std::unique_ptr<uint16_t[]> framebuf; //!< array of words of the raw bitmap that is displayed
std::unique_ptr<uint8_t[]> patterns; //!< array of 65536 patterns (16 bytes) with 1 byte per pixel
std::unique_ptr<bitmap_ind16> bitmap; //!< MAME bitmap with 16 bit indices
diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp
index 4c45a93e698..7f4eb9d6650 100644
--- a/src/devices/cpu/drcbearm64.cpp
+++ b/src/devices/cpu/drcbearm64.cpp
@@ -251,6 +251,12 @@ inline bool is_valid_immediate(uint64_t val, size_t bits)
return val < (uint64_t(1) << bits);
}
+constexpr bool is_valid_immediate_addsub(uint64_t val)
+{
+ // 12-bit unsigned immediate value, optionally left-shifted by 12 bits
+ return !(val & ~util::make_bitmask<uint64_t>(12)) || !(val & ~(util::make_bitmask<uint64_t>(12) << 12));
+}
+
inline constexpr bool is_valid_immediate_signed(int64_t val, size_t bits)
{
return util::sext(val, bits) == val;
@@ -752,18 +758,20 @@ a64::Vec drcbe_arm64::be_parameter::select_register(a64::Vec const &reg, uint32_
{
if (m_type == PTYPE_FLOAT_REGISTER)
return get_register_float(regsize);
- if (regsize == 4)
+ else if (regsize == 4)
return reg.s();
- return reg.d();
+ else
+ return reg.d();
}
a64::Gp drcbe_arm64::be_parameter::select_register(a64::Gp const &reg, uint32_t regsize) const
{
if (m_type == PTYPE_INT_REGISTER)
return get_register_int(regsize);
- if (regsize == 4)
+ else if (regsize == 4)
return reg.w();
- return reg.x();
+ else
+ return reg.x();
}
void drcbe_arm64::get_imm_relative(a64::Assembler &a, const a64::Gp &reg, const uint64_t val) const
@@ -3234,7 +3242,7 @@ template <a64::Inst::Id Opcode> void drcbe_arm64::op_add(a64::Assembler &a, cons
if (Opcode == a64::Inst::kIdAdcs)
load_carry(a);
- if (src1p.is_immediate() && is_valid_immediate(src1p.immediate(), 11))
+ if (src1p.is_immediate() && is_valid_immediate_addsub(src1p.immediate()))
{
const a64::Gp src = src2p.select_register(TEMP_REG2, inst.size());
@@ -3245,7 +3253,7 @@ template <a64::Inst::Id Opcode> void drcbe_arm64::op_add(a64::Assembler &a, cons
a.emit(Opcode, output, src, src1p.immediate());
mov_param_reg(a, inst.size(), dstp, output);
}
- else if (src2p.is_immediate() && is_valid_immediate(src2p.immediate(), 11))
+ else if (src2p.is_immediate() && is_valid_immediate_addsub(src2p.immediate()))
{
const a64::Gp src = src1p.select_register(TEMP_REG1, inst.size());
@@ -3285,7 +3293,7 @@ template <a64::Inst::Id Opcode> void drcbe_arm64::op_sub(a64::Assembler &a, cons
const a64::Gp output = dstp.select_register(TEMP_REG3, inst.size());
- if (src2p.is_immediate() && is_valid_immediate(src2p.immediate(), 11))
+ if (src2p.is_immediate() && is_valid_immediate_addsub(src2p.immediate()))
{
const a64::Gp src = select_register(TEMP_REG1, inst.size());
@@ -3319,22 +3327,23 @@ void drcbe_arm64::op_cmp(a64::Assembler &a, const uml::instruction &inst)
be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
- const a64::Gp temp = select_register(TEMP_REG1, inst.size());
- const a64::Gp temp2 = select_register(TEMP_REG2, inst.size());
+ const a64::Gp src1 = src1p.select_register(TEMP_REG1, inst.size());
- mov_reg_param(a, inst.size(), temp, src1p);
+ mov_reg_param(a, inst.size(), src1, src1p);
- if (src2p.is_immediate() && is_valid_immediate(src2p.immediate(), 11))
+ if (src2p.is_immediate() && is_valid_immediate_addsub(src2p.immediate()))
{
if (src2p.is_immediate_value(0))
- a.cmp(temp, select_register(a64::xzr, inst.size()));
+ a.cmp(src1, select_register(a64::xzr, inst.size()));
else
- a.cmp(temp, src2p.immediate());
+ a.cmp(src1, src2p.immediate());
}
else
{
- mov_reg_param(a, inst.size(), temp2, src2p);
- a.cmp(temp, temp2);
+ const a64::Gp src2 = src2p.select_register(TEMP_REG2, inst.size());
+
+ mov_reg_param(a, inst.size(), src2, src2p);
+ a.cmp(src1, src2);
}
store_carry(a, true);
@@ -3728,17 +3737,35 @@ void drcbe_arm64::op_test(a64::Assembler &a, const uml::instruction &inst)
const a64::Gp src1 = src1p.select_register(TEMP_REG1, inst.size());
const a64::Gp src2 = src2p.select_register(TEMP_REG2, inst.size());
- mov_reg_param(a, inst.size(), src1, src1p);
+ if (src1p.is_immediate_value(0) || src2p.is_immediate_value(0))
+ {
+ const a64::Gp zero = select_register(a64::xzr, inst.size());
- if (src2p.is_immediate() && is_valid_immediate_mask(src2p.immediate(), inst.size()))
+ a.tst(zero, zero);
+ }
+ else if (src2p.is_immediate_value(util::make_bitmask<uint64_t>(inst.size() * 8)))
{
- if (src2p.is_immediate_value(0))
- a.tst(src1, select_register(a64::xzr, inst.size()));
- else
- a.tst(src1, src2p.immediate());
+ mov_reg_param(a, inst.size(), src1, src1p);
+ a.tst(src1, src1);
+ }
+ else if (src1p.is_immediate_value(util::make_bitmask<uint64_t>(inst.size() * 8)))
+ {
+ mov_reg_param(a, inst.size(), src2, src2p);
+ a.tst(src2, src2);
+ }
+ else if (src2p.is_immediate() && is_valid_immediate_mask(src2p.immediate(), inst.size()))
+ {
+ mov_reg_param(a, inst.size(), src1, src1p);
+ a.tst(src1, src2p.immediate());
+ }
+ else if (src1p.is_immediate() && is_valid_immediate_mask(src1p.immediate(), inst.size()))
+ {
+ mov_reg_param(a, inst.size(), src2, src2p);
+ a.tst(src2, src1p.immediate());
}
else
{
+ mov_reg_param(a, inst.size(), src1, src1p);
mov_reg_param(a, inst.size(), src2, src2p);
a.tst(src1, src2);
}
diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp
index 06da8344592..3133529e5c2 100644
--- a/src/devices/cpu/powerpc/ppcdrc.cpp
+++ b/src/devices/cpu/powerpc/ppcdrc.cpp
@@ -1021,32 +1021,30 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
/* check for unaligned accesses and break into two */
if (!ismasked && size != 1)
{
- /* in little-endian mode, anything misaligned generates an exception */
if ((mode & MODE_LITTLE_ENDIAN) || masked == nullptr || !(m_cap & PPCCAP_MISALIGNED))
{
+ /* in little-endian mode, anything misaligned generates an exception */
UML_TEST(block, I0, size - 1); // test i0,size-1
- UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
}
-
- /* in big-endian mode, it's more complicated */
else
{
- /* 8-byte accesses must be word-aligned */
+ /* in big-endian mode, it's more complicated */
if (size == 8)
{
+ /* 8-byte accesses must be word-aligned */
UML_TEST(block, I0, 3); // test i0,3
- UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
/* word aligned accesses need to be broken up */
UML_TEST(block, I0, 4); // test i0,4
UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned, nz
}
-
- /* unaligned 2 and 4 byte accesses need to be broken up */
else
{
+ /* unaligned 2 and 4 byte accesses need to be broken up */
UML_TEST(block, I0, size - 1); // test i0,size-1
- UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned,nz
+ UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned,nz
}
}
}
@@ -1054,12 +1052,12 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
/* general case: assume paging and perform a translation */
if (((m_cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION)) || (iswrite && (m_cap & PPCCAP_4XX) && (mode & MODE_PROTECTION)))
{
- UML_SHR(block, I3, I0, 12); // shr i3,i0,12
- UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword
- UML_TEST(block, I3, (uint64_t)1 << translate_type); // test i3,1 << translate_type
- UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
- UML_LABEL(block, tlbreturn = label++); // tlbreturn:
- UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
+ UML_SHR(block, I3, I0, 12); // shr i3,i0,12
+ UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4); // load i3,[vtlb],i3,dword
+ UML_TEST(block, I3, (uint64_t)1 << translate_type); // test i3,1 << translate_type
+ UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
+ UML_LABEL(block, tlbreturn = label++); // tlbreturn:
+ UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
}
else if (m_cap & PPCCAP_4XX)
UML_AND(block, I0, I0, 0x7fffffff); // and i0,i0,0x7fffffff