From 0f69801b6d9cdf41f62abdb59597862d5f9ccf13 Mon Sep 17 00:00:00 2001 From: Alvin Cheng Date: Wed, 1 Jan 2025 20:17:57 +1100 Subject: [PATCH] Revised `op_write_opcode` function (#25) * Revised `op_write_opcode` function Happy new year, this pull has revised the `op_write_opcode` function, which was previously mis-interpreted. According to the Intel x86 docs, a instruction **including** a byte-sized operand **MUST** use the byte instruction opcode. This is demonstrated in the MOVZX instruction's docs on 4-136 Vol. 2B where a seperate opcode is used with `r/m8`. * Added *normal* opcode In the previous commit, 20efed7a2b1d9a01591cbbd5c39b248184e9106b, I've forgotten to return the normal opcode (Slap slap) which caused some of the unit tests to fail where the normal operands are given. --- libjas/operand.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/libjas/operand.c b/libjas/operand.c index b83a46d..0aaa040 100644 --- a/libjas/operand.c +++ b/libjas/operand.c @@ -64,26 +64,15 @@ uint8_t op_sizeof(enum operands input) { return 0; } +/* Instructions containing a byte-sized operand uses the byte opcode (see. 4-136 Vol. 2B, MOVZX—Move With Zero-Extend) */ uint8_t *op_write_opcode(operand_t *op_arr, instr_encode_table_t *instr_ref) { if (!instr_ref->has_byte_opcode) return instr_ref->opcode; - - // According to Oracle's - // (Yeah seriously - Oracle has a x86 Assembly Language Reference Manual) - // Only when *BOTH* operands are byte-sized, the opcode will also be byte-sized - // So, wel'll check if they are *BOTH* byte sized then write that. - - const uint8_t reference = op_sizeof(op_arr[0].type); - const uint8_t sizes[] = - {reference, op_sizeof(op_arr[1].type), - op_sizeof(op_arr[2].type), op_sizeof(op_arr[3].type)}; - - bool sizes_are_byte = reference == 8; - for (unsigned char i = 0; i < 4; i++) { + for (uint8_t i = 0; i < 4; i++) { if (op_arr[i].type == OP_NULL) break; - if (sizes[i] != 8 && sizes_are_byte) sizes_are_byte = false; + if (op_byte(op_arr[i].type)) return instr_ref->byte_instr_opcode; + continue; } - if (sizes_are_byte) return instr_ref->byte_instr_opcode; return instr_ref->opcode; }