123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- {
- Copyright (c) 2014 by Jonas Maebe
- Generate AArch64 code for in memory related nodes
- 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 ncpumem;
- {$i fpcdefs.inc}
- interface
- uses
- globtype,
- cgbase,
- symtype,
- node,nmem,ncgmem;
- type
- taarch64loadparentfpnode = class(tcgloadparentfpnode)
- procedure pass_generate_code; override;
- end;
- taarch64vecnode = class(tcgvecnode)
- protected
- function valid_index_size(size: tcgsize): boolean; override;
- public
- procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint); override;
- end;
- implementation
- uses
- cutils,verbose,
- defutil,
- aasmdata,cpubase,
- cgutils,
- cgobj;
- { taarch64loadparentfpnode }
- procedure taarch64loadparentfpnode.pass_generate_code;
- begin
- inherited pass_generate_code;
- { see the comments in tcgaarch64.g_proc_entry }
- if (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
- (location.register=NR_STACK_POINTER_REG) then
- if (kind=lpf_forpara) then
- location.register:=NR_FRAME_POINTER_REG
- else
- begin
- { load stack pointer in a different register, as many instructions
- cannot directly work with the stack pointer. The register
- allocator can merge them if possible }
- location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
- cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_STACK_POINTER_REG,location.register);
- location.loc:=LOC_REGISTER;
- end;
- end;
- { taarch64vecnode }
- function taarch64vecnode.valid_index_size(size: tcgsize): boolean;
- begin
- { all sizes are ok if we handle the "reference reg mul", because
- a) we use a 64 bit register for 64 bit values, and a 32 bit one (that
- we can sign/zero-extend inside the reference) for smaller values
- b) for values < 32 bit, the entire 32 bit register always contains the
- sign/zero-extended version of the value }
- result:=
- not is_packed_array(left.resultdef) and
- (get_mul_size in [1,2,4,8,16]);
- end;
- procedure taarch64vecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
- var
- base: tregister;
- oldoffset: asizeint;
- shift: byte;
- begin
- { we can only scale the index by shl 0..4 }
- if not(l in [1,2,4,8,16]) then
- begin
- inherited;
- exit;
- end;
- { we need a base set and an index available }
- if (location.reference.base=NR_NO) or
- (location.reference.index<>NR_NO) then
- begin
- { don't integrate the offset yet, make_simple_ref() may be able to
- handle it more efficiently later (unless an offset is all we have
- -> optimization for someone that wants to add support for AArch64
- embedded targets) }
- oldoffset:=location.reference.offset;
- location.reference.offset:=0;
- base:=cg.getaddressregister(current_asmdata.CurrAsmList);
- cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,base);
- reference_reset_base(location.reference,base,oldoffset,location.reference.temppos,location.reference.alignment,location.reference.volatility);
- end;
- shift:=BsfDWord(l);
- location.reference.index:=maybe_const_reg;
- { sign/zero-extend? }
- if regsize.size=8 then
- if shift<>0 then
- location.reference.shiftmode:=SM_LSL
- else
- location.reference.shiftmode:=SM_NONE
- else if is_signed(regsize) then
- location.reference.shiftmode:=SM_SXTW
- else if shift<>0 then
- location.reference.shiftmode:=SM_UXTW
- else
- { the upper 32 bits are always already zero-extended -> just use 64 bit
- register }
- location.reference.index:=cg.makeregsize(current_asmdata.CurrAsmList,location.reference.index,OS_64);
- location.reference.shiftimm:=shift;
- location.reference.alignment:=newalignment(location.reference.alignment,l);
- end;
- begin
- cloadparentfpnode:=taarch64loadparentfpnode;
- cvecnode:=taarch64vecnode;
- end.
|