Bug 1323642 - IonMonkey: MIPS64: Fix load unsigned 48-bit immediate

Issue:
In ma_li(Register, ImmWord):
	Load unsigned 48-bit immediate: 0x0000_8000_0000_0000
	Wrong instructions stream:
		lui	reg, 0x8000
		dsll	reg, reg, 16 # reg = 0xffff_8000_0000_0000
	Fixed instructions stream:
		lui	reg, 0x8000
		dinsu	reg, zero, 32, 32
		dsll	reg, reg, 16

Tag: #1542
This commit is contained in:
Jiaxun Yang 2020-05-12 12:40:05 +08:00 committed by Roy Tam
commit e293ccbcd4

View file

@ -258,36 +258,45 @@ MacroAssemblerMIPS64::ma_li(Register dest, ImmWord imm)
{
int64_t value = imm.value;
if (value >= INT16_MIN && value <= INT16_MAX) {
if (-1 == (value >> 15) || 0 == (value >> 15)) {
as_addiu(dest, zero, value);
} else if (imm.value <= UINT16_MAX) {
as_ori(dest, zero, Imm16::Lower(Imm32(value)).encode());
} else if (value >= INT32_MIN && value <= INT32_MAX) {
as_lui(dest, Imm16::Upper(Imm32(value)).encode());
if (value & 0xffff)
as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
} else if (imm.value <= UINT32_MAX) {
as_lui(dest, Imm16::Upper(Imm32(value)).encode());
if (value & 0xffff)
as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
as_dinsu(dest, zero, 32, 32);
} else {
uint64_t high = imm.value >> 32;
return;
}
if (0 == (value >> 16)) {
as_ori(dest, zero, value);
return;
}
if (imm.value >> 48) {
as_lui(dest, Imm16::Upper(Imm32(high)).encode());
if (high & 0xffff)
as_ori(dest, dest, Imm16::Lower(Imm32(high)).encode());
if (-1 == (value >> 31) || 0 == (value >> 31)) {
as_lui(dest, uint16_t(value >> 16));
} else if (0 == (value >> 32)) {
as_lui(dest, uint16_t(value >> 16));
as_dinsu(dest, zero, 32, 32);
} else if (-1 == (value >> 47) || 0 == (value >> 47)) {
as_lui(dest, uint16_t(value >> 32));
if (uint16_t(value >> 16))
as_ori(dest, dest, uint16_t(value >> 16));
as_dsll(dest, dest, 16);
} else if (0 == (value >> 48)) {
as_lui(dest, uint16_t(value >> 32));
as_dinsu(dest, zero, 32, 32);
if (uint16_t(value >> 16))
as_ori(dest, dest, uint16_t(value >> 16));
as_dsll(dest, dest, 16);
} else {
as_lui(dest, uint16_t(value >> 48));
if (uint16_t(value >> 32))
as_ori(dest, dest, uint16_t(value >> 32));
if (uint16_t(value >> 16)) {
as_dsll(dest, dest, 16);
as_ori(dest, dest, uint16_t(value >> 16));
as_dsll(dest, dest, 16);
} else {
as_lui(dest, Imm16::Lower(Imm32(high)).encode());
as_dsll32(dest, dest, 32);
}
if ((imm.value >> 16) & 0xffff)
as_ori(dest, dest, Imm16::Upper(Imm32(value)).encode());
as_dsll(dest, dest, 16);
if (value & 0xffff)
as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
}
if (uint16_t(value))
as_ori(dest, dest, uint16_t(value));
}
// This method generates lui, dsll and ori instruction block that can be modified