mirror of
https://github.com/n64dev/cen64.git
synced 2024-06-22 05:52:37 -04:00
Basic RSP LTV/STV support
This commit is contained in:
parent
50be16a0ef
commit
b08188f388
|
@ -256,6 +256,7 @@ set(ARCH_X86_64_SOURCES
|
||||||
${PROJECT_SOURCE_DIR}/arch/x86_64/rsp/vdivh.c
|
${PROJECT_SOURCE_DIR}/arch/x86_64/rsp/vdivh.c
|
||||||
${PROJECT_SOURCE_DIR}/arch/x86_64/rsp/rsp.c
|
${PROJECT_SOURCE_DIR}/arch/x86_64/rsp/rsp.c
|
||||||
${PROJECT_SOURCE_DIR}/arch/x86_64/rsp/vrsq.c
|
${PROJECT_SOURCE_DIR}/arch/x86_64/rsp/vrsq.c
|
||||||
|
${PROJECT_SOURCE_DIR}/arch/x86_64/rsp/transpose.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(BUS_SOURCES
|
set(BUS_SOURCES
|
||||||
|
|
|
@ -209,6 +209,7 @@ void rsp_vstore_group4(struct rsp *rsp, uint32_t addr, unsigned element,
|
||||||
uint16_t *regp, rsp_vect_t reg, rsp_vect_t dqm);
|
uint16_t *regp, rsp_vect_t reg, rsp_vect_t dqm);
|
||||||
|
|
||||||
#include "arch/x86_64/rsp/clamp.h"
|
#include "arch/x86_64/rsp/clamp.h"
|
||||||
|
#include "arch/x86_64/rsp/transpose.h"
|
||||||
#include "arch/x86_64/rsp/vabs.h"
|
#include "arch/x86_64/rsp/vabs.h"
|
||||||
#include "arch/x86_64/rsp/vadd.h"
|
#include "arch/x86_64/rsp/vadd.h"
|
||||||
#include "arch/x86_64/rsp/vaddc.h"
|
#include "arch/x86_64/rsp/vaddc.h"
|
||||||
|
|
36
arch/x86_64/rsp/transpose.c
Normal file
36
arch/x86_64/rsp/transpose.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// arch/x86_64/rsp/transpose.c
|
||||||
|
//
|
||||||
|
// This file is subject to the terms and conditions defined in
|
||||||
|
// 'LICENSE', which is part of this source code package.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "rsp/cpu.h"
|
||||||
|
#include "rsp/rsp.h"
|
||||||
|
|
||||||
|
void rsp_ltv(struct rsp *rsp, uint32_t addr, unsigned element, unsigned vt) {
|
||||||
|
struct rsp_exdf_latch *exdf_latch = &rsp->pipeline.exdf_latch;
|
||||||
|
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
uint16_t slice;
|
||||||
|
|
||||||
|
memcpy(&slice, rsp->mem + addr + (i << 1), sizeof(slice));
|
||||||
|
slice = byteswap_16(slice);
|
||||||
|
|
||||||
|
rsp->cp2.regs[vt + i].e[(i - element) & 7] = slice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rsp_stv(struct rsp *rsp, uint32_t addr, unsigned element, unsigned vt) {
|
||||||
|
struct rsp_exdf_latch *exdf_latch = &rsp->pipeline.exdf_latch;
|
||||||
|
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
uint16_t slice = rsp->cp2.regs[vt + ((i + element) & 7)].e[i];
|
||||||
|
slice = byteswap_16(slice);
|
||||||
|
|
||||||
|
memcpy(rsp->mem + addr + (i << 1), &slice, sizeof(slice));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
10
arch/x86_64/rsp/transpose.h
Normal file
10
arch/x86_64/rsp/transpose.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//
|
||||||
|
// arch/x86_64/rsp/transpose.h
|
||||||
|
//
|
||||||
|
// This file is subject to the terms and conditions defined in
|
||||||
|
// 'LICENSE', which is part of this source code package.
|
||||||
|
//
|
||||||
|
|
||||||
|
void rsp_ltv(struct rsp *rsp, uint32_t addr, unsigned vt, unsigned element);
|
||||||
|
|
||||||
|
void rsp_stv(struct rsp *rsp, uint32_t addr, unsigned vt, unsigned element);
|
17
common.h.in
17
common.h.in
|
@ -162,6 +162,23 @@ static inline uint32_t byteswap_32(uint32_t word) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__attribute__((pure))
|
||||||
|
#endif
|
||||||
|
static inline uint16_t byteswap_16(uint16_t hword) {
|
||||||
|
#ifdef BIG_ENDIAN_HOST
|
||||||
|
return hword;
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
return _byteswap_ushort(hword);
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
return __builtin_bswap16(hword);
|
||||||
|
#else
|
||||||
|
return
|
||||||
|
((((hword) >> 8) & 0x00FF) | \
|
||||||
|
(((hword) << 8) & 0xFF00));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Return from simulation function.
|
// Return from simulation function.
|
||||||
struct bus_controller;
|
struct bus_controller;
|
||||||
|
|
||||||
|
|
|
@ -471,6 +471,27 @@ void RSP_LQRV_SQRV(struct rsp *rsp,
|
||||||
exdf_latch->request.packet.p_vect.dest = dest;
|
exdf_latch->request.packet.p_vect.dest = dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// LTV
|
||||||
|
// STV
|
||||||
|
//
|
||||||
|
void RSP_LTV_STV(struct rsp *rsp,
|
||||||
|
uint32_t iw, uint32_t rs, uint32_t rt) {
|
||||||
|
struct rsp_exdf_latch *exdf_latch = &rsp->pipeline.exdf_latch;
|
||||||
|
unsigned op = iw >> 29 & 0x1;
|
||||||
|
|
||||||
|
exdf_latch->request.addr = rs + (sign_extend_6(iw) << 4);
|
||||||
|
exdf_latch->request.packet.p_vect.element = GET_EL(iw);
|
||||||
|
exdf_latch->request.type = RSP_MEM_REQUEST_TRANSPOSE;
|
||||||
|
|
||||||
|
exdf_latch->request.packet.p_transpose.vt = GET_VT(iw) & 0x18;
|
||||||
|
exdf_latch->request.packet.p_transpose.element = GET_EL(iw) >> 1;
|
||||||
|
|
||||||
|
exdf_latch->request.packet.p_transpose.transpose_func = op
|
||||||
|
? rsp_stv
|
||||||
|
: rsp_ltv;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// NOR
|
// NOR
|
||||||
//
|
//
|
||||||
|
|
|
@ -129,7 +129,7 @@
|
||||||
#define LQV RSP_BUILD_OP(LQV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, LOAD))
|
#define LQV RSP_BUILD_OP(LQV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, LOAD))
|
||||||
#define LRV RSP_BUILD_OP(LRV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, LOAD))
|
#define LRV RSP_BUILD_OP(LRV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, LOAD))
|
||||||
#define LSV RSP_BUILD_OP(LSV, LBDLSV_SBDLSV, INFO3(NEEDRS, NEEDVT, LOAD))
|
#define LSV RSP_BUILD_OP(LSV, LBDLSV_SBDLSV, INFO3(NEEDRS, NEEDVT, LOAD))
|
||||||
#define LTV RSP_BUILD_OP(LTV, INVALID, INFO1(NONE))
|
#define LTV RSP_BUILD_OP(LTV, LTV_STV, INFO3(NEEDRS, NEEDVT, LOAD))
|
||||||
#define LUV RSP_BUILD_OP(LUV, LFHPUV_SFHPUV, INFO3(NEEDRS, NEEDVT, LOAD))
|
#define LUV RSP_BUILD_OP(LUV, LFHPUV_SFHPUV, INFO3(NEEDRS, NEEDVT, LOAD))
|
||||||
|
|
||||||
#define SBV RSP_BUILD_OP(SBV, LBDLSV_SBDLSV, INFO3(NEEDRS, NEEDVT, STORE))
|
#define SBV RSP_BUILD_OP(SBV, LBDLSV_SBDLSV, INFO3(NEEDRS, NEEDVT, STORE))
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
#define SQV RSP_BUILD_OP(SQV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, STORE))
|
#define SQV RSP_BUILD_OP(SQV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, STORE))
|
||||||
#define SRV RSP_BUILD_OP(SRV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, STORE))
|
#define SRV RSP_BUILD_OP(SRV, LQRV_SQRV, INFO3(NEEDRS, NEEDVT, STORE))
|
||||||
#define SSV RSP_BUILD_OP(SSV, LBDLSV_SBDLSV, INFO3(NEEDRS, NEEDVT, STORE))
|
#define SSV RSP_BUILD_OP(SSV, LBDLSV_SBDLSV, INFO3(NEEDRS, NEEDVT, STORE))
|
||||||
#define STV RSP_BUILD_OP(STV, INVALID, INFO1(NONE))
|
#define STV RSP_BUILD_OP(STV, LTV_STV, INFO3(NEEDRS, NEEDVT, LOAD))
|
||||||
#define SUV RSP_BUILD_OP(SUV, LFHPUV_SFHPUV, INFO3(NEEDRS, NEEDVT, STORE))
|
#define SUV RSP_BUILD_OP(SUV, LFHPUV_SFHPUV, INFO3(NEEDRS, NEEDVT, STORE))
|
||||||
#define SWV RSP_BUILD_OP(SWV, INVALID, INFO1(NONE))
|
#define SWV RSP_BUILD_OP(SWV, INVALID, INFO1(NONE))
|
||||||
|
|
||||||
|
|
|
@ -161,8 +161,32 @@ cen64_flatten static inline void rsp_df_stage(struct rsp *rsp) {
|
||||||
|
|
||||||
addr = request->addr & 0xFFF;
|
addr = request->addr & 0xFFF;
|
||||||
|
|
||||||
|
// Scalar unit DMEM access.
|
||||||
|
if (request->type == RSP_MEM_REQUEST_INT_MEM) {
|
||||||
|
uint32_t rdqm = request->packet.p_int.rdqm;
|
||||||
|
uint32_t wdqm = request->packet.p_int.wdqm;
|
||||||
|
uint32_t data = request->packet.p_int.data;
|
||||||
|
unsigned rshift = request->packet.p_int.rshift;
|
||||||
|
uint32_t word;
|
||||||
|
|
||||||
|
memcpy(&word, rsp->mem + addr, sizeof(word));
|
||||||
|
|
||||||
|
word = byteswap_32(word);
|
||||||
|
dfwb_latch->result.result = rdqm & (((int32_t) word) >> rshift);
|
||||||
|
word = byteswap_32((word & ~wdqm) | (data & wdqm));
|
||||||
|
|
||||||
|
memcpy(rsp->mem + addr, &word, sizeof(word));
|
||||||
|
}
|
||||||
|
// Transposed vector unit DMEM access.
|
||||||
|
else if (request->type == RSP_MEM_REQUEST_TRANSPOSE) {
|
||||||
|
unsigned element = request->packet.p_transpose.element;
|
||||||
|
unsigned vt = request->packet.p_transpose.vt;
|
||||||
|
|
||||||
|
exdf_latch->request.packet.p_transpose.transpose_func(
|
||||||
|
rsp, addr, element, vt);
|
||||||
|
}
|
||||||
// Vector unit DMEM access.
|
// Vector unit DMEM access.
|
||||||
if (request->type != RSP_MEM_REQUEST_INT_MEM) {
|
else {
|
||||||
uint16_t *regp = rsp->cp2.regs[request->packet.p_vect.dest].e;
|
uint16_t *regp = rsp->cp2.regs[request->packet.p_vect.dest].e;
|
||||||
unsigned element = request->packet.p_vect.element;
|
unsigned element = request->packet.p_vect.element;
|
||||||
rsp_vect_t reg, dqm;
|
rsp_vect_t reg, dqm;
|
||||||
|
@ -179,22 +203,6 @@ cen64_flatten static inline void rsp_df_stage(struct rsp *rsp) {
|
||||||
rsp, addr, element, regp, reg, dqm);
|
rsp, addr, element, regp, reg, dqm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scalar unit DMEM access.
|
|
||||||
else {
|
|
||||||
uint32_t rdqm = request->packet.p_int.rdqm;
|
|
||||||
uint32_t wdqm = request->packet.p_int.wdqm;
|
|
||||||
uint32_t data = request->packet.p_int.data;
|
|
||||||
unsigned rshift = request->packet.p_int.rshift;
|
|
||||||
uint32_t word;
|
|
||||||
|
|
||||||
memcpy(&word, rsp->mem + addr, sizeof(word));
|
|
||||||
|
|
||||||
word = byteswap_32(word);
|
|
||||||
dfwb_latch->result.result = rdqm & (((int32_t) word) >> rshift);
|
|
||||||
word = byteswap_32((word & ~wdqm) | (data & wdqm));
|
|
||||||
|
|
||||||
memcpy(rsp->mem + addr, &word, sizeof(word));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writeback stage.
|
// Writeback stage.
|
||||||
|
|
|
@ -26,7 +26,8 @@ enum rsp_mem_request_type {
|
||||||
RSP_MEM_REQUEST_PACK,
|
RSP_MEM_REQUEST_PACK,
|
||||||
RSP_MEM_REQUEST_QUAD,
|
RSP_MEM_REQUEST_QUAD,
|
||||||
RSP_MEM_REQUEST_REST,
|
RSP_MEM_REQUEST_REST,
|
||||||
RSP_MEM_REQUEST_UPACK
|
RSP_MEM_REQUEST_UPACK,
|
||||||
|
RSP_MEM_REQUEST_TRANSPOSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rsp_int_mem_packet {
|
struct rsp_int_mem_packet {
|
||||||
|
@ -37,6 +38,14 @@ struct rsp_int_mem_packet {
|
||||||
unsigned rshift;
|
unsigned rshift;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rsp_transpose_mem_packet {
|
||||||
|
void (*transpose_func)(struct rsp *rsp, uint32_t addr, unsigned element,
|
||||||
|
unsigned vt);
|
||||||
|
|
||||||
|
unsigned element;
|
||||||
|
unsigned vt;
|
||||||
|
};
|
||||||
|
|
||||||
struct rsp_vect_mem_packet {
|
struct rsp_vect_mem_packet {
|
||||||
union aligned_rsp_1vect_t vdqm;
|
union aligned_rsp_1vect_t vdqm;
|
||||||
|
|
||||||
|
@ -49,6 +58,7 @@ struct rsp_vect_mem_packet {
|
||||||
|
|
||||||
union rsp_mem_packet {
|
union rsp_mem_packet {
|
||||||
struct rsp_int_mem_packet p_int;
|
struct rsp_int_mem_packet p_int;
|
||||||
|
struct rsp_transpose_mem_packet p_transpose;
|
||||||
struct rsp_vect_mem_packet p_vect;
|
struct rsp_vect_mem_packet p_vect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue