summary refs log tree commit diff stats
path: root/results/classifier/zero-shot-user-mode/output/instruction/2375
diff options
context:
space:
mode:
Diffstat (limited to 'results/classifier/zero-shot-user-mode/output/instruction/2375')
-rw-r--r--results/classifier/zero-shot-user-mode/output/instruction/237591
1 files changed, 91 insertions, 0 deletions
diff --git a/results/classifier/zero-shot-user-mode/output/instruction/2375 b/results/classifier/zero-shot-user-mode/output/instruction/2375
new file mode 100644
index 00000000..e9073282
--- /dev/null
+++ b/results/classifier/zero-shot-user-mode/output/instruction/2375
@@ -0,0 +1,91 @@
+instruction: 0.376
+runtime: 0.368
+syscall: 0.256
+
+
+
+A bug in AArch64 FJCVTZS instruction
+Description of problem:
+fjcvtzs instruction converts a double-precision floating-point value in the source register into a 32-bit signed integer, and stores the result in the destination register. The contents of the FPCR register influence the exception result. Especially, when FPCR.FZ (Flushing denormalized numbers to Zero) is set and an input is a denormalized number, the PSTATE.Z flag should be cleared even if the conversion result is zero.
+
+However, because the helper function for this instruction does not properly check the denormalized case, the Z flag will have an incorrect value:
+```
+// target/arm/vfp_helper.c
+uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus)
+{
+    float_status *status = vstatus;
+    uint32_t inexact, frac;
+    uint32_t e_old, e_new;
+
+    e_old = get_float_exception_flags(status);
+    set_float_exception_flags(0, status);
+    frac = float64_to_int32_modulo(value, float_round_to_zero, status);
+    e_new = get_float_exception_flags(status);
+    set_float_exception_flags(e_old | e_new, status);
+
+    if (value == float64_chs(float64_zero)) {
+        /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
+        inexact = 1;
+    } else {
+        /* Normal inexact or overflow or NaN */
+        inexact = e_new & (float_flag_inexact | float_flag_invalid); // float_flag_input_denormal should also be checked.
+    }
+
+    /* Pack the result and the env->ZF representation of Z together.  */
+    return deposit64(frac, 32, 32, inexact);
+}
+```
+Steps to reproduce:
+1. Write `test.c`.
+```
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+char i_D27[8] = { 0x0, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0 };
+uint64_t i_fpcr = 0x01000000; // FZ = 1;
+char o_X28[8];
+uint64_t o_nzcv;
+
+void __attribute__ ((noinline)) show_state() {
+    char Z = ((o_nzcv >> 30) & 1);
+
+    printf("PSTATE.Z: %d\n", Z);
+    printf("X28: ");
+    for (int i = 0; i < 8; i++) {
+        printf("%02x ", o_X28[i]);
+    }
+    printf("\n");
+}
+
+void __attribute__ ((noinline)) run() {
+    __asm__ (
+        "adrp x29, i_D27\n"
+        "add x29, x29, :lo12:i_D27\n"
+        "ldr d27, [x29]\n"
+        "adrp x29, i_fpcr\n"
+        "add x29, x29, :lo12:i_fpcr\n"
+        "ldr x29, [x29]\n"
+        "msr fpcr, x29\n"
+        ".inst 0x1e7e037c\n" // fjcvtzs w28, d27
+        "mrs x26, nzcv\n"
+        "adrp x29, o_nzcv\n"
+        "add x29, x29, :lo12:o_nzcv\n"
+        "str x26, [x29]\n"
+        "adrp x29, o_X28\n"
+        "add x29, x29, :lo12:o_X28\n"
+        "str x28, [x29]\n"
+    );
+}
+
+int main(int argc, char **argv) {
+    run();
+    show_state();
+    return 0;
+}
+```
+2. Compile `test.bin` using this command: `aarch64-linux-gnu-gcc-12 -O2 -no-pie ./test.c -o ./test.bin`.
+3. Run QEMU using this command: `qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./test.bin`.
+4. The program, runs on top of the buggy QEMU, prints the value of Z as `01`. It should print `00` after the bug is fixed.
+Additional information:
+