Skip to content

Commit b9a52b6

Browse files
committed
fix(M68K): fix cross-arch bugs in cpush/cinv and dc.w printing
build_cpush_cinv: use op1->reg instead of op1->imm for address register operand. Writing to imm (uint64_t) when reg (m68k_reg, uint32_t) is read back causes garbage values on big-endian targets (PPC64, s390x) due to union byte order mismatch. M68K_printInst: cast imm to uint32_t before passing to PRIx32 format. Passing uint64_t to a PRIx32 format specifier is UB; on 32-bit big-endian MIPS the high word (0) is read instead of the low word containing the instruction bytes. Fixes cstest details failures on QEMU Linux PPC64, s390x, Mips32.
1 parent cbf8a9e commit b9a52b6

2 files changed

Lines changed: 33 additions & 13 deletions

File tree

arch/M68K/M68KDisassembler.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@
9999

100100
#define M68010_ONLY TYPE_68010
101101
#define M68010_LESS (TYPE_68000 | TYPE_68010)
102-
#define M68010_PLUS (TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040 | TYPE_68060)
102+
#define M68010_PLUS \
103+
(TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040 | TYPE_68060)
103104

104105
#define M68020_ONLY TYPE_68020
105106
#define M68020_LESS (TYPE_68010 | TYPE_68020)
@@ -1246,7 +1247,7 @@ static void build_cpush_cinv(m68k_info *info, int op_offset)
12461247

12471248
op1->type = M68K_OP_MEM;
12481249
op1->address_mode = M68K_AM_REG_DIRECT_ADDR;
1249-
op1->imm = M68K_REG_A0 + (info->ir & 7);
1250+
op1->reg = M68K_REG_A0 + (info->ir & 7);
12501251
}
12511252

12521253
static void build_movep_re(m68k_info *info, int size)
@@ -3600,10 +3601,18 @@ static void d68cpu32_tbl(m68k_info *info)
36003601
size_bits = (ext_word >> 6) & 3;
36013602

36023603
switch (size_bits) {
3603-
case 0: size = 1; break; /* byte */
3604-
case 1: size = 2; break; /* word */
3605-
case 2: size = 4; break; /* long */
3606-
default: d68000_invalid(info); return;
3604+
case 0:
3605+
size = 1;
3606+
break; /* byte */
3607+
case 1:
3608+
size = 2;
3609+
break; /* word */
3610+
case 2:
3611+
size = 4;
3612+
break; /* long */
3613+
default:
3614+
d68000_invalid(info);
3615+
return;
36073616
}
36083617

36093618
if (is_signed && is_round)
@@ -3680,7 +3689,8 @@ static void d68030_pmmu(m68k_info *info)
36803689
/* PFLUSH #fc, #mask, (ea) */
36813690
int mask = (cmd >> 5) & 7;
36823691
int fc = cmd & 0x1f;
3683-
cs_m68k *ext = build_init_op(info, M68K_INS_PFLUSH, 3, 0);
3692+
cs_m68k *ext =
3693+
build_init_op(info, M68K_INS_PFLUSH, 3, 0);
36843694
cs_m68k_op *op0 = &ext->operands[0];
36853695
cs_m68k_op *op1 = &ext->operands[1];
36863696
cs_m68k_op *op2 = &ext->operands[2];
@@ -3751,9 +3761,15 @@ static void d68030_pmmu(m68k_info *info)
37513761
cs_m68k_op *op1;
37523762

37533763
switch (preg) {
3754-
case 0: pmmu_reg = M68K_REG_TC; break;
3755-
case 2: pmmu_reg = M68K_REG_SRP; break;
3756-
case 3: pmmu_reg = M68K_REG_CRP; break;
3764+
case 0:
3765+
pmmu_reg = M68K_REG_TC;
3766+
break;
3767+
case 2:
3768+
pmmu_reg = M68K_REG_SRP;
3769+
break;
3770+
case 3:
3771+
pmmu_reg = M68K_REG_CRP;
3772+
break;
37573773
default:
37583774
d68000_invalid(info);
37593775
return;
@@ -3864,8 +3880,12 @@ static void d68030_pmmu(m68k_info *info)
38643880
cs_m68k_op *op1;
38653881

38663882
switch (preg) {
3867-
case 2: pmmu_reg = M68K_REG_TT0; break;
3868-
case 3: pmmu_reg = M68K_REG_TT1; break;
3883+
case 2:
3884+
pmmu_reg = M68K_REG_TT0;
3885+
break;
3886+
case 3:
3887+
pmmu_reg = M68K_REG_TT1;
3888+
break;
38693889
default:
38703890
d68000_invalid(info);
38713891
return;

arch/M68K/M68KInstPrinter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ void M68K_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
383383
if (MI->Opcode == M68K_INS_INVALID) {
384384
if (ext->op_count)
385385
SStream_concat(O, "dc.w $%" PRIx32,
386-
ext->operands[0].imm);
386+
(uint32_t)ext->operands[0].imm);
387387
else
388388
SStream_concat(O, "dc.w $<unknown>");
389389
return;

0 commit comments

Comments
 (0)