summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2020-12-14 13:26:33 -0500
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:26 -0400
commit868a6809e7d15b95f14bff822268e2962747fb06 (patch)
treee66e2b51d3e3fe105c1d07e9235a94c9788a2645
parent8ae354e9bedbe5995e97206b170f3e406fc5b617 (diff)
Add sign-extended mode for test() instruction
-rw-r--r--ujit_asm.c34
-rw-r--r--ujit_asm_tests.c1
2 files changed, 24 insertions, 11 deletions
diff --git a/ujit_asm.c b/ujit_asm.c
index 4cb7bb7caa..4fb0cc764a 100644
--- a/ujit_asm.c
+++ b/ujit_asm.c
@@ -1516,22 +1516,34 @@ void test(codeblock_t* cb, x86opnd_t rm_opnd, x86opnd_t test_opnd)
if (test_opnd.type == OPND_IMM)
{
x86opnd_t imm_opnd = test_opnd;
- assert (imm_opnd.as.imm >= 0);
- assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= 32);
- assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= rm_opnd.num_bits);
- // Use the smallest operand size possible
- rm_opnd = resize_opnd(rm_opnd, unsig_imm_size(imm_opnd.as.unsig_imm));
-
- if (rm_opnd.num_bits == 8)
+ if (imm_opnd.as.imm >= 0)
{
- cb_write_rm(cb, false, false, NO_OPND, rm_opnd, 0x00, 1, 0xF6);
- cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits);
+ assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= 32);
+ assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= rm_opnd.num_bits);
+
+ // Use the smallest operand size possible
+ rm_opnd = resize_opnd(rm_opnd, unsig_imm_size(imm_opnd.as.unsig_imm));
+
+ if (rm_opnd.num_bits == 8)
+ {
+ cb_write_rm(cb, false, false, NO_OPND, rm_opnd, 0x00, 1, 0xF6);
+ cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits);
+ }
+ else
+ {
+ cb_write_rm(cb, rm_opnd.num_bits == 16, false, NO_OPND, rm_opnd, 0x00, 1, 0xF7);
+ cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits);
+ }
}
else
{
- cb_write_rm(cb, rm_opnd.num_bits == 16, false, NO_OPND, rm_opnd, 0x00, 1, 0xF7);
- cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits);
+ // This mode only applies to 64-bit R/M operands with 32-bit signed immediates
+ assert (imm_opnd.as.imm < 0);
+ assert (sig_imm_size(imm_opnd.as.imm) <= 32);
+ assert (rm_opnd.num_bits == 64);
+ cb_write_rm(cb, false, true, NO_OPND, rm_opnd, 0x00, 1, 0xF7);
+ cb_write_int(cb, imm_opnd.as.imm, 32);
}
}
else
diff --git a/ujit_asm_tests.c b/ujit_asm_tests.c
index 532fb5367c..8f2fbdfcbf 100644
--- a/ujit_asm_tests.c
+++ b/ujit_asm_tests.c
@@ -315,6 +315,7 @@ void run_tests()
cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, 16), imm_opnd(1)); check_bytes(cb, "F6461001");
cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, -16), imm_opnd(1)); check_bytes(cb, "F646F001");
cb_set_pos(cb, 0); test(cb, mem_opnd(32, RSI, 64), EAX); check_bytes(cb, "854640");
+ cb_set_pos(cb, 0); test(cb, mem_opnd(64, RSI, 64), imm_opnd(~0x08)); check_bytes(cb, "48F74640F7FFFFFF");
// xor
cb_set_pos(cb, 0); xor(cb, EAX, EAX); check_bytes(cb, "31C0");