Skip to content

M68K: Fix fmove.x 96-bit extended immediate decode length and printing - #3016

Open
b1llow wants to merge 1 commit into
capstone-engine:nextfrom
b1llow:m68k-fix-96b
Open

M68K: Fix fmove.x 96-bit extended immediate decode length and printing#3016
b1llow wants to merge 1 commit into
capstone-engine:nextfrom
b1llow:m68k-fix-96b

Conversation

@b1llow

@b1llow b1llow commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Your checklist for this pull request

  • I've documented or updated the documentation of every API function and struct this PR changes.
  • I've added tests that prove my fix is effective or that my feature works (if possible)

Detailed description

Summary

fmove.x #<imm> did not consume the full Motorola 96-bit extended-precision immediate, so instruction size and following bytes were wrong, and the immediate could not be printed usefully.

References

Motorola MC68881/MC68882 Floating-Point Coprocessor User’s Manual, first edition (1987):

https://www.bitsavers.org/components/motorola/68000/68020/MC68881_MC68882_Floating-Point_Coprocessor_Users_Manual_1ed_1987.pdf

Topic Manual
External Extended Precision Real (X) format §3 — 96-bit/12-byte layout: 16-bit sign+biased exponent, 16-bit unused/reserved word, 64-bit significand (explicit integer bit). Internal FP registers are 80-bit; external X pads to 96 bits.
Immediate operand size for .x / .p §4.7 / §4.7.1 (General Type / FMOVE) — immediate X is six 16-bit words (12 bytes) after the F-line + command word; longest FPCP form.
Source format field Command word source specifier — extended = format code for .x (repo: M68K_FPSRC_EXTENDED).

Same X layout is summarized in the M68000 Family Programmer’s Reference Manual (.X = extended-precision real).

Conversion of that external encoding to IEEE-754 binary64 for Capstone’s dimm / printer is an implementation detail of this patch; the ISA requirement is correct 12-byte consumption and format interpretation per the manual above.

Bug

For M68K_FPSRC_EXTENDED immediates the decoder used the generic EA path with size 12 and did not treat the 12-byte X encoding as a proper FP immediate:

  1. Decode length — sign/exponent word, reserved word, and 64-bit significand were not always fully consumed, so fmove.x size was wrong and trailing instructions (e.g. nop) were mis-decoded. Contradicts the manual’s 6-word immediate X operand.
  2. Printing — the printer keyed off inst->op_size.fpu_size. Extended immediates never became a printable FP operand type, so they showed as #<unsupported>.

The sign bit is only the normal high bit of the manual’s sign+exponent word in the X→binary64 conversion. It is not the bug; the failures were undersized/incorrect immediate reads and size-based print dispatch.

Fix

  • read_imm_extended() / extended_to_double() — read the 12-byte X immediate per §3 (ignore reserved word) and convert to binary64 with integer arithmetic (round-ties-to-even, signed zero, inf, qNaN, subnormals).
  • Immediate EA on the extended fmove path — M68K_AM_IMMEDIATE + M68K_OP_FP_DOUBLE, value in dimm.
  • Print FP immediates by operand type (M68K_OP_FP_SINGLE / M68K_OP_FP_DOUBLE) so extended values in dimm print as #….

Tests

tests/details/m68k.yaml for fmove.x immediates:

  • canonical +1.0, size 16, following nops
  • signed finite (-2.5)
  • reserved word ignored → 0.0, still full length
  • ties-to-even round-up / round-down
  • overflow → inf, NaN, signed zero, subnormal
  • memory EA .x source (no inline 12-byte immediate)

Impact

  • arch/M68K/M68KDisassembler.c — X immediate read/conversion; immediate path for M68K_FPSRC_EXTENDED
  • arch/M68K/M68KInstPrinter.c — print by FP operand type
  • tests/details/m68k.yaml — cases above

Closing issues

closes #3013

@github-actions github-actions Bot added the M68K Arch label Aug 6, 2026
@Rot127

Rot127 commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Please add a PR description. What does the signing have to do with the bug?

Comment thread arch/M68K/M68KDisassembler.c Outdated
if (!get_ea_mode_op(info, op0, info->ir, 12)) {
if (m68k_ea_is_immediate(info->ir)) {
op0->address_mode = M68K_AM_IMMEDIATE;
op0->type = M68K_OP_FP_DOUBLE;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be a new operand type? Since the 96 bit is not a 64bit double? wdyt?

@github-actions github-actions Bot added Python Bindings java bindings ocaml bindings labels Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

java bindings M68K Arch ocaml bindings Python Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

M68K: Incorrect disassembly for fmove.x/fmove.p

2 participants