diff --git a/target/i386/latx/include/reg-alloc.h b/target/i386/latx/include/reg-alloc.h index b94e905f40..4df72f831f 100644 --- a/target/i386/latx/include/reg-alloc.h +++ b/target/i386/latx/include/reg-alloc.h @@ -167,6 +167,7 @@ bool ld_imm_to_imm_reg(uint64); #define ra_free_ftemp(phy_id) RA_FREE_CODE(ftemp, phy_id) void ra_free_all(void); bool itemp_is_free(int itemp_num); +void ra_free_mem_temp(IR2_OPND opnd); IR2_OPND ra_alloc_num_4095(void); void ra_free_num_4095(IR2_OPND); void free_imm_reg(int itemp_num); diff --git a/target/i386/latx/translator/mem-interface.c b/target/i386/latx/translator/mem-interface.c index 0aca12bd6e..a1b6731759 100644 --- a/target/i386/latx/translator/mem-interface.c +++ b/target/i386/latx/translator/mem-interface.c @@ -579,7 +579,14 @@ static IR2_OPND convert_mem_helper(IR1_OPND *opnd1, IR2_OPND *arg_dest_op, } addr_size = ir1_addr_size(pir1); - return adjust_dest(dest_op, arg_dest_op, dest_size, addr_size); + IR2_OPND ret_opnd = adjust_dest(dest_op, arg_dest_op, + dest_size, addr_size); + + if (arg_dest_op && dest_need_itmp) { + ra_free_mem_temp(dest_op); + } + + return ret_opnd; } void convert_mem_to_specific_gpr(IR1_OPND *opnd, IR2_OPND dest, int dest_size) diff --git a/target/i386/latx/translator/reg-alloc.c b/target/i386/latx/translator/reg-alloc.c index c3181760ff..3c60376bd9 100644 --- a/target/i386/latx/translator/reg-alloc.c +++ b/target/i386/latx/translator/reg-alloc.c @@ -381,6 +381,13 @@ void imm_cache_free_temp_helper(IR2_OPND dest_op) imm_log("[free_temp_helper]call but not free\n"); } +void ra_free_mem_temp(IR2_OPND opnd) +{ + if (ir2_opnd_is_itemp(&opnd) && !ir2_opnd_is_imm_reg(&opnd)) { + ra_free_temp(opnd); + } +} + IR2_OPND ra_alloc_num_4095(void) { IR2_OPND num = ra_alloc_itemp(); diff --git a/target/i386/latx/translator/tr-opnd-process.c b/target/i386/latx/translator/tr-opnd-process.c index bca7bc8134..b5cbc3104f 100644 --- a/target/i386/latx/translator/tr-opnd-process.c +++ b/target/i386/latx/translator/tr-opnd-process.c @@ -248,9 +248,7 @@ void load_ireg_from_ir1_mem(IR2_OPND opnd2, IR1_OPND *opnd1, lsassert(0); } } - if (ir2_opnd_is_itemp(&mem_opnd) && !ir2_opnd_is_imm_reg(&mem_opnd)) { - ra_free_temp(mem_opnd); - } + ra_free_mem_temp(mem_opnd); } IR2_OPND load_ireg_from_ir2_mem(IR2_OPND mem_opnd, int mem_imm, int mem_size, @@ -617,9 +615,7 @@ static void store_ireg_to_ir1_mem(IR2_OPND value_opnd, IR1_OPND *opnd1, lsassert(0); } } - if (ir2_opnd_is_itemp(&mem_opnd) && !ir2_opnd_is_imm_reg(&mem_opnd)) { - ra_free_temp(mem_opnd); - } + ra_free_mem_temp(mem_opnd); } void store_ireg_to_ir1_seg(IR2_OPND seg_value_opnd, IR1_OPND *opnd1) @@ -949,6 +945,8 @@ static void load_freg_from_ir1_mem(IR2_OPND opnd2, IR1_OPND *opnd1, } else { load_64_bit_freg_from_ir1_80_bit_mem(opnd2, mem_opnd, mem_imm); } + + ra_free_mem_temp(mem_opnd); } /* Clear lsenv->mode_trans_mmx_fpu to transfer to MMX mode */ @@ -1185,6 +1183,8 @@ static void store_freg_to_ir1_mem(IR2_OPND opnd2, IR1_OPND *opnd1, } else { store_64_bit_freg_to_ir1_80_bit_mem(opnd2, mem_opnd, mem_imm); } + + ra_free_mem_temp(mem_opnd); } static void store_freg_to_ir1_gpr(IR2_OPND opnd2, IR1_OPND *opnd1) @@ -1323,6 +1323,7 @@ void load_freg128_from_ir1_mem(IR2_OPND opnd2, IR1_OPND *opnd1){ IR2_OPND mem_opnd = convert_mem(opnd1, &little_disp); gen_test_page_flag(mem_opnd, little_disp, PAGE_READ, 16); la_vld(opnd2, mem_opnd, little_disp); + ra_free_mem_temp(mem_opnd); return; } @@ -1336,6 +1337,7 @@ void store_freg128_to_ir1_mem(IR2_OPND opnd2, IR1_OPND *opnd1){ gen_test_page_flag(mem_opnd, little_disp, PAGE_WRITE | PAGE_WRITE_ORG, 16); la_vst(opnd2, mem_opnd, little_disp); + ra_free_mem_temp(mem_opnd); return; } @@ -1373,6 +1375,7 @@ void store_freg256_to_ir1_mem(IR2_OPND opnd2, IR1_OPND * opnd1) { gen_test_page_flag(mem_opnd, little_disp, PAGE_WRITE | PAGE_WRITE_ORG, 32); la_xvst(opnd2, mem_opnd, little_disp); + ra_free_mem_temp(mem_opnd); } void load_freg256_from_ir1_mem(IR2_OPND opnd2, IR1_OPND * opnd1) { @@ -1383,6 +1386,7 @@ void load_freg256_from_ir1_mem(IR2_OPND opnd2, IR1_OPND * opnd1) { IR2_OPND mem_opnd = convert_mem(opnd1, & little_disp); gen_test_page_flag(mem_opnd, little_disp, PAGE_READ, 32); la_xvld(opnd2, mem_opnd, little_disp); + ra_free_mem_temp(mem_opnd); } IR2_OPND load_freg256_from_ir1(IR1_OPND * opnd1) { diff --git a/target/i386/latx/translator/tr-pattern.c b/target/i386/latx/translator/tr-pattern.c index 55f139ae90..ee15720703 100644 --- a/target/i386/latx/translator/tr-pattern.c +++ b/target/i386/latx/translator/tr-pattern.c @@ -1247,6 +1247,8 @@ static bool translate_test_xxcc(IR1_INST *pir1) generate_eflag_calculation(src0, src0, src1, curr, true); temp = ra_alloc_itemp(); la_and(temp, src0, src1); + ra_free_temp_auto(src0); + ra_free_temp_auto(src1); } lsenv->tr_data->curr_ir1_inst = next; diff --git a/tests/integration/latx-mt-test-cmov-mem.asm b/tests/integration/latx-mt-test-cmov-mem.asm new file mode 100644 index 0000000000..e05f82779a --- /dev/null +++ b/tests/integration/latx-mt-test-cmov-mem.asm @@ -0,0 +1,24 @@ +default rel + +section .text +global _start +_start: + test byte [test_value], 0x20 + cmovne rax, [selected_value] + cmp al, 1 + jne failed + + xor edi, edi + mov eax, 60 + syscall + +failed: + mov edi, 1 + mov eax, 60 + syscall + +section .data +test_value: + db 0x20 +selected_value: + dq 1 diff --git a/tests/integration/registrations/process/meson.build b/tests/integration/registrations/process/meson.build index 1a09752481..46c3379202 100644 --- a/tests/integration/registrations/process/meson.build +++ b/tests/integration/registrations/process/meson.build @@ -99,6 +99,14 @@ if 'x86_64-linux-user' in target_dirs ], 'timeout': 90, }] + latx_integration_tests += [{ + 'name': 'test-latx-mt-test-cmov-mem', + 'runner': find_program('../../test-latx-mt-test-cmov-mem.sh'), + 'args': [ + emulators['latx-x86_64'], + files('../../latx-mt-test-cmov-mem.asm'), + ], + }] latx_integration_tests += [{ 'name': 'test-cmdline-other-task', 'runner': find_program('../../test-cmdline-other-task.sh'), diff --git a/tests/integration/test-latx-mt-test-cmov-mem.sh b/tests/integration/test-latx-mt-test-cmov-mem.sh new file mode 100755 index 0000000000..10359a6fa0 --- /dev/null +++ b/tests/integration/test-latx-mt-test-cmov-mem.sh @@ -0,0 +1,36 @@ +#!/bin/sh +set -eu + +emulator=$(readlink -f "$1") +source_file=$(readlink -f "$2") +workdir=$(mktemp -d) +trap 'rm -rf "$workdir"' EXIT HUP INT TERM + +if [ "$(getconf PAGESIZE)" != 16384 ]; then + echo "SKIP: LATX_MT requires a 16K host page" + exit 77 +fi + +if ! command -v nasm >/dev/null 2>&1; then + echo "SKIP: nasm is required to build the x86_64 guest" + exit 77 +fi + +if ! command -v ld.lld >/dev/null 2>&1; then + echo "SKIP: ld.lld is required to build the x86_64 guest" + exit 77 +fi + +guest="$workdir/latx-mt-test-cmov-mem" +nasm -f elf64 "$source_file" -o "$workdir/guest.o" +ld.lld -m elf_x86_64 -static --build-id=none "$workdir/guest.o" -o "$guest" + +for mode in 0 1 2; do + if ! LATX_AOT=0 LATX_KZT=0 LATX_MT="$mode" \ + timeout 30 "$emulator" "$guest"; then + echo "FAIL: LATX_MT=$mode did not execute TEST+CMOVcc" >&2 + exit 1 + fi +done + +echo "PASS: TEST+CMOVcc memory pair runs with LATX_MT=0/1/2"