sh4: fix FMOV* opcodes,

half of FPU was not correct, but who cares ?)
This commit is contained in:
MetalliC 2017-01-26 16:47:10 +02:00
parent 07ef2097d3
commit 4f85c189fa

View File

@ -2556,21 +2556,7 @@ inline void sh34_base_device::PREFM(const uint16_t opcode)
* OPCODE DISPATCHERS * OPCODE DISPATCHERS
*****************************************************************************/ *****************************************************************************/
// TODO: current SZ=1(64bit) FMOVs correct for SH4 in LE mode only
/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */ /* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */
/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */ /* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */
@ -2580,35 +2566,36 @@ inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode)
{ {
uint32_t m = Rm; uint32_t n = Rn; uint32_t m = Rm; uint32_t n = Rn;
if (m_fpu_pr) { /* PR = 1 */
n = n & 14;
m_ea = m_r[m];
m_r[m] += 8;
m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
} else { /* PR = 0 */
if (m_fpu_sz) { /* SZ = 1 */ if (m_fpu_sz) { /* SZ = 1 */
if (n & 1) { if (n & 1) {
n = n & 14; n &= 14;
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_ea = m_r[m]; m_ea = m_r[m];
m_xf[n] = RL(m_ea ); m_xf[n] = RL(m_ea );
m_r[m] += 4; m_r[m] += 4;
m_xf[n+1] = RL(m_ea+4 ); m_xf[n^1] = RL(m_ea+4 );
m_r[m] += 4; m_r[m] += 4;
} else { } else {
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_ea = m_r[m]; m_ea = m_r[m];
m_fr[n] = RL(m_ea ); m_fr[n] = RL(m_ea );
m_r[m] += 4; m_r[m] += 4;
m_fr[n+1] = RL(m_ea+4 ); m_fr[n^1] = RL(m_ea+4 );
m_r[m] += 4; m_r[m] += 4;
} }
} else { /* SZ = 0 */ } else { /* SZ = 0 */
m_ea = m_r[m]; m_ea = m_r[m];
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_fr[n] = RL(m_ea ); m_fr[n] = RL(m_ea );
m_r[m] += 4; m_r[m] += 4;
} }
} }
}
/* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */ /* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */
/* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */ /* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */
@ -2618,29 +2605,31 @@ inline void sh34_base_device::FMOVFRMR(const uint16_t opcode)
{ {
uint32_t m = Rm; uint32_t n = Rn; uint32_t m = Rm; uint32_t n = Rn;
if (m_fpu_pr) { /* PR = 1 */
m= m & 14;
m_ea = m_r[n];
WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
} else { /* PR = 0 */
if (m_fpu_sz) { /* SZ = 1 */ if (m_fpu_sz) { /* SZ = 1 */
if (m & 1) { if (m & 1) {
m= m & 14; m &= 14;
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
m_ea = m_r[n]; m_ea = m_r[n];
WL(m_ea,m_xf[m] ); WL(m_ea,m_xf[m] );
WL(m_ea+4,m_xf[m+1] ); WL(m_ea+4,m_xf[m^1] );
} else { } else {
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
m_ea = m_r[n]; m_ea = m_r[n];
WL(m_ea,m_fr[m] ); WL(m_ea,m_fr[m] );
WL(m_ea+4,m_fr[m+1] ); WL(m_ea+4,m_fr[m^1] );
} }
} else { /* SZ = 0 */ } else { /* SZ = 0 */
m_ea = m_r[n]; m_ea = m_r[n];
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
WL(m_ea,m_fr[m] ); WL(m_ea,m_fr[m] );
} }
} }
}
/* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */ /* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */
/* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */ /* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */
@ -2650,33 +2639,34 @@ inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode)
{ {
uint32_t m = Rm; uint32_t n = Rn; uint32_t m = Rm; uint32_t n = Rn;
if (m_fpu_pr) { /* PR = 1 */
m= m & 14;
m_r[n] -= 8;
m_ea = m_r[n];
WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
} else { /* PR = 0 */
if (m_fpu_sz) { /* SZ = 1 */ if (m_fpu_sz) { /* SZ = 1 */
if (m & 1) { if (m & 1) {
m= m & 14; m &= 14;
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
m_r[n] -= 8; m_r[n] -= 8;
m_ea = m_r[n]; m_ea = m_r[n];
WL(m_ea,m_xf[m] ); WL(m_ea,m_xf[m] );
WL(m_ea+4,m_xf[m+1] ); WL(m_ea+4,m_xf[m^1] );
} else { } else {
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
m_r[n] -= 8; m_r[n] -= 8;
m_ea = m_r[n]; m_ea = m_r[n];
WL(m_ea,m_fr[m] ); WL(m_ea,m_fr[m] );
WL(m_ea+4,m_fr[m+1] ); WL(m_ea+4,m_fr[m^1] );
} }
} else { /* SZ = 0 */ } else { /* SZ = 0 */
m_r[n] -= 4; m_r[n] -= 4;
m_ea = m_r[n]; m_ea = m_r[n];
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
WL(m_ea,m_fr[m] ); WL(m_ea,m_fr[m] );
} }
} }
}
/* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */ /* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */
/* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */ /* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */
@ -2686,29 +2676,31 @@ inline void sh34_base_device::FMOVFRS0(const uint16_t opcode)
{ {
uint32_t m = Rm; uint32_t n = Rn; uint32_t m = Rm; uint32_t n = Rn;
if (m_fpu_pr) { /* PR = 1 */
m= m & 14;
m_ea = m_r[0] + m_r[n];
WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
} else { /* PR = 0 */
if (m_fpu_sz) { /* SZ = 1 */ if (m_fpu_sz) { /* SZ = 1 */
if (m & 1) { if (m & 1) {
m= m & 14; m &= 14;
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
m_ea = m_r[0] + m_r[n]; m_ea = m_r[0] + m_r[n];
WL(m_ea,m_xf[m] ); WL(m_ea,m_xf[m] );
WL(m_ea+4,m_xf[m+1] ); WL(m_ea+4,m_xf[m^1] );
} else { } else {
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
m_ea = m_r[0] + m_r[n]; m_ea = m_r[0] + m_r[n];
WL(m_ea,m_fr[m] ); WL(m_ea,m_fr[m] );
WL(m_ea+4,m_fr[m+1] ); WL(m_ea+4,m_fr[m^1] );
} }
} else { /* SZ = 0 */ } else { /* SZ = 0 */
m_ea = m_r[0] + m_r[n]; m_ea = m_r[0] + m_r[n];
#ifdef LSB_FIRST
m ^= m_fpu_pr;
#endif
WL(m_ea,m_fr[m] ); WL(m_ea,m_fr[m] );
} }
} }
}
/* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */ /* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */
/* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */ /* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */
@ -2718,29 +2710,31 @@ inline void sh34_base_device::FMOVS0FR(const uint16_t opcode)
{ {
uint32_t m = Rm; uint32_t n = Rn; uint32_t m = Rm; uint32_t n = Rn;
if (m_fpu_pr) { /* PR = 1 */
n= n & 14;
m_ea = m_r[0] + m_r[m];
m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
} else { /* PR = 0 */
if (m_fpu_sz) { /* SZ = 1 */ if (m_fpu_sz) { /* SZ = 1 */
if (n & 1) { if (n & 1) {
n= n & 14; n &= 14;
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_ea = m_r[0] + m_r[m]; m_ea = m_r[0] + m_r[m];
m_xf[n] = RL(m_ea ); m_xf[n] = RL(m_ea );
m_xf[n+1] = RL(m_ea+4 ); m_xf[n^1] = RL(m_ea+4 );
} else { } else {
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_ea = m_r[0] + m_r[m]; m_ea = m_r[0] + m_r[m];
m_fr[n] = RL(m_ea ); m_fr[n] = RL(m_ea );
m_fr[n+1] = RL(m_ea+4 ); m_fr[n^1] = RL(m_ea+4 );
} }
} else { /* SZ = 0 */ } else { /* SZ = 0 */
m_ea = m_r[0] + m_r[m]; m_ea = m_r[0] + m_r[m];
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_fr[n] = RL(m_ea ); m_fr[n] = RL(m_ea );
} }
} }
}
/* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */ /* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */
/* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */ /* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */
@ -2751,37 +2745,31 @@ inline void sh34_base_device::FMOVMRFR(const uint16_t opcode)
{ {
uint32_t m = Rm; uint32_t n = Rn; uint32_t m = Rm; uint32_t n = Rn;
if (m_fpu_pr) { /* PR = 1 */
if (n & 1) {
n= n & 14;
m_ea = m_r[m];
m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
} else {
n= n & 14;
m_ea = m_r[m];
m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
}
} else { /* PR = 0 */
if (m_fpu_sz) { /* SZ = 1 */ if (m_fpu_sz) { /* SZ = 1 */
if (n & 1) { if (n & 1) {
n= n & 14; n &= 14;
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_ea = m_r[m]; m_ea = m_r[m];
m_xf[n] = RL(m_ea ); m_xf[n] = RL(m_ea );
m_xf[n+1] = RL(m_ea+4 ); m_xf[n^1] = RL(m_ea+4 );
} else { } else {
n= n & 14; #ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_ea = m_r[m]; m_ea = m_r[m];
m_fr[n] = RL(m_ea ); m_fr[n] = RL(m_ea );
m_fr[n+1] = RL(m_ea+4 ); m_fr[n^1] = RL(m_ea+4 );
} }
} else { /* SZ = 0 */ } else { /* SZ = 0 */
m_ea = m_r[m]; m_ea = m_r[m];
#ifdef LSB_FIRST
n ^= m_fpu_pr;
#endif
m_fr[n] = RL(m_ea ); m_fr[n] = RL(m_ea );
} }
} }
}
/* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */ /* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */
/* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */ /* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */
@ -2792,9 +2780,14 @@ inline void sh34_base_device::FMOVFR(const uint16_t opcode)
{ {
uint32_t m = Rm; uint32_t n = Rn; uint32_t m = Rm; uint32_t n = Rn;
if ((m_fpu_sz == 0) && (m_fpu_pr == 0)) /* SZ = 0 */ if (m_fpu_sz == 0) { /* SZ = 0 */
#ifdef LSB_FIRST
n ^= m_fpu_pr;
m ^= m_fpu_pr;
#endif
m_fr[n] = m_fr[m]; m_fr[n] = m_fr[m];
else { /* SZ = 1 or PR = 1 */ }
else { /* SZ = 1 */
if (m & 1) { if (m & 1) {
if (n & 1) { if (n & 1) {
m_xf[n & 14] = m_xf[m & 14]; m_xf[n & 14] = m_xf[m & 14];
@ -2818,25 +2811,41 @@ inline void sh34_base_device::FMOVFR(const uint16_t opcode)
/* FLDI1 FRn 1111nnnn10011101 */ /* FLDI1 FRn 1111nnnn10011101 */
inline void sh34_base_device::FLDI1(const uint16_t opcode) inline void sh34_base_device::FLDI1(const uint16_t opcode)
{ {
#ifdef LSB_FIRST
m_fr[Rn ^ m_fpu_pr] = 0x3F800000;
#else
m_fr[Rn] = 0x3F800000; m_fr[Rn] = 0x3F800000;
#endif
} }
/* FLDI0 FRn 1111nnnn10001101 */ /* FLDI0 FRn 1111nnnn10001101 */
inline void sh34_base_device::FLDI0(const uint16_t opcode) inline void sh34_base_device::FLDI0(const uint16_t opcode)
{ {
#ifdef LSB_FIRST
m_fr[Rn ^ m_fpu_pr] = 0;
#else
m_fr[Rn] = 0; m_fr[Rn] = 0;
#endif
} }
/* FLDS FRm,FPUL 1111mmmm00011101 */ /* FLDS FRm,FPUL 1111mmmm00011101 */
inline void sh34_base_device:: FLDS(const uint16_t opcode) inline void sh34_base_device:: FLDS(const uint16_t opcode)
{ {
#ifdef LSB_FIRST
m_fpul = m_fr[Rn ^ m_fpu_pr];
#else
m_fpul = m_fr[Rn]; m_fpul = m_fr[Rn];
#endif
} }
/* FSTS FPUL,FRn 1111nnnn00001101 */ /* FSTS FPUL,FRn 1111nnnn00001101 */
inline void sh34_base_device:: FSTS(const uint16_t opcode) inline void sh34_base_device:: FSTS(const uint16_t opcode)
{ {
#ifdef LSB_FIRST
m_fr[Rn ^ m_fpu_pr] = m_fpul;
#else
m_fr[Rn] = m_fpul; m_fr[Rn] = m_fpul;
#endif
} }
/* FRCHG 1111101111111101 */ /* FRCHG 1111101111111101 */