aboutsummaryrefslogtreecommitdiff
path: root/py/asmthumb.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-05-07 17:24:22 +0100
committerDamien George <damien.p.george@gmail.com>2014-05-07 17:24:22 +0100
commit36db6bcf54fd32a247c85719832a9cf43e124ab5 (patch)
tree9d23c6efc069a8410d894b2a27caf88b5f2bfba8 /py/asmthumb.c
parentca25c15d560f3f5337819bac65832cccc4752495 (diff)
py, compiler: Improve passes; add an extra pass for native emitter.
Diffstat (limited to 'py/asmthumb.c')
-rw-r--r--py/asmthumb.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c
index c739a6dd2..a21a3da30 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -42,7 +42,7 @@
#define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)
struct _asm_thumb_t {
- int pass;
+ uint pass;
uint code_offset;
uint code_size;
byte *code_base;
@@ -58,14 +58,9 @@ struct _asm_thumb_t {
asm_thumb_t *asm_thumb_new(uint max_num_labels) {
asm_thumb_t *as;
- as = m_new(asm_thumb_t, 1);
- as->pass = 0;
- as->code_offset = 0;
- as->code_size = 0;
- as->code_base = NULL;
+ as = m_new0(asm_thumb_t, 1);
as->max_num_labels = max_num_labels;
as->label_offsets = m_new(int, max_num_labels);
- as->num_locals = 0;
return as;
}
@@ -89,16 +84,16 @@ void asm_thumb_free(asm_thumb_t *as, bool free_code) {
m_del_obj(asm_thumb_t, as);
}
-void asm_thumb_start_pass(asm_thumb_t *as, int pass) {
+void asm_thumb_start_pass(asm_thumb_t *as, uint pass) {
as->pass = pass;
as->code_offset = 0;
- if (pass == ASM_THUMB_PASS_2) {
+ if (pass == ASM_THUMB_PASS_COMPUTE) {
memset(as->label_offsets, -1, as->max_num_labels * sizeof(int));
}
}
void asm_thumb_end_pass(asm_thumb_t *as) {
- if (as->pass == ASM_THUMB_PASS_2) {
+ if (as->pass == ASM_THUMB_PASS_COMPUTE) {
// calculate size of code in bytes
as->code_size = as->code_offset;
as->code_base = m_new(byte, as->code_size);
@@ -120,7 +115,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
// all functions must go through this one to emit bytes
STATIC byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int num_bytes_to_write) {
//printf("emit %d\n", num_bytes_to_write);
- if (as->pass < ASM_THUMB_PASS_3) {
+ if (as->pass < ASM_THUMB_PASS_EMIT) {
as->code_offset += num_bytes_to_write;
return as->dummy_data;
} else {
@@ -224,12 +219,12 @@ void asm_thumb_exit(asm_thumb_t *as) {
void asm_thumb_label_assign(asm_thumb_t *as, uint label) {
assert(label < as->max_num_labels);
- if (as->pass == ASM_THUMB_PASS_2) {
+ if (as->pass < ASM_THUMB_PASS_EMIT) {
// assign label offset
assert(as->label_offsets[label] == -1);
as->label_offsets[label] = as->code_offset;
- } else if (as->pass == ASM_THUMB_PASS_3) {
- // ensure label offset has not changed from PASS_2 to PASS_3
+ } else {
+ // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
//printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset);
assert(as->label_offsets[label] == as->code_offset);
}
@@ -383,20 +378,35 @@ void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {
}
}
+// i32 is stored as a full word in the code, and aligned to machine-word boundary
+// TODO this is very inefficient, improve it!
+void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {
+ // align on machine-word + 2
+ if ((as->code_offset & 3) == 0) {
+ asm_thumb_op16(as, ASM_THUMB_OP_NOP);
+ }
+ // jump over the i32 value (instruction prefect adds 4 to PC)
+ asm_thumb_op16(as, OP_B_N(0));
+ // store i32 on machine-word aligned boundary
+ asm_thumb_data(as, 4, i32);
+ // do the actual load of the i32 value
+ asm_thumb_mov_reg_i32_optimised(as, reg_dest, i32);
+}
+
#define OP_STR_TO_SP_OFFSET(rlo_dest, word_offset) (0x9000 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
#define OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) {
assert(rlo_src < REG_R8);
int word_offset = as->num_locals - local_num - 1;
- assert(as->pass < ASM_THUMB_PASS_3 || word_offset >= 0);
+ assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset));
}
void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
assert(rlo_dest < REG_R8);
int word_offset = as->num_locals - local_num - 1;
- assert(as->pass < ASM_THUMB_PASS_3 || word_offset >= 0);
+ assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset));
}
@@ -405,7 +415,7 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) {
assert(rlo_dest < REG_R8);
int word_offset = as->num_locals - local_num - 1;
- assert(as->pass < ASM_THUMB_PASS_3 || word_offset >= 0);
+ assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset));
}