[python] Upgrade to micropython 1.11

This commit is contained in:
Léa Saviot
2019-08-21 09:59:33 +02:00
parent 127a166762
commit 0975ba0f10
115 changed files with 4605 additions and 2450 deletions

View File

@@ -73,8 +73,10 @@
#define OPCODE_CMP_R64_WITH_RM64 (0x39) /* /r */
//#define OPCODE_CMP_RM32_WITH_R32 (0x3b)
#define OPCODE_TEST_R8_WITH_RM8 (0x84) /* /r */
#define OPCODE_TEST_R64_WITH_RM64 (0x85) /* /r */
#define OPCODE_JMP_REL8 (0xeb)
#define OPCODE_JMP_REL32 (0xe9)
#define OPCODE_JMP_RM64 (0xff) /* /4 */
#define OPCODE_JCC_REL8 (0x70) /* | jcc type */
#define OPCODE_JCC_REL32_A (0x0f)
#define OPCODE_JCC_REL32_B (0x80) /* | jcc type */
@@ -181,21 +183,22 @@ STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
*/
STATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) {
assert(disp_r64 != ASM_X64_REG_RSP);
if (disp_r64 == ASM_X64_REG_R12) {
// special case for r12; not fully implemented
assert(SIGNED_FIT8(disp_offset));
asm_x64_write_byte_3(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), 0x24, IMM32_L0(disp_offset));
return;
}
if (disp_offset == 0 && disp_r64 != ASM_X64_REG_RBP) {
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP0 | MODRM_RM_R64(disp_r64));
uint8_t rm_disp;
if (disp_offset == 0 && (disp_r64 & 7) != ASM_X64_REG_RBP) {
rm_disp = MODRM_RM_DISP0;
} else if (SIGNED_FIT8(disp_offset)) {
asm_x64_write_byte_2(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), IMM32_L0(disp_offset));
rm_disp = MODRM_RM_DISP8;
} else {
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP32 | MODRM_RM_R64(disp_r64));
rm_disp = MODRM_RM_DISP32;
}
asm_x64_write_byte_1(as, MODRM_R64(r64) | rm_disp | MODRM_RM_R64(disp_r64));
if ((disp_r64 & 7) == ASM_X64_REG_RSP) {
// Special case for rsp and r12, they need a SIB byte
asm_x64_write_byte_1(as, 0x24);
}
if (rm_disp == MODRM_RM_DISP8) {
asm_x64_write_byte_1(as, IMM32_L0(disp_offset));
} else if (rm_disp == MODRM_RM_DISP32) {
asm_x64_write_word32(as, disp_offset);
}
}
@@ -331,14 +334,16 @@ void asm_x64_mov_i8_to_r8(asm_x64_t *as, int src_i8, int dest_r64) {
}
*/
STATIC void asm_x64_mov_i32_to_r64(asm_x64_t *as, int src_i32, int dest_r64) {
size_t asm_x64_mov_i32_to_r64(asm_x64_t *as, int src_i32, int dest_r64) {
// cpu defaults to i32 to r64, with zero extension
if (dest_r64 < 8) {
asm_x64_write_byte_1(as, OPCODE_MOV_I64_TO_R64 | dest_r64);
} else {
asm_x64_write_byte_2(as, REX_PREFIX | REX_B, OPCODE_MOV_I64_TO_R64 | (dest_r64 & 7));
}
size_t loc = mp_asm_base_get_code_pos(&as->base);
asm_x64_write_word32(as, src_i32);
return loc;
}
void asm_x64_mov_i64_to_r64(asm_x64_t *as, int64_t src_i64, int dest_r64) {
@@ -361,15 +366,6 @@ void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r
}
}
// src_i64 is stored as a full word in the code, and aligned to machine-word boundary
void asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64) {
// mov instruction uses 2 bytes for the instruction, before the i64
while (((as->base.code_offset + 2) & (WORD_SIZE - 1)) != 0) {
asm_x64_nop(as);
}
asm_x64_mov_i64_to_r64(as, src_i64, dest_r64);
}
void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {
asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_AND_R64_TO_RM64);
}
@@ -465,17 +461,25 @@ void asm_x64_cmp_i32_with_r32(asm_x64_t *as, int src_i32, int src_r32) {
*/
void asm_x64_test_r8_with_r8(asm_x64_t *as, int src_r64_a, int src_r64_b) {
// TODO implement for other registers
assert(src_r64_a == ASM_X64_REG_RAX);
assert(src_r64_b == ASM_X64_REG_RAX);
assert(src_r64_a < 8);
assert(src_r64_b < 8);
asm_x64_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R64(src_r64_a) | MODRM_RM_REG | MODRM_RM_R64(src_r64_b));
}
void asm_x64_test_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b) {
asm_x64_generic_r64_r64(as, src_r64_b, src_r64_a, OPCODE_TEST_R64_WITH_RM64);
}
void asm_x64_setcc_r8(asm_x64_t *as, int jcc_type, int dest_r8) {
assert(dest_r8 < 8);
asm_x64_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R64(0) | MODRM_RM_REG | MODRM_RM_R64(dest_r8));
}
void asm_x64_jmp_reg(asm_x64_t *as, int src_r64) {
assert(src_r64 < 8);
asm_x64_write_byte_2(as, OPCODE_JMP_RM64, MODRM_R64(4) | MODRM_RM_REG | MODRM_RM_R64(src_r64));
}
STATIC mp_uint_t get_label_dest(asm_x64_t *as, mp_uint_t label) {
assert(label < as->base.max_num_labels);
return as->base.label_offsets[label];
@@ -528,63 +532,72 @@ void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) {
void asm_x64_entry(asm_x64_t *as, int num_locals) {
assert(num_locals >= 0);
asm_x64_push_r64(as, ASM_X64_REG_RBP);
asm_x64_mov_r64_r64(as, ASM_X64_REG_RBP, ASM_X64_REG_RSP);
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
asm_x64_push_r64(as, ASM_X64_REG_RBX);
asm_x64_push_r64(as, ASM_X64_REG_R12);
asm_x64_push_r64(as, ASM_X64_REG_R13);
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
as->num_locals = num_locals;
}
void asm_x64_exit(asm_x64_t *as) {
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, -as->num_locals * WORD_SIZE);
asm_x64_pop_r64(as, ASM_X64_REG_R13);
asm_x64_pop_r64(as, ASM_X64_REG_R12);
asm_x64_pop_r64(as, ASM_X64_REG_RBX);
asm_x64_write_byte_1(as, OPCODE_LEAVE);
asm_x64_pop_r64(as, ASM_X64_REG_RBP);
asm_x64_ret(as);
}
// locals:
// - stored on the stack in ascending order
// - numbered 0 through as->num_locals-1
// - RBP points above the last local
// - RSP points to the first local
//
// | RBP
// v
// | RSP
// v
// l0 l1 l2 ... l(n-1)
// ^ ^
// | low address | high address in RAM
//
STATIC int asm_x64_local_offset_from_ebp(asm_x64_t *as, int local_num) {
return (-as->num_locals + local_num) * WORD_SIZE;
STATIC int asm_x64_local_offset_from_rsp(asm_x64_t *as, int local_num) {
(void)as;
// Stack is full descending, RSP points to local0
return local_num * WORD_SIZE;
}
void asm_x64_mov_local_to_r64(asm_x64_t *as, int src_local_num, int dest_r64) {
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, src_local_num), dest_r64);
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, src_local_num), dest_r64);
}
void asm_x64_mov_r64_to_local(asm_x64_t *as, int src_r64, int dest_local_num) {
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, dest_local_num));
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, dest_local_num));
}
void asm_x64_mov_local_addr_to_r64(asm_x64_t *as, int local_num, int dest_r64) {
int offset = asm_x64_local_offset_from_ebp(as, local_num);
int offset = asm_x64_local_offset_from_rsp(as, local_num);
if (offset == 0) {
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RBP);
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RSP);
} else {
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RBP, offset, dest_r64);
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RSP, offset, dest_r64);
}
}
void asm_x64_mov_reg_pcrel(asm_x64_t *as, int dest_r64, mp_uint_t label) {
mp_uint_t dest = get_label_dest(as, label);
mp_int_t rel = dest - (as->base.code_offset + 7);
asm_x64_write_byte_3(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64), OPCODE_LEA_MEM_TO_R64, MODRM_R64(dest_r64) | MODRM_RM_R64(5));
asm_x64_write_word32(as, rel);
}
/*
void asm_x64_push_local(asm_x64_t *as, int local_num) {
asm_x64_push_disp(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, local_num));
asm_x64_push_disp(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, local_num));
}
void asm_x64_push_local_addr(asm_x64_t *as, int local_num, int temp_r64) {
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RBP);
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_ebp(as, local_num), temp_r64);
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RSP);
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_rsp(as, local_num), temp_r64);
asm_x64_push_r64(as, temp_r64);
}
*/
@@ -610,21 +623,10 @@ void asm_x64_call_i1(asm_x64_t *as, void* func, int i1) {
}
*/
void asm_x64_call_ind(asm_x64_t *as, void *ptr, int temp_r64) {
void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r64) {
assert(temp_r64 < 8);
#ifdef __LP64__
asm_x64_mov_i64_to_r64_optimised(as, (int64_t)ptr, temp_r64);
#else
// If we get here, sizeof(int) == sizeof(void*).
asm_x64_mov_i64_to_r64_optimised(as, (int64_t)(unsigned int)ptr, temp_r64);
#endif
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_FUN_TABLE, fun_id * WORD_SIZE, temp_r64);
asm_x64_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R64(2) | MODRM_RM_REG | MODRM_RM_R64(temp_r64));
// this reduces code size by 2 bytes per call, but doesn't seem to speed it up at all
// doesn't work anymore because calls are 64 bits away
/*
asm_x64_write_byte_1(as, OPCODE_CALL_REL32);
asm_x64_write_word32(as, ptr - (void*)(as->code_base + as->code_offset + 4));
*/
}
#endif // MICROPY_EMIT_X64