summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2025-09-08 13:55:25 +1000
committer Vas Crabb <vas@vastheman.com>2025-09-08 13:55:25 +1000
commit5cca9a22a45d7afeef5b4da2027a49365e43aa7e (patch)
tree7e09896d0c5dd755fcc70b23fa2b90ad9014805c
parent5604d34659127c22a228f32f8b856229500a034f (diff)
-cpu/drcbec.cpp: Improved behaviour for float-to-int conversion.
-docs: Documented several DRC UML shift/rotate instructions.
-rw-r--r--docs/source/techspecs/uml_instructions.rst352
-rw-r--r--src/devices/cpu/drcbec.cpp124
2 files changed, 423 insertions, 53 deletions
diff --git a/docs/source/techspecs/uml_instructions.rst b/docs/source/techspecs/uml_instructions.rst
index 7a2b2f019f9..621a0803bbd 100644
--- a/docs/source/techspecs/uml_instructions.rst
+++ b/docs/source/techspecs/uml_instructions.rst
@@ -1603,7 +1603,8 @@ zero (Z)
Set if the result is zero, or cleared otherwise.
sign (S)
Set to the value of the most significant bit of the result (set if
- the result is a negative signed integer, or cleared otherwise).
+ the result is a negative signed integer value, or cleared
+ otherwise).
unordered (U)
Undefined.
@@ -1665,7 +1666,8 @@ zero (Z)
Set if the result is zero, or cleared otherwise.
sign (S)
Set to the value of the most significant bit of the result (set if
- the result is a negative signed integer, or cleared otherwise).
+ the result is a negative signed integer value, or cleared
+ otherwise).
unordered (U)
Undefined.
@@ -1722,21 +1724,22 @@ zero (Z)
and subtrahend are equal, or cleared otherwise).
sign (S)
Set to the value of the most significant bit of the result (set if
- the result is a negative signed integer, or cleared otherwise).
+ the result is a negative signed integer value, or cleared
+ otherwise).
unordered (U)
Undefined.
Simplification rules
^^^^^^^^^^^^^^^^^^^^
-* Immediate values for the ``src1`` and ``src2`` operands are truncated
- to the instruction size.
* Converted to :ref:`MOV <umlinst-mov>`, :ref:`AND <umlinst-and>` or
:ref:`OR <umlinst-or>` if the ``src1`` and ``src2`` operands are both
immediate values and the carry and overflow flags are not required.
* Converted to :ref:`MOV <umlinst-mov>` or :ref:`AND <umlinst-and>` if
the ``src2`` operand is the immediate value zero and the carry and
overflow flags are not required.
+* Immediate values for the ``src1`` and ``src2`` operands are truncated
+ to the instruction size.
.. _umlinst-subb:
@@ -1782,7 +1785,8 @@ zero (Z)
otherwise).
sign (S)
Set to the value of the most significant bit of the result (set if
- the result is a negative signed integer, or cleared otherwise).
+ the result is a negative signed integer value, or cleared
+ otherwise).
unordered (U)
Undefined.
@@ -1889,7 +1893,8 @@ zero (Z)
Set if the result is zero, or cleared otherwise.
sign (S)
Set to the value of the most significant bit of the result (set if
- the result is a negative signed integer, or cleared otherwise).
+ the result is a negative signed integer value, or cleared
+ otherwise).
unordered (U)
Undefined.
@@ -2031,7 +2036,8 @@ zero (Z)
Set if the result is zero, or cleared otherwise.
sign (S)
Set to the value of the most significant bit of the result (set if
- the result is a negative signed integer, or cleared otherwise).
+ the result is a negative signed integer value, or cleared
+ otherwise).
unordered (U)
Undefined.
@@ -2105,7 +2111,8 @@ zero (Z)
Set if the result is zero, or cleared otherwise.
sign (S)
Set to the value of the most significant bit of the result (set if
- the result is a negative signed integer, or cleared otherwise).
+ the result is a negative signed integer value, or cleared
+ otherwise).
unordered (U)
Undefined.
@@ -2212,6 +2219,333 @@ Simplification rules
the ``src`` operand is an immediate value.
+.. _umlinst-intshift:
+
+Integer shift and rotate
+------------------------
+
+.. _umlinst-shl:
+
+SHL
+~~~
+
+Shift an integer value to the left (toward the most significant bit
+position), shifting zeroes into the least significant bit.
+
++---------------------------+---------------------------------------+
+| Disassembly | Usage |
++===========================+=======================================+
+| .. code-block:: | .. code-block:: |
+| | |
+| shl dst,src,count | UML_SHL(block, dst, src, count); |
+| dshl dst,src,count | UML_DSHL(block, dst, src, count); |
++---------------------------+---------------------------------------+
+
+Sets ``dst`` to the value of ``src`` shifted left by ``count`` bit
+positions modulo the operand size in bits. Zeroes are shifted into the
+least significant bit position.
+
+Operands
+^^^^^^^^
+
+dst (32-bit or 64-bit – memory, integer register)
+ The destination where the shifted value will be stored.
+src (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The value to shift.
+count (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The number of bit positions to shift by. Only the least significant
+ five bits or six bits of this operand are used, depending on the
+ instruction size.
+
+Flags
+^^^^^
+
+carry (C)
+ Set to the value of the last bit shifted out of the most significant
+ bit position if the shift count modulo the operand size in bits is
+ non-zero, or cleared if the shift count modulo the operand size in
+ bits is zero.
+overflow (V)
+ Undefined.
+zero (Z)
+ Set if the result is zero, or cleared otherwise.
+sign (S)
+ Set to the value of the most significant bit of the result (set if
+ the result is a negative signed integer value, or cleared
+ otherwise).
+unordered (U)
+ Undefined.
+
+Simplification rules
+^^^^^^^^^^^^^^^^^^^^
+
+* Converted to :ref:`MOV <umlinst-mov>`, :ref:`AND <umlinst-and>` or
+ :ref:`OR <umlinst-or>` if the ``src`` and ``count`` operands are both
+ immediate values or the ``count`` operand is the immediate value zero
+ and the carry flag is not required.
+* Immediate values for the ``src`` operand are truncated to the
+ instruction size.
+* Immediate values for the ``count`` operand are truncated to five or
+ six bits for 32-bit or 64-bit operands, respectively.
+
+.. _umlinst-shr:
+
+SHR
+~~~
+
+Shift an integer value to the right (toward the least significant bit
+position), shifting zeroes into the most significant bit.
+
++---------------------------+---------------------------------------+
+| Disassembly | Usage |
++===========================+=======================================+
+| .. code-block:: | .. code-block:: |
+| | |
+| shr dst,src,count | UML_SHR(block, dst, src, count); |
+| dshr dst,src,count | UML_DSHR(block, dst, src, count); |
++---------------------------+---------------------------------------+
+
+Sets ``dst`` to the value of ``src`` shifted right by ``count`` bit
+positions modulo the operand size in bits. Zeroes are shifted into the
+most significant bit position.
+
+Operands
+^^^^^^^^
+
+dst (32-bit or 64-bit – memory, integer register)
+ The destination where the shifted value will be stored.
+src (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The value to shift.
+count (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The number of bit positions to shift by. Only the least significant
+ five bits or six bits of this operand are used, depending on the
+ instruction size.
+
+Flags
+^^^^^
+
+carry (C)
+ Set to the value of the last bit shifted out of the least
+ significant bit position if the shift count modulo the operand size
+ in bits is non-zero, or cleared if the shift count modulo the
+ operand size in bits is zero.
+overflow (V)
+ Undefined.
+zero (Z)
+ Set if the result is zero, or cleared otherwise.
+sign (S)
+ Set to the value of the most significant bit of the result (set if
+ the result is a negative signed integer value, or cleared
+ otherwise).
+unordered (U)
+ Undefined.
+
+Simplification rules
+^^^^^^^^^^^^^^^^^^^^
+
+* Converted to :ref:`MOV <umlinst-mov>`, :ref:`AND <umlinst-and>` or
+ :ref:`OR <umlinst-or>` if the ``src`` and ``count`` operands are both
+ immediate values or the ``count`` operand is the immediate value zero
+ and the carry flag is not required.
+* Immediate values for the ``src`` operand are truncated to the
+ instruction size.
+* Immediate values for the ``count`` operand are truncated to five or
+ six bits for 32-bit or 64-bit operands, respectively.
+
+.. _umlinst-sar:
+
+SAR
+~~~
+
+Shift an integer value to the right (toward the least significant bit
+position), preserving the value of the most significant bit.
+
++---------------------------+---------------------------------------+
+| Disassembly | Usage |
++===========================+=======================================+
+| .. code-block:: | .. code-block:: |
+| | |
+| sar dst,src,count | UML_SAR(block, dst, src, count); |
+| dsar dst,src,count | UML_DSAR(block, dst, src, count); |
++---------------------------+---------------------------------------+
+
+Sets ``dst`` to the value of ``src`` shifted right by ``count`` bit
+positions modulo the operand size in bits. The value of the most
+significant bit is preserved after each shift step.
+
+Operands
+^^^^^^^^
+
+dst (32-bit or 64-bit – memory, integer register)
+ The destination where the shifted value will be stored.
+src (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The value to shift.
+count (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The number of bit positions to shift by. Only the least significant
+ five bits or six bits of this operand are used, depending on the
+ instruction size.
+
+Flags
+^^^^^
+
+carry (C)
+ Set to the value of the last bit shifted out of the least
+ significant bit position if the shift count modulo the operand size
+ in bits is non-zero, or cleared if the shift count modulo the
+ operand size in bits is zero.
+overflow (V)
+ Undefined.
+zero (Z)
+ Set if the result is zero, or cleared otherwise.
+sign (S)
+ Set to the value of the most significant bit of the result (set if
+ the result is a negative signed integer value, or cleared
+ otherwise).
+unordered (U)
+ Undefined.
+
+Simplification rules
+^^^^^^^^^^^^^^^^^^^^
+
+* Converted to :ref:`MOV <umlinst-mov>`, :ref:`AND <umlinst-and>` or
+ :ref:`OR <umlinst-or>` if the ``src`` and ``count`` operands are both
+ immediate values or the ``count`` operand is the immediate value zero
+ and the carry flag is not required.
+* Immediate values for the ``src`` operand are truncated to the
+ instruction size.
+* Immediate values for the ``count`` operand are truncated to five or
+ six bits for 32-bit or 64-bit operands, respectively.
+
+.. _umlinst-rol:
+
+ROL
+~~~
+
+Rotate an integer value to the left (toward the most significant bit
+position). Bits shifted out of the most significant bit position are
+shifted into the least significant bit position.
+
++---------------------------+---------------------------------------+
+| Disassembly | Usage |
++===========================+=======================================+
+| .. code-block:: | .. code-block:: |
+| | |
+| rol dst,src,count | UML_ROL(block, dst, src, count); |
+| drol dst,src,count | UML_DROL(block, dst, src, count); |
++---------------------------+---------------------------------------+
+
+Sets ``dst`` to the value of ``src`` rotated left by ``count`` bit
+positions.
+
+Operands
+^^^^^^^^
+
+dst (32-bit or 64-bit – memory, integer register)
+ The destination where the rotated value will be stored.
+src (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The value to rotated.
+count (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The number of bit positions to rotate by. Only the least
+ significant five bits or six bits of this operand are used,
+ depending on the instruction size.
+
+Flags
+^^^^^
+
+carry (C)
+ Set to the value of the last bit rotated out of the most significant
+ bit position (set to the least significant bit of the result) if the
+ shift count modulo the operand size in bits is non-zero, or cleared
+ if the shift count modulo the operand size in bits is zero.
+overflow (V)
+ Undefined.
+zero (Z)
+ Set if the result is zero, or cleared otherwise.
+sign (S)
+ Set to the value of the most significant bit of the result (set if
+ the result is a negative signed integer value, or cleared
+ otherwise).
+unordered (U)
+ Undefined.
+
+Simplification rules
+^^^^^^^^^^^^^^^^^^^^
+
+* Converted to :ref:`MOV <umlinst-mov>`, :ref:`AND <umlinst-and>` or
+ :ref:`OR <umlinst-or>` if the ``src`` and ``count`` operands are both
+ immediate values or the ``count`` operand is the immediate value zero
+ and the carry flag is not required.
+* Immediate values for the ``src`` operand are truncated to the
+ instruction size.
+* Immediate values for the ``count`` operand are truncated to five or
+ six bits for 32-bit or 64-bit operands, respectively.
+
+.. _umlinst-ror:
+
+ROR
+~~~
+
+Rotate an integer value to the right (toward the least significant bit
+position). Bits shifted out of the least significant bit position are
+shifted into the most significant bit position.
+
++---------------------------+---------------------------------------+
+| Disassembly | Usage |
++===========================+=======================================+
+| .. code-block:: | .. code-block:: |
+| | |
+| ror dst,src,count | UML_ROR(block, dst, src, count); |
+| dror dst,src,count | UML_DROR(block, dst, src, count); |
++---------------------------+---------------------------------------+
+
+Sets ``dst`` to the value of ``src`` rotated right by ``count`` bit
+positions.
+
+Operands
+^^^^^^^^
+
+dst (32-bit or 64-bit – memory, integer register)
+ The destination where the rotated value will be stored.
+src (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The value to rotated.
+count (32-bit or 64-bit – memory, integer register, immediate, map variable)
+ The number of bit positions to rotate by. Only the least
+ significant five bits or six bits of this operand are used,
+ depending on the instruction size.
+
+Flags
+^^^^^
+
+carry (C)
+ Set to the value of the last bit rotated out of the least
+ significant bit position (set to the most significant bit of the
+ result) if the shift count modulo the operand size in bits is
+ non-zero, or cleared if the shift count modulo the operand size in
+ bits is zero.
+overflow (V)
+ Undefined.
+zero (Z)
+ Set if the result is zero, or cleared otherwise.
+sign (S)
+ Set to the value of the most significant bit of the result (set if
+ the result is a negative signed integer value, or cleared
+ otherwise).
+unordered (U)
+ Undefined.
+
+Simplification rules
+^^^^^^^^^^^^^^^^^^^^
+
+* Converted to :ref:`MOV <umlinst-mov>`, :ref:`AND <umlinst-and>` or
+ :ref:`OR <umlinst-or>` if the ``src`` and ``count`` operands are both
+ immediate values or the ``count`` operand is the immediate value zero
+ and the carry flag is not required.
+* Immediate values for the ``src`` operand are truncated to the
+ instruction size.
+* Immediate values for the ``count`` operand are truncated to five or
+ six bits for 32-bit or 64-bit operands, respectively.
+
+
.. _umlinst-fparith:
Floating point arithmetic
diff --git a/src/devices/cpu/drcbec.cpp b/src/devices/cpu/drcbec.cpp
index 5ec9a0b94e4..cccce38663f 100644
--- a/src/devices/cpu/drcbec.cpp
+++ b/src/devices/cpu/drcbec.cpp
@@ -2132,55 +2132,73 @@ int drcbe_c::execute(code_handle &entry)
break;
case MAKE_OPCODE_SHORT(OP_FTOI4T, 4, 0): // FSTOI4T dst,src1
- if (FSPARAM1 >= 0)
- *inst[0].pint32 = floor(FSPARAM1);
- else
- *inst[0].pint32 = ceil(FSPARAM1);
+ *inst[0].pint32 = int32_t(FSPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI4R, 4, 0): // FSTOI4R dst,src1
- if (FSPARAM1 >= 0)
- *inst[0].pint32 = floor(FSPARAM1 + 0.5f);
- else
- *inst[0].pint32 = ceil(FSPARAM1 - 0.5f);
+ *inst[0].pint32 = lroundf(FSPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI4F, 4, 0): // FSTOI4F dst,src1
- *inst[0].pint32 = floor(FSPARAM1);
+ *inst[0].pint32 = int32_t(floorf(FSPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI4C, 4, 0): // FSTOI4C dst,src1
- *inst[0].pint32 = ceil(FSPARAM1);
+ *inst[0].pint32 = int32_t(ceilf(FSPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI4, 4, 0): // FSTOI4 dst,src1
- *inst[0].pint32 = FSPARAM1;
+ switch (m_state.fmod)
+ {
+ default:
+ case ROUND_TRUNC:
+ *inst[0].pint32 = int32_t(FSPARAM1);
+ break;
+ case ROUND_ROUND:
+ *inst[0].pint32 = lroundf(FSPARAM1);
+ break;
+ case ROUND_FLOOR:
+ *inst[0].pint32 = int32_t(floorf(FSPARAM1));
+ break;
+ case ROUND_CEIL:
+ *inst[0].pint32 = int32_t(ceilf(FSPARAM1));
+ break;
+ }
break;
case MAKE_OPCODE_SHORT(OP_FTOI8T, 4, 0): // FSTOI8T dst,src1
- if (FSPARAM1 >= 0)
- *inst[0].pint64 = floor(FSPARAM1);
- else
- *inst[0].pint64 = ceil(FSPARAM1);
+ *inst[0].pint64 = int64_t(FSPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI8R, 4, 0): // FSTOI8R dst,src1
- if (FSPARAM1 >= 0)
- *inst[0].pint64 = floor(FSPARAM1 + 0.5f);
- else
- *inst[0].pint64 = ceil(FSPARAM1 - 0.5f);
+ *inst[0].pint64 = llroundf(FSPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI8F, 4, 0): // FSTOI8F dst,src1
- *inst[0].pint64 = floor(FSPARAM1);
+ *inst[0].pint64 = int64_t(floorf(FSPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI8C, 4, 0): // FSTOI8C dst,src1
- *inst[0].pint64 = ceil(FSPARAM1);
+ *inst[0].pint64 = int64_t(ceilf(FSPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI8, 4, 0): // FSTOI8 dst,src1
- *inst[0].pint64 = FSPARAM1;
+ switch (m_state.fmod)
+ {
+ default:
+ case ROUND_TRUNC:
+ *inst[0].pint64 = int64_t(FSPARAM1);
+ break;
+ case ROUND_ROUND:
+ *inst[0].pint64 = llroundf(FSPARAM1);
+ break;
+ case ROUND_FLOOR:
+ *inst[0].pint64 = int64_t(floorf(FSPARAM1));
+ break;
+ case ROUND_CEIL:
+ *inst[0].pint64 = int64_t(ceilf(FSPARAM1));
+ break;
+ }
break;
case MAKE_OPCODE_SHORT(OP_FFRI4, 4, 0): // FSFRI4 dst,src1
@@ -2275,55 +2293,73 @@ int drcbe_c::execute(code_handle &entry)
break;
case MAKE_OPCODE_SHORT(OP_FTOI4T, 8, 0): // FDTOI4T dst,src1
- if (FDPARAM1 >= 0)
- *inst[0].pint32 = floor(FDPARAM1);
- else
- *inst[0].pint32 = ceil(FDPARAM1);
+ *inst[0].pint32 = int32_t(FDPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI4R, 8, 0): // FDTOI4R dst,src1
- if (FDPARAM1 >= 0)
- *inst[0].pint32 = floor(FDPARAM1 + 0.5);
- else
- *inst[0].pint32 = ceil(FDPARAM1 - 0.5);
+ *inst[0].pint32 = lround(FDPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI4F, 8, 0): // FDTOI4F dst,src1
- *inst[0].pint32 = floor(FDPARAM1);
+ *inst[0].pint32 = int32_t(floor(FDPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI4C, 8, 0): // FDTOI4C dst,src1
- *inst[0].pint32 = ceil(FDPARAM1);
+ *inst[0].pint32 = int32_t(ceil(FDPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI4, 8, 0): // FDTOI4 dst,src1
- *inst[0].pint32 = FDPARAM1;
+ switch (m_state.fmod)
+ {
+ default:
+ case ROUND_TRUNC:
+ *inst[0].pint32 = int32_t(FDPARAM1);
+ break;
+ case ROUND_ROUND:
+ *inst[0].pint32 = lround(FDPARAM1);
+ break;
+ case ROUND_FLOOR:
+ *inst[0].pint32 = int32_t(floor(FDPARAM1));
+ break;
+ case ROUND_CEIL:
+ *inst[0].pint32 = int32_t(ceil(FDPARAM1));
+ break;
+ }
break;
case MAKE_OPCODE_SHORT(OP_FTOI8T, 8, 0): // FDTOI8T dst,src1
- if (FDPARAM1 >= 0)
- *inst[0].pint64 = floor(FDPARAM1);
- else
- *inst[0].pint64 = ceil(FDPARAM1);
+ *inst[0].pint64 = int64_t(FDPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI8R, 8, 0): // FDTOI8R dst,src1
- if (FDPARAM1 >= 0)
- *inst[0].pint64 = floor(FDPARAM1 + 0.5);
- else
- *inst[0].pint64 = ceil(FDPARAM1 - 0.5);
+ *inst[0].pint64 = llround(FDPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FTOI8F, 8, 0): // FDTOI8F dst,src1
- *inst[0].pint64 = floor(FDPARAM1);
+ *inst[0].pint64 = int64_t(floor(FDPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI8C, 8, 0): // FDTOI8C dst,src1
- *inst[0].pint64 = ceil(FDPARAM1);
+ *inst[0].pint64 = int64_t(ceil(FDPARAM1));
break;
case MAKE_OPCODE_SHORT(OP_FTOI8, 8, 0): // FDTOI8 dst,src1
- *inst[0].pint64 = FDPARAM1;
+ switch (m_state.fmod)
+ {
+ default:
+ case ROUND_TRUNC:
+ *inst[0].pint64 = int64_t(FDPARAM1);
+ break;
+ case ROUND_ROUND:
+ *inst[0].pint64 = llround(FDPARAM1);
+ break;
+ case ROUND_FLOOR:
+ *inst[0].pint64 = int64_t(floor(FDPARAM1));
+ break;
+ case ROUND_CEIL:
+ *inst[0].pint64 = int64_t(ceil(FDPARAM1));
+ break;
+ }
break;
case MAKE_OPCODE_SHORT(OP_FFRI4, 8, 0): // FDFRI4 dst,src1