123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- {
- Copyright (c) 1998-2002 by Florian Klaempfl
- This unit implements the code generator for the SPARC
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit cgcpu;
- {$i fpcdefs.inc}
- interface
- uses
- globtype,parabase,
- cgbase,cgutils,cgobj,
- cg64f32,
- aasmbase,aasmtai,aasmdata,aasmcpu,
- cpubase,cpuinfo,
- node,symconst,SymType,symdef,
- rgcpu,
- cgsparc;
- type
- TCGSparc=class(TCGSparcGen)
- procedure a_load_reg_reg(list : TAsmList; fromsize,tosize : tcgsize; reg1,reg2 : tregister);override;
- procedure a_load_const_reg(list : TAsmList; size : TCGSize; a : tcgint; reg : TRegister);override;
- end;
- TCg64Sparc=class(tcg64f32)
- private
- procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
- public
- procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
- procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
- procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
- 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;regdst: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;
- implementation
- uses
- verbose,
- systems;
- procedure TCGSparc.a_load_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1,reg2:tregister);
- var
- instr : taicpu;
- begin
- if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
- ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
- (fromsize <> tosize)) or
- { needs to mask out the sign in the top 16 bits }
- ((fromsize = OS_S8) and
- (tosize = OS_16)) then
- case tosize of
- OS_8 :
- list.concat(taicpu.op_reg_const_reg(A_AND,reg1,$ff,reg2));
- OS_16 :
- begin
- list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
- list.concat(taicpu.op_reg_const_reg(A_SRL,reg2,16,reg2));
- end;
- OS_32,
- OS_S32 :
- begin
- instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
- list.Concat(instr);
- { Notify the register allocator that we have written a move instruction so
- it can try to eliminate it. }
- add_move_instruction(instr);
- end;
- OS_S8 :
- begin
- list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,24,reg2));
- list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,24,reg2));
- end;
- OS_S16 :
- begin
- list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
- list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,16,reg2));
- end;
- else
- internalerror(2002090901);
- end
- else
- begin
- instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
- list.Concat(instr);
- { Notify the register allocator that we have written a move instruction so
- it can try to eliminate it. }
- add_move_instruction(instr);
- end;
- end;
- procedure TCGSparc.a_load_const_reg(list : TAsmList;size : TCGSize;a : tcgint;reg : TRegister);
- begin
- { we don't use the set instruction here because it could be evalutated to two
- instructions which would cause problems with the delay slot (FK) }
- if (a=0) then
- list.concat(taicpu.op_reg(A_CLR,reg))
- else if (a>=simm13lo) and (a<=simm13hi) then
- list.concat(taicpu.op_const_reg(A_MOV,a,reg))
- else
- begin
- list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 10,reg));
- if (aint(a) and aint($3ff))<>0 then
- list.concat(taicpu.op_reg_const_reg(A_OR,reg,aint(a) and aint($3ff),reg));
- end;
- end;
- {****************************************************************************
- TCG64Sparc
- ****************************************************************************}
- procedure tcg64sparc.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
- var
- tmpref: treference;
- begin
- { Override this function to prevent loading the reference twice }
- tmpref:=ref;
- cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
- inc(tmpref.offset,4);
- cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,tmpref);
- end;
- procedure tcg64sparc.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
- var
- tmpref: treference;
- begin
- { Override this function to prevent loading the reference twice }
- tmpref:=ref;
- cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
- inc(tmpref.offset,4);
- cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
- end;
- procedure tcg64sparc.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
- var
- hreg64 : tregister64;
- begin
- { Override this function to prevent loading the reference twice.
- Use here some extra registers, but those are optimized away by the RA }
- hreg64.reglo:=cg.GetIntRegister(list,OS_32);
- hreg64.reghi:=cg.GetIntRegister(list,OS_32);
- a_load64_ref_reg(list,r,hreg64);
- a_load64_reg_cgpara(list,hreg64,paraloc);
- end;
- procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
- begin
- case op of
- OP_ADD :
- begin
- op1:=A_ADDCC;
- if checkoverflow then
- op2:=A_ADDXCC
- else
- op2:=A_ADDX;
- end;
- OP_SUB :
- begin
- op1:=A_SUBCC;
- if checkoverflow then
- op2:=A_SUBXCC
- else
- op2:=A_SUBX;
- end;
- OP_XOR :
- begin
- op1:=A_XOR;
- op2:=A_XOR;
- end;
- OP_OR :
- begin
- op1:=A_OR;
- op2:=A_OR;
- end;
- OP_AND :
- begin
- op1:=A_AND;
- op2:=A_AND;
- end;
- else
- internalerror(2002032409);
- end;
- end;
- procedure TCg64Sparc.a_op64_reg_reg(list:TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);
- begin
- case op of
- OP_NEG :
- begin
- { Use the simple code: y=0-z }
- list.concat(taicpu.op_reg_reg_reg(A_SUBcc,NR_G0,regsrc.reglo,regdst.reglo));
- list.concat(taicpu.op_reg_reg_reg(A_SUBX,NR_G0,regsrc.reghi,regdst.reghi));
- end;
- OP_NOT :
- begin
- list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reglo,NR_G0,regdst.reglo));
- list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reghi,NR_G0,regdst.reghi));
- end;
- else
- a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
- end;
- end;
- procedure TCg64Sparc.a_op64_const_reg(list:TAsmList;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);
- begin
- a_op64_const_reg_reg(list,op,size,value,regdst,regdst);
- end;
- procedure tcg64sparc.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
- var
- l : tlocation;
- begin
- a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,l);
- end;
- procedure tcg64sparc.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
- var
- l : tlocation;
- begin
- a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,l);
- end;
- procedure tcg64sparc.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
- var
- op1,op2:TAsmOp;
- begin
- case op of
- OP_NEG,
- OP_NOT :
- internalerror(2003060102);
- OP_AND,OP_OR,OP_XOR:
- begin
- cg.a_op_const_reg_reg(list,op,OS_INT,tcgint(lo(value)),regsrc.reglo,regdst.reglo);
- cg.a_op_const_reg_reg(list,op,OS_INT,tcgint(hi(value)),regsrc.reghi,regdst.reghi);
- end;
- else
- get_64bit_ops(op,op1,op2,setflags);
- tcgsparc(cg).handle_reg_const_reg(list,op1,regsrc.reglo,tcgint(lo(value)),regdst.reglo);
- tcgsparc(cg).handle_reg_const_reg(list,op2,regsrc.reghi,tcgint(hi(value)),regdst.reghi);
- end;
- end;
- procedure tcg64sparc.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
- var
- op1,op2:TAsmOp;
- begin
- case op of
- OP_NEG,
- OP_NOT :
- internalerror(2003060103);
- else
- ;
- end;
- get_64bit_ops(op,op1,op2,setflags);
- list.concat(taicpu.op_reg_reg_reg(op1,regsrc2.reglo,regsrc1.reglo,regdst.reglo));
- list.concat(taicpu.op_reg_reg_reg(op2,regsrc2.reghi,regsrc1.reghi,regdst.reghi));
- end;
- procedure create_codegen;
- begin
- cg:=TCgSparc.Create;
- if target_info.system=system_sparc_linux then
- TCgSparc(cg).use_unlimited_pic_mode:=true
- else
- TCgSparc(cg).use_unlimited_pic_mode:=false;
- cg64:=TCg64Sparc.Create;
- end;
- end.
|