Skip to content

Commit

Permalink
Fix broken disassembly of floating point immediates on big endian hos…
Browse files Browse the repository at this point in the history
…ts (#2222)

Disassembling single floating points with immediate values currently
gives wrong results on big endian hosts (like s390x), e.g.:

 ./cstool/cstool m68k40 'f2 3c 44 22 40 49 0e 56'
  0  f2 3c 44 22 40 49 0e 56  fadd.s     #0.000000, fp0

While it should be (like on x86):

 ./cstool/cstool m68k40 'f2 3c 44 22 40 49 0e 56'
  0  f2 3c 44 22 40 49 0e 56  fadd.s     #3.141500, fp0

The problem is that these single float values are supposed to be stored
in the 32-bit "simm" field of struct cs_m68k_op (see e.g. the printing
of M68K_FPU_SIZE_SINGLE in printAddressingMode() in M68KInstPrinter.c),
but currently the immediate is only written to the 64-bit "imm" field
of the union in cs_m68k_op. This works on little endian systems, since
the least significant bytes overlap in the union there. For example,
let's assume that the value 0x01020304 gets written to "imm":

 04 03 02 01 00 00 00 00    uint64_t imm
 xx xx xx xx xx xx xx xx    double dimm;
 xx xx xx xx .. .. .. ..    float simm;

But on big endian hosts, the important bytes do not overlap, so "simm"
is always zero there:

 00 00 00 00 01 02 03 04    uint64_t imm
 xx xx xx xx xx xx xx xx    double dimm;
 xx xx xx xx .. .. .. ..    float simm;

To fix the problem, let's always set "simm" explicitly, this works on
both, big endian and little endian hosts.

Thanks to Michal Schulz for his initial analysis of the problem
(in #1710) and to Travis Finkenauer for providing an easy example
to reproduce the issue (in #1931).

Closes: #1710
  • Loading branch information
huth committed Dec 21, 2023
1 parent 484c7e5 commit e3a2b4c
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 0 deletions.
2 changes: 2 additions & 0 deletions arch/M68K/M68KDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "../../cs_priv.h"
#include "../../utils.h"

#include "../../MathExtras.h"
#include "../../MCInst.h"
#include "../../MCInstrDesc.h"
#include "../../MCRegisterInfo.h"
Expand Down Expand Up @@ -2077,6 +2078,7 @@ static void d68020_cpgen(m68k_info *info)
ext->op_size.type = M68K_SIZE_TYPE_FPU;
ext->op_size.fpu_size = M68K_FPU_SIZE_SINGLE;
get_ea_mode_op(info, op0, info->ir, 4);
op0->simm = BitsToFloat(op0->imm);
op0->type = M68K_OP_FP_SINGLE;
break;

Expand Down
4 changes: 4 additions & 0 deletions suite/cstest/issues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@
0x33,0xc0 == xor ax, ax
0xba,0x5a,0xff == mov dx, 0xff5a

!# issue 1710 M68K floating point immediates broken on big endian hosts
!# CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, None
0xf2,0x3c,0x44,0x22,0x40,0x49,0x0e,0x56 == fadd.s #3.141500, fp0

!# issue 1708 M68K floating point loads and stores generate the same op_str
!# CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, None
0xf2,0x27,0x74,0x00 == fmove.d fp0, -(a7)
Expand Down

0 comments on commit e3a2b4c

Please sign in to comment.