diff options
author | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2011-04-19 20:17:52 +0000 |
---|---|---|
committer | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2011-04-19 20:17:52 +0000 |
commit | 2dca8fd004f11acbb1d4f5825b8f43645b9438f4 (patch) | |
tree | 60c6228d001e260c8ef3901dc295d55f0ba9425e /compiler/avr | |
parent | c38b26532690a89dd936037853fee2fc042b13dd (diff) | |
download | fpc-2dca8fd004f11acbb1d4f5825b8f43645b9438f4.tar.gz |
* reintegrate avr branch into trunk, work on avr is less invasive than I thought so it can be continued in trunk
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@17348 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/avr')
-rw-r--r-- | compiler/avr/aasmcpu.pas | 28 | ||||
-rw-r--r-- | compiler/avr/agavrgas.pas | 159 | ||||
-rw-r--r-- | compiler/avr/aoptcpu.pas | 38 | ||||
-rw-r--r-- | compiler/avr/cgcpu.pas | 690 | ||||
-rw-r--r-- | compiler/avr/cpubase.pas | 31 | ||||
-rw-r--r-- | compiler/avr/cpuinfo.pas | 49 | ||||
-rw-r--r-- | compiler/avr/cpupara.pas | 22 | ||||
-rw-r--r-- | compiler/avr/cpupi.pas | 16 | ||||
-rw-r--r-- | compiler/avr/itcpugas.pas | 2 | ||||
-rw-r--r-- | compiler/avr/navradd.pas | 34 | ||||
-rw-r--r-- | compiler/avr/navrcnv.pas | 123 | ||||
-rw-r--r-- | compiler/avr/raavrgas.pas | 19 | ||||
-rw-r--r-- | compiler/avr/rgcpu.pas | 66 |
13 files changed, 868 insertions, 409 deletions
diff --git a/compiler/avr/aasmcpu.pas b/compiler/avr/aasmcpu.pas index d8dfe60d34..3902623a88 100644 --- a/compiler/avr/aasmcpu.pas +++ b/compiler/avr/aasmcpu.pas @@ -209,14 +209,14 @@ implementation function taicpu.spilling_get_operation_type(opnr: longint): topertype; begin - result := operand_read; + result:=operand_read; case opcode of - A_CP,A_CPC,A_CPI : + A_CP,A_CPC,A_CPI,A_PUSH : ; else begin - if opnr=ops-1 then - result := operand_write; + if opnr=0 then + result:=operand_write; end; end; end; @@ -226,9 +226,15 @@ implementation begin case getregtype(r) of R_INTREGISTER : - result:=taicpu.op_ref_reg(A_LD,ref,r); + if ref.offset<>0 then + result:=taicpu.op_reg_ref(A_LDD,r,ref) + else + result:=taicpu.op_reg_ref(A_LD,r,ref); R_ADDRESSREGISTER : - result:=taicpu.op_ref_reg(A_LD,ref,r); + if ref.offset<>0 then + result:=taicpu.op_reg_ref(A_LDD,r,ref) + else + result:=taicpu.op_reg_ref(A_LD,r,ref); else internalerror(200401041); end; @@ -239,9 +245,15 @@ implementation begin case getregtype(r) of R_INTREGISTER : - result:=taicpu.op_reg_ref(A_ST,r,ref); + if ref.offset<>0 then + result:=taicpu.op_ref_reg(A_STD,ref,r) + else + result:=taicpu.op_ref_reg(A_ST,ref,r); R_ADDRESSREGISTER : - result:=taicpu.op_reg_ref(A_ST,r,ref); + if ref.offset<>0 then + result:=taicpu.op_ref_reg(A_STD,ref,r) + else + result:=taicpu.op_ref_reg(A_ST,ref,r); else internalerror(200401041); end; diff --git a/compiler/avr/agavrgas.pas b/compiler/avr/agavrgas.pas index b73e7b4583..74b95429de 100644 --- a/compiler/avr/agavrgas.pas +++ b/compiler/avr/agavrgas.pas @@ -29,13 +29,18 @@ unit agavrgas; interface uses + globtype, aasmtai,aasmdata, aggas, cpubase; type + + { TAVRGNUAssembler } + TAVRGNUAssembler=class(TGNUassembler) constructor create(smart: boolean); override; + function MakeCmdLine: TCmdStr; override; end; TAVRInstrWriter=class(TCPUInstrWriter) @@ -51,6 +56,7 @@ unit agavrgas; assemble, aasmcpu, itcpugas, + cpuinfo, cgbase,cgutils; {****************************************************************************} @@ -68,69 +74,102 @@ unit agavrgas; { Helper routines for Instruction Writer } {****************************************************************************} - function getreferencestring(var ref : treference) : string; - var - s : string; - begin - with ref do - begin -{$ifdef extdebug} - // if base=NR_NO then - // internalerror(200308292); - - // if ((index<>NR_NO) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then - // internalerror(200308293); -{$endif extdebug} - - if assigned(symbol) then - begin - s:=symbol.name; - if offset<0 then - s:=s+tostr(offset) - else if offset>0 then - s:=s+'+'+tostr(offset); - end - else - begin - s:=gas_regname(base); - end; - end; - getreferencestring:=s; - end; + Procedure TAVRInstrWriter.WriteInstruction(hp : tai); + + function getreferencestring(var ref : treference) : string; + var + s : string; + begin + with ref do + begin + {$ifdef extdebug} + // if base=NR_NO then + // internalerror(200308292); + + // if ((index<>NR_NO) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then + // internalerror(200308293); + {$endif extdebug} + if index<>NR_NO then + internalerror(2011021701) + else if base<>NR_NO then + begin + if addressmode=AM_PREDRECEMENT then + s:='-' + else + s:=''; + case base of + NR_R26: + s:=s+'X'; + NR_R28: + s:=s+'Y'; + NR_R30: + s:=s+'Z'; + else + s:=gas_regname(base); + end; + if addressmode=AM_POSTINCREMENT then + s:=s+'+'; + + if offset>0 then + s:=s+'+'+tostr(offset) + else if offset<0 then + s:=s+tostr(offset) + end + else if assigned(symbol) or (offset<>0) then + begin + if assigned(symbol) then + s:=ReplaceForbiddenChars(symbol.name) + else + s:=''; + + if offset<0 then + s:=s+tostr(offset) + else if offset>0 then + s:=s+'+'+tostr(offset); + case refaddr of + addr_hi8: + s:='hi8('+s+')'; + addr_lo8: + s:='lo8('+s+')'; + else + s:='('+s+')'; + end; + end; + end; + getreferencestring:=s; + end; - function getopstr(const o:toper) : string; - var - hs : string; - first : boolean; - r : tsuperregister; - begin - case o.typ of - top_reg: - getopstr:=gas_regname(o.reg); - top_const: - getopstr:='#'+tostr(longint(o.val)); - top_ref: - if o.ref^.refaddr=addr_full then - begin - hs:=o.ref^.symbol.name; - if o.ref^.offset>0 then - hs:=hs+'+'+tostr(o.ref^.offset) - else - if o.ref^.offset<0 then - hs:=hs+tostr(o.ref^.offset); - getopstr:=hs; - end + function getopstr(const o:toper) : string; + var + hs : string; + first : boolean; + r : tsuperregister; + begin + case o.typ of + top_reg: + getopstr:=gas_regname(o.reg); + top_const: + getopstr:=tostr(longint(o.val)); + top_ref: + if o.ref^.refaddr=addr_full then + begin + hs:=ReplaceForbiddenChars(o.ref^.symbol.name); + if o.ref^.offset>0 then + hs:=hs+'+'+tostr(o.ref^.offset) + else + if o.ref^.offset<0 then + hs:=hs+tostr(o.ref^.offset); + getopstr:=hs; + end + else + getopstr:=getreferencestring(o.ref^); else - getopstr:=getreferencestring(o.ref^); - else - internalerror(2002070604); + internalerror(2002070604); + end; end; - end; - - Procedure TAVRInstrWriter.WriteInstruction(hp : tai); var op: TAsmOp; s: string; i: byte; @@ -151,6 +190,12 @@ unit agavrgas; end; + function TAVRGNUAssembler.MakeCmdLine: TCmdStr; + begin + result := '-mmcu='+lower(cputypestr[current_settings.cputype])+' '+inherited MakeCmdLine; + end; + + const as_arm_gas_info : tasminfo = ( diff --git a/compiler/avr/aoptcpu.pas b/compiler/avr/aoptcpu.pas index 18d74edd3c..90611a1e78 100644 --- a/compiler/avr/aoptcpu.pas +++ b/compiler/avr/aoptcpu.pas @@ -40,7 +40,7 @@ Type Implementation uses - aasmbase,aasmcpu; + aasmbase,aasmcpu,cgbase; function CanBeCond(p : tai) : boolean; begin @@ -53,8 +53,44 @@ Implementation next1: tai; begin result := false; + case p.typ of + ait_instruction: + begin + case taicpu(p).opcode of + A_MOV: + begin + { fold + mov reg2,reg0 + mov reg3,reg1 + to + movw reg2,reg0 + } + if (taicpu(p).ops=2) and + (taicpu(p).oper[0]^.typ = top_reg) and + (taicpu(p).oper[1]^.typ = top_reg) and + getnextinstruction(p,next1) and + (next1.typ = ait_instruction) and + (taicpu(next1).opcode = A_MOV) and + (taicpu(next1).ops=2) and + (taicpu(next1).oper[0]^.typ = top_reg) and + (taicpu(next1).oper[1]^.typ = top_reg) and + (getsupreg(taicpu(next1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and + ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and + ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and + (getsupreg(taicpu(next1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then + begin + taicpu(p).opcode:=A_MOVW; + asml.remove(next1); + next1.free; + result := true; + end; + end; + end; + end; + end; end; + procedure TCpuAsmOptimizer.PeepHoleOptPass2; begin end; diff --git a/compiler/avr/cgcpu.pas b/compiler/avr/cgcpu.pas index be57425737..52cbd66b1c 100644 --- a/compiler/avr/cgcpu.pas +++ b/compiler/avr/cgcpu.pas @@ -34,7 +34,6 @@ unit cgcpu; parabase, cpubase,cpuinfo,node,cg64f32,rgcpu; - type { tcgavr } @@ -46,6 +45,7 @@ unit cgcpu; procedure done_register_allocators;override; function getintregister(list:TAsmList;size:Tcgsize):Tregister;override; + function getaddressregister(list:TAsmList):TRegister;override; procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);override; procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override; @@ -81,32 +81,29 @@ unit cgcpu; procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override; procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override; - procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);override; procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint); - procedure g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean); procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override; -// procedure g_save_registers(list : TAsmList);override; -// procedure g_restore_registers(list : TAsmList);override; + procedure g_save_registers(list : TAsmList);override; + procedure g_restore_registers(list : TAsmList);override; procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel); procedure fixref(list : TAsmList;var ref : treference); - function normalize_ref(list:TAsmList;ref: treference):treference; + function normalize_ref(list : TAsmList;ref : treference; + tmpreg : tregister) : treference; procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override; procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister); procedure a_adjust_sp(list: TAsmList; value: longint); + function GetLoad(const ref : treference) : tasmop; + function GetStore(const ref: treference): tasmop; end; tcg64favr = class(tcg64f32) procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override; procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override; - procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override; - procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override; - procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override; - procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override; end; procedure create_codegen; @@ -130,18 +127,19 @@ unit cgcpu; begin inherited init_register_allocators; rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE, - [RS_R0,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9, + [RS_R8,RS_R9, RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19, - RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25],first_int_imreg,[]); - rg[R_ADDRESSREGISTER]:=trgintcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE, - [RS_R26,RS_R30],first_int_imreg,[]); + RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25, + RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7],first_int_imreg,[]); + { rg[R_ADDRESSREGISTER]:=trgintcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE, + [RS_R26,RS_R30],first_int_imreg,[]); } end; procedure tcgavr.done_register_allocators; begin rg[R_INTREGISTER].free; - rg[R_ADDRESSREGISTER].free; + // rg[R_ADDRESSREGISTER].free; inherited done_register_allocators; end; @@ -190,6 +188,12 @@ unit cgcpu; end; + function tcgavr.getaddressregister(list: TAsmList): TRegister; + begin + Result:=getintregister(list,OS_ADDR); + end; + + procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara); var ref: treference; @@ -375,16 +379,16 @@ unit cgcpu; procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); var + countreg, tmpreg: tregister; i : integer; instr : taicpu; + paraloc1,paraloc2,paraloc3 : TCGPara; + l1,l2 : tasmlabel; begin case op of OP_ADD: begin - if src<>dst then - a_load_reg_reg(list,size,size,src,dst); - list.concat(taicpu.op_reg_reg(A_ADD,dst,src)); if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then begin @@ -400,9 +404,6 @@ unit cgcpu; OP_SUB: begin - if src<>dst then - a_load_reg_reg(list,size,size,src,dst); - list.concat(taicpu.op_reg_reg(A_SUB,dst,src)); if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then begin @@ -432,7 +433,7 @@ unit cgcpu; tmpreg:=GetNextReg(dst); for i:=2 to tcgsize2size[size] do begin - list.concat(taicpu.op_const_reg(A_SBCI,-1,dst)); + list.concat(taicpu.op_reg_const(A_SBCI,dst,-1)); tmpreg:=GetNextReg(tmpreg); end; end @@ -456,6 +457,29 @@ unit cgcpu; begin if size in [OS_8,OS_S8] then list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src)) + else if size=OS_16 then + begin + paraloc1.init; + paraloc2.init; + paraloc3.init; + paramanager.getintparaloc(pocall_default,1,paraloc1); + paramanager.getintparaloc(pocall_default,2,paraloc2); + paramanager.getintparaloc(pocall_default,3,paraloc3); + a_load_const_cgpara(list,OS_8,0,paraloc3); + a_load_reg_cgpara(list,OS_16,src,paraloc2); + a_load_reg_cgpara(list,OS_16,dst,paraloc1); + paramanager.freecgpara(list,paraloc3); + paramanager.freecgpara(list,paraloc2); + paramanager.freecgpara(list,paraloc1); + alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default)); + a_call_name(list,'FPC_MUL_WORD',false); + dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default)); + cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG); + cg.a_load_reg_reg(list,OS_16,OS_16,NR_FUNCTION_RESULT_REG,dst); + paraloc3.done; + paraloc2.done; + paraloc1.done; + end else internalerror(2011022002); end; @@ -467,14 +491,73 @@ unit cgcpu; OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR: begin - {!!!!!!!} + current_asmdata.getjumplabel(l1); + current_asmdata.getjumplabel(l2); + countreg:=getintregister(list,OS_8); + a_load_reg_reg(list,size,OS_8,src,countreg); + list.concat(taicpu.op_reg_const(A_CP,countreg,0)); + a_jmp_flags(list,F_EQ,l2); + cg.a_label(list,l1); + case op of + OP_SHR: + list.concat(taicpu.op_reg(A_LSR,GetOffsetReg(dst,tcgsize2size[size]-1))); + OP_SHL: + list.concat(taicpu.op_reg(A_LSL,dst)); + OP_SAR: + list.concat(taicpu.op_reg(A_ASR,GetOffsetReg(dst,tcgsize2size[size]-1))); + OP_ROR: + begin + { load carry? } + if not(size in [OS_8,OS_S8]) then + begin + list.concat(taicpu.op_none(A_CLC)); + list.concat(taicpu.op_reg_const(A_SBRC,src,0)); + list.concat(taicpu.op_none(A_SEC)); + end; + list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-1))); + end; + OP_ROL: + begin + { load carry? } + if not(size in [OS_8,OS_S8]) then + begin + list.concat(taicpu.op_none(A_CLC)); + list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg(dst,tcgsize2size[size]-1),7)); + list.concat(taicpu.op_none(A_SEC)); + end; + list.concat(taicpu.op_reg(A_ROL,dst)) + end; + else + internalerror(2011030901); + end; + if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then + begin + for i:=2 to tcgsize2size[size] do + begin + case op of + OP_ROR, + OP_SHR: + list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i))); + OP_ROL, + OP_SHL: + list.concat(taicpu.op_reg(A_ROL,GetOffsetReg(dst,i-1))); + OP_SAR: + list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i))); + else + internalerror(2011030902); + end; + end; + end; + + a_op_const_reg(list,OP_SUB,OS_8,1,countreg); + a_jmp_flags(list,F_NE,l1); + // keep registers alive + list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg)); + cg.a_label(list,l2); end; OP_AND,OP_OR,OP_XOR: begin - if src<>dst then - a_load_reg_reg(list,size,size,src,dst); - for i:=1 to tcgsize2size[size] do begin list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src)); @@ -482,7 +565,7 @@ unit cgcpu; src:=GetNextReg(src); end; end; - else + else internalerror(2011022004); end; end; @@ -498,7 +581,11 @@ unit cgcpu; shift:=0; for i:=1 to tcgsize2size[size] do begin - list.concat(taicpu.op_reg_const(A_LDI,reg,(qword(a) and mask) shr shift)); + if ((qword(a) and mask) shr shift)=0 then + emit_mov(list,reg,NR_R1) + else + list.concat(taicpu.op_reg_const(A_LDI,reg,(qword(a) and mask) shr shift)); + mask:=mask shl 8; inc(shift,8); reg:=GetNextReg(reg); @@ -506,14 +593,11 @@ unit cgcpu; end; - function tcgavr.normalize_ref(list:TAsmList;ref: treference):treference; + function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference; var - tmpreg : tregister; tmpref : treference; l : tasmlabel; begin - tmpreg:=NR_NO; - Result:=ref; if ref.addressmode<>AM_UNCHANGED then @@ -530,14 +614,14 @@ unit cgcpu; end; if assigned(ref.symbol) or (ref.offset<>0) then begin - tmpreg:=getaddressregister(list); reference_reset(tmpref,0); tmpref.symbol:=ref.symbol; - tmpref.offset:=lo(word(ref.offset)); + tmpref.offset:=ref.offset; tmpref.refaddr:=addr_lo8; + getcpuregister(list,tmpreg); list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref)); - tmpref.offset:=hi(word(ref.offset)); tmpref.refaddr:=addr_hi8; + getcpuregister(list,GetNextReg(tmpreg)); list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref)); if (ref.base<>NR_NO) then begin @@ -546,20 +630,42 @@ unit cgcpu; end; if (ref.index<>NR_NO) then begin - list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base)); - list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base))); + list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index)); + list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index))); end; + ref.symbol:=nil; + ref.offset:=0; ref.base:=tmpreg; ref.index:=NR_NO; end else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then begin - tmpreg:=getaddressregister(list); - list.concat(taicpu.op_reg_reg(A_MOVW,tmpreg,ref.index)); + getcpuregister(list,tmpreg); + emit_mov(list,tmpreg,ref.index); + getcpuregister(list,GetNextReg(tmpreg)); + emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index)); list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base)); list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base))); ref.base:=tmpreg; ref.index:=NR_NO; + end + else if (ref.base<>NR_NO) then + begin + getcpuregister(list,tmpreg); + emit_mov(list,tmpreg,ref.base); + getcpuregister(list,GetNextReg(tmpreg)); + emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base)); + ref.base:=tmpreg; + ref.index:=NR_NO; + end + else if (ref.index<>NR_NO) then + begin + getcpuregister(list,tmpreg); + emit_mov(list,tmpreg,ref.index); + getcpuregister(list,GetNextReg(tmpreg)); + emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index)); + ref.base:=tmpreg; + ref.index:=NR_NO; end; Result:=ref; end; @@ -571,8 +677,23 @@ unit cgcpu; conv_done: boolean; tmpreg : tregister; i : integer; + QuickRef : Boolean; begin - href:=normalize_ref(list,Ref); + QuickRef:=false; + if not((Ref.addressmode=AM_UNCHANGED) and + (Ref.symbol=nil) and + ((Ref.base=NR_R28) or + (Ref.base=NR_R29)) and + (Ref.Index=NR_No) and + (Ref.Offset in [0..64-tcgsize2size[tosize]])) and + not((Ref.Base=NR_NO) and (Ref.Index=NR_NO)) then + href:=normalize_ref(list,Ref,NR_R30) + else + begin + QuickRef:=true; + href:=Ref; + end; + if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then internalerror(2011021307); @@ -585,109 +706,109 @@ unit cgcpu; case fromsize of OS_8: begin - if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then + if not(QuickRef) and (tcgsize2size[tosize]>1) then href.addressmode:=AM_POSTINCREMENT; - list.concat(taicpu.op_ref_reg(A_ST,href,reg)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,reg)); for i:=2 to tcgsize2size[tosize] do begin - if (href.offset<>0) or assigned(href.symbol) then + if QuickRef then inc(href.offset); - if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then + if not(QuickRef) and (i<tcgsize2size[fromsize]) then href.addressmode:=AM_POSTINCREMENT else href.addressmode:=AM_UNCHANGED; - list.concat(taicpu.op_ref_reg(A_ST,href,NR_R1)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1)); end; end; OS_S8: begin - if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then + if not(QuickRef) and (tcgsize2size[tosize]>1) then href.addressmode:=AM_POSTINCREMENT; - list.concat(taicpu.op_ref_reg(A_ST,href,reg)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,reg)); if tcgsize2size[tosize]>1 then begin tmpreg:=getintregister(list,OS_8); list.concat(taicpu.op_reg(A_CLR,tmpreg)); - list.concat(taicpu.op_reg_const(A_SBIC,reg,7)); + list.concat(taicpu.op_reg_const(A_SBRC,reg,7)); list.concat(taicpu.op_reg(A_COM,tmpreg)); for i:=2 to tcgsize2size[tosize] do begin - if (href.offset<>0) or assigned(href.symbol) then + if QuickRef then inc(href.offset); - if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then + if not(QuickRef) and (i<tcgsize2size[fromsize]) then href.addressmode:=AM_POSTINCREMENT else href.addressmode:=AM_UNCHANGED; - list.concat(taicpu.op_ref_reg(A_ST,href,tmpreg)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg)); end; end; end; OS_16: begin - if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then + if not(QuickRef) and (tcgsize2size[tosize]>1) then href.addressmode:=AM_POSTINCREMENT; - list.concat(taicpu.op_ref_reg(A_ST,href,reg)); - if (href.offset<>0) or assigned(href.symbol) then + list.concat(taicpu.op_ref_reg(GetStore(href),href,reg)); + if QuickRef then inc(href.offset) - else if (href.base<>NR_NO) and (tcgsize2size[fromsize]>2) then + else if not(QuickRef) and (tcgsize2size[fromsize]>2) then href.addressmode:=AM_POSTINCREMENT else href.addressmode:=AM_UNCHANGED; reg:=GetNextReg(reg); - list.concat(taicpu.op_ref_reg(A_ST,href,reg)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,reg)); for i:=3 to tcgsize2size[tosize] do begin - if (href.offset<>0) or assigned(href.symbol) then + if QuickRef then inc(href.offset); - if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then + if not(QuickRef) and (i<tcgsize2size[fromsize]) then href.addressmode:=AM_POSTINCREMENT else href.addressmode:=AM_UNCHANGED; - list.concat(taicpu.op_ref_reg(A_ST,href,NR_R1)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1)); end; end; OS_S16: begin - if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then + if not(QuickRef) and (tcgsize2size[tosize]>1) then href.addressmode:=AM_POSTINCREMENT; - list.concat(taicpu.op_ref_reg(A_ST,href,reg)); - if (href.offset<>0) or assigned(href.symbol) then + list.concat(taicpu.op_ref_reg(GetStore(href),href,reg)); + if QuickRef then inc(href.offset) - else if (href.base<>NR_NO) and (tcgsize2size[fromsize]>2) then + else if not(QuickRef) and (tcgsize2size[fromsize]>2) then href.addressmode:=AM_POSTINCREMENT else href.addressmode:=AM_UNCHANGED; reg:=GetNextReg(reg); - list.concat(taicpu.op_ref_reg(A_ST,href,reg)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,reg)); if tcgsize2size[tosize]>2 then begin tmpreg:=getintregister(list,OS_8); list.concat(taicpu.op_reg(A_CLR,tmpreg)); - list.concat(taicpu.op_reg_const(A_SBIC,reg,7)); + list.concat(taicpu.op_reg_const(A_SBRC,reg,7)); list.concat(taicpu.op_reg(A_COM,tmpreg)); for i:=3 to tcgsize2size[tosize] do begin - if (href.offset<>0) or assigned(href.symbol) then + if QuickRef then inc(href.offset); - if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then + if not(QuickRef) and (i<tcgsize2size[fromsize]) then href.addressmode:=AM_POSTINCREMENT else href.addressmode:=AM_UNCHANGED; - list.concat(taicpu.op_ref_reg(A_ST,href,tmpreg)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg)); end; end; end; @@ -699,19 +820,25 @@ unit cgcpu; begin for i:=1 to tcgsize2size[fromsize] do begin - if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then + if not(QuickRef) and (i<tcgsize2size[fromsize]) then href.addressmode:=AM_POSTINCREMENT else href.addressmode:=AM_UNCHANGED; - list.concat(taicpu.op_ref_reg(A_ST,href,reg)); + list.concat(taicpu.op_ref_reg(GetStore(href),href,reg)); - if (href.offset<>0) or assigned(href.symbol) then + if QuickRef then inc(href.offset); reg:=GetNextReg(reg); end; end; + + if not(QuickRef) then + begin + ungetcpuregister(list,href.base); + ungetcpuregister(list,GetNextReg(href.base)); + end; end; @@ -722,8 +849,23 @@ unit cgcpu; conv_done: boolean; tmpreg : tregister; i : integer; + QuickRef : boolean; begin - href:=normalize_ref(list,Ref); + QuickRef:=false; + if not((Ref.addressmode=AM_UNCHANGED) and + (Ref.symbol=nil) and + ((Ref.base=NR_R28) or + (Ref.base=NR_R29)) and + (Ref.Index=NR_No) and + (Ref.Offset in [0..64-tcgsize2size[fromsize]])) and + not((Ref.Base=NR_NO) and (Ref.Index=NR_NO)) then + href:=normalize_ref(list,Ref,NR_R30) + else + begin + QuickRef:=true; + href:=Ref; + end; + if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then internalerror(2011021307); @@ -736,7 +878,7 @@ unit cgcpu; case fromsize of OS_8: begin - list.concat(taicpu.op_reg_ref(A_LD,reg,href)); + list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href)); for i:=2 to tcgsize2size[tosize] do begin reg:=GetNextReg(reg); @@ -745,14 +887,14 @@ unit cgcpu; end; OS_S8: begin - list.concat(taicpu.op_reg_ref(A_LD,reg,href)); + list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href)); tmpreg:=reg; if tcgsize2size[tosize]>1 then begin reg:=GetNextReg(reg); list.concat(taicpu.op_reg(A_CLR,reg)); - list.concat(taicpu.op_reg_const(A_SBIC,tmpreg,7)); + list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7)); list.concat(taicpu.op_reg(A_COM,reg)); tmpreg:=reg; for i:=3 to tcgsize2size[tosize] do @@ -764,16 +906,16 @@ unit cgcpu; end; OS_16: begin - if href.base<>NR_NO then + if not(QuickRef) then href.addressmode:=AM_POSTINCREMENT; - list.concat(taicpu.op_reg_ref(A_LD,reg,href)); + list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href)); - if (href.offset<>0) or assigned(href.symbol) then + if QuickRef then inc(href.offset); href.addressmode:=AM_UNCHANGED; reg:=GetNextReg(reg); - list.concat(taicpu.op_reg_ref(A_LD,reg,href)); + list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href)); for i:=3 to tcgsize2size[tosize] do begin @@ -783,20 +925,20 @@ unit cgcpu; end; OS_S16: begin - if href.base<>NR_NO then + if not(QuickRef) then href.addressmode:=AM_POSTINCREMENT; - list.concat(taicpu.op_reg_ref(A_LD,reg,href)); - if (href.offset<>0) or assigned(href.symbol) then + list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href)); + if QuickRef then inc(href.offset); href.addressmode:=AM_UNCHANGED; reg:=GetNextReg(reg); - list.concat(taicpu.op_reg_ref(A_LD,reg,href)); + list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href)); tmpreg:=reg; reg:=GetNextReg(reg); list.concat(taicpu.op_reg(A_CLR,reg)); - list.concat(taicpu.op_reg_const(A_SBIC,tmpreg,7)); + list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7)); list.concat(taicpu.op_reg(A_COM,reg)); tmpreg:=reg; for i:=4 to tcgsize2size[tosize] do @@ -813,19 +955,25 @@ unit cgcpu; begin for i:=1 to tcgsize2size[fromsize] do begin - if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then - href.addressmode:=AM_POSTINCREMENT - else - href.addressmode:=AM_UNCHANGED; + if not(QuickRef) and (i<tcgsize2size[fromsize]) then + href.addressmode:=AM_POSTINCREMENT + else + href.addressmode:=AM_UNCHANGED; - list.concat(taicpu.op_reg_ref(A_LD,reg,href)); + list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href)); - if (href.offset<>0) or assigned(href.symbol) then + if QuickRef then inc(href.offset); reg:=GetNextReg(reg); end; end; + + if not(QuickRef) then + begin + ungetcpuregister(list,href.base); + ungetcpuregister(list,GetNextReg(href.base)); + end; end; @@ -861,7 +1009,7 @@ unit cgcpu; reg2:=GetNextReg(reg2); list.concat(taicpu.op_reg(A_CLR,reg2)); - list.concat(taicpu.op_reg_const(A_SBIC,reg1,7)); + list.concat(taicpu.op_reg_const(A_SBRC,reg1,7)); list.concat(taicpu.op_reg(A_COM,reg2)); tmpreg:=reg2; for i:=3 to tcgsize2size[tosize] do @@ -895,7 +1043,7 @@ unit cgcpu; reg2:=GetNextReg(reg2); list.concat(taicpu.op_reg(A_CLR,reg2)); - list.concat(taicpu.op_reg_const(A_SBIC,reg1,7)); + list.concat(taicpu.op_reg_const(A_SBRC,reg1,7)); list.concat(taicpu.op_reg(A_COM,reg2)); tmpreg:=reg2; for i:=4 to tcgsize2size[tosize] do @@ -921,22 +1069,116 @@ unit cgcpu; { comparison operations } - procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister; - l : tasmlabel); + procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize; + cmp_op : topcmp;a : aint;reg : tregister;l : tasmlabel); + var + swapped : boolean; + tmpreg : tregister; + i : byte; begin - internalerror(2011021311); + if a=0 then + begin + { swap parameters? } + case cmp_op of + OC_GT: + begin + swapped:=true; + cmp_op:=OC_LT; + end; + OC_LTE: + begin + swapped:=true; + cmp_op:=OC_GTE; + end; + OC_BE: + begin + swapped:=true; + cmp_op:=OC_AE; + end; + OC_A: + begin + swapped:=true; + cmp_op:=OC_A; + end; + end; + + if swapped then + list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1)) + else + list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg)); + + for i:=2 to tcgsize2size[size] do + begin + reg:=GetNextReg(reg); + if swapped then + list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1)) + else + list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg)); + end; + + a_jmp_cond(list,cmp_op,l); + end + else + inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l); end; - procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); + procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize; + cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); + var + swapped : boolean; + tmpreg : tregister; + i : byte; begin - internalerror(2011021312); + { swap parameters? } + case cmp_op of + OC_GT: + begin + swapped:=true; + cmp_op:=OC_LT; + end; + OC_LTE: + begin + swapped:=true; + cmp_op:=OC_GTE; + end; + OC_BE: + begin + swapped:=true; + cmp_op:=OC_AE; + end; + OC_A: + begin + swapped:=true; + cmp_op:=OC_A; + end; + end; + if swapped then + begin + tmpreg:=reg1; + reg1:=reg2; + reg2:=tmpreg; + end; + list.concat(taicpu.op_reg_reg(A_CP,reg1,reg2)); + + for i:=2 to tcgsize2size[size] do + begin + reg1:=GetNextReg(reg1); + reg2:=GetNextReg(reg2); + list.concat(taicpu.op_reg_reg(A_CPC,reg1,reg2)); + end; + + a_jmp_cond(list,cmp_op,l); end; procedure tcgavr.a_jmp_name(list : TAsmList;const s : string); + var + ai : taicpu; begin - internalerror(2011021313); + ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s)); + ai.is_jmp:=true; + list.concat(ai); end; @@ -961,10 +1203,31 @@ unit cgcpu; procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); + var + l : TAsmLabel; + tmpflags : TResFlags; begin - internalerror(2011021316); + current_asmdata.getjumplabel(l); + { + if flags_to_cond(f) then + begin + tmpflags:=f; + inverse_flags(tmpflags); + list.concat(taicpu.op_reg(A_CLR,reg)); + a_jmp_flags(list,tmpflags,l); + list.concat(taicpu.op_reg_const(A_LDI,reg,1)); + end + else + } + begin + list.concat(taicpu.op_reg_const(A_LDI,reg,1)); + a_jmp_flags(list,f,l); + list.concat(taicpu.op_reg(A_CLR,reg)); + end; + cg.a_label(list,l); end; + procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint); var i : integer; @@ -1006,6 +1269,29 @@ unit cgcpu; end; end; + + function tcgavr.GetLoad(const ref: treference) : tasmop; + begin + if (ref.base=NR_NO) and (ref.index=NR_NO) then + result:=A_LDS + else if (ref.base<>NR_NO) and (ref.offset<>0) then + result:=A_LDD + else + result:=A_LD; + end; + + + function tcgavr.GetStore(const ref: treference) : tasmop; + begin + if (ref.base=NR_NO) and (ref.index=NR_NO) then + result:=A_STS + else if (ref.base<>NR_NO) and (ref.offset<>0) then + result:=A_STD + else + result:=A_ST; + end; + + procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean); var regs : tcpuregisterset; @@ -1050,12 +1336,12 @@ unit cgcpu; begin LocalSize:=current_procinfo.calc_stackframe_size; a_adjust_sp(list,LocalSize); + regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall); for reg:=RS_R0 to RS_R31 do if reg in regs then list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE))); - regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall); end else { the framepointer cannot be omitted on avr because sp @@ -1068,8 +1354,47 @@ unit cgcpu; procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister); + var + tmpref : treference; begin - //!!!! + if ref.addressmode<>AM_UNCHANGED then + internalerror(2011021701); + + if assigned(ref.symbol) or (ref.offset<>0) then + begin + reference_reset(tmpref,0); + tmpref.symbol:=ref.symbol; + tmpref.offset:=ref.offset; + tmpref.refaddr:=addr_lo8; + list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref)); + tmpref.refaddr:=addr_hi8; + list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref)); + if (ref.base<>NR_NO) then + begin + list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base)); + list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base))); + end; + if (ref.index<>NR_NO) then + begin + list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index)); + list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index))); + end; + end + else if (ref.base<>NR_NO)then + begin + emit_mov(list,r,ref.base); + emit_mov(list,GetNextReg(r),GetNextReg(ref.base)); + if (ref.index<>NR_NO) then + begin + list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index)); + list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index))); + end; + end + else if (ref.index<>NR_NO) then + begin + emit_mov(list,r,ref.index); + emit_mov(list,GetNextReg(r),GetNextReg(ref.index)); + end; end; @@ -1104,17 +1429,6 @@ unit cgcpu; end; - procedure tcgavr.g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean); - begin - internalerror(2011021321); - end; - - procedure tcgavr.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint); - begin - g_concatcopy_internal(list,source,dest,len,false); - end; - - procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : aint); var countreg,tmpreg : tregister; @@ -1122,11 +1436,19 @@ unit cgcpu; copysize,countregsize : tcgsize; l : TAsmLabel; i : longint; + SrcQuickRef, DestQuickRef : Boolean; begin - current_asmdata.getjumplabel(l); if len>16 then begin - {!!!!!!! load refs!} + current_asmdata.getjumplabel(l); + + reference_reset(srcref,0); + reference_reset(dstref,0); + srcref.base:=NR_R30; + srcref.addressmode:=AM_POSTINCREMENT; + dstref.base:=NR_R26; + dstref.addressmode:=AM_POSTINCREMENT; + copysize:=OS_8; if len<256 then countregsize:=OS_8 @@ -1136,38 +1458,99 @@ unit cgcpu; internalerror(2011022007); countreg:=getintregister(list,countregsize); a_load_const_reg(list,countregsize,len,countreg); + a_loadaddr_ref_reg(list,source,NR_R30); + tmpreg:=getaddressregister(list); + a_loadaddr_ref_reg(list,dest,tmpreg); + + { X is used for spilling code so we can load it + only by a push/pop sequence, this can be + optimized later on by the peephole optimizer + } + list.concat(taicpu.op_reg(A_PUSH,tmpreg)); + list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg))); + list.concat(taicpu.op_reg(A_POP,NR_R27)); + list.concat(taicpu.op_reg(A_POP,NR_R26)); cg.a_label(list,l); - tmpreg:=getintregister(list,copysize); - list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref)); - list.concat(taicpu.op_ref_reg(A_ST,dstref,tmpreg)); + list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref)); + list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0)); a_op_const_reg(list,OP_SUB,countregsize,1,countreg); a_jmp_flags(list,F_NE,l); + // keep registers alive + list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg)); end else begin + SrcQuickRef:=false; + DestQuickRef:=false; + if not((source.addressmode=AM_UNCHANGED) and + (source.symbol=nil) and + ((source.base=NR_R28) or + (source.base=NR_R29)) and + (source.Index=NR_No) and + (source.Offset in [0..64-len])) and + not((source.Base=NR_NO) and (source.Index=NR_NO)) then + srcref:=normalize_ref(list,source,NR_R30) + else + begin + SrcQuickRef:=true; + srcref:=source; + end; + + if not((dest.addressmode=AM_UNCHANGED) and + (dest.symbol=nil) and + ((dest.base=NR_R28) or + (dest.base=NR_R29)) and + (dest.Index=NR_No) and + (dest.Offset in [0..64-len])) and + not((dest.Base=NR_NO) and (dest.Index=NR_NO)) then + begin + if not(SrcQuickRef) then + begin + tmpreg:=getaddressregister(list); + dstref:=normalize_ref(list,dest,tmpreg); + + { X is used for spilling code so we can load it + only by a push/pop sequence, this can be + optimized later on by the peephole optimizer + } + list.concat(taicpu.op_reg(A_PUSH,tmpreg)); + list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg))); + list.concat(taicpu.op_reg(A_POP,NR_R27)); + list.concat(taicpu.op_reg(A_POP,NR_R26)); + end + else + dstref:=normalize_ref(list,dest,NR_R30); + end + else + begin + DestQuickRef:=true; + dstref:=dest; + end; + for i:=1 to len do begin - srcref:=normalize_ref(list,source); - dstref:=normalize_ref(list,source); - copysize:=OS_8; - tmpreg:=getintregister(list,copysize); - if (srcref.base<>NR_NO) and (i<len) then + if not(SrcQuickRef) and (i<len) then srcref.addressmode:=AM_POSTINCREMENT else srcref.addressmode:=AM_UNCHANGED; - if (dstref.base<>NR_NO) and (i<len) then + + if not(DestQuickRef) and (i<len) then dstref.addressmode:=AM_POSTINCREMENT else dstref.addressmode:=AM_UNCHANGED; - list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref)); - list.concat(taicpu.op_ref_reg(A_ST,dstref,tmpreg)); - - if (dstref.offset<>0) or assigned(dstref.symbol) then - inc(dstref.offset); - if (srcref.offset<>0) or assigned(srcref.symbol) then - inc(srcref.offset); + list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref)); + list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0)); + if SrcQuickRef then + inc(srcref.offset); + if DestQuickRef then + inc(dstref.offset); + end; + if not(SrcQuickRef) then + begin + ungetcpuregister(list,srcref.base); + ungetcpuregister(list,GetNextReg(srcref.base)); end; end; end; @@ -1198,11 +1581,24 @@ unit cgcpu; end; + procedure tcgavr.g_save_registers(list: TAsmList); + begin + { this is done by the entry code } + end; + + + procedure tcgavr.g_restore_registers(list: TAsmList); + begin + { this is done by the exit code } + end; + + procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel); var ai : taicpu; begin - {!!!!! + { TODO : fix a_jmp_cond } + { ai:=Taicpu.Op_sym(A_BRxx,l); case cond of OC_EQ: @@ -1243,41 +1639,13 @@ unit cgcpu; procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64); begin - internalerror(2011021325); + { TODO : a_op64_reg_reg } end; procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64); begin - a_op64_const_reg_reg(list,op,size,value,reg,reg); - end; - - - procedure tcg64favr.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64); - var - ovloc : tlocation; - begin - a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,ovloc); - end; - - - procedure tcg64favr.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64); - var - ovloc : tlocation; - begin - a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,ovloc); - end; - - - procedure tcg64favr.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation); - begin - internalerror(2011021326); - end; - - - procedure tcg64favr.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation); - begin - internalerror(2011021327); + { TODO : a_op64_const_reg } end; diff --git a/compiler/avr/cpubase.pas b/compiler/avr/cpubase.pas index 4356358107..94ab41a06b 100644 --- a/compiler/avr/cpubase.pas +++ b/compiler/avr/cpubase.pas @@ -44,7 +44,7 @@ unit cpubase; type TAsmOp=(A_None, - A_ADD,A_ADC,A_ADIW,A_SUB,A_SUBI,A_SBC,A_SBCI,A_SBIW,A_AND,A_ANDI, + A_ADD,A_ADC,A_ADIW,A_SUB,A_SUBI,A_SBC,A_SBCI,A_SBRC,A_SBRS,A_CLC,A_SEC,A_SBIW,A_AND,A_ANDI, A_OR,A_ORI,A_EOR,A_COM,A_NEG,A_SBR,A_CBR,A_INC,A_DEC,A_TST,A_CLR, A_SER,A_MUL,A_MULS,A_FMUL,A_FMULS,A_FMULSU,A_RJMP,A_IJMP, A_EIJMP,A_JMP,A_RCALL,A_ICALL,R_EICALL,A_CALL,A_RET,A_RETI,A_CPSE, @@ -121,7 +121,7 @@ unit cpubase; {$i ravrdwa.inc} ); { registers which may be destroyed by calls } - VOLATILE_INTREGISTERS = [RS_R18..RS_R27,RS_R30..RS_R31]; + VOLATILE_INTREGISTERS = [RS_R0,RS_R1,RS_R8..RS_R27,RS_R30,RS_R31]; VOLATILE_FPUREGISTERS = []; type @@ -259,8 +259,8 @@ unit cpubase; NR_STACK_POINTER_REG = NR_R13; RS_STACK_POINTER_REG = RS_R13; { Frame pointer register } - RS_FRAME_POINTER_REG = RS_R11; - NR_FRAME_POINTER_REG = NR_R11; + RS_FRAME_POINTER_REG = RS_R28; + NR_FRAME_POINTER_REG = NR_R28; { Register for addressing absolute data in a position independant way, such as in PIC code. The exact meaning is ABI specific. For further information look at GCC source : PIC_OFFSET_TABLE_REGNUM @@ -306,8 +306,10 @@ unit cpubase; This value can be deduced from the CALLED_USED_REGISTERS array in the GCC source. } - saved_standard_registers : array[0..6] of tsuperregister = - (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10); + { on avr, gen_entry/gen_exit code saves/restores registers, so + we don't need this array } + saved_standard_registers : array[0..0] of tsuperregister = + (RS_INVALID); { Required parameter alignment when calling a routine declared as stdcall and cdecl. The alignment value should be the one defined by GCC or the target ABI. @@ -341,6 +343,11 @@ unit cpubase; { returns the next virtual register } function GetNextReg(const r : TRegister) : TRegister; + { returns the last virtual register } + function GetLastReg(const r : TRegister) : TRegister; + + function GetOffsetReg(const r : TRegister;ofs : shortint) : TRegister; + implementation uses @@ -469,4 +476,16 @@ unit cpubase; result:=TRegister(longint(r)+1); end; + + function GetLastReg(const r: TRegister): TRegister; + begin + result:=TRegister(longint(r)-1); + end; + + + function GetOffsetReg(const r: TRegister;ofs : shortint): TRegister; + begin + result:=TRegister(longint(r)+ofs); + end; + end. diff --git a/compiler/avr/cpuinfo.pas b/compiler/avr/cpuinfo.pas index 0195b88e7b..9496374a63 100644 --- a/compiler/avr/cpuinfo.pas +++ b/compiler/avr/cpuinfo.pas @@ -32,8 +32,30 @@ Type { possible supported processors for this target } tcputype = (cpu_none, - cpu_avr + cpu_avr1, + cpu_avr2, + cpu_avr25, + cpu_avr3, + cpu_avr31, + cpu_avr35, + cpu_avr4, + cpu_avr5, + cpu_avr51, + cpu_avr6 ); + + tcpuflags = + (AVR_HAVE_JMP_CALL, + AVR_HAVE_MOVW, + AVR_HAVE_LPMX, + AVR_HAVE_MUL, + AVR_HAVE_RAMPZ, + AVR_HAVE_ELPM, + AVR_HAVE_ELPMX, + AVR_2_BYTE_PC, + AVR_3_BYTE_PC + ); + tfputype = (fpu_none, fpu_soft, @@ -72,7 +94,16 @@ Const ]; cputypestr : array[tcputype] of string[5] = ('', - 'AVR' + 'AVR1', + 'AVR2', + 'AVR25', + 'AVR3', + 'AVR31', + 'AVR35', + 'AVR4', + 'AVR5', + 'AVR51', + 'AVR6' ); fputypestr : array[tfputype] of string[6] = ( @@ -112,6 +143,20 @@ Const [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion]; level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}]; + cpu_capabilities : array[tcputype] of set of tcpuflags = + ( { cpu_none } [], + { cpu_avr1 } [], + { cpu_avr2 } [], + { cpu_avr25 } [], + { cpu_avr3 } [], + { cpu_avr31 } [], + { cpu_avr35 } [], + { cpu_avr4 } [], + { cpu_avr5 } [], + { cpu_avr51 } [], + { cpu_avr6 } [] + ); + Implementation end. diff --git a/compiler/avr/cpupara.pas b/compiler/avr/cpupara.pas index 57d84ffb89..d313d24896 100644 --- a/compiler/avr/cpupara.pas +++ b/compiler/avr/cpupara.pas @@ -84,17 +84,17 @@ unit cpupara; begin size:=OS_INT; { the four first parameters are passed into registers } - if nr<=4 then + if nr<=9 then begin loc:=LOC_REGISTER; - register:=newreg(R_INTREGISTER,RS_R0+nr-1,R_SUBWHOLE); + 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-5)*4; + reference.offset:=(nr-10)*2; end; end; end; @@ -200,13 +200,14 @@ unit cpupara; procedure tavrparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); begin - curintreg:=RS_R0; + curintreg:=RS_R25; curfloatreg:=RS_INVALID; curmmreg:=RS_INVALID; cur_stack_offset:=0; end; + { TODO : fix tavrparamanager.create_paraloc_info_intern } function tavrparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint; @@ -225,7 +226,7 @@ unit cpupara; begin { In case of po_delphi_nested_cc, the parent frame pointer is always passed on the stack. } - if (nextintreg<=RS_R3) and + if (nextintreg>RS_R8) and (not(vo_is_parentfp in hp.varoptions) or not(po_delphi_nested_cc in p.procoptions)) then begin @@ -238,7 +239,7 @@ unit cpupara; paraloc^.loc:=LOC_REFERENCE; paraloc^.reference.index:=NR_STACK_POINTER_REG; paraloc^.reference.offset:=stack_offset; - inc(stack_offset,4); + dec(stack_offset,2); end; end; @@ -265,7 +266,7 @@ unit cpupara; paraloc:=hp.paraloc[side].add_location; { hack: the paraloc must be valid, but is not actually used } paraloc^.loc:=LOC_REGISTER; - paraloc^.register:=NR_R0; + paraloc^.register:=NR_R25; paraloc^.size:=OS_ADDR; break; end; @@ -333,11 +334,11 @@ unit cpupara; begin { this is not abi compliant why? (FK) } - if nextintreg<=RS_R3 then + if nextintreg>=RS_R8 then begin paraloc^.loc:=LOC_REGISTER; paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE); - inc(nextintreg); + dec(nextintreg); end else begin @@ -374,7 +375,7 @@ unit cpupara; if paraloc^.loc=LOC_REFERENCE then begin paraloc^.reference.index:=NR_FRAME_POINTER_REG; - inc(paraloc^.reference.offset,4); + inc(paraloc^.reference.offset,2); end; end; dec(paralen,tcgsize2size[paraloc^.size]); @@ -408,6 +409,7 @@ unit cpupara; end; + { TODO : fix tavrparamanager.get_funcretloc } function tavrparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara; var retcgsize : tcgsize; diff --git a/compiler/avr/cpupi.pas b/compiler/avr/cpupi.pas index 18a92a8f4a..e6934f07c3 100644 --- a/compiler/avr/cpupi.pas +++ b/compiler/avr/cpupi.pas @@ -33,7 +33,6 @@ unit cpupi; type tavrprocinfo = class(tcgprocinfo) - floatregstart : aint; // procedure handle_body_start;override; // procedure after_pass1;override; procedure set_first_temp_offset;override; @@ -54,26 +53,14 @@ unit cpupi; procedure tavrprocinfo.set_first_temp_offset; begin - { We allocate enough space to save all registers because we can't determine - the necessary space because the used registers aren't known before - secondpass is run. Even worse, patching - the local offsets after generating the code could cause trouble because - "shifter" constants could change to non-"shifter" constants. This - is especially a problem when taking the address of a local. For now, - this extra memory should hurt less than generating all local contants with offsets - >256 as non shifter constants } if tg.direction = -1 then - tg.setfirsttemp(-12-28) + tg.setfirsttemp(0) else tg.setfirsttemp(maxpushedparasize); end; function tavrprocinfo.calc_stackframe_size:longint; - var - firstfloatreg,lastfloatreg, - r : byte; - floatsavesize : aword; begin maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4)); end; @@ -82,3 +69,4 @@ unit cpupi; begin cprocinfo:=tavrprocinfo; end. + diff --git a/compiler/avr/itcpugas.pas b/compiler/avr/itcpugas.pas index 1d48e93011..6af73515c7 100644 --- a/compiler/avr/itcpugas.pas +++ b/compiler/avr/itcpugas.pas @@ -35,7 +35,7 @@ interface processor manufacturer. } gas_op2str : op2strtable = ('', - 'add','adc','adiw','sub','subi','sbc','sbci','sbiw','and','andi', + 'add','adc','adiw','sub','subi','sbc','sbci','sbrc','sbrs','clc','sec','sbiw','and','andi', 'or','ori','eor','com','neg','sbr','cbr','inc','dec','tst','clr', 'ser','mul','muls','fmul','fmuls','fmulsu','rjmp','ijmp', 'eijmp','jmp','rcall','icall','eicall','call','ret','reti','cpse', diff --git a/compiler/avr/navradd.pas b/compiler/avr/navradd.pas index ab94bc1305..aefa78955b 100644 --- a/compiler/avr/navradd.pas +++ b/compiler/avr/navradd.pas @@ -120,25 +120,36 @@ interface procedure tavraddnode.second_cmpsmallset; + + procedure gencmp(tmpreg1,tmpreg2 : tregister); + var + i : byte; + begin + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,tmpreg1,tmpreg2)); + for i:=2 to tcgsize2size[left.location.size] do + begin + tmpreg1:=GetNextReg(tmpreg1); + tmpreg2:=GetNextReg(tmpreg2); + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,tmpreg2)); + end; + end; + var tmpreg : tregister; begin - { pass_left_right; - location_reset(location,LOC_FLAGS,OS_NO); - force_reg_left_right(false,false); case nodetype of equaln: begin - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register)); + gencmp(left.location.register,right.location.register); location.resflags:=F_EQ; end; unequaln: begin - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register)); + gencmp(left.location.register,right.location.register); location.resflags:=F_NE; end; lten, @@ -150,14 +161,14 @@ interface (nodetype = gten)) then swapleftright; tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register)); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register)); + cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,location.size, + left.location.register,right.location.register,tmpreg); + gencmp(tmpreg,right.location.register); location.resflags:=F_EQ; end; else internalerror(2004012401); end; - } end; @@ -182,6 +193,13 @@ interface for i:=2 to tcgsize2size[left.location.size] do begin + tmpreg1:=GetNextReg(tmpreg1); + tmpreg2:=GetNextReg(tmpreg2); + if i=5 then + begin + tmpreg1:=left.location.registerhi; + tmpreg2:=right.location.registerhi; + end; current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,tmpreg2)); end; diff --git a/compiler/avr/navrcnv.pas b/compiler/avr/navrcnv.pas index fd5cbd218d..4afaf6bc95 100644 --- a/compiler/avr/navrcnv.pas +++ b/compiler/avr/navrcnv.pas @@ -44,7 +44,7 @@ interface { procedure second_cord_to_pointer;override; } { procedure second_proc_to_procvar;override; } { procedure second_bool_to_int;override; } - procedure second_int_to_bool;override; + { procedure second_int_to_bool;override; } { procedure second_load_smallset;override; } { procedure second_ansistring_to_pchar;override; } { procedure second_pchar_to_string;override; } @@ -54,127 +54,6 @@ interface implementation - uses - verbose,globtype,globals,systems, - symconst,symdef,aasmbase,aasmtai,aasmdata, - defutil, - cgbase,cgutils, - pass_1,pass_2,procinfo, - ncon,ncal, - ncgutil, - cpubase,aasmcpu, - rgobj,tgobj,cgobj,cgcpu; - - - procedure tarmtypeconvnode.second_int_to_bool; - var - hregister : tregister; - href : treference; - resflags : tresflags; - hlabel,oldTrueLabel,oldFalseLabel : tasmlabel; - newsize : tcgsize; - begin - { - oldTrueLabel:=current_procinfo.CurrTrueLabel; - oldFalseLabel:=current_procinfo.CurrFalseLabel; - current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel); - current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel); - secondpass(left); - if codegenerror then - exit; - - { Explicit typecasts from any ordinal type to a boolean type } - { must not change the ordinal value } - if (nf_explicit in flags) and - not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then - begin - location_copy(location,left.location); - newsize:=def_cgsize(resultdef); - { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend } - if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or - ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then - location_force_reg(current_asmdata.CurrAsmList,location,newsize,true) - else - location.size:=newsize; - current_procinfo.CurrTrueLabel:=oldTrueLabel; - current_procinfo.CurrFalseLabel:=oldFalseLabel; - exit; - end; - - { Load left node into flag F_NE/F_E } - resflags:=F_NE; - case left.location.loc of - LOC_CREFERENCE, - LOC_REFERENCE : - begin - if left.location.size in [OS_64,OS_S64] then - begin - hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hregister); - href:=left.location.reference; - inc(href.offset,4); - tcgarm(cg).cgsetflags:=true; - cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hregister); - tcgarm(cg).cgsetflags:=false; - end - else - begin - location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true); - tcgarm(cg).cgsetflags:=true; - cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register); - tcgarm(cg).cgsetflags:=false; - end; - end; - LOC_FLAGS : - begin - resflags:=left.location.resflags; - end; - LOC_REGISTER,LOC_CREGISTER : - begin - if left.location.size in [OS_64,OS_S64] then - begin - hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); - cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,hregister); - tcgarm(cg).cgsetflags:=true; - cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister); - tcgarm(cg).cgsetflags:=false; - end - else - begin - tcgarm(cg).cgsetflags:=true; - cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register); - tcgarm(cg).cgsetflags:=false; - end; - end; - LOC_JUMP : - begin - hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); - current_asmdata.getjumplabel(hlabel); - cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel); - cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hregister); - cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel); - cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel); - cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hregister); - cg.a_label(current_asmdata.CurrAsmList,hlabel); - tcgarm(cg).cgsetflags:=true; - cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,hregister,hregister); - tcgarm(cg).cgsetflags:=false; - end; - else - internalerror(200311301); - end; - { load flags to register } - location_reset(location,LOC_REGISTER,def_cgsize(resultdef)); - location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size); - cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,location.register); - if (is_cbool(resultdef)) then - cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,location.register,location.register); - current_procinfo.CurrTrueLabel:=oldTrueLabel; - current_procinfo.CurrFalseLabel:=oldFalseLabel; - } - end; - - begin ctypeconvnode:=tarmtypeconvnode; end. diff --git a/compiler/avr/raavrgas.pas b/compiler/avr/raavrgas.pas index 252f4a7ce9..c5ce6d1fa0 100644 --- a/compiler/avr/raavrgas.pas +++ b/compiler/avr/raavrgas.pas @@ -333,13 +333,6 @@ Unit raavrgas; BuildReference(oper); end; - AS_HASH: { Constant expression } - Begin - Consume(AS_HASH); - BuildConstantOperand(oper); - end; - - (* AS_INTNUM, AS_MINUS, AS_PLUS: @@ -348,16 +341,18 @@ Unit raavrgas; { This must absolutely be followed by ( } oper.InitRef; oper.opr.ref.offset:=BuildConstExpression(True,False); - if actasmtoken<>AS_LPAREN then + + { absolute memory addresss? } + if actopcode in [A_LDS,A_STS] then + BuildReference(oper) + else begin ofs:=oper.opr.ref.offset; BuildConstantOperand(oper); inc(oper.opr.val,ofs); - end - else - BuildReference(oper); + end; end; - *) + AS_ID: { A constant expression, or a Variable ref. } Begin { Local Label ? } diff --git a/compiler/avr/rgcpu.pas b/compiler/avr/rgcpu.pas index 34e5f728b0..602ec1c2ff 100644 --- a/compiler/avr/rgcpu.pas +++ b/compiler/avr/rgcpu.pas @@ -87,28 +87,80 @@ unit rgcpu; end; - procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister); + var + helpins : tai; + tmpref : treference; + helplist : TAsmList; + hreg : tregister; begin - inherited do_spill_read(list,pos,spilltemp,tempreg); + if abs(spilltemp.offset)>63 then + begin + helplist:=TAsmList.create; + + helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset)))); + helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset)))); + helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base)); + helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base))); + + reference_reset_base(tmpref,NR_R26,0,1); + helpins:=spilling_create_load(tmpref,tempreg); + helplist.concat(helpins); + list.insertlistafter(pos,helplist); + helplist.free; + end + else + inherited do_spill_read(list,pos,spilltemp,tempreg); end; procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister); + var + tmpref : treference; + helplist : TAsmList; + hreg : tregister; begin - inherited do_spill_written(list,pos,spilltemp,tempreg); - end; + if abs(spilltemp.offset)>63 then + begin + helplist:=TAsmList.create; + + helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset)))); + helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset)))); + helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base)); + helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base))); + + reference_reset_base(tmpref,NR_R26,0,1); + helplist.concat(spilling_create_store(tempreg,tmpref)); + list.insertlistafter(pos,helplist); + helplist.free; + end + else + inherited do_spill_written(list,pos,spilltemp,tempreg); + end; procedure trgintcpu.add_cpu_interferences(p : tai); var - r : tregister; + r : tsuperregister; begin if p.typ=ait_instruction then begin case taicpu(p).opcode of - A_LD: - ; + A_CPI, + A_ANDI, + A_ORI, + A_SUBI, + A_SBCI, + A_LDI: + for r:=RS_R0 to RS_R15 do + add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg)); + A_MULS: + begin + for r:=RS_R0 to RS_R15 do + add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg)); + for r:=RS_R0 to RS_R15 do + add_edge(r,GetSupReg(taicpu(p).oper[1]^.reg)); + end; end; end; end; |