py/asm: Remove need for dummy_data when doing initial assembler passes.

For all but the last pass the assembler only needs to count how much space
is needed for the machine code, it doesn't actually need to emit anything.
The dummy_data just uses unnecessary RAM and without it the code is not
any more complex (and code size does not increase for Thumb and Xtensa
archs).
This commit is contained in:
Damien George 2016-12-09 22:50:58 +11:00
parent e920bab976
commit 155fdc74d5
9 changed files with 84 additions and 62 deletions

View File

@ -55,7 +55,10 @@ void asm_arm_end_pass(asm_arm_t *as) {
// Insert word into instruction flow // Insert word into instruction flow
STATIC void emit(asm_arm_t *as, uint op) { STATIC void emit(asm_arm_t *as, uint op) {
*(uint*)asm_arm_get_cur_to_write_bytes(as, 4) = op; uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);
if (c != NULL) {
*(uint32_t*)c = op;
}
} }
// Insert word into instruction flow, add "ALWAYS" condition code // Insert word into instruction flow, add "ALWAYS" condition code

View File

@ -59,18 +59,17 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) {
} }
// all functions must go through this one to emit bytes // all functions must go through this one to emit bytes
// if as->pass < MP_ASM_PASS_EMIT, then this function returns dummy_data // if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number
// of bytes needed and returns NULL, and callers should not store any data
uint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write) { uint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write) {
if (as->pass < MP_ASM_PASS_EMIT) { uint8_t *c = NULL;
as->code_offset += num_bytes_to_write; if (as->pass == MP_ASM_PASS_EMIT) {
return as->dummy_data;
} else {
assert(as->code_offset + num_bytes_to_write <= as->code_size); assert(as->code_offset + num_bytes_to_write <= as->code_size);
uint8_t *c = as->code_base + as->code_offset; c = as->code_base + as->code_offset;
}
as->code_offset += num_bytes_to_write; as->code_offset += num_bytes_to_write;
return c; return c;
} }
}
void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) { void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) {
assert(label < as->max_num_labels); assert(label < as->max_num_labels);
@ -92,8 +91,7 @@ void mp_asm_base_align(mp_asm_base_t* as, unsigned int align) {
// this function assumes a little endian machine // this function assumes a little endian machine
void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val) { void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val) {
uint8_t *c = mp_asm_base_get_cur_to_write_bytes(as, bytesize); uint8_t *c = mp_asm_base_get_cur_to_write_bytes(as, bytesize);
// only write to the buffer in the emit pass (otherwise we may overflow dummy_data) if (c != NULL) {
if (as->pass == MP_ASM_PASS_EMIT) {
for (unsigned int i = 0; i < bytesize; i++) { for (unsigned int i = 0; i < bytesize; i++) {
*c++ = val; *c++ = val;
val >>= 8; val >>= 8;

View File

@ -40,9 +40,6 @@ typedef struct _mp_asm_base_t {
size_t max_num_labels; size_t max_num_labels;
size_t *label_offsets; size_t *label_offsets;
// must be last in struct
uint8_t dummy_data[4];
} mp_asm_base_t; } mp_asm_base_t;
void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels); void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels);

View File

@ -162,19 +162,23 @@ STATIC mp_uint_t get_label_dest(asm_thumb_t *as, uint label) {
void asm_thumb_op16(asm_thumb_t *as, uint op) { void asm_thumb_op16(asm_thumb_t *as, uint op) {
byte *c = asm_thumb_get_cur_to_write_bytes(as, 2); byte *c = asm_thumb_get_cur_to_write_bytes(as, 2);
if (c != NULL) {
// little endian // little endian
c[0] = op; c[0] = op;
c[1] = op >> 8; c[1] = op >> 8;
} }
}
void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) { void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) {
byte *c = asm_thumb_get_cur_to_write_bytes(as, 4); byte *c = asm_thumb_get_cur_to_write_bytes(as, 4);
if (c != NULL) {
// little endian, op1 then op2 // little endian, op1 then op2
c[0] = op1; c[0] = op1;
c[1] = op1 >> 8; c[1] = op1 >> 8;
c[2] = op2; c[2] = op2;
c[3] = op2 >> 8; c[3] = op2 >> 8;
} }
}
#define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest)) #define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest))

View File

@ -122,32 +122,41 @@ static inline byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int n) {
STATIC void asm_x64_write_byte_1(asm_x64_t *as, byte b1) { STATIC void asm_x64_write_byte_1(asm_x64_t *as, byte b1) {
byte* c = asm_x64_get_cur_to_write_bytes(as, 1); byte* c = asm_x64_get_cur_to_write_bytes(as, 1);
if (c != NULL) {
c[0] = b1; c[0] = b1;
} }
}
STATIC void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) { STATIC void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) {
byte* c = asm_x64_get_cur_to_write_bytes(as, 2); byte* c = asm_x64_get_cur_to_write_bytes(as, 2);
if (c != NULL) {
c[0] = b1; c[0] = b1;
c[1] = b2; c[1] = b2;
} }
}
STATIC void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) { STATIC void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) {
byte* c = asm_x64_get_cur_to_write_bytes(as, 3); byte* c = asm_x64_get_cur_to_write_bytes(as, 3);
if (c != NULL) {
c[0] = b1; c[0] = b1;
c[1] = b2; c[1] = b2;
c[2] = b3; c[2] = b3;
} }
}
STATIC void asm_x64_write_word32(asm_x64_t *as, int w32) { STATIC void asm_x64_write_word32(asm_x64_t *as, int w32) {
byte* c = asm_x64_get_cur_to_write_bytes(as, 4); byte* c = asm_x64_get_cur_to_write_bytes(as, 4);
if (c != NULL) {
c[0] = IMM32_L0(w32); c[0] = IMM32_L0(w32);
c[1] = IMM32_L1(w32); c[1] = IMM32_L1(w32);
c[2] = IMM32_L2(w32); c[2] = IMM32_L2(w32);
c[3] = IMM32_L3(w32); c[3] = IMM32_L3(w32);
} }
}
STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) { STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) {
byte* c = asm_x64_get_cur_to_write_bytes(as, 8); byte* c = asm_x64_get_cur_to_write_bytes(as, 8);
if (c != NULL) {
c[0] = IMM32_L0(w64); c[0] = IMM32_L0(w64);
c[1] = IMM32_L1(w64); c[1] = IMM32_L1(w64);
c[2] = IMM32_L2(w64); c[2] = IMM32_L2(w64);
@ -157,6 +166,7 @@ STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) {
c[6] = IMM64_L6(w64); c[6] = IMM64_L6(w64);
c[7] = IMM64_L7(w64); c[7] = IMM64_L7(w64);
} }
}
/* unused /* unused
STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) { STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {

View File

@ -72,7 +72,6 @@
typedef struct _asm_x64_t { typedef struct _asm_x64_t {
mp_asm_base_t base; mp_asm_base_t base;
byte dummy_data[4]; // in addition to dummy_data in base
int num_locals; int num_locals;
} asm_x64_t; } asm_x64_t;

View File

@ -101,30 +101,38 @@
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
STATIC void asm_x86_write_byte_1(asm_x86_t *as, byte b1) { STATIC void asm_x86_write_byte_1(asm_x86_t *as, byte b1) {
byte* c = asm_x86_get_cur_to_write_bytes(as, 1); byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 1);
if (c != NULL) {
c[0] = b1; c[0] = b1;
} }
}
STATIC void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) { STATIC void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) {
byte* c = asm_x86_get_cur_to_write_bytes(as, 2); byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2);
if (c != NULL) {
c[0] = b1; c[0] = b1;
c[1] = b2; c[1] = b2;
} }
}
STATIC void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) { STATIC void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) {
byte* c = asm_x86_get_cur_to_write_bytes(as, 3); byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3);
if (c != NULL) {
c[0] = b1; c[0] = b1;
c[1] = b2; c[1] = b2;
c[2] = b3; c[2] = b3;
} }
}
STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) { STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) {
byte* c = asm_x86_get_cur_to_write_bytes(as, 4); byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);
if (c != NULL) {
c[0] = IMM32_L0(w32); c[0] = IMM32_L0(w32);
c[1] = IMM32_L1(w32); c[1] = IMM32_L1(w32);
c[2] = IMM32_L2(w32); c[2] = IMM32_L2(w32);
c[3] = IMM32_L3(w32); c[3] = IMM32_L3(w32);
} }
}
STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) { STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) {
assert(disp_r32 != ASM_X86_REG_ESP); assert(disp_r32 != ASM_X86_REG_ESP);

View File

@ -75,7 +75,6 @@
typedef struct _asm_x86_t { typedef struct _asm_x86_t {
mp_asm_base_t base; mp_asm_base_t base;
byte dummy_data[4]; // in addition to dummy_data in base
int num_locals; int num_locals;
} asm_x86_t; } asm_x86_t;

View File

@ -97,16 +97,20 @@ STATIC uint32_t get_label_dest(asm_xtensa_t *as, uint label) {
void asm_xtensa_op16(asm_xtensa_t *as, uint16_t op) { void asm_xtensa_op16(asm_xtensa_t *as, uint16_t op) {
uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2); uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2);
if (c != NULL) {
c[0] = op; c[0] = op;
c[1] = op >> 8; c[1] = op >> 8;
} }
}
void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op) { void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op) {
uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3); uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3);
if (c != NULL) {
c[0] = op; c[0] = op;
c[1] = op >> 8; c[1] = op >> 8;
c[2] = op >> 16; c[2] = op >> 16;
} }
}
void asm_xtensa_j_label(asm_xtensa_t *as, uint label) { void asm_xtensa_j_label(asm_xtensa_t *as, uint label) {
uint32_t dest = get_label_dest(as, label); uint32_t dest = get_label_dest(as, label);
@ -147,7 +151,7 @@ void asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) {
// load the constant // load the constant
asm_xtensa_op_l32r(as, reg_dest, as->base.code_offset, 4 + as->cur_const * WORD_SIZE); asm_xtensa_op_l32r(as, reg_dest, as->base.code_offset, 4 + as->cur_const * WORD_SIZE);
// store the constant in the table // store the constant in the table
if (as->base.pass == MP_ASM_PASS_EMIT) { if (as->const_table != NULL) {
as->const_table[as->cur_const] = i32; as->const_table[as->cur_const] = i32;
} }
++as->cur_const; ++as->cur_const;