Skip to content

Commit c40b158

Browse files
committed
[M68k][Disassembler] Use custom decoder for 32-bit immediates
32-bit immediates require special cares because they go across the normal word (16 bits) boundaries. This patch also fixes some incorrect disassembler test cases. Differential Revision: https://reviews.llvm.org/D142080
1 parent 36c19ea commit c40b158

File tree

6 files changed

+34
-26
lines changed

6 files changed

+34
-26
lines changed

llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
9494
llvm_unreachable("unimplemented");
9595
}
9696

97+
static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
98+
const void *Decoder) {
99+
Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm)));
100+
return DecodeStatus::Success;
101+
}
102+
97103
#include "M68kGenDisassemblerTable.inc"
98104

99105
/// A disassembler class for M68k.

llvm/lib/Target/M68k/M68kInstrFormats.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ class MxEncAddrMode_abs<string opnd_name, bit size_w_l = false> : MxEncMemOp {
346346
// Absolute address
347347
let Supplement = !if(size_w_l,
348348
// abs.L
349-
(operand "$"#opnd_name, 32, (encoder "encodeRelocImm<32>")),
349+
(operand "$"#opnd_name, 32, (encoder "encodeRelocImm<32>"),
350+
(decoder "DecodeImm32")),
350351
// abs.W
351352
(operand "$"#opnd_name, 16, (encoder "encodeRelocImm<16>"))
352353
);

llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "llvm/MC/MCExpr.h"
2323
#include "llvm/Support/DataTypes.h"
24+
#include "llvm/Support/Endian.h"
2425
#include "llvm/Support/ErrorHandling.h"
2526

2627
#define GET_INSTRINFO_MI_OPS_INFO
@@ -46,6 +47,24 @@ enum { MemDisp = 0, MemBase = 1, MemIndex = 2, MemOuter = 3 };
4647
/// ([bd,PC],Xn,od)
4748
/// ([bd,PC,Xn],od)
4849
enum { PCRelDisp = 0, PCRelIndex = 1, PCRelOuter = 2 };
50+
51+
// On a LE host:
52+
// MSB LSB MSB LSB
53+
// | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 |
54+
// (On a BE host nothing changes)
55+
template <typename value_t> value_t swapWord(value_t Val) {
56+
const unsigned NumWords = sizeof(Val) / 2;
57+
if (NumWords <= 1)
58+
return Val;
59+
Val = support::endian::byte_swap(Val, support::big);
60+
value_t NewVal = 0;
61+
for (unsigned i = 0U; i != NumWords; ++i) {
62+
uint16_t Part = (Val >> (i * 16)) & 0xFFFF;
63+
Part = support::endian::byte_swap(Part, support::big);
64+
NewVal |= (Part << (i * 16));
65+
}
66+
return NewVal;
67+
}
4968
} // namespace M68k
5069

5170
namespace M68kBeads {

llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -84,24 +84,6 @@ template <unsigned Size> struct select_uint_t {
8484
uint64_t>::type>::type>::type;
8585
};
8686

87-
// On a LE host:
88-
// MSB LSB MSB LSB
89-
// | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 |
90-
// (On a BE host nothing changes)
91-
template <typename value_t> static value_t swapWord(value_t Val) {
92-
const unsigned NumWords = sizeof(Val) / 2;
93-
if (NumWords <= 1)
94-
return Val;
95-
Val = support::endian::byte_swap(Val, support::big);
96-
value_t NewVal = 0;
97-
for (unsigned i = 0U; i != NumWords; ++i) {
98-
uint16_t Part = (Val >> (i * 16)) & 0xFFFF;
99-
Part = support::endian::byte_swap(Part, support::big);
100-
NewVal |= (Part << (i * 16));
101-
}
102-
return NewVal;
103-
}
104-
10587
// Figure out which byte we're at in big endian mode.
10688
template <unsigned Size> static unsigned getBytePosition(unsigned BitPos) {
10789
if (Size % 16) {
@@ -135,14 +117,14 @@ void M68kMCCodeEmitter::encodeRelocImm(const MCInst &MI, unsigned OpIdx,
135117
using value_t = typename select_uint_t<Size>::type;
136118
const MCOperand &MCO = MI.getOperand(OpIdx);
137119
if (MCO.isImm()) {
138-
Value |= swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
120+
Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
139121
} else if (MCO.isExpr()) {
140122
const MCExpr *Expr = MCO.getExpr();
141123

142124
// Absolute address
143125
int64_t Addr;
144126
if (Expr->evaluateAsAbsolute(Addr)) {
145-
Value |= swapWord<value_t>(static_cast<value_t>(Addr));
127+
Value |= M68k::swapWord<value_t>(static_cast<value_t>(Addr));
146128
return;
147129
}
148130

@@ -162,7 +144,7 @@ void M68kMCCodeEmitter::encodePCRelImm(const MCInst &MI, unsigned OpIdx,
162144
const MCOperand &MCO = MI.getOperand(OpIdx);
163145
if (MCO.isImm()) {
164146
using value_t = typename select_uint_t<Size>::type;
165-
Value |= swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
147+
Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
166148
} else if (MCO.isExpr()) {
167149
const MCExpr *Expr = MCO.getExpr();
168150
unsigned InsertByte = getBytePosition<Size>(InsertPos);

llvm/test/MC/Disassembler/M68k/arithmetic.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
# CHECK: add.l (4660,%sp), %d5
6060
0xda 0xaf 0x12 0x34
6161

62-
# CHECK: cmpi.w #769, $3012022
62+
# CHECK: cmpi.w #769, $20220301
6363
0x0c 0x79 0x03 0x01 0x20 0x22 0x03 0x01
6464

6565
# CHECK: cmpi.w #5416, %d7
@@ -74,7 +74,7 @@
7474
# CHECK: cmpi.l #50403411, $1
7575
0x0c 0xb9 0x03 0x01 0x18 0x53 0x00 0x01 0x00 0x00
7676

77-
# CHECK: cmpi.b #64, $15400301
77+
# CHECK: cmpi.b #64, $3011540
7878
0x0c 0x39 0x00 0x40 0x03 0x01 0x15 0x40
7979

8080
# CHECK: cmp.b %d5, %d7

llvm/test/MC/Disassembler/M68k/data.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
0x20 0x37 0x88 0x40
3838

3939
# CHECK: move.l $f0000000, %a5
40-
0x2a 0x79 0x00 0x00 0xf0 0x00
40+
0x2a 0x79 0xf0 0x00 0x00 0x00
4141

42-
# CHECK: move.l $1, %d0
42+
# CHECK: move.l $10000, %d0
4343
0x20 0x39 0x00 0x01 0x00 0x00
4444

4545
# CHECK: move.l (32768,%pc), %a2

0 commit comments

Comments
 (0)