Răsfoiți Sursa

* arm thumb: take care of large offsets in interface wrappers

git-svn-id: trunk@24203 -
florian 12 ani în urmă
părinte
comite
f80b6f4774
1 a modificat fișierele cu 57 adăugiri și 8 ștergeri
  1. 57 8
      compiler/arm/cgcpu.pas

+ 57 - 8
compiler/arm/cgcpu.pas

@@ -2942,15 +2942,40 @@ unit cgcpu;
 
       procedure loadvmttor12;
         var
+          tmpref,
           href : treference;
+          extrareg : boolean;
+          l : TAsmLabel;
         begin
           reference_reset_base(href,NR_R0,0,sizeof(pint));
           if current_settings.cputype in cpu_thumb then
             begin
-              list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
-              cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
-              list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
-              list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+              if (href.offset in [0..124]) and ((href.offset mod 4)=0) then
+                begin
+                  list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+                  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                  list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                  list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+                end
+              else
+                begin
+                  list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+                  { create consts entry }
+                  reference_reset(tmpref,4);
+                  current_asmdata.getjumplabel(l);
+                  current_procinfo.aktlocaldata.Concat(tai_align.Create(4));
+                  cg.a_label(current_procinfo.aktlocaldata,l);
+                  tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+                  current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(href.offset));
+                  tmpref.symbol:=l;
+                  tmpref.base:=NR_PC;
+                  list.concat(taicpu.op_reg_ref(A_LDR,NR_R1,tmpref));
+                  href.offset:=0;
+                  href.index:=NR_R1;
+                  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                  list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                  list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+                end;
             end
           else
             cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
@@ -2959,17 +2984,41 @@ unit cgcpu;
 
       procedure op_onr12methodaddr;
         var
+          tmpref,
           href : treference;
+          l : TAsmLabel;
         begin
           if (procdef.extnumber=$ffff) then
             Internalerror(200006139);
           if current_settings.cputype in cpu_thumb then
             begin
               reference_reset_base(href,NR_R0,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
-              list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
-              cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
-              list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
-              list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+              if (href.offset in [0..124]) and ((href.offset mod 4)=0) then
+                begin
+                  list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+                  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                  list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                  list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+                end
+              else
+                begin
+                  list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+                  { create consts entry }
+                  reference_reset(tmpref,4);
+                  current_asmdata.getjumplabel(l);
+                  current_procinfo.aktlocaldata.Concat(tai_align.Create(4));
+                  cg.a_label(current_procinfo.aktlocaldata,l);
+                  tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+                  current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(href.offset));
+                  tmpref.symbol:=l;
+                  tmpref.base:=NR_PC;
+                  list.concat(taicpu.op_reg_ref(A_LDR,NR_R1,tmpref));
+                  href.offset:=0;
+                  href.index:=NR_R1;
+                  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                  list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                  list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+                end;
               list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
             end
           else