diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index 27188f16c4..0a1500a785 100644 --- a/compiler/arm/cgcpu.pas +++ b/compiler/arm/cgcpu.pas @@ -165,6 +165,7 @@ unit cgcpu; procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src,dst: TRegister);override; procedure a_op_const_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; dst: tregister);override; + procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); override; procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override; @@ -1122,23 +1123,41 @@ unit cgcpu; ) or ((current_settings.cputype in cpu_thumb) and (((oppostfix in [PF_SB,PF_SH]) and (ref.offset<>0)) or - ((oppostfix=PF_None) and ((ref.offset<0) or (ref.offset>124) or ((ref.offset mod 4)<>0))) or + ((oppostfix=PF_None) and ((ref.offset<0) or ((ref.base<>NR_STACK_POINTER_REG) and (ref.offset>124)) or + ((ref.base=NR_STACK_POINTER_REG) and (ref.offset>1020)) or ((ref.offset mod 4)<>0))) or ((oppostfix=PF_H) and ((ref.offset<0) or (ref.offset>62) or ((ref.offset mod 2)<>0))) or - ((oppostfix=PF_B) and ((ref.offset<0) or (ref.offset>31))) + ((oppostfix=PF_B) and ((ref.offset<0) or (ref.offset>31) or ((getsupreg(ref.base) in [RS_R8..RS_R15]) and (ref.offset<>0)))) ) ) then begin fixref(list,ref); end; - { certain thumb load require base and index } - if (current_settings.cputype in cpu_thumb) and - (oppostfix in [PF_SB,PF_SH]) and - (ref.base<>NR_NO) and (ref.index=NR_NO) then + if current_settings.cputype in cpu_thumb then begin - tmpreg:=getintregister(list,OS_ADDR); - a_load_const_reg(list,OS_INT,0,tmpreg); - ref.index:=tmpreg; + { certain thumb load require base and index } + if (oppostfix in [PF_SB,PF_SH]) and + (ref.base<>NR_NO) and (ref.index=NR_NO) then + begin + tmpreg:=getintregister(list,OS_ADDR); + a_load_const_reg(list,OS_ADDR,0,tmpreg); + ref.index:=tmpreg; + end; + + { "hi" registers cannot be used as base or index } + if (getsupreg(ref.base) in [RS_R8..RS_R12,RS_R14]) or + ((ref.base=NR_R13) and (ref.index<>NR_NO)) then + begin + tmpreg:=getintregister(list,OS_ADDR); + a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.base,tmpreg); + ref.base:=tmpreg; + end; + if getsupreg(ref.index) in [RS_R8..RS_R14] then + begin + tmpreg:=getintregister(list,OS_ADDR); + a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.index,tmpreg); + ref.index:=tmpreg; + end; end; { fold if there is base, index and offset, however, don't fold @@ -3849,6 +3868,15 @@ unit cgcpu; end; + procedure tthumbcgarm.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); + begin + if (op=OP_ADD) and (src=NR_R13) and (dst<>NR_R13) and ((a mod 4)=0) and (a>0) and (a<=1020) then + list.concat(taicpu.op_reg_reg_const(A_ADD,dst,src,a)) + else + inherited a_op_const_reg_reg(list,op,size,a,src,dst); + end; + + procedure tthumbcgarm.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); var l : tasmlabel;