42 #define OPCODE_NOP (0x90) 43 #define OPCODE_PUSH_R32 (0x50) 46 #define OPCODE_POP_R32 (0x58) 47 #define OPCODE_RET (0xc3) 49 #define OPCODE_MOV_I32_TO_R32 (0xb8) 51 #define OPCODE_MOV_R8_TO_RM8 (0x88) 52 #define OPCODE_MOV_R32_TO_RM32 (0x89) 53 #define OPCODE_MOV_RM32_TO_R32 (0x8b) 54 #define OPCODE_MOVZX_RM8_TO_R32 (0xb6) 55 #define OPCODE_MOVZX_RM16_TO_R32 (0xb7) 56 #define OPCODE_LEA_MEM_TO_R32 (0x8d) 57 #define OPCODE_AND_R32_TO_RM32 (0x21) 58 #define OPCODE_OR_R32_TO_RM32 (0x09) 59 #define OPCODE_XOR_R32_TO_RM32 (0x31) 60 #define OPCODE_ADD_R32_TO_RM32 (0x01) 61 #define OPCODE_ADD_I32_TO_RM32 (0x81) 62 #define OPCODE_ADD_I8_TO_RM32 (0x83) 63 #define OPCODE_SUB_R32_FROM_RM32 (0x29) 64 #define OPCODE_SUB_I32_FROM_RM32 (0x81) 65 #define OPCODE_SUB_I8_FROM_RM32 (0x83) 69 #define OPCODE_SHL_RM32_CL (0xd3) 70 #define OPCODE_SAR_RM32_CL (0xd3) 73 #define OPCODE_CMP_R32_WITH_RM32 (0x39) 75 #define OPCODE_TEST_R8_WITH_RM8 (0x84) 76 #define OPCODE_JMP_REL8 (0xeb) 77 #define OPCODE_JMP_REL32 (0xe9) 78 #define OPCODE_JCC_REL8 (0x70) 79 #define OPCODE_JCC_REL32_A (0x0f) 80 #define OPCODE_JCC_REL32_B (0x80) 81 #define OPCODE_SETCC_RM8_A (0x0f) 82 #define OPCODE_SETCC_RM8_B (0x90) 83 #define OPCODE_CALL_REL32 (0xe8) 84 #define OPCODE_CALL_RM32 (0xff) 85 #define OPCODE_LEAVE (0xc9) 87 #define MODRM_R32(x) ((x) << 3) 88 #define MODRM_RM_DISP0 (0x00) 89 #define MODRM_RM_DISP8 (0x40) 90 #define MODRM_RM_DISP32 (0x80) 91 #define MODRM_RM_REG (0xc0) 92 #define MODRM_RM_R32(x) (x) 94 #define OP_SIZE_PREFIX (0x66) 96 #define IMM32_L0(x) ((x) & 0xff) 97 #define IMM32_L1(x) (((x) >> 8) & 0xff) 98 #define IMM32_L2(x) (((x) >> 16) & 0xff) 99 #define IMM32_L3(x) (((x) >> 24) & 0xff) 101 #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) 130 c[0] = IMM32_L0(w32);
131 c[1] = IMM32_L1(w32);
132 c[2] = IMM32_L2(w32);
133 c[3] = IMM32_L3(w32);
137 STATIC void asm_x86_write_r32_disp(
asm_x86_t *as,
int r32,
int disp_r32,
int disp_offset) {
141 asm_x86_write_byte_1(as, MODRM_R32(r32) | MODRM_RM_DISP0 | MODRM_RM_R32(disp_r32));
142 }
else if (SIGNED_FIT8(disp_offset)) {
143 asm_x86_write_byte_2(as, MODRM_R32(r32) | MODRM_RM_DISP8 | MODRM_RM_R32(disp_r32), IMM32_L0(disp_offset));
145 asm_x86_write_byte_1(as, MODRM_R32(r32) | MODRM_RM_DISP32 | MODRM_RM_R32(disp_r32));
146 asm_x86_write_word32(as, disp_offset);
150 STATIC void asm_x86_generic_r32_r32(
asm_x86_t *as,
int dest_r32,
int src_r32,
int op) {
151 asm_x86_write_byte_2(as, op, MODRM_R32(src_r32) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
155 asm_x86_write_byte_1(as, OPCODE_NOP);
159 asm_x86_write_byte_1(as, OPCODE_PUSH_R32 | src_r32);
163 void asm_x86_push_i32(
asm_x86_t *as,
int src_i32) {
164 asm_x86_write_byte_1(as, OPCODE_PUSH_I32);
165 asm_x86_write_word32(as, src_i32);
168 void asm_x86_push_disp(
asm_x86_t *as,
int src_r32,
int src_offset) {
169 asm_x86_write_byte_1(as, OPCODE_PUSH_M32);
170 asm_x86_write_r32_disp(as, 6, src_r32, src_offset);
175 asm_x86_write_byte_1(as, OPCODE_POP_R32 | dest_r32);
179 asm_x86_write_byte_1(as, OPCODE_RET);
183 asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_MOV_R32_TO_RM32);
187 asm_x86_write_byte_1(as, OPCODE_MOV_R8_TO_RM8);
188 asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp);
192 asm_x86_write_byte_2(as, OP_SIZE_PREFIX, OPCODE_MOV_R32_TO_RM32);
193 asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp);
197 asm_x86_write_byte_1(as, OPCODE_MOV_R32_TO_RM32);
198 asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp);
202 asm_x86_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM8_TO_R32);
203 asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);
207 asm_x86_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM16_TO_R32);
208 asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);
212 asm_x86_write_byte_1(as, OPCODE_MOV_RM32_TO_R32);
213 asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);
216 STATIC void asm_x86_lea_disp_to_r32(
asm_x86_t *as,
int src_r32,
int src_disp,
int dest_r32) {
217 asm_x86_write_byte_1(as, OPCODE_LEA_MEM_TO_R32);
218 asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);
222 void asm_x86_mov_i8_to_r8(
asm_x86_t *as,
int src_i8,
int dest_r32) {
223 asm_x86_write_byte_2(as, OPCODE_MOV_I8_TO_R8 | dest_r32, src_i8);
228 asm_x86_write_byte_1(as, OPCODE_MOV_I32_TO_R32 | dest_r32);
229 asm_x86_write_word32(as, src_i32);
242 asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_AND_R32_TO_RM32);
246 asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_OR_R32_TO_RM32);
250 asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_XOR_R32_TO_RM32);
254 asm_x86_generic_r32_r32(as, dest_r32, 4, OPCODE_SHL_RM32_CL);
258 asm_x86_generic_r32_r32(as, dest_r32, 7, OPCODE_SAR_RM32_CL);
262 asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_ADD_R32_TO_RM32);
265 STATIC void asm_x86_add_i32_to_r32(
asm_x86_t *as,
int src_i32,
int dest_r32) {
266 if (SIGNED_FIT8(src_i32)) {
267 asm_x86_write_byte_2(as, OPCODE_ADD_I8_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
268 asm_x86_write_byte_1(as, src_i32 & 0xff);
270 asm_x86_write_byte_2(as, OPCODE_ADD_I32_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
271 asm_x86_write_word32(as, src_i32);
276 asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_SUB_R32_FROM_RM32);
279 STATIC void asm_x86_sub_r32_i32(
asm_x86_t *as,
int dest_r32,
int src_i32) {
280 if (SIGNED_FIT8(src_i32)) {
282 asm_x86_write_byte_2(as, OPCODE_SUB_I8_FROM_RM32, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
283 asm_x86_write_byte_1(as, src_i32 & 0xff);
286 asm_x86_write_byte_2(as, OPCODE_SUB_I32_FROM_RM32, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
287 asm_x86_write_word32(as, src_i32);
293 asm_x86_write_byte_3(as, 0x0f, 0xaf, MODRM_R32(dest_r32) | MODRM_RM_REG | MODRM_RM_R32(src_r32));
298 void asm_x86_shl_r32_by_imm(
asm_x86_t *as,
int r32,
int imm) {
299 asm_x86_write_byte_2(as, OPCODE_SHL_RM32_BY_I8, MODRM_R32(4) | MODRM_RM_REG | MODRM_RM_R32(r32));
300 asm_x86_write_byte_1(as, imm);
303 void asm_x86_shr_r32_by_imm(
asm_x86_t *as,
int r32,
int imm) {
304 asm_x86_write_byte_2(as, OPCODE_SHR_RM32_BY_I8, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(r32));
305 asm_x86_write_byte_1(as, imm);
308 void asm_x86_sar_r32_by_imm(
asm_x86_t *as,
int r32,
int imm) {
309 asm_x86_write_byte_2(as, OPCODE_SAR_RM32_BY_I8, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(r32));
310 asm_x86_write_byte_1(as, imm);
315 asm_x86_write_byte_2(as, OPCODE_CMP_R32_WITH_RM32, MODRM_R32(src_r32_a) | MODRM_RM_REG | MODRM_RM_R32(src_r32_b));
319 void asm_x86_cmp_i32_with_r32(
asm_x86_t *as,
int src_i32,
int src_r32) {
320 if (SIGNED_FIT8(src_i32)) {
321 asm_x86_write_byte_2(as, OPCODE_CMP_I8_WITH_RM32, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(src_r32));
322 asm_x86_write_byte_1(as, src_i32 & 0xff);
324 asm_x86_write_byte_2(as, OPCODE_CMP_I32_WITH_RM32, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(src_r32));
325 asm_x86_write_word32(as, src_i32);
334 asm_x86_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R32(src_r32_a) | MODRM_RM_REG | MODRM_RM_R32(src_r32_b));
338 asm_x86_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r8));
342 assert(label < as->base.max_num_labels);
347 mp_uint_t dest = get_label_dest(as, label);
353 if (SIGNED_FIT8(rel)) {
354 asm_x86_write_byte_2(as, OPCODE_JMP_REL8, rel & 0xff);
363 asm_x86_write_byte_1(as, OPCODE_JMP_REL32);
364 asm_x86_write_word32(as, rel);
369 mp_uint_t dest = get_label_dest(as, label);
375 if (SIGNED_FIT8(rel)) {
376 asm_x86_write_byte_2(as, OPCODE_JCC_REL8 | jcc_type, rel & 0xff);
385 asm_x86_write_byte_2(as, OPCODE_JCC_REL32_A, OPCODE_JCC_REL32_B | jcc_type);
386 asm_x86_write_word32(as, rel);
393 if (num_locals > 0) {
407 asm_x86_write_byte_1(as, OPCODE_LEAVE);
412 void asm_x86_push_arg(
asm_x86_t *as,
int src_arg_num) {
413 asm_x86_push_disp(as,
ASM_X86_REG_EBP, 2 * WORD_SIZE + src_arg_num * WORD_SIZE);
422 void asm_x86_mov_r32_to_arg(
asm_x86_t *as,
int src_r32,
int dest_arg_num) {
438 STATIC int asm_x86_local_offset_from_ebp(
asm_x86_t *as,
int local_num) {
439 return (-as->
num_locals + local_num) * WORD_SIZE;
451 int offset = asm_x86_local_offset_from_ebp(as, local_num);
460 void asm_x86_push_local(
asm_x86_t *as,
int local_num) {
461 asm_x86_push_disp(as,
ASM_X86_REG_EBP, asm_x86_local_offset_from_ebp(as, local_num));
464 void asm_x86_push_local_addr(
asm_x86_t *as,
int local_num,
int temp_r32)
467 asm_x86_add_i32_to_r32(as, asm_x86_local_offset_from_ebp(as, local_num), temp_r32);
468 asm_x86_push_r32(as, temp_r32);
498 asm_x86_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R32(2) | MODRM_RM_REG | MODRM_RM_R32(temp_r32));
511 #endif // MICROPY_EMIT_X86 uint8_t * mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write)
void asm_x86_entry(asm_x86_t *as, mp_uint_t num_locals)
void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32)
void asm_x86_sub_r32_r32(asm_x86_t *as, int dest_r32, int src_r32)
void asm_x86_or_r32_r32(asm_x86_t *as, int dest_r32, int src_r32)
#define ASM_X86_REG_ARG_2
void asm_x86_setcc_r8(asm_x86_t *as, mp_uint_t jcc_type, int dest_r8)
void asm_x86_mul_r32_r32(asm_x86_t *as, int dest_r32, int src_r32)
void asm_x86_mov_mem16_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32)
void asm_x86_mov_r8_to_mem8(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp)
void asm_x86_test_r8_with_r8(asm_x86_t *as, int src_r32_a, int src_r32_b)
void asm_x86_mov_mem8_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32)
void asm_x86_mov_r32_r32(asm_x86_t *as, int dest_r32, int src_r32)
void asm_x86_cmp_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b)
void asm_x86_shl_r32_cl(asm_x86_t *as, int dest_r32)
void asm_x86_jcc_label(asm_x86_t *as, mp_uint_t jcc_type, mp_uint_t label)
#define ASM_X86_REG_ARG_5
void asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32)
void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32)
void asm_x86_exit(asm_x86_t *as)
#define ASM_X86_REG_ARG_3
void asm_x86_mov_local_addr_to_r32(asm_x86_t *as, int local_num, int dest_r32)
void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32)
void asm_x86_jmp_label(asm_x86_t *as, mp_uint_t label)
void asm_x86_add_r32_r32(asm_x86_t *as, int dest_r32, int src_r32)
void asm_x86_mov_i32_to_r32_aligned(asm_x86_t *as, int32_t src_i32, int dest_r32)
void asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp)
void asm_x86_mov_r16_to_mem16(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp)
void asm_x86_sar_r32_cl(asm_x86_t *as, int dest_r32)
void asm_x86_mov_local_to_r32(asm_x86_t *as, int src_local_num, int dest_r32)
#define ASM_X86_REG_ARG_1
void asm_x86_xor_r32_r32(asm_x86_t *as, int dest_r32, int src_r32)
void asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32)
#define ASM_X86_REG_ARG_4
void asm_x86_mov_r32_to_local(asm_x86_t *as, int src_r32, int dest_local_num)