summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCamil Staps2016-10-02 12:05:50 +0000
committerCamil Staps2016-10-02 12:05:50 +0000
commit5effb5bfcaf95ad12e42a298c2306fab36dd402e (patch)
treee774eba7f4545701be6a22fa182113b2758685a8
parentAdd .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.c20
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();