implement lvsl/lvsr instructions

This commit is contained in:
gbeauche 2005-04-15 17:03:49 +00:00
parent ac6b7d760e
commit 8db2a3ef62
5 changed files with 82 additions and 0 deletions

View File

@ -427,6 +427,8 @@ private:
void execute_invalidate_cache_range();
template< class RA, class RB >
void execute_dcbz(uint32 opcode);
template< bool SL >
void execute_vector_load_for_shift(uint32 opcode);
template< class VD, class RA, class RB >
void execute_vector_load(uint32 opcode);
template< class VS, class RA, class RB >

View File

@ -754,6 +754,18 @@ const powerpc_cpu::instr_info_t powerpc_cpu::powerpc_ii_table[] = {
PPC_I(LVEWX),
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",
EXECUTE_VECTOR_LOADSTORE(load, V2DI, RA_or_0, RB),
NULL,

View File

@ -1231,6 +1231,19 @@ void powerpc_cpu::execute_dcbz(uint32 opcode)
* 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 >
void powerpc_cpu::execute_vector_load(uint32 opcode)
{

View File

@ -131,6 +131,8 @@ enum powerpc_instruction {
PPC_I(LVEBX),
PPC_I(LVEHX),
PPC_I(LVEWX),
PPC_I(LVSL),
PPC_I(LVSR),
PPC_I(LVX),
PPC_I(LVXL),
PPC_I(LWARX),

View File

@ -98,6 +98,7 @@ typedef uintptr_t uintptr;
#define TEST_LOGICAL 1
#define TEST_COMPARE 1
#define TEST_CR_LOGICAL 1
#define TEST_VMX_LOADSH 1
#define TEST_VMX_LOAD 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) )
// 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_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); }
@ -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)
{ test_one_vector(code, vt, (uint8 *)vA, (uint8 *)vB, (uint8 *)vC); }
void test_vector_load(void);
void test_vector_load_for_shift(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
}
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)
{
#if TEST_VMX_LOAD
@ -2038,6 +2090,7 @@ bool powerpc_test_cpu::test(void)
// Execute VMX tests
#if TEST_VMX_OPS
if (has_altivec) {
test_vector_load_for_shift();
test_vector_load();
test_vector_arith();
}