diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index 2723132816..e4ad19e994 100644 --- a/compiler/arm/cgcpu.pas +++ b/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