diff options
author | 2019-09-13 11:56:12 +0200 | |
---|---|---|
committer | 2019-09-13 11:56:12 +0200 | |
commit | 4d83176feb766d996c5a62ed8c88b0e5b13030ba (patch) | |
tree | 4d95e5c08b2a0cbec52295cab6c397c79158ea28 | |
parent | 18946a88e76bd6b04c1910050b55a9a5c2136a7f (diff) |
Experimental unimplemented instruction trap code, with funny results ...
-rw-r--r-- | hash/archimedes.xml | 5 | ||||
-rw-r--r-- | src/devices/cpu/arm/arm.cpp | 281 | ||||
-rw-r--r-- | src/devices/cpu/arm/arm.h | 13 | ||||
-rw-r--r-- | src/devices/cpu/arm/armfpu.cpp | 349 |
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(); + } +} |