target/i386: Incorrect TCG translation of rcr instruction
## Host environment - Operating system: Linux - OS/kernel version: Linux simon-macbookpro 6.19.11+ #1 SMP PREEMPT_DYNAMIC Wed Apr 8 12:57:43 CEST 2026 aarch64 GNU/Linux - Architecture: ARM - QEMU flavor: qemu-x86_64 - QEMU version: qemu-x86_64 master branch (commit aa15257174da180c6a8a9d58f87319cfe61c5520) ## Emulated/Virtualized environment - Operating system: Linux - Architecture: x86 ## Description of problem When executing the x86 `rcr` instruction on an 8-bit register on an ARM64 host, a specific edge case in the translation logic causes an integer underflow resulting in an incorrect value for the target register. This occurs when the rotation count modulo 9 equals exactly 0 (e.g., a shift count of 9). Because `rcr` on an 8-bit register operates as a 9-bit circular buffer (8-bit register + 1 bit Carry Flag), any rotation count of 9 or higher wraps around. Hence executing, e.g., `rcr bh, 9` should **not** alter the target register `bh`. However qemu generates the following TCG code: ``` ---- 0000555555555143 0000000000000000 0000000000000000 mov_i64 loc0,$0xdeadbeef mov_i64 rbx,loc0 ---- 000055555555514d 0000000000000000 0000000000000000 extract_i64 loc0,rbx,$0x8,$0x8 mov_i64 loc1,$0x9 mov_i64 loc15,$0x9 add_i64 loc19,loc15,$0xffffffffffffffee movcond_i64 loc15,loc19,$0x0,loc19,loc15,ge add_i64 loc19,loc15,$0xfffffffffffffff7 movcond_i64 loc15,loc19,$0x0,loc19,loc15,ge mov_i64 loc23,cc_src deposit_i64 loc17,loc23,loc0,$0x1,$0x3f add_i64 loc15,loc15,$0xffffffffffffffff ``` Before the last line, the modulo logic successfully reduces `loc15` to `0`. Therefore, the `add_i64` instruction adds `-1`, **underflowing** `loc15` to `-1`. The subsequent TCG code will therefore use the underflowed `loc15` and produce a wrong result: ``` shr_i64 loc16,loc0,loc15 extract_i64 loc22,loc16,$0x0,$0x1 shr_i64 loc16,loc16,$0x1 xor_i64 loc18,loc15,$0x7 shl_i64 loc17,loc17,loc18 mov_i64 loc24,loc0 or_i64 loc0,loc16,loc17 xor_i64 loc24,loc24,loc0 extract_i64 loc24,loc24,$0x7,$0x1 deposit_i64 rbx,rbx,loc0,$0x8,$0x8 mov_i64 cc_dst,loc22 mov_i64 cc_src,loc23 mov_i64 cc_src2,loc24 ``` ## Steps to reproduce 1. Execute `qemu-x86_64` with the following C program: ```c #include <stdint.h> #include <stdio.h> int main() { uint64_t final_rbx; __asm__ __volatile__(".intel_syntax noprefix\n\t" "push rbx;" "clc;" "mov rbx, 0xdeadbeef;" "rcr bh, 9;" "mov %0, rbx;" "pop rbx;" ".att_syntax prefix\n\t" : "=r"(final_rbx) : : "cc"); printf("RBX: 0x%lx\n", final_rbx); return 0; } ``` 2. Observe that `RBX: 0xdead00ef` is printed instead of the correct result `RBX: 0xdeadbeef`!
issue