summaryrefslogtreecommitdiff
path: root/compiler/arm/cgcpu.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/arm/cgcpu.pas')
-rw-r--r--compiler/arm/cgcpu.pas93
1 files changed, 78 insertions, 15 deletions
diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas
index a41aef9a0b..82884fae57 100644
--- a/compiler/arm/cgcpu.pas
+++ b/compiler/arm/cgcpu.pas
@@ -71,6 +71,8 @@ unit cgcpu;
procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+ procedure g_profilecode(list : TAsmList); override;
+
procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
procedure g_maybe_got_init(list : TAsmList); override;
@@ -182,6 +184,8 @@ unit cgcpu;
procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint); override;
function handle_load_store(list: TAsmList; op: tasmop; oppostfix: toppostfix; reg: tregister; ref: treference): treference; override;
+
+ procedure g_external_wrapper(list : TAsmList; procdef : tprocdef; const externalname : string); override;
end;
tthumbcg64farm = class(tbasecg64farm)
@@ -1794,6 +1798,16 @@ unit cgcpu;
list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond(flags_to_cond(f))));
end;
+ procedure tbasecgarm.g_profilecode(list : TAsmList);
+ begin
+ if target_info.system = system_arm_linux then
+ begin
+ list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R14]));
+ a_call_name(list,'__gnu_mcount_nc',false);
+ end
+ else
+ internalerror(2014091201);
+ end;
procedure tbasecgarm.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
var
@@ -3201,6 +3215,7 @@ unit cgcpu;
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]));
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R0,NR_R12));
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]));
@@ -3218,20 +3233,21 @@ unit cgcpu;
tmpref.symbol:=l;
tmpref.base:=NR_PC;
list.concat(taicpu.op_reg_ref(A_LDR,NR_R1,tmpref));
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R0,NR_R12));
href.offset:=0;
+ href.base:=NR_R0;
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
begin
reference_reset_base(href,NR_R12,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
- list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
end;
+ list.concat(taicpu.op_reg(A_BX,NR_R12));
end;
var
@@ -3248,6 +3264,9 @@ unit cgcpu;
if procdef.owner.symtabletype<>ObjectSymtable then
Internalerror(200109191);
+ if GenerateThumbCode or GenerateThumb2Code then
+ list.concat(tai_thumb_func.create);
+
make_global:=false;
if (not current_module.is_unit) or
create_smartlink or
@@ -3293,7 +3312,7 @@ unit cgcpu;
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,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]));
- list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
+ list.concat(taicpu.op_reg(A_BX,NR_R12));
end
else
list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
@@ -4050,18 +4069,36 @@ unit cgcpu;
tmpreg : TRegister;
begin
href:=ref;
- if (op in [A_STR,A_STRB,A_STRH]) and
- (abs(ref.offset)>124) then
- begin
- tmpreg:=getintregister(list,OS_ADDR);
- a_loadaddr_ref_reg(list,ref,tmpreg);
-
- reference_reset_base(href,tmpreg,0,ref.alignment);
- end
- else if (op=A_LDR) and
- (oppostfix in [PF_None]) and
- (ref.base<>NR_STACK_POINTER_REG) and
- (abs(ref.offset)>124) then
+ if { LDR/STR limitations }
+ (
+ (((op=A_LDR) and (oppostfix=PF_None)) or
+ ((op=A_STR) and (oppostfix=PF_None))) and
+ (ref.base<>NR_STACK_POINTER_REG) and
+ (abs(ref.offset)>124)
+ ) or
+ { LDRB/STRB limitations }
+ (
+ (((op=A_LDR) and (oppostfix=PF_B)) or
+ ((op=A_LDRB) and (oppostfix=PF_None)) or
+ ((op=A_STR) and (oppostfix=PF_B)) or
+ ((op=A_STRB) and (oppostfix=PF_None))) and
+ ((ref.base=NR_STACK_POINTER_REG) or
+ (ref.index=NR_STACK_POINTER_REG) or
+ (abs(ref.offset)>31)
+ )
+ ) or
+ { LDRH/STRH limitations }
+ (
+ (((op=A_LDR) and (oppostfix=PF_H)) or
+ ((op=A_LDRH) and (oppostfix=PF_None)) or
+ ((op=A_STR) and (oppostfix=PF_H)) or
+ ((op=A_STRH) and (oppostfix=PF_None))) and
+ ((ref.base=NR_STACK_POINTER_REG) or
+ (ref.index=NR_STACK_POINTER_REG) or
+ (abs(ref.offset)>62) or
+ ((abs(ref.offset) mod 2)<>0)
+ )
+ ) then
begin
tmpreg:=getintregister(list,OS_ADDR);
a_loadaddr_ref_reg(list,ref,tmpreg);
@@ -4274,6 +4311,32 @@ unit cgcpu;
end;
+ procedure tthumbcgarm.g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string);
+ var
+ tmpref : treference;
+ l : tasmlabel;
+ begin
+ { there is no branch instruction on thumb which allows big distances and which leaves LR as it is
+ and which allows to switch the instruction set }
+
+ { create const entry }
+ reference_reset(tmpref,4);
+ current_asmdata.getjumplabel(l);
+ tmpref.symbol:=l;
+ tmpref.base:=NR_PC;
+ list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+ list.concat(taicpu.op_reg_ref(A_LDR,NR_R0,tmpref));
+ 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]));
+ list.concat(taicpu.op_reg(A_BX,NR_R12));
+
+ { append const entry }
+ list.Concat(tai_align.Create(4));
+ list.Concat(tai_label.create(l));
+ list.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(externalname)));
+ end;
+
+
procedure tthumb2cgarm.init_register_allocators;
begin
inherited init_register_allocators;