Mercurial > repos > blastem
diff gen_x86.c @ 15:c0f339564819
Make x86 generator generic with respect to operand size for immediate parameters.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 27 Nov 2012 22:43:32 -0800 |
parents | 2bdad0f52f42 |
children | 3e7bfde7606e |
line wrap: on
line diff
--- a/gen_x86.c Tue Nov 27 09:28:13 2012 -0800 +++ b/gen_x86.c Tue Nov 27 22:43:32 2012 -0800 @@ -29,6 +29,7 @@ #define OP_MOV_I8R 0xB0 #define OP_MOV_IR 0xB8 #define OP_RETN 0xC3 +#define OP_MOV_IEA 0xC6 #define OP_CALL 0xE8 #define OP_CALL_EA 0xFF @@ -197,79 +198,77 @@ return out; } -uint8_t * x86_i8r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, uint8_t val, uint8_t dst) +uint8_t * x86_ir(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst, uint8_t size) { - if (dst == RAX) { + uint8_t sign_extend = 0; + if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) { + sign_extend = 1; + opcode |= BIT_DIR; + } + if (size == SZ_W) { + *(out++) = PRE_SIZE; + } + if (dst == RAX && !sign_extend) { + if (size != SZ_B) { + al_opcode |= BIT_SIZE; + if (size == SZ_Q) { + *out = PRE_REX | REX_QUAD; + } + } *(out++) = al_opcode | BIT_IMMED_RAX; } else { + if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { + *out = PRE_REX; + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (dst >= R8) { + *out |= REX_RM_FIELD; + dst -= (R8 - X86_R8); + } + out++; + } if (dst >= AH && dst <= BH) { dst -= (AH-X86_AH); - } else if(dst >= R8) { - *(out++) = PRE_REX | REX_RM_FIELD; + } + if (size != SZ_B) { + opcode |= BIT_SIZE; } *(out++) = opcode; *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); } *(out++) = val; + if (size != SZ_B && !sign_extend) { + val >>= 8; + *(out++) = val; + if (size != SZ_W) { + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + } + } return out; } -uint8_t * x86_i32r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst) -{ - uint8_t sign_extend = 0; - if (val <= 0x7F && val >= -0x80) { - sign_extend = 1; - opcode |= BIT_DIR; - } - if (dst == RAX && !sign_extend) { - *(out++) = al_opcode | BIT_IMMED_RAX | BIT_SIZE; - } else { - if(dst >= R8) { - *(out++) = PRE_REX | REX_RM_FIELD; - } - *(out++) = opcode | BIT_SIZE; - *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); - } - *(out++) = val; - if (!sign_extend) { - val >>= 8; - *(out++) = val; - val >>= 8; - *(out++) = val; - val >>= 8; - *(out++) = val; - } - return out; -} uint8_t * add_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) { return x86_rr_sizedir(out, OP_ADD, src, dst, size); } -uint8_t * add_i8r(uint8_t * out, uint8_t val, uint8_t dst) +uint8_t * add_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size) { - return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst); -} - -uint8_t * add_i32r(uint8_t * out, int32_t val, uint8_t dst) -{ - return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst); + return x86_ir(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst, size); } uint8_t * or_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) { return x86_rr_sizedir(out, OP_OR, src, dst, size); } - -uint8_t * or_i8r(uint8_t * out, uint8_t val, uint8_t dst) +uint8_t * or_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size) { - return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst); -} - -uint8_t * or_i32r(uint8_t * out, int32_t val, uint8_t dst) -{ - return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst); + return x86_ir(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst, size); } uint8_t * and_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) @@ -277,14 +276,9 @@ return x86_rr_sizedir(out, OP_AND, src, dst, size); } -uint8_t * and_i8r(uint8_t * out, uint8_t val, uint8_t dst) +uint8_t * and_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size) { - return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst); -} - -uint8_t * and_i32r(uint8_t * out, int32_t val, uint8_t dst) -{ - return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst); + return x86_ir(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst, size); } uint8_t * xor_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) @@ -292,14 +286,9 @@ return x86_rr_sizedir(out, OP_XOR, src, dst, size); } -uint8_t * xor_i8r(uint8_t * out, uint8_t val, uint8_t dst) +uint8_t * xor_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size) { - return x86_i8r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst); -} - -uint8_t * xor_i32r(uint8_t * out, int32_t val, uint8_t dst) -{ - return x86_i32r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst); + return x86_ir(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst, size); } uint8_t * sub_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) @@ -307,30 +296,19 @@ return x86_rr_sizedir(out, OP_SUB, src, dst, size); } -uint8_t * sub_i8r(uint8_t * out, uint8_t val, uint8_t dst) +uint8_t * sub_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size) { - return x86_i8r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst); + return x86_ir(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst, size); } -uint8_t * sub_i32r(uint8_t * out, int32_t val, uint8_t dst) -{ - return x86_i32r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst); -} - - uint8_t * cmp_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) { return x86_rr_sizedir(out, OP_CMP, src, dst, size); } -uint8_t * cmp_i8r(uint8_t * out, uint8_t val, uint8_t dst) +uint8_t * cmp_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size) { - return x86_i8r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst); -} - -uint8_t * cmp_i32r(uint8_t * out, int32_t val, uint8_t dst) -{ - return x86_i32r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst); + return x86_ir(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst, size); } uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) @@ -358,49 +336,58 @@ return x86_rrind_sizedir(out, OP_MOV, dst, src, size, BIT_DIR); } -uint8_t * mov_i8r(uint8_t * out, uint8_t val, uint8_t dst) -{ - if (dst >= AH && dst <= BH) { - dst -= AH - X86_AH; - } else if (dst >= RSP && dst <= RDI) { - *(out++) = PRE_REX; - } else if (dst >= R8) { - *(out++) = PRE_REX | REX_RM_FIELD; - dst -= R8 - X86_R8; +uint8_t * mov_ir(uint8_t * out, int64_t val, uint8_t dst, uint8_t size) +{ + uint8_t sign_extend = 0; + if (size == SZ_Q && val <= 0x7FFFFFFF && val >= -2147483648) { + sign_extend = 1; + } + if (size == SZ_W) { + *(out++) = PRE_SIZE; } - *(out++) = OP_MOV_I8R | dst; - *(out++) = val; - return out; -} - -uint8_t * mov_i16r(uint8_t * out, uint16_t val, uint8_t dst) -{ - *(out++) = PRE_SIZE; - if (dst >= R8) { - *(out++) = PRE_REX | REX_RM_FIELD; - dst -= R8 - X86_R8; + if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { + *out = PRE_REX; + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (dst >= R8) { + *out |= REX_RM_FIELD; + dst -= (R8 - X86_R8); + } + out++; + } + if (dst >= AH && dst <= BH) { + dst -= (AH-X86_AH); } - *(out++) = OP_MOV_IR | dst; - *(out++) = val; - val >>= 8; + if (size == SZ_B) { + *(out++) = OP_MOV_I8R; + } else if (size == SZ_Q && sign_extend) { + *(out++) = OP_MOV_IEA | BIT_SIZE; + *(out++) = MODE_REG_DIRECT | dst; + } else { + *(out++) = OP_MOV_IR; + } *(out++) = val; - return out; -} - -uint8_t * mov_i32r(uint8_t * out, uint32_t val, uint8_t dst) -{ - if (dst >= R8) { - *(out++) = PRE_REX | REX_RM_FIELD; - dst -= R8 - X86_R8; + if (size != SZ_B) { + val >>= 8; + *(out++) = val; + if (size != SZ_W) { + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + if (size == SZ_Q && !sign_extend) { + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + } + } } - *(out++) = OP_MOV_IR | dst; - *(out++) = val; - val >>= 8; - *(out++) = val; - val >>= 8; - *(out++) = val; - val >>= 8; - *(out++) = val; return out; }