mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-30 04:00:02 +02:00
[python] Upgrade to micropython 1.11
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user