[MC][AVR] Implement decoding ST/LD

Reviewed By: aykevl, dylanmckay

Differential Revision: https://reviews.llvm.org/D123476
This commit is contained in:
Ben Shi 2022-04-11 01:44:49 +00:00
parent cef2739d68
commit b1dcd6bafb
3 changed files with 133 additions and 3 deletions

View File

@ -276,9 +276,11 @@ static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
uint64_t Address,
const MCDisassembler *Decoder) {
// Get the register will be loaded or stored.
unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
// Decode LDD/STD with offset less than 8.
if ((Insn & 0xf000) == 0x8000) {
unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
unsigned Offset = Insn & 7; // We need not consider offset > 7.
if ((Insn & 0x200) == 0) { // Decode LDD.
@ -295,8 +297,85 @@ static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
return MCDisassembler::Success;
}
// TODO: Decode ST/LD with postinc/predec properly.
return MCDisassembler::Fail;
// Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
// bits 8~4 indicate the value register, bits 3-2 indicate the base address
// register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
// 01-postinc, 10-predec).
// ST X, Rr : 1001 001r rrrr 1100
// ST X+, Rr : 1001 001r rrrr 1101
// ST -X, Rr : 1001 001r rrrr 1110
// ST Y+, Rr : 1001 001r rrrr 1001
// ST -Y, Rr : 1001 001r rrrr 1010
// ST Z+, Rr : 1001 001r rrrr 0001
// ST -Z, Rr : 1001 001r rrrr 0010
// LD Rd, X : 1001 000d dddd 1100
// LD Rd, X+ : 1001 000d dddd 1101
// LD Rd, -X : 1001 000d dddd 1110
// LD Rd, Y+ : 1001 000d dddd 1001
// LD Rd, -Y : 1001 000d dddd 1010
// LD Rd, Z+ : 1001 000d dddd 0001
// LD Rd, -Z : 1001 000d dddd 0010
if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
return MCDisassembler::Fail;
// Get the base address register.
unsigned RegBase;
switch (Insn & 0xc) {
case 0xc:
RegBase = AVR::R27R26;
break;
case 0x8:
RegBase = AVR::R29R28;
break;
case 0x0:
RegBase = AVR::R31R30;
break;
default:
return MCDisassembler::Fail;
}
// Set the opcode.
switch (Insn & 0x203) {
case 0x200:
Inst.setOpcode(AVR::STPtrRr);
Inst.addOperand(MCOperand::createReg(RegBase));
Inst.addOperand(MCOperand::createReg(RegVal));
return MCDisassembler::Success;
case 0x201:
Inst.setOpcode(AVR::STPtrPiRr);
break;
case 0x202:
Inst.setOpcode(AVR::STPtrPdRr);
break;
case 0:
Inst.setOpcode(AVR::LDRdPtr);
Inst.addOperand(MCOperand::createReg(RegVal));
Inst.addOperand(MCOperand::createReg(RegBase));
return MCDisassembler::Success;
case 1:
Inst.setOpcode(AVR::LDRdPtrPi);
break;
case 2:
Inst.setOpcode(AVR::LDRdPtrPd);
break;
default:
return MCDisassembler::Fail;
}
// Build postinc/predec machine instructions.
if ((Insn & 0x200) == 0) { // This is a load instruction.
Inst.addOperand(MCOperand::createReg(RegVal));
Inst.addOperand(MCOperand::createReg(RegBase));
Inst.addOperand(MCOperand::createReg(RegBase));
} else { // This is a store instruction.
Inst.addOperand(MCOperand::createReg(RegBase));
Inst.addOperand(MCOperand::createReg(RegBase));
Inst.addOperand(MCOperand::createReg(RegVal));
// STPtrPiRr and STPtrPdRr have an extra immediate operand.
Inst.addOperand(MCOperand::createImm(1));
}
return MCDisassembler::Success;
}
static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
@ -357,7 +436,12 @@ DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
// Try to auto-decode a 16-bit instruction.
Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
this, STI);
if (Result != MCDisassembler::Fail)
return Result;
// Try to decode to a load/store instruction. ST/LD need a specified
// DecoderMethod, as they already have a specified PostEncoderMethod.
Result = decodeLoadStore(Instr, Insn, Address, this);
if (Result != MCDisassembler::Fail)
return Result;
}

View File

@ -1,4 +1,6 @@
; RUN: llvm-mc -triple avr -mattr=sram -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram < %s \
; RUN: | llvm-objdump -d --mattr=sram - | FileCheck --check-prefix=INST %s
foo:
@ -71,3 +73,24 @@ foo:
; CHECK: ld r10, -Z ; encoding: [0xa2,0x90]
; CHECK: ld r2, -Z ; encoding: [0x22,0x90]
; INST: ld r10, X
; INST: ld r17, X
; INST: ldd r30, Y+0
; INST: ldd r19, Y+0
; INST: ldd r10, Z+0
; INST: ldd r2, Z+0
; INST: ld r10, X+
; INST: ld r17, X+
; INST: ld r30, Y+
; INST: ld r19, Y+
; INST: ld r10, Z+
; INST: ld r2, Z+
; INST: ld r10, -X
; INST: ld r17, -X
; INST: ld r30, -Y
; INST: ld r19, -Y
; INST: ld r10, -Z
; INST: ld r2, -Z

View File

@ -1,4 +1,6 @@
; RUN: llvm-mc -triple avr -mattr=sram -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram < %s \
; RUN: | llvm-objdump -d --mattr=sram - | FileCheck --check-prefix=INST %s
foo:
@ -69,3 +71,24 @@ foo:
; CHECK: st -Z, r10 ; encoding: [0xa2,0x92]
; CHECK: st -Z, r2 ; encoding: [0x22,0x92]
; INST: st X, r10
; INST: st X, r17
; INST: std Y+0, r30
; INST: std Y+0, r19
; INST: std Z+0, r10
; INST: std Z+0, r2
; INST: st X+, r10
; INST: st X+, r17
; INST: st Y+, r30
; INST: st Y+, r19
; INST: st Z+, r10
; INST: st Z+, r2
; INST: st -X, r10
; INST: st -X, r17
; INST: st -Y, r30
; INST: st -Y, r19
; INST: st -Z, r10
; INST: st -Z, r2