4242#define SIGNED_FIT12 (x ) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)
4343
4444struct _asm_thumb_t {
45- int pass ;
45+ uint pass ;
4646 uint code_offset ;
4747 uint code_size ;
4848 byte * code_base ;
@@ -58,14 +58,9 @@ struct _asm_thumb_t {
5858asm_thumb_t * asm_thumb_new (uint max_num_labels ) {
5959 asm_thumb_t * as ;
6060
61- as = m_new (asm_thumb_t , 1 );
62- as -> pass = 0 ;
63- as -> code_offset = 0 ;
64- as -> code_size = 0 ;
65- as -> code_base = NULL ;
61+ as = m_new0 (asm_thumb_t , 1 );
6662 as -> max_num_labels = max_num_labels ;
6763 as -> label_offsets = m_new (int , max_num_labels );
68- as -> num_locals = 0 ;
6964
7065 return as ;
7166}
@@ -89,16 +84,16 @@ void asm_thumb_free(asm_thumb_t *as, bool free_code) {
8984 m_del_obj (asm_thumb_t , as );
9085}
9186
92- void asm_thumb_start_pass (asm_thumb_t * as , int pass ) {
87+ void asm_thumb_start_pass (asm_thumb_t * as , uint pass ) {
9388 as -> pass = pass ;
9489 as -> code_offset = 0 ;
95- if (pass == ASM_THUMB_PASS_2 ) {
90+ if (pass == ASM_THUMB_PASS_COMPUTE ) {
9691 memset (as -> label_offsets , -1 , as -> max_num_labels * sizeof (int ));
9792 }
9893}
9994
10095void asm_thumb_end_pass (asm_thumb_t * as ) {
101- if (as -> pass == ASM_THUMB_PASS_2 ) {
96+ if (as -> pass == ASM_THUMB_PASS_COMPUTE ) {
10297 // calculate size of code in bytes
10398 as -> code_size = as -> code_offset ;
10499 as -> code_base = m_new (byte , as -> code_size );
@@ -120,7 +115,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
120115// all functions must go through this one to emit bytes
121116STATIC byte * asm_thumb_get_cur_to_write_bytes (asm_thumb_t * as , int num_bytes_to_write ) {
122117 //printf("emit %d\n", num_bytes_to_write);
123- if (as -> pass < ASM_THUMB_PASS_3 ) {
118+ if (as -> pass < ASM_THUMB_PASS_EMIT ) {
124119 as -> code_offset += num_bytes_to_write ;
125120 return as -> dummy_data ;
126121 } else {
@@ -224,12 +219,12 @@ void asm_thumb_exit(asm_thumb_t *as) {
224219
225220void asm_thumb_label_assign (asm_thumb_t * as , uint label ) {
226221 assert (label < as -> max_num_labels );
227- if (as -> pass == ASM_THUMB_PASS_2 ) {
222+ if (as -> pass < ASM_THUMB_PASS_EMIT ) {
228223 // assign label offset
229224 assert (as -> label_offsets [label ] == -1 );
230225 as -> label_offsets [label ] = as -> code_offset ;
231- } else if ( as -> pass == ASM_THUMB_PASS_3 ) {
232- // ensure label offset has not changed from PASS_2 to PASS_3
226+ } else {
227+ // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
233228 //printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset);
234229 assert (as -> label_offsets [label ] == as -> code_offset );
235230 }
@@ -383,20 +378,35 @@ void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {
383378 }
384379}
385380
381+ // i32 is stored as a full word in the code, and aligned to machine-word boundary
382+ // TODO this is very inefficient, improve it!
383+ void asm_thumb_mov_reg_i32_aligned (asm_thumb_t * as , uint reg_dest , int i32 ) {
384+ // align on machine-word + 2
385+ if ((as -> code_offset & 3 ) == 0 ) {
386+ asm_thumb_op16 (as , ASM_THUMB_OP_NOP );
387+ }
388+ // jump over the i32 value (instruction prefect adds 4 to PC)
389+ asm_thumb_op16 (as , OP_B_N (0 ));
390+ // store i32 on machine-word aligned boundary
391+ asm_thumb_data (as , 4 , i32 );
392+ // do the actual load of the i32 value
393+ asm_thumb_mov_reg_i32_optimised (as , reg_dest , i32 );
394+ }
395+
386396#define OP_STR_TO_SP_OFFSET (rlo_dest , word_offset ) (0x9000 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
387397#define OP_LDR_FROM_SP_OFFSET (rlo_dest , word_offset ) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
388398
389399void asm_thumb_mov_local_reg (asm_thumb_t * as , int local_num , uint rlo_src ) {
390400 assert (rlo_src < REG_R8 );
391401 int word_offset = as -> num_locals - local_num - 1 ;
392- assert (as -> pass < ASM_THUMB_PASS_3 || word_offset >= 0 );
402+ assert (as -> pass < ASM_THUMB_PASS_EMIT || word_offset >= 0 );
393403 asm_thumb_op16 (as , OP_STR_TO_SP_OFFSET (rlo_src , word_offset ));
394404}
395405
396406void asm_thumb_mov_reg_local (asm_thumb_t * as , uint rlo_dest , int local_num ) {
397407 assert (rlo_dest < REG_R8 );
398408 int word_offset = as -> num_locals - local_num - 1 ;
399- assert (as -> pass < ASM_THUMB_PASS_3 || word_offset >= 0 );
409+ assert (as -> pass < ASM_THUMB_PASS_EMIT || word_offset >= 0 );
400410 asm_thumb_op16 (as , OP_LDR_FROM_SP_OFFSET (rlo_dest , word_offset ));
401411}
402412
@@ -405,7 +415,7 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
405415void asm_thumb_mov_reg_local_addr (asm_thumb_t * as , uint rlo_dest , int local_num ) {
406416 assert (rlo_dest < REG_R8 );
407417 int word_offset = as -> num_locals - local_num - 1 ;
408- assert (as -> pass < ASM_THUMB_PASS_3 || word_offset >= 0 );
418+ assert (as -> pass < ASM_THUMB_PASS_EMIT || word_offset >= 0 );
409419 asm_thumb_op16 (as , OP_ADD_REG_SP_OFFSET (rlo_dest , word_offset ));
410420}
411421
0 commit comments