mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-10-13 11:23:51 +00:00
implement lvsl/lvsr instructions
This commit is contained in:
parent
ac6b7d760e
commit
8db2a3ef62
@ -427,6 +427,8 @@ private:
|
|||||||
void execute_invalidate_cache_range();
|
void execute_invalidate_cache_range();
|
||||||
template< class RA, class RB >
|
template< class RA, class RB >
|
||||||
void execute_dcbz(uint32 opcode);
|
void execute_dcbz(uint32 opcode);
|
||||||
|
template< bool SL >
|
||||||
|
void execute_vector_load_for_shift(uint32 opcode);
|
||||||
template< class VD, class RA, class RB >
|
template< class VD, class RA, class RB >
|
||||||
void execute_vector_load(uint32 opcode);
|
void execute_vector_load(uint32 opcode);
|
||||||
template< class VS, class RA, class RB >
|
template< class VS, class RA, class RB >
|
||||||
|
@ -754,6 +754,18 @@ const powerpc_cpu::instr_info_t powerpc_cpu::powerpc_ii_table[] = {
|
|||||||
PPC_I(LVEWX),
|
PPC_I(LVEWX),
|
||||||
X_form, 31, 71, CFLOW_NORMAL
|
X_form, 31, 71, CFLOW_NORMAL
|
||||||
},
|
},
|
||||||
|
{ "lvsl",
|
||||||
|
EXECUTE_1(vector_load_for_shift, 1),
|
||||||
|
NULL,
|
||||||
|
PPC_I(LVSL),
|
||||||
|
X_form, 31, 6, CFLOW_NORMAL
|
||||||
|
},
|
||||||
|
{ "lvsr",
|
||||||
|
EXECUTE_1(vector_load_for_shift, 0),
|
||||||
|
NULL,
|
||||||
|
PPC_I(LVSR),
|
||||||
|
X_form, 31, 38, CFLOW_NORMAL
|
||||||
|
},
|
||||||
{ "lvx",
|
{ "lvx",
|
||||||
EXECUTE_VECTOR_LOADSTORE(load, V2DI, RA_or_0, RB),
|
EXECUTE_VECTOR_LOADSTORE(load, V2DI, RA_or_0, RB),
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -1231,6 +1231,19 @@ void powerpc_cpu::execute_dcbz(uint32 opcode)
|
|||||||
* Vector load/store instructions
|
* Vector load/store instructions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
template< bool SL >
|
||||||
|
void powerpc_cpu::execute_vector_load_for_shift(uint32 opcode)
|
||||||
|
{
|
||||||
|
const uint32 ra = operand_RA_or_0::get(this, opcode);
|
||||||
|
const uint32 rb = operand_RB::get(this, opcode);
|
||||||
|
const uint32 ea = ra + rb;
|
||||||
|
powerpc_vr & vD = vr(vD_field::extract(opcode));
|
||||||
|
int j = SL ? (ea & 0xf) : (0x10 - (ea & 0xf));
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
vD.b[ev_mixed::byte_element(i)] = j++;
|
||||||
|
increment_pc(4);
|
||||||
|
}
|
||||||
|
|
||||||
template< class VD, class RA, class RB >
|
template< class VD, class RA, class RB >
|
||||||
void powerpc_cpu::execute_vector_load(uint32 opcode)
|
void powerpc_cpu::execute_vector_load(uint32 opcode)
|
||||||
{
|
{
|
||||||
|
@ -131,6 +131,8 @@ enum powerpc_instruction {
|
|||||||
PPC_I(LVEBX),
|
PPC_I(LVEBX),
|
||||||
PPC_I(LVEHX),
|
PPC_I(LVEHX),
|
||||||
PPC_I(LVEWX),
|
PPC_I(LVEWX),
|
||||||
|
PPC_I(LVSL),
|
||||||
|
PPC_I(LVSR),
|
||||||
PPC_I(LVX),
|
PPC_I(LVX),
|
||||||
PPC_I(LVXL),
|
PPC_I(LVXL),
|
||||||
PPC_I(LWARX),
|
PPC_I(LWARX),
|
||||||
|
@ -98,6 +98,7 @@ typedef uintptr_t uintptr;
|
|||||||
#define TEST_LOGICAL 1
|
#define TEST_LOGICAL 1
|
||||||
#define TEST_COMPARE 1
|
#define TEST_COMPARE 1
|
||||||
#define TEST_CR_LOGICAL 1
|
#define TEST_CR_LOGICAL 1
|
||||||
|
#define TEST_VMX_LOADSH 1
|
||||||
#define TEST_VMX_LOAD 1
|
#define TEST_VMX_LOAD 1
|
||||||
#define TEST_VMX_ARITH 1
|
#define TEST_VMX_ARITH 1
|
||||||
|
|
||||||
@ -128,6 +129,7 @@ typedef uintptr_t uintptr;
|
|||||||
#define _VA( OP,VD,VA,VB,VC,XO ) _I((_u6(OP)<<26)|(_u5(VD)<<21)|(_u5(VA)<<16)|( _u5(VB)<<11)|(_u5(VC)<< 6)| _u6(XO) )
|
#define _VA( OP,VD,VA,VB,VC,XO ) _I((_u6(OP)<<26)|(_u5(VD)<<21)|(_u5(VA)<<16)|( _u5(VB)<<11)|(_u5(VC)<< 6)| _u6(XO) )
|
||||||
|
|
||||||
// PowerPC opcodes
|
// PowerPC opcodes
|
||||||
|
static inline uint32 POWERPC_LI(int RD, uint32 v) { return _D(14,RD,00,(v&0xffff)); }
|
||||||
static inline uint32 POWERPC_MR(int RD, int RA) { return _X(31,RA,RD,RA,444,0); }
|
static inline uint32 POWERPC_MR(int RD, int RA) { return _X(31,RA,RD,RA,444,0); }
|
||||||
static inline uint32 POWERPC_MFCR(int RD) { return _X(31,RD,00,00,19,0); }
|
static inline uint32 POWERPC_MFCR(int RD) { return _X(31,RD,00,00,19,0); }
|
||||||
static inline uint32 POWERPC_LVX(int vD, int rA, int rB) { return _X(31,vD,rA,rB,103,0); }
|
static inline uint32 POWERPC_LVX(int vD, int rA, int rB) { return _X(31,vD,rA,rB,103,0); }
|
||||||
@ -748,6 +750,7 @@ private:
|
|||||||
void test_one_vector(uint32 *code, vector_test_t const & vt, vector_t const *vA = 0, vector_t const *vB = 0, vector_t const *vC = 0)
|
void test_one_vector(uint32 *code, vector_test_t const & vt, vector_t const *vA = 0, vector_t const *vB = 0, vector_t const *vC = 0)
|
||||||
{ test_one_vector(code, vt, (uint8 *)vA, (uint8 *)vB, (uint8 *)vC); }
|
{ test_one_vector(code, vt, (uint8 *)vA, (uint8 *)vB, (uint8 *)vC); }
|
||||||
void test_vector_load(void);
|
void test_vector_load(void);
|
||||||
|
void test_vector_load_for_shift(void);
|
||||||
void test_vector_arith(void);
|
void test_vector_arith(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1671,6 +1674,55 @@ void powerpc_test_cpu::test_one_vector(uint32 *code, vector_test_t const & vt, u
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void powerpc_test_cpu::test_vector_load_for_shift(void)
|
||||||
|
{
|
||||||
|
#if TEST_VMX_LOADSH
|
||||||
|
// Tested instructions
|
||||||
|
static const vector_test_t tests[] = {
|
||||||
|
{ "lvsl", 'b', 0, _X (31,00,00,00, 6,0), { vD, rA, rB } },
|
||||||
|
{ "lvsr", 'b', 0, _X (31,00,00,00, 38,0), { vD, rA, rB } },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Code template
|
||||||
|
static uint32 code[] = {
|
||||||
|
POWERPC_MFSPR(12, 256), // mfvrsave r12
|
||||||
|
_D(15,0,0,0x1000), // lis r0,0x1000 ([v3])
|
||||||
|
POWERPC_MTSPR(0, 256), // mtvrsave r0
|
||||||
|
POWERPC_LI(RA, 0), // li rB,<val>
|
||||||
|
0, // <insn>
|
||||||
|
POWERPC_STVX(RD, 0, RD), // stvx v3,r3(0)
|
||||||
|
POWERPC_MTSPR(12, 256), // mtvrsave r12
|
||||||
|
POWERPC_BLR // blr
|
||||||
|
};
|
||||||
|
|
||||||
|
int i_opcode = -1;
|
||||||
|
const int n_instructions = sizeof(code) / sizeof(code[0]);
|
||||||
|
for (int i = 0; i < n_instructions; i++) {
|
||||||
|
if (code[i] == 0) {
|
||||||
|
i_opcode = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(i_opcode != -1);
|
||||||
|
|
||||||
|
const int n_elements = sizeof(tests) / sizeof(tests[0]);
|
||||||
|
for (int i = 0; i < n_elements; i++) {
|
||||||
|
vector_test_t const & vt = tests[i];
|
||||||
|
code[i_opcode] = vt.opcode;
|
||||||
|
vD_field::insert(code[i_opcode], RD);
|
||||||
|
rA_field::insert(code[i_opcode], 00);
|
||||||
|
rB_field::insert(code[i_opcode], RA);
|
||||||
|
|
||||||
|
printf("Testing %s\n", vt.name);
|
||||||
|
for (int j = 0; j < 32; j++) {
|
||||||
|
UIMM_field::insert(code[i_opcode - 1], j);
|
||||||
|
flush_icache_range(code, sizeof(code));
|
||||||
|
test_one_vector(code, vt, (uint8 *)NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void powerpc_test_cpu::test_vector_load(void)
|
void powerpc_test_cpu::test_vector_load(void)
|
||||||
{
|
{
|
||||||
#if TEST_VMX_LOAD
|
#if TEST_VMX_LOAD
|
||||||
@ -2038,6 +2090,7 @@ bool powerpc_test_cpu::test(void)
|
|||||||
// Execute VMX tests
|
// Execute VMX tests
|
||||||
#if TEST_VMX_OPS
|
#if TEST_VMX_OPS
|
||||||
if (has_altivec) {
|
if (has_altivec) {
|
||||||
|
test_vector_load_for_shift();
|
||||||
test_vector_load();
|
test_vector_load();
|
||||||
test_vector_arith();
|
test_vector_arith();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user