mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 02:29:18 +00:00
Move the ARM SSAT and USAT optional shift amount operand out of the
instruction opcode. This also fixes part of PR7792. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110875 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d29583bd32
commit
eaf1c98a7c
@ -120,8 +120,10 @@ namespace {
|
||||
void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O);
|
||||
void printBitfieldInvMaskImmOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O);
|
||||
void printSatShiftOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O);
|
||||
|
||||
void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O);
|
||||
@ -669,6 +671,25 @@ ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op,
|
||||
O << "#" << lsb << ", #" << width;
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printSatShiftOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O) {
|
||||
unsigned ShiftOp = MI->getOperand(OpNum).getImm();
|
||||
ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
|
||||
switch (Opc) {
|
||||
case ARM_AM::no_shift:
|
||||
return;
|
||||
case ARM_AM::lsl:
|
||||
O << ", lsl #";
|
||||
break;
|
||||
case ARM_AM::asr:
|
||||
O << ", asr #";
|
||||
break;
|
||||
default:
|
||||
assert(0 && "unexpected shift opcode for saturate shift operand");
|
||||
}
|
||||
O << ARM_AM::getSORegOffset(ShiftOp);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op,
|
||||
|
@ -1247,9 +1247,7 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) {
|
||||
|
||||
// Encode saturate bit position.
|
||||
unsigned Pos = MI.getOperand(1).getImm();
|
||||
if (TID.Opcode == ARM::SSATlsl ||
|
||||
TID.Opcode == ARM::SSATasr ||
|
||||
TID.Opcode == ARM::SSAT16)
|
||||
if (TID.Opcode == ARM::SSAT || TID.Opcode == ARM::SSAT16)
|
||||
Pos -= 1;
|
||||
assert((Pos < 16 || (Pos < 32 &&
|
||||
TID.Opcode != ARM::SSAT16 &&
|
||||
@ -1262,9 +1260,12 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) {
|
||||
|
||||
// Encode shift_imm.
|
||||
if (TID.getNumOperands() == 4) {
|
||||
unsigned ShiftOp = MI.getOperand(3).getImm();
|
||||
ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
|
||||
if (Opc == ARM_AM::asr)
|
||||
Binary |= (1 << 6);
|
||||
unsigned ShiftAmt = MI.getOperand(3).getImm();
|
||||
if (ShiftAmt == 32 &&
|
||||
(TID.Opcode == ARM::SSATasr || TID.Opcode == ARM::USATasr))
|
||||
if (ShiftAmt == 32 && Opc == ARM_AM::asr)
|
||||
ShiftAmt = 0;
|
||||
assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!");
|
||||
Binary |= ShiftAmt << ARMII::ShiftShift;
|
||||
|
@ -1810,20 +1810,15 @@ def USADA8 : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
|
||||
|
||||
// Signed/Unsigned saturate -- for disassembly only
|
||||
|
||||
def SSATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
|
||||
SatFrm, NoItinerary,
|
||||
"ssat", "\t$dst, $bit_pos, $a, lsl $shamt",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{27-21} = 0b0110101;
|
||||
let Inst{6-4} = 0b001;
|
||||
def sat_shift : Operand<i32> {
|
||||
let PrintMethod = "printSatShiftOperand";
|
||||
}
|
||||
|
||||
def SSATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
|
||||
SatFrm, NoItinerary,
|
||||
"ssat", "\t$dst, $bit_pos, $a, asr $shamt",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
def SSAT : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, sat_shift:$sh),
|
||||
SatFrm, NoItinerary, "ssat", "\t$dst, $bit_pos, $a$sh",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{27-21} = 0b0110101;
|
||||
let Inst{6-4} = 0b101;
|
||||
let Inst{5-4} = 0b01;
|
||||
}
|
||||
|
||||
def SSAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
|
||||
@ -1833,20 +1828,11 @@ def SSAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
|
||||
let Inst{7-4} = 0b0011;
|
||||
}
|
||||
|
||||
def USATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
|
||||
SatFrm, NoItinerary,
|
||||
"usat", "\t$dst, $bit_pos, $a, lsl $shamt",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
def USAT : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, sat_shift:$sh),
|
||||
SatFrm, NoItinerary, "usat", "\t$dst, $bit_pos, $a$sh",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{27-21} = 0b0110111;
|
||||
let Inst{6-4} = 0b001;
|
||||
}
|
||||
|
||||
def USATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
|
||||
SatFrm, NoItinerary,
|
||||
"usat", "\t$dst, $bit_pos, $a, asr $shamt",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{27-21} = 0b0110111;
|
||||
let Inst{6-4} = 0b101;
|
||||
let Inst{5-4} = 0b01;
|
||||
}
|
||||
|
||||
def USAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
|
||||
@ -1856,8 +1842,8 @@ def USAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
|
||||
let Inst{7-4} = 0b0011;
|
||||
}
|
||||
|
||||
def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSATlsl imm:$pos, GPR:$a, 0)>;
|
||||
def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USATlsl imm:$pos, GPR:$a, 0)>;
|
||||
def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSAT imm:$pos, GPR:$a, 0)>;
|
||||
def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Bitwise Instructions.
|
||||
|
@ -461,9 +461,9 @@ void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
|
||||
assert(0 && "FIXME: Implement printAddrModePCOperand");
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
|
||||
unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
|
||||
unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO = MI->getOperand(OpNum);
|
||||
uint32_t v = ~MO.getImm();
|
||||
int32_t lsb = CountTrailingZeros_32(v);
|
||||
@ -472,6 +472,25 @@ void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
|
||||
O << '#' << lsb << ", #" << width;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printSatShiftOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
unsigned ShiftOp = MI->getOperand(OpNum).getImm();
|
||||
ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
|
||||
switch (Opc) {
|
||||
case ARM_AM::no_shift:
|
||||
return;
|
||||
case ARM_AM::lsl:
|
||||
O << ", lsl #";
|
||||
break;
|
||||
case ARM_AM::asr:
|
||||
O << ", asr #";
|
||||
break;
|
||||
default:
|
||||
assert(0 && "unexpected shift opcode for saturate shift operand");
|
||||
}
|
||||
O << ARM_AM::getSORegOffset(ShiftOp);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
O << "{";
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
|
||||
void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printSatShiftOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
|
||||
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
|
@ -106,7 +106,7 @@ static unsigned decodeARMInstruction(uint32_t &insn) {
|
||||
// Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1 & A2.
|
||||
// As a result, the decoder fails to deocode SSAT properly.
|
||||
if (slice(insn, 27, 21) == 0x35 && slice(insn, 5, 4) == 1)
|
||||
return slice(insn, 6, 6) == 0 ? ARM::SSATlsl : ARM::SSATasr;
|
||||
return ARM::SSAT;
|
||||
|
||||
// Ditto for RSCrs, which is a super-instruction for A8.6.146 & A8.6.147.
|
||||
// As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT.
|
||||
|
@ -1466,9 +1466,7 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||
decodeRd(insn))));
|
||||
|
||||
unsigned Pos = slice(insn, 20, 16);
|
||||
if (Opcode == ARM::SSATlsl ||
|
||||
Opcode == ARM::SSATasr ||
|
||||
Opcode == ARM::SSAT16)
|
||||
if (Opcode == ARM::SSAT || Opcode == ARM::SSAT16)
|
||||
Pos += 1;
|
||||
MI.addOperand(MCOperand::CreateImm(Pos));
|
||||
|
||||
@ -1476,12 +1474,17 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||
decodeRm(insn))));
|
||||
|
||||
if (NumOpsAdded == 4) {
|
||||
ARM_AM::ShiftOpc Opc = (slice(insn, 6, 6) != 0 ? ARM_AM::asr : ARM_AM::lsl);
|
||||
// Inst{11-7} encodes the imm5 shift amount.
|
||||
unsigned ShAmt = slice(insn, 11, 7);
|
||||
// A8.6.183. Possible ASR shift amount of 32...
|
||||
if ((Opcode == ARM::SSATasr || Opcode == ARM::USATasr) && ShAmt == 0)
|
||||
ShAmt = 32;
|
||||
MI.addOperand(MCOperand::CreateImm(ShAmt));
|
||||
if (ShAmt == 0) {
|
||||
// A8.6.183. Possible ASR shift amount of 32...
|
||||
if (Opc == ARM_AM::asr)
|
||||
ShAmt = 32;
|
||||
else
|
||||
Opc = ARM_AM::no_shift;
|
||||
}
|
||||
MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShAmt)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -78,6 +78,10 @@
|
||||
# CHECK: ssat r8, #1, r10, lsl #8
|
||||
0x1a 0x84 0xa0 0xe6
|
||||
|
||||
# CHECK-NOT: ssatmi r0, #17, r12, lsl #0
|
||||
# CHECK: ssatmi r0, #17, r12
|
||||
0x1c 0x00 0xb0 0x46
|
||||
|
||||
# CHECK: stmdb r10!, {r4, r5, r6, r7, lr}
|
||||
0xf0 0x40 0x2a 0xe9
|
||||
|
||||
|
@ -607,6 +607,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
IMM("jt2block_operand");
|
||||
IMM("t_imm_s4");
|
||||
IMM("pclabel");
|
||||
IMM("sat_shift");
|
||||
|
||||
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||
|
Loading…
Reference in New Issue
Block a user