diff options
author | Camil Staps | 2016-10-02 12:05:50 +0000 |
---|---|---|
committer | Camil Staps | 2016-10-02 12:05:50 +0000 |
commit | 5effb5bfcaf95ad12e42a298c2306fab36dd402e (patch) | |
tree | e774eba7f4545701be6a22fa182113b2758685a8 | |
parent | Add .align before pushing program counter (diff) |
Fix storing the program counter
The previous solution was to add 9 (8 for the offset, 1 for the Thumb
state). However, the lowest bit is used for something else (garbage
collection / evaluation status), so this gives some problems.
This solution adds only 8 (the offset), so that we don't alter the
lowest two bits. Then, when jumping, the address is IORed with 1, so
that the Thumb state bit is set.
-rw-r--r-- | cgthumb2was.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/cgthumb2was.c b/cgthumb2was.c index 334bd16..4881263 100644 --- a/cgthumb2was.c +++ b/cgthumb2was.c @@ -1486,7 +1486,7 @@ static void w_as_jsr_instruction (struct instruction *instruction) case P_INDIRECT_WITH_UPDATE: w_as_instruction_without_parameters (".align"); w_as_opcode ("add"); - fprintf (assembly_file,"lr,pc,#9"); + fprintf (assembly_file,"lr,pc,#8"); w_as_newline_after_instruction(); w_as_opcode ("str"); fprintf (assembly_file,"lr,[sp,#%d]!",instruction->instruction_parameters[1].parameter_offset); @@ -1500,20 +1500,18 @@ static void w_as_jsr_instruction (struct instruction *instruction) if (instruction->instruction_arity>1) w_as_instruction_without_parameters (".align"); w_as_opcode ("add"); - w_as_scratch_register_comma(); - fprintf (assembly_file,"pc,#9"); + fprintf (assembly_file,"lr,pc,#%d", + instruction->instruction_parameters[0].parameter_type==P_REGISTER ? 6 : 8); w_as_newline_after_instruction(); switch (instruction->instruction_parameters[1].parameter_type){ case P_INDIRECT_WITH_UPDATE: w_as_opcode ("str"); - w_as_scratch_register_comma(); - fprintf (assembly_file,"[sp,#%d]!",instruction->instruction_parameters[1].parameter_offset); + fprintf (assembly_file,"lr,[sp,#%d]!",instruction->instruction_parameters[1].parameter_offset); w_as_newline_after_instruction(); break; case P_INDIRECT: w_as_opcode ("str"); - w_as_scratch_register_comma(); - fprintf (assembly_file,"[sp,#%d]",instruction->instruction_parameters[1].parameter_offset); + fprintf (assembly_file,"lr,[sp,#%d]",instruction->instruction_parameters[1].parameter_offset); w_as_newline_after_instruction(); break; } @@ -2315,7 +2313,13 @@ static void w_as_fmovel_instruction (struct instruction *instruction) static void w_as_rts_instruction (void) { w_as_opcode ("ldr"); - fprintf (assembly_file,"pc,[sp],#4"); + fprintf (assembly_file,"lr,[sp],#4"); + w_as_newline_after_instruction(); + w_as_opcode ("orr"); + fprintf (assembly_file,"lr,lr,#1"); + w_as_newline_after_instruction(); + w_as_opcode ("mov"); + fprintf (assembly_file,"pc,lr"); w_as_newline_after_instruction(); write_float_constants(); |