summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2019-09-13 11:56:12 +0200
committer angelosa <lordkale4@gmail.com>2019-09-13 11:56:12 +0200
commit4d83176feb766d996c5a62ed8c88b0e5b13030ba (patch)
tree4d95e5c08b2a0cbec52295cab6c397c79158ea28
parent18946a88e76bd6b04c1910050b55a9a5c2136a7f (diff)
Experimental unimplemented instruction trap code, with funny results ...
-rw-r--r--hash/archimedes.xml5
-rw-r--r--src/devices/cpu/arm/arm.cpp281
-rw-r--r--src/devices/cpu/arm/arm.h13
-rw-r--r--src/devices/cpu/arm/armfpu.cpp349
4 files changed, 457 insertions, 191 deletions
diff --git a/hash/archimedes.xml b/hash/archimedes.xml
index cda7bfce63f..5b496d91e8b 100644
--- a/hash/archimedes.xml
+++ b/hash/archimedes.xml
@@ -1995,8 +1995,9 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
- <!-- boot OK, cannot take off, trips unemulated COPRO opcode, to be rechecked -->
- <software name="mig29">
+ <!-- boot OK, trips various unemulated COPRO opcode -->
+ <!-- Has internal joystick calibration -->
+ <software name="mig29" supported="partial">
<description>Mig 29 Fulcrum</description>
<year>1991</year>
<publisher>Krisalis</publisher>
diff --git a/src/devices/cpu/arm/arm.cpp b/src/devices/cpu/arm/arm.cpp
index 5d1431be7d5..2003421fa48 100644
--- a/src/devices/cpu/arm/arm.cpp
+++ b/src/devices/cpu/arm/arm.cpp
@@ -420,22 +420,24 @@ void arm_cpu_device::execute_run()
{
HandleBranch(insn);
}
- else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */
+ else if (((insn & 0x0f000000u) == 0x0e000000u) || ((insn & 0x0e000000u) == 0x0c000000u)) /* Coprocessor */
{
if (m_copro_type == copro_type::VL86C020)
- HandleCoProVL86C020(insn);
+ {
+ bool validcopro = HandleCoProVL86C020(insn);
+
+ if (validcopro == true)
+ R15 += 4;
+ }
else
+ {
HandleCoPro(insn);
-
- R15 += 4;
+ R15 += 4;
+ }
}
- else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */
+ else if ((insn & 0x0f000000u) == 0x0f000000u) // SWI - Software interrupt
{
- pc=R15+4;
- R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */
- SetRegister( 14, pc ); /* save PC */
- R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK);
- m_icount -= 2 * S_CYCLE + N_CYCLE;
+ HandleTrap(0x08);
}
else /* Undefined */
{
@@ -447,10 +449,22 @@ void arm_cpu_device::execute_run()
} while( m_icount > 0 );
} /* arm_execute */
+void arm_cpu_device::HandleTrap(uint8_t vector)
+{
+ if (vector == 0x04)
+ printf("%08x\n",R15&0x3fffffc);
+
+ uint32_t pc = R15+4;
+ R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */
+ SetRegister( 14, pc ); /* save PC */
+ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|(vector)|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK);
+
+ m_icount -= 2 * S_CYCLE + N_CYCLE;
+}
void arm_cpu_device::arm_check_irq_state()
{
- uint32_t pc = R15+4; /* save old pc (already incremented in pipeline) */;
+ uint32_t pc = R15+4; /* save old pc (already incremented in pipeline) */
/* Exception priorities (from ARM6, not specifically ARM2/3):
@@ -543,17 +557,6 @@ void arm_cpu_device::device_start()
state_add( ARM32_IR14, "IR14", m_sArmRegister[eR14_IRQ] ).formatstr("%08X");
state_add( ARM32_SR13, "SR13", m_sArmRegister[eR13_SVC] ).formatstr("%08X");
state_add( ARM32_SR14, "SR14", m_sArmRegister[eR14_SVC] ).formatstr("%08X");
- if (m_copro_type == copro_type::VL86C020)
- {
- state_add( COPRO_F0, "F0", m_coproRegister[0] ).formatstr("%08X");
- state_add( COPRO_F1, "F1", m_coproRegister[1] ).formatstr("%08X");
- state_add( COPRO_F2, "F2", m_coproRegister[2] ).formatstr("%08X");
- state_add( COPRO_F3, "F3", m_coproRegister[3] ).formatstr("%08X");
- state_add( COPRO_F4, "F4", m_coproRegister[4] ).formatstr("%08X");
- state_add( COPRO_F5, "F5", m_coproRegister[5] ).formatstr("%08X");
- state_add( COPRO_F6, "F6", m_coproRegister[6] ).formatstr("%08X");
- state_add( COPRO_F7, "F7", m_coproRegister[7] ).formatstr("%08X");
- }
state_add(STATE_GENPC, "GENPC", m_sArmRegister[15]).mask(ADDRESS_MASK).formatstr("%8s").noshow();
state_add(STATE_GENPCBASE, "CURPC", m_sArmRegister[15]).mask(ADDRESS_MASK).formatstr("%8s").noshow();
@@ -1435,165 +1438,36 @@ uint32_t arm_cpu_device::DecimalToBCD(uint32_t value)
return accumulator;
}
-inline float32_t arm_cpu_device::ReadCoProRegOrConst32(const uint32_t idx)
-{
- if (idx & 8)
- {
- float32_t table[8] = { 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x40a00000, 0x3f000000, 0x41200000 };
- return table[idx & 7];
- }
-
- return ui32_to_f32(m_coproRegister[idx]);
-}
-
-inline float64_t arm_cpu_device::ReadCoProRegOrConst64(const uint32_t idx)
-{
- if (idx & 8)
- {
- float64_t table[8] = { 0x0000000000000000, 0x3ff0000000000000, 0x4000000000000000, 0x4008000000000000,
- 0x4010000000000000, 0x4014000000000000, 0x3fe0000000000000, 0x4024000000000000 };
- return table[idx & 7];
- }
-
- return ui32_to_f64(m_coproRegister[idx]);
-}
-
-
-void arm_cpu_device::HandleCoProVL86C020( uint32_t insn )
+bool arm_cpu_device::HandleCoProVL86C020( uint32_t insn )
{
uint32_t rn = (insn>>12)&0xf;
uint32_t crn = (insn>>16)&0x7;
- uint32_t crn2 = insn & 0xf;
- // nearest, Plus infinity, Minus infinity, Zero
- const uint_fast8_t arm_to_sf_rounding[4] = {
- softfloat_round_near_even,
- softfloat_round_max,
- softfloat_round_min,
- softfloat_round_near_maxMag
- };
- uint8_t round_mode = arm_to_sf_rounding[(insn>>5)&0x3];
- // Single, Double, double Extended, Packed decimal
- uint8_t precision_mode = (BIT(insn,20)<<1)|(BIT(insn,7));
-
m_icount -= S_CYCLE;
- if (precision_mode >= 2)
- {
- //printf("%08x: Unimplemented VL86C020 copro precision mode %08x %d %d\n", R15 & 0x3ffffff, insn,rn,crn);
- return;
- }
-
- // FLT - integer to floating point reg
- if((insn & 0x0ff00f1f) == 0x0e000110)
- {
- m_coproRegister[crn] = GetRegister(rn);
- }
- // FIX - floating point to integer reg
- else if ((insn & 0x0fff0f98) == 0x0e100110)
- {
- uint32_t result;
- switch(precision_mode)
- {
- case 0:
- {
- float32_t src = ui32_to_f32(m_coproRegister[crn]);
- result = f32_to_ui32(src, round_mode, true);
- break;
- }
- case 1:
- {
- float64_t src = ui32_to_f64(m_coproRegister[crn]);
- result = f64_to_ui32(src, round_mode, true);
- break;
- }
- }
-
- SetRegister(rn, result);
- }
- // ADF - Addition between floating point regs
- else if ((insn&0x0ff08f10)==0x0e000100 )
- {
- uint32_t result;
- rn &= 7;
- switch(precision_mode)
- {
- case 0:
- {
- float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
- float32_t op2 = ReadCoProRegOrConst32(crn2);
- float32_t fres = f32_add(op1, op2);
- result = f32_to_ui32(fres, round_mode, true);
- break;
- }
- case 1:
- {
- float64_t op1 = ui32_to_f64(m_coproRegister[crn]);
- float64_t op2 = ReadCoProRegOrConst64(crn2);
- float64_t fres = f64_add(op1, op2);
- result = f64_to_ui32(fres, round_mode, true);
- break;
- }
- }
-
- m_coproRegister[rn] = result;
- }
- // MVF - Move
- else if ( (insn&0x0ff08f10)==0x0e008100 )
- {
- uint32_t result;
-
- switch(precision_mode)
- {
- case 0:
- {
- float32_t fres = ReadCoProRegOrConst32(crn2);
- result = f32_to_ui32(fres, round_mode, true);
- break;
- }
- case 1:
- {
- float64_t fres = ReadCoProRegOrConst64(crn2);
- result = f64_to_ui32(fres, round_mode, true);
- break;
- }
- }
-
- m_coproRegister[crn] = result;
- }
- // CMFS - compare
- else if ( (insn&0x0ff8fff0) == 0x0e90f110)
- {
- bool result;
-
- // TODO: according to "The Hacker" on AA, op2 ignores constants here, needs to be counterchecked.
- switch(precision_mode)
- {
- case 0:
- {
- float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
- float32_t op2 = ui32_to_f32(m_coproRegister[crn2 & 7]);
- result = f32_eq(op1, op2);
- break;
- }
- case 1:
- {
- float64_t op1 = ui32_to_f64(m_coproRegister[crn]);
- float64_t op2 = ui32_to_f64(m_coproRegister[crn2 & 7]);
- result = f64_eq(op1, op2);
- break;
- }
- }
-
- if (result == true)
- R15 |= (Z_MASK);
- else
- R15 &= ~(Z_MASK);
-
- // TODO: V flag
- R15 &= ~(V_MASK);
- }
- /* MRC - transfer copro register to main register */
- else if( (insn&0x0f100010)==0x0e100010 )
+#if 0
+ printf("%08x OPCODE\n",insn);
+ // TODO: this is actually correct for ARM250, but RiscOS 3.xx fails at boot with "SWI &706F74 not known" (???)
+ // it does that by accessing RFC / RFS, which is fun
+ HandleTrap(0x04);
+// machine().debug_break();
+ return false;
+#endif
+
+ // simcity (PC=0x12bf0)
+ // 0xed900100 LDFS F0,[R0]
+ // 0xee101170 FIXSZ R1,F0
+ // on unimplemented opcode trap it returns at PC=0x1822cc8 with
+ // 0xe8fd7fff LDMFD R13!,{R0-R14}^
+ // 0xe8fd8000 LDMFD R13!,{PC}^
+ // 0xe8bd1fff LDMFD R13!,{R0-R12}
+ // Edit: after adding the 0xc / 0xd group opcodes it doesn't survive the first opcode of these at PC=0x12cc4
+ // 0xed6d7103 STFE F7,[R13,#12]!
+ // 0xed6d6103 STFE F6,[R13,#12]!
+ // 0xed6d5103
+ // 0xed6d4103
+
+ /* MRC - transfer copro register to main register (enable CP15 only for now) */
+ if( (insn&0x0f100f10)==0x0e100f10 )
{
if(crn == 0) // ID, read only
{
@@ -1608,22 +1482,67 @@ void arm_cpu_device::HandleCoProVL86C020( uint32_t insn )
}
else if (crn >= 2 && crn < 6)
SetRegister(rn, m_coproControl[crn]);
-
}
/* MCR - transfer main register to copro register */
- else if( (insn&0x0f100010)==0x0e000010 )
+ else if( (insn&0x0f100f10)==0x0e000f10 )
{
if(crn >= 2 && crn < 6)
m_coproControl[crn]=GetRegister(rn);
-
+
// TODO: cache, trap if accessed in user mode, undefined instruction trap if any illegal access occurs (probably)
//printf("%08x: VL86C020 copro instruction write %08x %d %d\n", R15 & 0x3ffffff, insn,rn,crn);
}
+ // WFS - Write Floating Point status
+ else if ( (insn&0x0fff0fff) == 0x0e200110)
+ {
+ // upper byte is ID, on which we currently cheat and inform it's using SW emulation
+ // known list, courtesy of https://heyrick.eu/assembler/fpops.html#unop
+ // mig29 and simcity have a FPE v2.xx in case you need one
+ //&00 Old FPE - FPE module prior to v4.00
+ //&80 FPPC - Interface between ARM and WE32206 (AT&T MAU)
+ //&01 FPE 400 - FPE module v4.00 or later
+ //&81 FPA - ARM FPU
+ // as for the other bits, (m=mask, f=flag)
+ // ---m ---- ---- ---- ---x ---- INeXact
+ // ---- m--- ---- ---- ---- x--- UnderFLow
+ // ---- -m-- ---- ---- ---- -x-- OverFLow
+ // ---- --m- ---- ---- ---- --x- DiVide by Zero
+ // ---- ---m ---- ---- ---- ---x InValid Operation
+ // RISC OS 3.xx sets IVO flag at 038fe1c4
+ m_coproFPsr = (GetRegister(rn) & 0xffffff) | (0x00<<24);
+ }
+ // RFS - Read Floating Point status
+ else if ( (insn&0x0fff0fff) == 0x0e300110)
+ {
+ SetRegister(rn, m_coproFPsr);
+ }
+ // WFC - Write Floating Point Control
+ else if ( (insn&0x0fff0fff) == 0x0e400110)
+ {
+ // TODO: check for user mode, throw access violation
+ m_coproFPcr = GetRegister(rn);
+ // TODO: check what it tries to do
+ printf("%08x: WFC write %08x\n", R15 & 0x3fffffc, m_coproFPcr);
+ }
+ // RFC - Read Floating Point Control
+ else if ( (insn&0x0fff0fff) == 0x0e500110)
+ {
+ // TODO: check for user mode, throw access violation
+ SetRegister(rn, m_coproFPcr);
+ }
else
{
- printf("%08x: Unimplemented VL86C020 copro instruction %08x %d %d\n", R15 & 0x3ffffff, insn,rn,crn);
- machine().debug_break();
+ printf("%08x OPCODE\n",insn);
+ HandleTrap(0x04);
+ if ((insn & 0x0e000000) == 0x0e000000)
+ machine().debug_break();
+ // HandleFPU(insn);
+ //printf("%08x: Unimplemented VL86C020 copro instruction %08x %d %d\n", R15 & 0x3ffffff, insn,rn,crn);
+
+ return false;
}
+
+ return true;
}
void arm_cpu_device::HandleCoPro( uint32_t insn )
diff --git a/src/devices/cpu/arm/arm.h b/src/devices/cpu/arm/arm.h
index c81bde20e8a..bedd2b7b3f5 100644
--- a/src/devices/cpu/arm/arm.h
+++ b/src/devices/cpu/arm/arm.h
@@ -6,8 +6,6 @@
#pragma once
-#include "softfloat3/source/include/softfloat.h"
-
/****************************************************************************************************
* INTERRUPT CONSTANTS
***************************************************************************************************/
@@ -40,8 +38,7 @@ protected:
ARM32_R0, ARM32_R1, ARM32_R2, ARM32_R3, ARM32_R4, ARM32_R5, ARM32_R6, ARM32_R7,
ARM32_R8, ARM32_R9, ARM32_R10, ARM32_R11, ARM32_R12, ARM32_R13, ARM32_R14, ARM32_R15,
ARM32_FR8, ARM32_FR9, ARM32_FR10, ARM32_FR11, ARM32_FR12, ARM32_FR13, ARM32_FR14,
- ARM32_IR13, ARM32_IR14, ARM32_SR13, ARM32_SR14,
- COPRO_F0, COPRO_F1, COPRO_F2, COPRO_F3, COPRO_F4, COPRO_F5, COPRO_F6, COPRO_F7
+ ARM32_IR13, ARM32_IR14, ARM32_SR13, ARM32_SR14
};
arm_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness);
@@ -70,8 +67,9 @@ protected:
int m_icount;
uint32_t m_sArmRegister[27];
- u32 m_coproRegister[16];
uint32_t m_coproControl[16];
+ uint32_t m_coproFPsr, m_coproFPcr;
+ uint32_t m_coproRegister[16];
uint8_t m_pendingIrq;
uint8_t m_pendingFiq;
address_space *m_program;
@@ -93,7 +91,8 @@ protected:
void HandleMemSingle(uint32_t insn);
void HandleMemBlock(uint32_t insn);
void HandleCoPro(uint32_t insn);
- void HandleCoProVL86C020(uint32_t insn);
+ bool HandleCoProVL86C020(uint32_t insn);
+ inline void HandleTrap(uint8_t vector);
uint32_t decodeShift(uint32_t insn, uint32_t *pCarry);
void arm_check_irq_state();
int loadInc(uint32_t pat, uint32_t rbv, uint32_t s);
@@ -102,8 +101,6 @@ protected:
int storeDec(uint32_t pat, uint32_t rbv);
static uint32_t BCDToDecimal(uint32_t value);
static uint32_t DecimalToBCD(uint32_t value);
- inline float32_t ReadCoProRegOrConst32(uint32_t idx);
- inline float64_t ReadCoProRegOrConst64(uint32_t idx);
};
diff --git a/src/devices/cpu/arm/armfpu.cpp b/src/devices/cpu/arm/armfpu.cpp
new file mode 100644
index 00000000000..3f18781584b
--- /dev/null
+++ b/src/devices/cpu/arm/armfpu.cpp
@@ -0,0 +1,349 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/*
+ ARM3 coprocessor FPU
+
+ TODO:
+ - Currently not hooked up to the main core: we rely on undefined instruction traps instead;
+ - This should also be a subdevice of ARM3. ARM250 doesn't have a FPU at all unless an additional board
+ is provided which interfaces with a WE32206 MAU (which has its own instruction set, fun)
+ - This is a good candidate for unit testing, and I mean it;
+*/
+
+inline float32_t arm_cpu_device::ReadCoProRegOrConst32(const uint32_t idx)
+{
+ if (idx & 8)
+ {
+ float32_t table[8] = { 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x40a00000, 0x3f000000, 0x41200000 };
+ return table[idx & 7];
+ }
+
+ return ui32_to_f32(m_coproRegister[idx]);
+}
+
+inline float64_t arm_cpu_device::ReadCoProRegOrConst64(const uint32_t idx)
+{
+ if (idx & 8)
+ {
+ float64_t table[8] = { 0x0000000000000000, 0x3ff0000000000000, 0x4000000000000000, 0x4008000000000000,
+ 0x4010000000000000, 0x4014000000000000, 0x3fe0000000000000, 0x4024000000000000 };
+ return table[idx & 7];
+ }
+
+ return ui32_to_f64(m_coproRegister[idx]);
+}
+
+void arm_cpu_device::HandleFPU( uint32_t insn )
+{
+ uint32_t rn = (insn>>12)&0xf;
+ uint32_t crn = (insn>>16)&0x7;
+ uint32_t crn2 = insn & 0xf;
+ // nearest, Plus infinity, Minus infinity, Zero
+ const uint_fast8_t arm_to_sf_rounding[4] = {
+ softfloat_round_near_even,
+ softfloat_round_max,
+ softfloat_round_min,
+ softfloat_round_near_maxMag
+ };
+ uint8_t round_mode = arm_to_sf_rounding[(insn>>5)&0x3];
+ // Single, Double, double Extended, Packed decimal, Extended Packed decimal
+ // TODO: we don't currently emulate this until we get the actual specs (i.e. registers actual parallelism, how they transfers etc.)
+ uint8_t precision_mode = (BIT(insn,20)<<1)|(BIT(insn,7));
+
+
+ //ee105f10 OPCODE
+ //0381167c
+ //ee105f10 OPCODE
+ //038b1094
+ //ee502110 OPCODE
+ //038fe1bc
+ //ee502110 OPCODE
+ //038fe1bc
+ //ee301110 OPCODE
+ //03877ac4
+
+ // bughunt
+ // ee888100 - SINE
+ // ee988100 - COSE
+ // dropship, powrband, starf3k
+ // 2e472029 - <not a COPRO inst>
+ // karmaft
+ // 3e694c3c - <not a COPRO inst, again ASCII?>
+ // ee80b180 - SIND
+ // ee90a180 - COSE
+ // ee108109 - MNFS
+ // ee109109 /
+ // mig29 (need to take off, terrain fill shapes?)
+ // eea08180 - TAND
+ // simosor
+ // 7e007e00 - <not a COPRO inst>
+
+ // FLT - integer to floating point reg
+ if((insn & 0x0ff00f1f) == 0x0e000110)
+ {
+ m_coproRegister[crn] = GetRegister(rn);
+ }
+ // FIX - floating point to integer reg
+ else if ((insn & 0x0fff0f98) == 0x0e100110)
+ {
+ uint32_t result;
+
+ switch(precision_mode)
+ {
+ case 0:
+ {
+ float32_t src = ui32_to_f32(m_coproRegister[crn]);
+ result = f32_to_ui32(src, round_mode, true);
+ break;
+ }
+ case 1:
+ {
+ float64_t src = ui32_to_f64(m_coproRegister[crn]);
+ result = f64_to_ui32(src, round_mode, true);
+ break;
+ }
+ default:
+ printf("%08x: Unimplemented VL86C020 copro instruction FIX%d %08x %d %d\n", R15 & 0x3fffffc, precision_mode, insn,rn,crn);
+ return;
+ }
+
+ SetRegister(rn, result);
+ }
+ // Basic Math
+ else if ((insn&0x0f008f10)==0x0e000100)
+ {
+ uint32_t result;
+ uint8_t optype = (insn & 0xf00000) >> 20;
+ rn &= 7;
+ // fast versions always use 32-bit precision
+ switch(optype)
+ {
+ case 0x0: // ADF - Add
+ {
+ switch(precision_mode)
+ {
+ case 0:
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ReadCoProRegOrConst32(crn2);
+ float32_t fres = f32_add(op1, op2);
+ result = f32_to_ui32(fres, round_mode, true);
+ break;
+ }
+ case 1:
+ {
+ float64_t op1 = ui32_to_f64(m_coproRegister[crn]);
+ float64_t op2 = ReadCoProRegOrConst64(crn2);
+ float64_t fres = f64_add(op1, op2);
+ result = f64_to_ui32(fres, round_mode, true);
+ break;
+ }
+ default:
+ printf("%08x: Unimplemented VL86C020 copro instruction ADF%d %08x %d %d\n", R15 & 0x3fffffc, precision_mode, insn,rn,crn);
+ return;
+ }
+ break;
+ }
+ case 0x1: // MUF - Multiply
+ case 0x9: // FML - Fast multiply
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ReadCoProRegOrConst32(crn2);
+ float32_t fres = f32_mul(op1, op2);
+ result = f32_to_ui32(fres, round_mode, true);
+ break;
+ }
+ case 0x2: // SUF - Subtract
+ {
+ switch(precision_mode)
+ {
+ case 0:
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ReadCoProRegOrConst32(crn2);
+ float32_t fres = f32_sub(op1, op2);
+ result = f32_to_ui32(fres, round_mode, true);
+ break;
+ }
+ case 1:
+ {
+ float64_t op1 = ui32_to_f64(m_coproRegister[crn]);
+ float64_t op2 = ReadCoProRegOrConst64(crn2);
+ float64_t fres = f64_sub(op1, op2);
+ result = f64_to_ui32(fres, round_mode, true);
+ break;
+ }
+ default:
+ printf("%08x: Unimplemented VL86C020 copro instruction SUF%d %08x %d %d\n", R15 & 0x3fffffc, precision_mode, insn,rn,crn);
+ return;
+ }
+ break;
+ }
+ case 0x3: // RSF - Reverse Subtract
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ReadCoProRegOrConst32(crn2);
+ float32_t fres = f32_sub(op2, op1);
+ result = f32_to_ui32(fres, round_mode, true);
+ break;
+ }
+ case 0x4: // DVF - Divide
+ case 0xa: // FDV - Fast Divide
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ReadCoProRegOrConst32(crn2);
+ float32_t fres = f32_div(op1, op2);
+ result = f32_to_ui32(fres, round_mode, true);
+ break;
+ }
+ case 0x5: // RDF - Reverse Divide
+ case 0xb: // FRD - Fast Reverse Divide
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ReadCoProRegOrConst32(crn2);
+ float32_t fres = f32_div(op2, op1);
+ result = f32_to_ui32(fres, round_mode, true);
+ break;
+ }
+ case 0x8: // RMF - Remainder
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ReadCoProRegOrConst32(crn2);
+ float32_t fres = f32_rem(op1, op2);
+ result = f32_to_ui32(fres, round_mode, true);
+ break;
+ }
+ case 0x6: // POW - Power
+ case 0x7: // RPW - Reverse Power
+ printf("%08x: Unimplemented VL86C020 copro instruction POW/RPW %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0xc: // POL - Polar Angle
+ printf("%08x: Unimplemented VL86C020 copro instruction POL %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ default:
+ printf("%08x: Illegal VL86C020 copro instruction %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ }
+
+ m_coproRegister[rn] = result;
+ }
+ // Advanced Math
+ else if ((insn&0x0f008f10)==0x0e008100)
+ {
+ uint32_t result;
+ uint8_t optype = (insn & 0xf00000) >> 20;
+ rn &= 7;
+// float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+// float32_t op2 = ReadCoProRegOrConst32(crn2);
+
+ switch(optype)
+ {
+ case 0x0: // MVF - Move
+ case 0x1: // MNF - Move Negated
+ {
+ switch(precision_mode)
+ {
+ case 0:
+ {
+ float32_t fres = ReadCoProRegOrConst32(crn2);
+ result = f32_to_ui32(fres, round_mode, true);
+ if (optype & 1)
+ result |= 1 << 31;
+ break;
+ }
+ case 1:
+ {
+ float64_t fres = ReadCoProRegOrConst64(crn2);
+ result = f64_to_ui32(fres, round_mode, true);
+ if (optype & 1)
+ result |= 1 << 31;
+ break;
+ }
+ default:
+ printf("%08x: Unimplemented VL86C020 copro instruction MVF/MNF%d %08x %d %d\n", R15 & 0x3fffffc, precision_mode, insn,rn,crn);
+ return;
+ }
+ }
+ case 0x2: // ABS - Absolute
+ printf("%08x: Unimplemented VL86C020 copro instruction ABS %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0x3: // RND - Round to Integral
+ printf("%08x: Unimplemented VL86C020 copro instruction RND %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0x4: // SQT - Square Root
+ printf("%08x: Unimplemented VL86C020 copro instruction SQT %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0x5: // LOG - logarithm to base 10
+ case 0x6: // LGN - logarithm to base e
+ printf("%08x: Unimplemented VL86C020 copro instruction LOG/LGN %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0x7: // EXP - Exponent
+ printf("%08x: Unimplemented VL86C020 copro instruction EXP %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0x8: // SIN - Sine
+ case 0x9: // COS - Cosine
+ case 0xa: // TAN - Tangent
+ printf("%08x: Unimplemented VL86C020 copro instruction SIN/COS/TAN %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0xb: // ASN - Arc Sine
+ printf("%08x: Unimplemented VL86C020 copro instruction ASN %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0xc: // ACS - Arc Cosine
+ printf("%08x: Unimplemented VL86C020 copro instruction ACS %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0xd: // ATN - Arc Tangent
+ printf("%08x: Unimplemented VL86C020 copro instruction ATN %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0xe: // URD - Unnormalized Round
+ printf("%08x: Unimplemented VL86C020 copro instruction URD %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ case 0xf: // NRM - Normalise
+ printf("%08x: Unimplemented VL86C020 copro instruction NRM %08x %d %d\n", R15 & 0x3fffffc, insn,rn,crn);
+ return;
+ }
+
+ m_coproRegister[rn] = result;
+ }
+ // CMF - compare
+ else if ( (insn&0x0ff8fff0) == 0x0e90f110)
+ {
+ bool result;
+
+ // TODO: according to "The Hacker" on AA, op2 ignores constants here, needs to be counterchecked.
+ switch(precision_mode)
+ {
+ case 0:
+ {
+ float32_t op1 = ui32_to_f32(m_coproRegister[crn]);
+ float32_t op2 = ui32_to_f32(m_coproRegister[crn2 & 7]);
+ result = f32_eq(op1, op2);
+ break;
+ }
+ case 1:
+ {
+ float64_t op1 = ui32_to_f64(m_coproRegister[crn]);
+ float64_t op2 = ui32_to_f64(m_coproRegister[crn2 & 7]);
+ result = f64_eq(op1, op2);
+ break;
+ }
+ default:
+ printf("%08x: Unimplemented VL86C020 copro instruction CMF%d %08x %d %d\n", R15 & 0x3fffffc, precision_mode, insn,rn,crn);
+ result = false;
+ return;
+ }
+
+ // TODO: verify if it's gonna go to R15 or in its own FPSR
+ if (result == true)
+ R15 |= (Z_MASK);
+ else
+ R15 &= ~(Z_MASK);
+
+ // TODO: V/C/N flags
+ R15 &= ~(V_MASK);
+ }
+ else
+ {
+ printf("%08x: Unimplemented VL86C020 copro instruction %08x %d %d\n", R15 & 0x3ffffff, insn,rn,crn);
+ machine().debug_break();
+ }
+}