From 91b18f26449521a71cd632773b93ace0235a651c Mon Sep 17 00:00:00 2001 From: Tyler Stachecki Date: Wed, 29 Jun 2016 21:38:25 -0400 Subject: [PATCH] rsp: Implement CTC2. --- arch/x86_64/rsp/rsp.c | 27 +++++++++++++++++++++++++++ arch/x86_64/rsp/rsp.h | 2 ++ rsp/cp2.c | 20 ++++++++++++++++++++ rsp/cp2.h | 1 + rsp/opcodes_priv.h | 2 +- 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/arch/x86_64/rsp/rsp.c b/arch/x86_64/rsp/rsp.c index 0f65136..9f12a88 100644 --- a/arch/x86_64/rsp/rsp.c +++ b/arch/x86_64/rsp/rsp.c @@ -227,6 +227,33 @@ static inline __m128i sse2_pshufb(__m128i v, const uint16_t *keys) { // Deallocates dynarec buffers for SSE2. void arch_rsp_destroy(struct rsp *rsp) {} +// Uses a LUT to populate flag registers. +void rsp_set_flags(uint16_t *flags, uint16_t rt) { + unsigned i; + + static const uint16_t array[16][4] = { + {0x0000, 0x0000, 0x0000, 0x0000}, + {0xFFFF, 0x0000, 0x0000, 0x0000}, + {0x0000, 0xFFFF, 0x0000, 0x0000}, + {0xFFFF, 0xFFFF, 0x0000, 0x0000}, + {0x0000, 0x0000, 0xFFFF, 0x0000}, + {0xFFFF, 0x0000, 0xFFFF, 0x0000}, + {0x0000, 0xFFFF, 0xFFFF, 0x0000}, + {0xFFFF, 0xFFFF, 0xFFFF, 0x0000}, + {0x0000, 0x0000, 0x0000, 0xFFFF}, + {0xFFFF, 0x0000, 0x0000, 0xFFFF}, + {0x0000, 0xFFFF, 0x0000, 0xFFFF}, + {0xFFFF, 0xFFFF, 0x0000, 0xFFFF}, + {0x0000, 0x0000, 0xFFFF, 0xFFFF}, + {0xFFFF, 0x0000, 0xFFFF, 0xFFFF}, + {0x0000, 0xFFFF, 0xFFFF, 0xFFFF}, + {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, + }; + + for (i = 0; i < 4; i++, rt >>= 4) + memcpy(flags + i * 4, array[rt & 0xF], sizeof(array[0])); +} + // Allocates dynarec buffers for SSE2. int arch_rsp_init(struct rsp *rsp) { return 0; } diff --git a/arch/x86_64/rsp/rsp.h b/arch/x86_64/rsp/rsp.h index 838d66c..681fc1a 100644 --- a/arch/x86_64/rsp/rsp.h +++ b/arch/x86_64/rsp/rsp.h @@ -182,6 +182,8 @@ static inline int16_t rsp_get_flags(const uint16_t *flags) { ); } +void rsp_set_flags(uint16_t *flags, uint16_t rt); + // Zeroes out a vector register. static inline __m128i rsp_vzero(void) { return _mm_setzero_si128(); diff --git a/rsp/cp2.c b/rsp/cp2.c index e0ab178..cbc072a 100644 --- a/rsp/cp2.c +++ b/rsp/cp2.c @@ -24,6 +24,7 @@ void RSP_CFC2(struct rsp *rsp, dest = GET_RT(iw); rd = GET_RD(iw); + // TODO: verify on hardware if ((src = rd & 0x3) == 0x3) src = 2; @@ -31,6 +32,25 @@ void RSP_CFC2(struct rsp *rsp, exdf_latch->result.dest = dest; } +// +// CTC2 +// +void RSP_CTC2(struct rsp *rsp, + uint32_t iw, uint32_t rs, uint32_t rt) { + struct rsp_cp2 *cp2 = &rsp->cp2; + unsigned rd, dest; + + rd = GET_RD(iw); + + // TODO: verify on hardware + if ((dest = rd & 0x3) >= 0x2) { + rt &= 0xFF; + dest = 2; + } + + rsp_set_flags(cp2->flags[dest].e, rt); +} + // // MFC2 // diff --git a/rsp/cp2.h b/rsp/cp2.h index a4b56a9..af46a77 100644 --- a/rsp/cp2.h +++ b/rsp/cp2.h @@ -51,6 +51,7 @@ struct rsp_cp2 { }; void RSP_CFC2(struct rsp *rsp, uint32_t iw, uint32_t rs, uint32_t rt); +void RSP_CTC2(struct rsp *rsp, uint32_t iw, uint32_t rs, uint32_t rt); void RSP_MFC2(struct rsp *rsp, uint32_t iw, uint32_t rs, uint32_t rt); void RSP_MTC2(struct rsp *rsp, uint32_t iw, uint32_t rs, uint32_t rt); diff --git a/rsp/opcodes_priv.h b/rsp/opcodes_priv.h index 4361f1a..5b6dc13 100644 --- a/rsp/opcodes_priv.h +++ b/rsp/opcodes_priv.h @@ -69,7 +69,7 @@ #define MTC0 RSP_BUILD_OP(MTC0, MTC0, INFO1(NEEDRT)) #define CFC2 RSP_BUILD_OP(CFC2, CFC2, INFO1(NONE)) -#define CTC2 RSP_BUILD_OP(CTC2, INVALID, INFO1(NONE)) +#define CTC2 RSP_BUILD_OP(CTC2, CTC2, INFO1(NEEDRT)) #define MFC2 RSP_BUILD_OP(MFC2, MFC2, INFO1(NONE)) #define MTC2 RSP_BUILD_OP(MTC2, MTC2, INFO1(NEEDRT))