From cb48c2afca70b76a6ef9be6c9f70b0eee8fdacef Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 11 Jan 2014 17:02:34 +0000 Subject: [PATCH] * some fixes for parameter handling on avr git-svn-id: trunk@26425 - --- compiler/avr/cgcpu.pas | 161 +++++++++++++++++++++++++++++---------- compiler/avr/cpupara.pas | 40 ---------- 2 files changed, 122 insertions(+), 79 deletions(-) diff --git a/compiler/avr/cgcpu.pas b/compiler/avr/cgcpu.pas index 04c2f452c4..08259b4ce3 100644 --- a/compiler/avr/cgcpu.pas +++ b/compiler/avr/cgcpu.pas @@ -50,6 +50,7 @@ unit cgcpu; procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override; procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override; procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override; + procedure a_load_reg_cgpara(list : TAsmList; size : tcgsize;r : tregister; const cgpara : tcgpara);override; procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override; procedure a_call_reg(list : TAsmList;reg: tregister);override; @@ -205,25 +206,124 @@ unit cgcpu; end; + procedure tcgavr.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara); + + procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation); + var + ref : treference; + begin + paramanager.allocparaloc(list,paraloc); + case paraloc^.loc of + LOC_REGISTER,LOC_CREGISTER: + a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register); + LOC_REFERENCE,LOC_CREFERENCE: + begin + reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,2); + a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref); + end; + else + internalerror(2002071004); + end; + end; + + var + i : longint; + hp : PCGParaLocation; + + begin +{ if use_push(cgpara) then + begin + if tcgsize2size[cgpara.Size] > 2 then + begin + if tcgsize2size[cgpara.Size] <> 4 then + internalerror(2013031101); + if cgpara.location^.Next = nil then + begin + if tcgsize2size[cgpara.location^.size] <> 4 then + internalerror(2013031101); + end + else + begin + if tcgsize2size[cgpara.location^.size] <> 2 then + internalerror(2013031101); + if tcgsize2size[cgpara.location^.Next^.size] <> 2 then + internalerror(2013031101); + if cgpara.location^.Next^.Next <> nil then + internalerror(2013031101); + end; + + if tcgsize2size[cgpara.size]>cgpara.alignment then + pushsize:=cgpara.size + else + pushsize:=int_cgsize(cgpara.alignment); + pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2); + list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2))); + list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16))); + end + else + begin + cgpara.check_simple_location; + if tcgsize2size[cgpara.location^.size]>cgpara.alignment then + pushsize:=cgpara.location^.size + else + pushsize:=int_cgsize(cgpara.alignment); + list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize))); + end; + + end + else } + begin + if not(tcgsize2size[cgpara.Size] in [1..4]) then + internalerror(2014011101); + + hp:=cgpara.location; + + for i:=1 to tcgsize2size[cgpara.Size] do + begin + if not(assigned(hp)) or + (tcgsize2size[hp^.size]<>1) or + (hp^.shiftval<>0) then + internalerror(2014011102); + load_para_loc(r,hp); + hp:=hp^.Next; + r:=GetNextReg(r); + end; + if assigned(hp) then + internalerror(2014011103); + end; + end; + + procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara); var - ref: treference; + i : longint; + hp : PCGParaLocation; begin - paraloc.check_simple_location; - paramanager.allocparaloc(list,paraloc.location); - case paraloc.location^.loc of - LOC_REGISTER,LOC_CREGISTER: - a_load_const_reg(list,size,a,paraloc.location^.register); - LOC_REFERENCE: - begin - reference_reset(ref,paraloc.alignment); - ref.base:=paraloc.location^.reference.index; - ref.offset:=paraloc.location^.reference.offset; - a_load_const_ref(list,size,a,ref); + if not(tcgsize2size[paraloc.Size] in [1..4]) then + internalerror(2014011101); + + hp:=paraloc.location; + + for i:=1 to tcgsize2size[paraloc.Size] do + begin + if not(assigned(hp)) or + (tcgsize2size[hp^.size]<>1) or + (hp^.shiftval<>0) then + internalerror(2014011105); + case hp^.loc of + LOC_REGISTER,LOC_CREGISTER: + a_load_const_reg(list,hp^.size,(a shr (i-1)) and $ff,hp^.register); + LOC_REFERENCE,LOC_CREFERENCE: + begin + list.concat(taicpu.op_const(A_PUSH,(a shr (i-1)) and $ff)); + end; + else + internalerror(2002071004); end; - else - internalerror(2002081101); - end; + hp:=hp^.Next; + end; + if assigned(hp) then + internalerror(2014011104); end; @@ -271,26 +371,11 @@ unit cgcpu; procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara); var - ref: treference; tmpreg: tregister; begin - paraloc.check_simple_location; - paramanager.allocparaloc(list,paraloc.location); - case paraloc.location^.loc of - LOC_REGISTER,LOC_CREGISTER: - a_loadaddr_ref_reg(list,r,paraloc.location^.register); - LOC_REFERENCE: - begin - reference_reset(ref,paraloc.alignment); - ref.base := paraloc.location^.reference.index; - ref.offset := paraloc.location^.reference.offset; - tmpreg := getintregister(list,OS_ADDR); - a_loadaddr_ref_reg(list,r,tmpreg); - a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref); - end; - else - internalerror(2002080701); - end; + tmpreg:=getaddressregister(list); + a_loadaddr_ref_reg(list,r,tmpreg); + a_load_reg_cgpara(list,OS_ADDR,tmpreg,paraloc); end; @@ -1175,6 +1260,7 @@ unit cgcpu; begin if a=0 then begin + swapped:=false; { swap parameters? } case cmp_op of OC_GT: @@ -1195,10 +1281,8 @@ unit cgcpu; OC_A: begin swapped:=true; - cmp_op:=OC_A; + cmp_op:=OC_B; end; - else - internalerror(2013113006); end; if swapped then @@ -1229,6 +1313,7 @@ unit cgcpu; tmpreg : tregister; i : byte; begin + swapped:=false; { swap parameters? } case cmp_op of OC_GT: @@ -1249,10 +1334,8 @@ unit cgcpu; OC_A: begin swapped:=true; - cmp_op:=OC_A; + cmp_op:=OC_B; end; - else - internalerror(2013113007); end; if swapped then begin diff --git a/compiler/avr/cpupara.pas b/compiler/avr/cpupara.pas index c4575e6bfc..abc057acb4 100644 --- a/compiler/avr/cpupara.pas +++ b/compiler/avr/cpupara.pas @@ -38,7 +38,6 @@ unit cpupara; function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override; function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override; function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override; - procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; @@ -68,45 +67,6 @@ unit cpupara; end; - procedure tavrparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara); - var - paraloc : pcgparalocation; - psym: tparavarsym; - pdef: tdef; - begin - if nr<1 then - internalerror(2002070801); - psym:=tparavarsym(pd.paras[nr-1]); - pdef:=psym.vardef; - if push_addr_param(psym.varspez,pdef,pd.proccalloption) then - pdef:=getpointerdef(pdef); - cgpara.reset; - cgpara.size:=def_cgsize(pdef); - cgpara.intsize:=tcgsize2size[cgpara.size]; - cgpara.alignment:=std_param_align; - cgpara.def:=pdef; - paraloc:=cgpara.add_location; - with paraloc^ do - begin - size:=def_cgsize(pdef); - def:=pdef; - { the four first parameters are passed into registers } - if nr<=9 then - begin - loc:=LOC_REGISTER; - register:=newreg(R_INTREGISTER,RS_R25-(nr-1)*2,R_SUBWHOLE); - end - else - begin - { the other parameters are passed on the stack } - loc:=LOC_REFERENCE; - reference.index:=NR_STACK_POINTER_REG; - reference.offset:=(nr-10)*2; - end; - end; - end; - - function getparaloc(calloption : tproccalloption; p : tdef) : tcgloc; begin { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER