diff --git a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp --- a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp +++ b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp @@ -94,6 +94,12 @@ llvm_unreachable("unimplemented"); } +static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address, + const void *Decoder) { + Inst.addOperand(MCOperand::createImm(M68k::swapWord(Imm))); + return DecodeStatus::Success; +} + #include "M68kGenDisassemblerTable.inc" /// A disassembler class for M68k. diff --git a/llvm/lib/Target/M68k/M68kInstrFormats.td b/llvm/lib/Target/M68k/M68kInstrFormats.td --- a/llvm/lib/Target/M68k/M68kInstrFormats.td +++ b/llvm/lib/Target/M68k/M68kInstrFormats.td @@ -346,7 +346,8 @@ // Absolute address let Supplement = !if(size_w_l, // abs.L - (operand "$"#opnd_name, 32, (encoder "encodeRelocImm<32>")), + (operand "$"#opnd_name, 32, (encoder "encodeRelocImm<32>"), + (decoder "DecodeImm32")), // abs.W (operand "$"#opnd_name, 16, (encoder "encodeRelocImm<16>")) ); diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h b/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h --- a/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h +++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h @@ -21,6 +21,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #define GET_INSTRINFO_MI_OPS_INFO @@ -46,6 +47,24 @@ /// ([bd,PC],Xn,od) /// ([bd,PC,Xn],od) enum { PCRelDisp = 0, PCRelIndex = 1, PCRelOuter = 2 }; + +// On a LE host: +// MSB LSB MSB LSB +// | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 | +// (On a BE host nothing changes) +template value_t swapWord(value_t Val) { + const unsigned NumWords = sizeof(Val) / 2; + if (NumWords <= 1) + return Val; + Val = support::endian::byte_swap(Val, support::big); + value_t NewVal = 0; + for (unsigned i = 0U; i != NumWords; ++i) { + uint16_t Part = (Val >> (i * 16)) & 0xFFFF; + Part = support::endian::byte_swap(Part, support::big); + NewVal |= (Part << (i * 16)); + } + return NewVal; +} } // namespace M68k namespace M68kBeads { diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp --- a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp +++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp @@ -84,24 +84,6 @@ uint64_t>::type>::type>::type; }; -// On a LE host: -// MSB LSB MSB LSB -// | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 | -// (On a BE host nothing changes) -template static value_t swapWord(value_t Val) { - const unsigned NumWords = sizeof(Val) / 2; - if (NumWords <= 1) - return Val; - Val = support::endian::byte_swap(Val, support::big); - value_t NewVal = 0; - for (unsigned i = 0U; i != NumWords; ++i) { - uint16_t Part = (Val >> (i * 16)) & 0xFFFF; - Part = support::endian::byte_swap(Part, support::big); - NewVal |= (Part << (i * 16)); - } - return NewVal; -} - // Figure out which byte we're at in big endian mode. template static unsigned getBytePosition(unsigned BitPos) { if (Size % 16) { @@ -135,14 +117,14 @@ using value_t = typename select_uint_t::type; const MCOperand &MCO = MI.getOperand(OpIdx); if (MCO.isImm()) { - Value |= swapWord(static_cast(MCO.getImm())); + Value |= M68k::swapWord(static_cast(MCO.getImm())); } else if (MCO.isExpr()) { const MCExpr *Expr = MCO.getExpr(); // Absolute address int64_t Addr; if (Expr->evaluateAsAbsolute(Addr)) { - Value |= swapWord(static_cast(Addr)); + Value |= M68k::swapWord(static_cast(Addr)); return; } @@ -162,7 +144,7 @@ const MCOperand &MCO = MI.getOperand(OpIdx); if (MCO.isImm()) { using value_t = typename select_uint_t::type; - Value |= swapWord(static_cast(MCO.getImm())); + Value |= M68k::swapWord(static_cast(MCO.getImm())); } else if (MCO.isExpr()) { const MCExpr *Expr = MCO.getExpr(); unsigned InsertByte = getBytePosition(InsertPos); diff --git a/llvm/test/MC/Disassembler/M68k/arithmetic.txt b/llvm/test/MC/Disassembler/M68k/arithmetic.txt --- a/llvm/test/MC/Disassembler/M68k/arithmetic.txt +++ b/llvm/test/MC/Disassembler/M68k/arithmetic.txt @@ -59,7 +59,7 @@ # CHECK: add.l (4660,%sp), %d5 0xda 0xaf 0x12 0x34 -# CHECK: cmpi.w #769, $3012022 +# CHECK: cmpi.w #769, $20220301 0x0c 0x79 0x03 0x01 0x20 0x22 0x03 0x01 # CHECK: cmpi.w #5416, %d7 @@ -74,7 +74,7 @@ # CHECK: cmpi.l #50403411, $1 0x0c 0xb9 0x03 0x01 0x18 0x53 0x00 0x01 0x00 0x00 -# CHECK: cmpi.b #64, $15400301 +# CHECK: cmpi.b #64, $3011540 0x0c 0x39 0x00 0x40 0x03 0x01 0x15 0x40 # CHECK: cmp.b %d5, %d7 diff --git a/llvm/test/MC/Disassembler/M68k/data.txt b/llvm/test/MC/Disassembler/M68k/data.txt --- a/llvm/test/MC/Disassembler/M68k/data.txt +++ b/llvm/test/MC/Disassembler/M68k/data.txt @@ -37,9 +37,9 @@ 0x20 0x37 0x88 0x40 # CHECK: move.l $f0000000, %a5 -0x2a 0x79 0x00 0x00 0xf0 0x00 +0x2a 0x79 0xf0 0x00 0x00 0x00 -# CHECK: move.l $1, %d0 +# CHECK: move.l $10000, %d0 0x20 0x39 0x00 0x01 0x00 0x00 # CHECK: move.l (32768,%pc), %a2