From e944af41b4687354b41cc135088627ff7bb82a29 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Wed, 16 Sep 2026 03:51:12 +0100 Subject: [PATCH] Fixed inline assembly operand sizes for out instructions --- amd64.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ i386.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/amd64.c b/amd64.c index 92b2384..1a1b049 100644 --- a/amd64.c +++ b/amd64.c @@ -33302,6 +33302,42 @@ static int inline_asm_template_is_out (const char *templ) { } +static int inline_asm_out_operand_size (const char *templ, const char *constraint) { + + if (!templ || !constraint) { + return 0; + } + + while (*templ == ' ' || *templ == '\t') { + templ++; + } + + /* OUT always uses DX for a register port operand. */ + if (strchr (constraint, 'd')) { + return 2; + } + + /* The accumulator width is determined by the OUT mnemonic. */ + if (strchr (constraint, 'a')) { + + if (strncmp (templ, "outb ", 5) == 0) { + return 1; + } + + if (strncmp (templ, "outw ", 5) == 0) { + return 2; + } + + if (strncmp (templ, "outl ", 5) == 0) { + return 4; + } + + } + + return 0; + +} + static int inline_asm_is_reg32_name (const char *s, size_t len) { return (len == 3 && strncmp (s, "rax", 3) == 0) || @@ -33605,6 +33641,16 @@ static void inline_asm_emit_input_load (const char *constraint, int input_index, inputs[input_index].size = inline_asm_identifier_size (tok.ident); } + if (inline_asm_template_is_out (templ)) { + + int out_size = inline_asm_out_operand_size (templ, constraint); + + if (out_size) { + inputs[input_index].size = out_size; + } + + } + subst = inline_asm_reg_for_size (reg32, inputs[input_index].size); if (inline_asm_reg_needs_restore (reg32) && state->ofp) { diff --git a/i386.c b/i386.c index e7cf72e..7943747 100644 --- a/i386.c +++ b/i386.c @@ -30605,6 +30605,42 @@ static int inline_asm_template_is_out (const char *templ) { } +static int inline_asm_out_operand_size (const char *templ, const char *constraint) { + + if (!templ || !constraint) { + return 0; + } + + while (*templ == ' ' || *templ == '\t') { + templ++; + } + + /* OUT always uses DX for a register port operand. */ + if (strchr (constraint, 'd')) { + return 2; + } + + /* The accumulator width is determined by the OUT mnemonic. */ + if (strchr (constraint, 'a')) { + + if (strncmp (templ, "outb ", 5) == 0) { + return 1; + } + + if (strncmp (templ, "outw ", 5) == 0) { + return 2; + } + + if (strncmp (templ, "outl ", 5) == 0) { + return 4; + } + + } + + return 0; + +} + static int inline_asm_is_reg32_name (const char *s, size_t len) { return (len == 3 && strncmp (s, "eax", 3) == 0) || @@ -30908,6 +30944,16 @@ static void inline_asm_emit_input_load (const char *constraint, int input_index, inputs[input_index].size = inline_asm_identifier_size (tok.ident); } + if (inline_asm_template_is_out (templ)) { + + int out_size = inline_asm_out_operand_size (templ, constraint); + + if (out_size) { + inputs[input_index].size = out_size; + } + + } + subst = inline_asm_reg_for_size (reg32, inputs[input_index].size); if (inline_asm_reg_needs_restore (reg32) && state->ofp) { -- 2.34.1