diff options
author | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2012-10-23 20:15:47 +0000 |
---|---|---|
committer | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2012-10-23 20:15:47 +0000 |
commit | 730ac6c8d11db26a48e90e894037bf5666a336db (patch) | |
tree | 8ab26da5e03e19a167f4c711e1acf2bc74686dd2 | |
parent | ecfe3558794cd08d846705ff50b85193a15b9dd0 (diff) | |
download | fpc-730ac6c8d11db26a48e90e894037bf5666a336db.tar.gz |
+ support of 64 bit operations on avr
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@22836 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r-- | compiler/avr/cgcpu.pas | 247 |
1 files changed, 155 insertions, 92 deletions
diff --git a/compiler/avr/cgcpu.pas b/compiler/avr/cgcpu.pas index a7ce99033f..2e7230d3cb 100644 --- a/compiler/avr/cgcpu.pas +++ b/compiler/avr/cgcpu.pas @@ -56,7 +56,7 @@ unit cgcpu; procedure a_call_ref(list : TAsmList;ref: treference);override; procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override; - procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override; + procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override; { move instructions } procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override; @@ -107,6 +107,9 @@ unit cgcpu; function GetStore(const ref: treference): tasmop; procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override; + protected + procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister); + procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister); end; tcg64favr = class(tcg64f32) @@ -332,60 +335,22 @@ unit cgcpu; procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); - var - mask : qword; - shift : byte; - i : byte; - tmpreg : tregister; begin - mask:=$ff; - shift:=0; - case op of - OP_OR: - begin - for i:=1 to tcgsize2size[size] do - begin - list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift)); - reg:=GetNextReg(reg); - mask:=mask shl 8; - inc(shift,8); - end; - end; - OP_AND: - begin - for i:=1 to tcgsize2size[size] do - begin - list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift)); - reg:=GetNextReg(reg); - mask:=mask shl 8; - inc(shift,8); - end; - end; - OP_SUB: - begin - list.concat(taicpu.op_reg_const(A_SUBI,reg,a)); - 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 - reg:=GetNextReg(reg); - mask:=mask shl 8; - inc(shift,8); - list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift)); - end; - end; - end; - else - begin - tmpreg:=getintregister(list,size); - a_load_const_reg(list,size,a,tmpreg); - a_op_reg_reg(list,op,size,tmpreg,reg); - end; - end; + if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then + internalerror(2012102403); + a_op_const_reg_internal(list,Op,size,a,reg,NR_NO); + end; + + + procedure tcgavr.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); + begin + if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then + internalerror(2012102401); + a_op_reg_reg_internal(list,Op,size,src,NR_NO,dst,NR_NO); end; - procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); + procedure tcgavr.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister); var countreg, tmpreg: tregister; @@ -393,6 +358,30 @@ unit cgcpu; instr : taicpu; paraloc1,paraloc2,paraloc3 : TCGPara; l1,l2 : tasmlabel; + + procedure NextSrcDst; + begin + if i=5 then + begin + dst:=dsthi; + src:=srchi; + end + else + begin + dst:=GetNextReg(dst); + src:=GetNextReg(src); + end; + end; + + { iterates TmpReg through all registers of dst } + procedure NextTmp; + begin + if i=5 then + tmpreg:=dsthi + else + tmpreg:=GetNextReg(tmpreg); + end; + begin case op of OP_ADD: @@ -402,12 +391,10 @@ unit cgcpu; begin for i:=2 to tcgsize2size[size] do begin - dst:=GetNextReg(dst); - src:=GetNextReg(src); + NextSrcDst; list.concat(taicpu.op_reg_reg(A_ADC,dst,src)); - end; - end - else + end; + end; end; OP_SUB: @@ -417,8 +404,7 @@ unit cgcpu; begin for i:=2 to tcgsize2size[size] do begin - dst:=GetNextReg(dst); - src:=GetNextReg(src); + NextSrcDst; list.concat(taicpu.op_reg_reg(A_SBC,dst,src)); end; end; @@ -435,18 +421,16 @@ unit cgcpu; for i:=2 to tcgsize2size[size] do begin list.concat(taicpu.op_reg(A_COM,tmpreg)); - tmpreg:=GetNextReg(tmpreg); + NextTmp; end; list.concat(taicpu.op_reg(A_NEG,dst)); tmpreg:=GetNextReg(dst); for i:=2 to tcgsize2size[size] do begin list.concat(taicpu.op_reg_const(A_SBCI,dst,-1)); - tmpreg:=GetNextReg(tmpreg); + NextTmp; end; - end - else - list.concat(taicpu.op_reg(A_NEG,dst)); + end; end; OP_NOT: @@ -456,8 +440,7 @@ unit cgcpu; if src<>dst then a_load_reg_reg(list,OS_8,OS_8,src,dst); list.concat(taicpu.op_reg(A_COM,dst)); - src:=GetNextReg(src); - dst:=GetNextReg(dst); + NextSrcDst; end; end; @@ -508,11 +491,11 @@ unit cgcpu; cg.a_label(list,l1); case op of OP_SHR: - list.concat(taicpu.op_reg(A_LSR,GetOffsetReg(dst,tcgsize2size[size]-1))); + list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,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))); + list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1))); OP_ROR: begin { load carry? } @@ -522,7 +505,7 @@ unit cgcpu; 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))); + list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1))); end; OP_ROL: begin @@ -530,7 +513,7 @@ unit cgcpu; 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_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7)); list.concat(taicpu.op_none(A_SEC)); end; list.concat(taicpu.op_reg(A_ROL,dst)) @@ -545,12 +528,12 @@ unit cgcpu; case op of OP_ROR, OP_SHR: - list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i))); + list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i))); OP_ROL, OP_SHL: - list.concat(taicpu.op_reg(A_ROL,GetOffsetReg(dst,i-1))); + list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1))); OP_SAR: - list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i))); + list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i))); else internalerror(2011030902); end; @@ -569,8 +552,7 @@ unit cgcpu; for i:=1 to tcgsize2size[size] do begin list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src)); - dst:=GetNextReg(dst); - src:=GetNextReg(src); + NextSrcDst; end; end; else @@ -578,6 +560,81 @@ unit cgcpu; end; end; + procedure tcgavr.a_op_const_reg_internal(list: TAsmList; Op: TOpCG; + size: TCGSize; a: tcgint; reg, reghi: TRegister); + + var + mask : qword; + shift : byte; + i : byte; + tmpreg : tregister; + tmpreg64 : tregister64; + + procedure NextReg; + begin + if i=5 then + reg:=reghi + else + reg:=GetNextReg(reg); + end; + + begin + mask:=$ff; + shift:=0; + case op of + OP_OR: + begin + for i:=1 to tcgsize2size[size] do + begin + list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift)); + NextReg; + mask:=mask shl 8; + inc(shift,8); + end; + end; + OP_AND: + begin + for i:=1 to tcgsize2size[size] do + begin + list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift)); + NextReg; + mask:=mask shl 8; + inc(shift,8); + end; + end; + OP_SUB: + begin + list.concat(taicpu.op_reg_const(A_SUBI,reg,a)); + 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 + NextReg; + mask:=mask shl 8; + inc(shift,8); + list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift)); + end; + end; + end; + else + begin + if size in [OS_64,OS_S64] then + begin + tmpreg64.reglo:=getintregister(list,OS_32); + tmpreg64.reghi:=getintregister(list,OS_32); + cg64.a_load64_const_reg(list,a,tmpreg64); + cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi)); + end + else + begin + tmpreg:=getintregister(list,size); + a_load_const_reg(list,size,a,tmpreg); + a_op_reg_reg(list,op,size,tmpreg,reg); + end; + end; + end; + end; + procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister); var @@ -1020,18 +1077,20 @@ unit cgcpu; end; OS_S8: begin - { dest is always at least 16 bit at this point } emit_mov(list,reg2,reg1); - reg2:=GetNextReg(reg2); - list.concat(taicpu.op_reg(A_CLR,reg2)); - 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 + if tcgsize2size[tosize]>1 then begin reg2:=GetNextReg(reg2); - emit_mov(list,reg2,tmpreg); + list.concat(taicpu.op_reg(A_CLR,reg2)); + 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 + begin + reg2:=GetNextReg(reg2); + emit_mov(list,reg2,tmpreg); + end; end; end; OS_16: @@ -1050,22 +1109,24 @@ unit cgcpu; end; OS_S16: begin - { dest is always at least 32 bit at this point } emit_mov(list,reg2,reg1); reg1:=GetNextReg(reg1); reg2:=GetNextReg(reg2); emit_mov(list,reg2,reg1); - reg2:=GetNextReg(reg2); - list.concat(taicpu.op_reg(A_CLR,reg2)); - 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 + if tcgsize2size[tosize]>2 then begin reg2:=GetNextReg(reg2); - emit_mov(list,reg2,tmpreg); + list.concat(taicpu.op_reg(A_CLR,reg2)); + 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 + begin + reg2:=GetNextReg(reg2); + emit_mov(list,reg2,tmpreg); + end; end; end; else @@ -1733,13 +1794,15 @@ unit cgcpu; procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64); begin - { TODO : a_op64_reg_reg } + if not(size in [OS_S64,OS_64]) then + internalerror(2012102402); + tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi); end; procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64); begin - { TODO : a_op64_const_reg } + tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi); end; |