Fixed inline assembly operand sizes for out instructions
authorRobert Pengelly <robertapengelly@hotmail.com>
Wed, 16 Sep 2026 02:51:12 +0000 (03:51 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Wed, 16 Sep 2026 02:51:12 +0000 (03:51 +0100)
amd64.c
i386.c

diff --git a/amd64.c b/amd64.c
index 92b2384206a409dea8d59dc78d5ab21fd6a59a10..1a1b049d888894d40451b6c426c85c822f96f8ac 100644 (file)
--- 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 e7cf72e68ddbdd1eed703f609f1daaebeb0fcb48..79437479990562bd162d1658b2f56135ef686889 100644 (file)
--- 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) {