Commit e1e50f3f authored by ivica.bogosavljevic's avatar ivica.bogosavljevic Committed by Commit bot

Implement byte swapping instructions on MIPS32 and MIPS64.

BUG=

Review-Url: https://codereview.chromium.org/2069933003
Cr-Commit-Position: refs/heads/master@{#37295}
parent 4af80298
......@@ -1912,7 +1912,6 @@ void Assembler::aui(Register rt, Register rs, int32_t j) {
GenInstrImmediate(LUI, rs, rt, j);
}
// ---------PC-Relative instructions-----------
void Assembler::addiupc(Register rs, int32_t imm19) {
......@@ -2147,6 +2146,21 @@ void Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) {
GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
}
// Byte swap.
void Assembler::wsbh(Register rd, Register rt) {
DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
}
void Assembler::seh(Register rd, Register rt) {
DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
}
void Assembler::seb(Register rd, Register rt) {
DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
}
// --------Coprocessor-instructions----------------
......
......@@ -854,6 +854,10 @@ class Assembler : public AssemblerBase {
void bitswap(Register rd, Register rt);
void align(Register rd, Register rs, Register rt, uint8_t bp);
void wsbh(Register rd, Register rt);
void seh(Register rd, Register rt);
void seb(Register rd, Register rt);
// --------Coprocessor-instructions----------------
// Load, store, and move.
......
......@@ -1186,11 +1186,10 @@ Instruction::Type Instruction::InstructionType(TypeChecks checks) const {
int sa = SaFieldRaw() >> kSaShift;
switch (sa) {
case BITSWAP:
return kRegisterType;
case WSBH:
case SEB:
case SEH:
return kUnsupported;
return kRegisterType;
}
sa >>= kBp2Bits;
switch (sa) {
......
......@@ -1264,11 +1264,30 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
}
break;
}
case SEB:
case SEH:
case WSBH:
UNREACHABLE();
case SEB: {
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
Format(instr, "seb 'rd, 'rt");
} else {
Unknown(instr);
}
break;
}
case SEH: {
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
Format(instr, "seh 'rd, 'rt");
} else {
Unknown(instr);
}
break;
}
case WSBH: {
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
Format(instr, "wsbh 'rd, 'rt");
} else {
Unknown(instr);
}
break;
}
default: {
sa >>= kBp2Bits;
switch (sa) {
......
......@@ -43,7 +43,6 @@ MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
}
}
void MacroAssembler::Load(Register dst,
const MemOperand& src,
Representation r) {
......@@ -80,7 +79,6 @@ void MacroAssembler::Store(Register src,
}
}
void MacroAssembler::LoadRoot(Register destination,
Heap::RootListIndex index) {
lw(destination, MemOperand(s6, index << kPointerSizeLog2));
......@@ -1204,6 +1202,79 @@ void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa,
// ------------Pseudo-instructions-------------
// Word Swap Byte
void MacroAssembler::ByteSwapSigned(Register reg, int operand_size) {
DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4);
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
if (operand_size == 2) {
seh(reg, reg);
} else if (operand_size == 1) {
seb(reg, reg);
}
// No need to do any preparation if operand_size is 4
wsbh(reg, reg);
rotr(reg, reg, 16);
} else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
if (operand_size == 1) {
sll(reg, reg, 24);
sra(reg, reg, 24);
} else if (operand_size == 2) {
sll(reg, reg, 16);
sra(reg, reg, 16);
}
// No need to do any preparation if operand_size is 4
Register tmp = t0;
Register tmp2 = t1;
andi(tmp2, reg, 0xFF);
sll(tmp2, tmp2, 24);
or_(tmp, zero_reg, tmp2);
andi(tmp2, reg, 0xFF00);
sll(tmp2, tmp2, 8);
or_(tmp, tmp, tmp2);
srl(reg, reg, 8);
andi(tmp2, reg, 0xFF00);
or_(tmp, tmp, tmp2);
srl(reg, reg, 16);
andi(tmp2, reg, 0xFF);
or_(tmp, tmp, tmp2);
or_(reg, tmp, zero_reg);
}
}
void MacroAssembler::ByteSwapUnsigned(Register reg, int operand_size) {
DCHECK(operand_size == 1 || operand_size == 2);
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
if (operand_size == 1) {
andi(reg, reg, 0xFF);
} else {
andi(reg, reg, 0xFFFF);
}
// No need to do any preparation if operand_size is 4
wsbh(reg, reg);
rotr(reg, reg, 16);
} else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
if (operand_size == 1) {
sll(reg, reg, 24);
} else {
Register tmp = t0;
andi(tmp, reg, 0xFF00);
sll(reg, reg, 24);
sll(tmp, tmp, 8);
or_(reg, tmp, reg);
}
}
}
void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
DCHECK(!rd.is(at));
DCHECK(!rs.rm().is(at));
......
......@@ -687,6 +687,10 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// Pseudo-instructions.
// Change endianness
void ByteSwapSigned(Register reg, int operand_size);
void ByteSwapUnsigned(Register reg, int operand_size);
void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
void Ulh(Register rd, const MemOperand& rs);
......
......@@ -3833,12 +3833,51 @@ void Simulator::DecodeTypeRegisterSPECIAL3() {
alu_out = static_cast<int32_t>(output);
break;
}
case SEB:
case SEH:
case WSBH:
alu_out = 0x12345678;
UNREACHABLE();
case SEB: {
uint8_t input = static_cast<uint8_t>(rt());
uint32_t output = input;
uint32_t mask = 0x00000080;
// Extending sign
if (mask & input) {
output |= 0xFFFFFF00;
}
alu_out = static_cast<int32_t>(output);
break;
}
case SEH: {
uint16_t input = static_cast<uint16_t>(rt());
uint32_t output = input;
uint32_t mask = 0x00008000;
// Extending sign
if (mask & input) {
output |= 0xFFFF0000;
}
alu_out = static_cast<int32_t>(output);
break;
}
case WSBH: {
uint32_t input = static_cast<uint32_t>(rt());
uint32_t output = 0;
uint32_t mask = 0xFF000000;
for (int i = 0; i < 4; i++) {
uint32_t tmp = mask & input;
if (i % 2 == 0) {
tmp = tmp >> 8;
} else {
tmp = tmp << 8;
}
output = output | tmp;
mask = mask >> 8;
}
alu_out = static_cast<int32_t>(output);
break;
}
default: {
const uint8_t bp = get_instr()->Bp2Value();
sa >>= kBp2Bits;
......
......@@ -2516,6 +2516,30 @@ void Assembler::dalign(Register rd, Register rs, Register rt, uint8_t bp) {
GenInstrRegister(SPECIAL3, rs, rt, rd, sa, DBSHFL);
}
void Assembler::wsbh(Register rd, Register rt) {
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
}
void Assembler::dsbh(Register rd, Register rt) {
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSBH, DBSHFL);
}
void Assembler::dshd(Register rd, Register rt) {
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSHD, DBSHFL);
}
void Assembler::seh(Register rd, Register rt) {
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
}
void Assembler::seb(Register rd, Register rt) {
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
}
// --------Coprocessor-instructions----------------
......@@ -3423,7 +3447,6 @@ void Assembler::set_target_address_at(Isolate* isolate, Address pc,
}
}
} // namespace internal
} // namespace v8
......
......@@ -911,6 +911,12 @@ class Assembler : public AssemblerBase {
void align(Register rd, Register rs, Register rt, uint8_t bp);
void dalign(Register rd, Register rs, Register rt, uint8_t bp);
void wsbh(Register rd, Register rt);
void dsbh(Register rd, Register rt);
void dshd(Register rd, Register rt);
void seh(Register rd, Register rt);
void seb(Register rd, Register rt);
// --------Coprocessor-instructions----------------
// Load, store, and move.
......
......@@ -1237,11 +1237,10 @@ Instruction::Type Instruction::InstructionType(TypeChecks checks) const {
int sa = SaFieldRaw() >> kSaShift;
switch (sa) {
case BITSWAP:
return kRegisterType;
case WSBH:
case SEB:
case SEH:
return kUnsupported;
return kRegisterType;
}
sa >>= kBp2Bits;
switch (sa) {
......@@ -1255,10 +1254,9 @@ Instruction::Type Instruction::InstructionType(TypeChecks checks) const {
int sa = SaFieldRaw() >> kSaShift;
switch (sa) {
case DBITSWAP:
return kRegisterType;
case DSBH:
case DSHD:
return kUnsupported;
return kRegisterType;
}
sa = SaFieldRaw() >> kSaShift;
sa >>= kBp3Bits;
......
......@@ -1457,11 +1457,18 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
Format(instr, "bitswap 'rd, 'rt");
break;
}
case SEB:
case SEH:
case WSBH:
UNREACHABLE();
case SEB: {
Format(instr, "seb 'rd, 'rt");
break;
}
case SEH: {
Format(instr, "seh 'rd, 'rt");
break;
}
case WSBH: {
Format(instr, "wsbh 'rd, 'rt");
break;
}
default: {
sa >>= kBp2Bits;
switch (sa) {
......@@ -1492,10 +1499,14 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
}
break;
}
case DSBH:
case DSHD:
UNREACHABLE();
case DSBH: {
Format(instr, "dsbh 'rd, 'rt");
break;
}
case DSHD: {
Format(instr, "dshd 'rd, 'rt");
break;
}
default: {
sa >>= kBp3Bits;
switch (sa) {
......
......@@ -41,7 +41,6 @@ MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
}
}
void MacroAssembler::Load(Register dst,
const MemOperand& src,
Representation r) {
......@@ -1336,6 +1335,49 @@ void MacroAssembler::Dlsa(Register rd, Register rt, Register rs, uint8_t sa,
// ------------Pseudo-instructions-------------
// Change endianness
void MacroAssembler::ByteSwapSigned(Register reg, int operand_size) {
DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4 ||
operand_size == 8);
DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2);
if (operand_size == 1) {
seb(reg, reg);
sll(reg, reg, 0);
dsbh(reg, reg);
dshd(reg, reg);
} else if (operand_size == 2) {
seh(reg, reg);
sll(reg, reg, 0);
dsbh(reg, reg);
dshd(reg, reg);
} else if (operand_size == 4) {
sll(reg, reg, 0);
dsbh(reg, reg);
dshd(reg, reg);
} else {
dsbh(reg, reg);
dshd(reg, reg);
}
}
void MacroAssembler::ByteSwapUnsigned(Register reg, int operand_size) {
DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4);
if (operand_size == 1) {
andi(reg, reg, 0xFF);
dsbh(reg, reg);
dshd(reg, reg);
} else if (operand_size == 2) {
andi(reg, reg, 0xFFFF);
dsbh(reg, reg);
dshd(reg, reg);
} else {
dsll32(reg, reg, 0);
dsrl32(reg, reg, 0);
dsbh(reg, reg);
dshd(reg, reg);
}
}
void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
DCHECK(!rd.is(at));
DCHECK(!rs.rm().is(at));
......
......@@ -722,6 +722,10 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// Pseudo-instructions.
// Change endianness
void ByteSwapSigned(Register reg, int operand_size);
void ByteSwapUnsigned(Register reg, int operand_size);
void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
void Ulh(Register rd, const MemOperand& rs);
......
......@@ -3977,12 +3977,57 @@ void Simulator::DecodeTypeRegisterSPECIAL3() {
alu_out = static_cast<int64_t>(static_cast<int32_t>(output));
break;
}
case SEB:
case SEH:
case WSBH:
alu_out = 0x12345678;
UNREACHABLE();
case SEB: {
uint8_t input = static_cast<uint8_t>(rt());
uint32_t output = input;
uint32_t mask = 0x00000080;
// Extending sign
if (mask & input) {
output |= 0xFFFFFF00;
}
alu_out = static_cast<int32_t>(output);
break;
}
case SEH: {
uint16_t input = static_cast<uint16_t>(rt());
uint32_t output = input;
uint32_t mask = 0x00008000;
// Extending sign
if (mask & input) {
output |= 0xFFFF0000;
}
alu_out = static_cast<int32_t>(output);
break;
}
case WSBH: {
uint32_t input = static_cast<uint32_t>(rt());
uint64_t output = 0;
uint32_t mask = 0xFF000000;
for (int i = 0; i < 4; i++) {
uint32_t tmp = mask & input;
if (i % 2 == 0) {
tmp = tmp >> 8;
} else {
tmp = tmp << 8;
}
output = output | tmp;
mask = mask >> 8;
}
mask = 0x80000000;
// Extending sign
if (mask & output) {
output |= 0xFFFFFFFF00000000;
}
alu_out = static_cast<int64_t>(output);
break;
}
default: {
const uint8_t bp2 = get_instr()->Bp2Value();
sa >>= kBp2Bits;
......@@ -4041,11 +4086,47 @@ void Simulator::DecodeTypeRegisterSPECIAL3() {
}
break;
}
case DSBH:
case DSHD:
alu_out = 0x12345678;
UNREACHABLE();
case DSBH: {
uint64_t input = static_cast<uint64_t>(rt());
uint64_t output = 0;
uint64_t mask = 0xFF00000000000000;
for (int i = 0; i < 8; i++) {
uint64_t tmp = mask & input;
if (i % 2 == 0)
tmp = tmp >> 8;
else
tmp = tmp << 8;
output = output | tmp;
mask = mask >> 8;
}
alu_out = static_cast<int64_t>(output);
break;
}
case DSHD: {
uint64_t input = static_cast<uint64_t>(rt());
uint64_t output = 0;
uint64_t mask = 0xFFFF000000000000;
for (int i = 0; i < 4; i++) {
uint64_t tmp = mask & input;
if (i == 0)
tmp = tmp >> 48;
else if (i == 1)
tmp = tmp >> 16;
else if (i == 2)
tmp = tmp << 16;
else
tmp = tmp << 48;
output = output | tmp;
mask = mask >> 16;
}
alu_out = static_cast<int64_t>(output);
break;
}
default: {
const uint8_t bp3 = get_instr()->Bp3Value();
sa >>= kBp3Bits;
......@@ -4095,31 +4176,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
DecodeTypeRegisterSPECIAL2();
break;
case SPECIAL3:
switch (instr->FunctionFieldRaw()) {
case BSHFL: {
int32_t saVal = sa();
saVal >>= kBp2Bits;
switch (saVal) {
case ALIGN: {
DecodeTypeRegisterSPECIAL3();
break;
}
}
}
case DBSHFL: {
int32_t saVal = sa();
saVal >>= kBp2Bits;
switch (saVal) {
case DALIGN: {
DecodeTypeRegisterSPECIAL3();
break;
}
}
}
default:
DecodeTypeRegisterSPECIAL3();
break;
}
DecodeTypeRegisterSPECIAL3();
break;
// Unimplemented opcodes raised an error in the configuration step before,
// so we can use the default here to set the destination register in common
......
......@@ -777,6 +777,20 @@ TEST(Type0) {
}
}
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
COMPARE(seb(a0, a1), "7c052420 seb a0, a1");
COMPARE(seb(s6, s7), "7c17b420 seb s6, s7");
COMPARE(seb(v0, v1), "7c031420 seb v0, v1");
COMPARE(seh(a0, a1), "7c052620 seh a0, a1");
COMPARE(seh(s6, s7), "7c17b620 seh s6, s7");
COMPARE(seh(v0, v1), "7c031620 seh v0, v1");
COMPARE(wsbh(a0, a1), "7c0520a0 wsbh a0, a1");
COMPARE(wsbh(s6, s7), "7c17b0a0 wsbh s6, s7");
COMPARE(wsbh(v0, v1), "7c0310a0 wsbh v0, v1");
}
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
COMPARE(ins_(a0, a1, 31, 1),
"7ca4ffc4 ins a0, a1, 31, 1");
......
......@@ -683,6 +683,26 @@ TEST(Type0) {
"70621020 clz v0, v1");
}
COMPARE(seb(a0, a1), "7c052420 seb a0, a1");
COMPARE(seb(s6, s7), "7c17b420 seb s6, s7");
COMPARE(seb(v0, v1), "7c031420 seb v0, v1");
COMPARE(seh(a0, a1), "7c052620 seh a0, a1");
COMPARE(seh(s6, s7), "7c17b620 seh s6, s7");
COMPARE(seh(v0, v1), "7c031620 seh v0, v1");
COMPARE(wsbh(a0, a1), "7c0520a0 wsbh a0, a1");
COMPARE(wsbh(s6, s7), "7c17b0a0 wsbh s6, s7");
COMPARE(wsbh(v0, v1), "7c0310a0 wsbh v0, v1");
COMPARE(dsbh(a0, a1), "7c0520a4 dsbh a0, a1");
COMPARE(dsbh(s6, s7), "7c17b0a4 dsbh s6, s7");
COMPARE(dsbh(v0, v1), "7c0310a4 dsbh v0, v1");
COMPARE(dshd(a0, a1), "7c052164 dshd a0, a1");
COMPARE(dshd(s6, s7), "7c17b164 dshd s6, s7");
COMPARE(dshd(v0, v1), "7c031164 dshd v0, v1");
COMPARE(ins_(a0, a1, 31, 1),
"7ca4ffc4 ins a0, a1, 31, 1");
COMPARE(ins_(s6, s7, 30, 2),
......
......@@ -60,6 +60,71 @@ static bool all_zeroes(const byte* beg, const byte* end) {
return true;
}
TEST(BYTESWAP) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope handles(isolate);
struct T {
int32_t r1;
int32_t r2;
int32_t r3;
int32_t r4;
int32_t r5;
};
T t;
MacroAssembler assembler(isolate, NULL, 0,
v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler;
__ lw(a2, MemOperand(a0, offsetof(T, r1)));
__ nop();
__ ByteSwapSigned(a2, 4);
__ sw(a2, MemOperand(a0, offsetof(T, r1)));
__ lw(a2, MemOperand(a0, offsetof(T, r2)));
__ nop();
__ ByteSwapSigned(a2, 2);
__ sw(a2, MemOperand(a0, offsetof(T, r2)));
__ lw(a2, MemOperand(a0, offsetof(T, r3)));
__ nop();
__ ByteSwapSigned(a2, 1);
__ sw(a2, MemOperand(a0, offsetof(T, r3)));
__ lw(a2, MemOperand(a0, offsetof(T, r4)));
__ nop();
__ ByteSwapUnsigned(a2, 1);
__ sw(a2, MemOperand(a0, offsetof(T, r4)));
__ lw(a2, MemOperand(a0, offsetof(T, r5)));
__ nop();
__ ByteSwapUnsigned(a2, 2);
__ sw(a2, MemOperand(a0, offsetof(T, r5)));
__ jr(ra);
__ nop();
CodeDesc desc;
masm->GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
::F3 f = FUNCTION_CAST<::F3>(code->entry());
t.r1 = 0x781A15C3;
t.r2 = 0x2CDE;
t.r3 = 0x9F;
t.r4 = 0x9F;
t.r5 = 0x2CDE;
Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
USE(dummy);
CHECK_EQ(static_cast<int32_t>(0xC3151A78), t.r1);
CHECK_EQ(static_cast<int32_t>(0xDE2C0000), t.r2);
CHECK_EQ(static_cast<int32_t>(0x9FFFFFFF), t.r3);
CHECK_EQ(static_cast<int32_t>(0x9F000000), t.r4);
CHECK_EQ(static_cast<int32_t>(0xDE2C0000), t.r5);
}
TEST(CopyBytes) {
CcTest::InitializeVM();
......
......@@ -61,6 +61,89 @@ static bool all_zeroes(const byte* beg, const byte* end) {
return true;
}
TEST(BYTESWAP) {
DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2);
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
struct T {
int64_t r1;
int64_t r2;
int64_t r3;
int64_t r4;
int64_t r5;
int64_t r6;
int64_t r7;
};
T t;
MacroAssembler assembler(isolate, NULL, 0,
v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler;
__ ld(a4, MemOperand(a0, offsetof(T, r1)));
__ nop();
__ ByteSwapSigned(a4, 8);
__ sd(a4, MemOperand(a0, offsetof(T, r1)));
__ ld(a4, MemOperand(a0, offsetof(T, r2)));
__ nop();
__ ByteSwapSigned(a4, 4);
__ sd(a4, MemOperand(a0, offsetof(T, r2)));
__ ld(a4, MemOperand(a0, offsetof(T, r3)));
__ nop();
__ ByteSwapSigned(a4, 2);
__ sd(a4, MemOperand(a0, offsetof(T, r3)));
__ ld(a4, MemOperand(a0, offsetof(T, r4)));
__ nop();
__ ByteSwapSigned(a4, 1);
__ sd(a4, MemOperand(a0, offsetof(T, r4)));
__ ld(a4, MemOperand(a0, offsetof(T, r5)));
__ nop();
__ ByteSwapUnsigned(a4, 1);
__ sd(a4, MemOperand(a0, offsetof(T, r5)));
__ ld(a4, MemOperand(a0, offsetof(T, r6)));
__ nop();
__ ByteSwapUnsigned(a4, 2);
__ sd(a4, MemOperand(a0, offsetof(T, r6)));
__ ld(a4, MemOperand(a0, offsetof(T, r7)));
__ nop();
__ ByteSwapUnsigned(a4, 4);
__ sd(a4, MemOperand(a0, offsetof(T, r7)));
__ jr(ra);
__ nop();
CodeDesc desc;
masm->GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
::F3 f = FUNCTION_CAST<::F3>(code->entry());
t.r1 = 0x5612FFCD9D327ACC;
t.r2 = 0x781A15C3;
t.r3 = 0xFCDE;
t.r4 = 0x9F;
t.r5 = 0x9F;
t.r6 = 0xFCDE;
t.r7 = 0xC81A15C3;
Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
USE(dummy);
CHECK_EQ(static_cast<int64_t>(0xCC7A329DCDFF1256), t.r1);
CHECK_EQ(static_cast<int64_t>(0xC3151A7800000000), t.r2);
CHECK_EQ(static_cast<int64_t>(0xDEFCFFFFFFFFFFFF), t.r3);
CHECK_EQ(static_cast<int64_t>(0x9FFFFFFFFFFFFFFF), t.r4);
CHECK_EQ(static_cast<int64_t>(0x9F00000000000000), t.r5);
CHECK_EQ(static_cast<int64_t>(0xDEFC000000000000), t.r6);
CHECK_EQ(static_cast<int64_t>(0xC3151AC800000000), t.r7);
}
TEST(CopyBytes) {
CcTest::InitializeVM();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment