1 { 2 Copyright (c) 1998-2008 by Florian Klaempfl 3 4 Generates AVR assembler for math nodes 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 20 **************************************************************************** 21 } 22 unit navrmat; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 node,nmat,ncgmat; 30 31 type 32 tavrnotnode = class(tcgnotnode) 33 procedure second_boolean;override; 34 end; 35 36 tavrshlshrnode = class(tcgshlshrnode) 37 procedure second_integer;override; 38 end; 39 40 implementation 41 42 uses 43 globtype,systems, 44 cutils,verbose,globals,constexp, 45 symtype,symdef, 46 aasmbase,aasmcpu,aasmtai,aasmdata, 47 defutil, 48 cgbase,cgobj,hlcgobj,cgutils, 49 pass_2,procinfo, 50 ncon, 51 cpubase, 52 ncgutil,cgcpu; 53 54 {***************************************************************************** 55 TAVRNOTNODE 56 *****************************************************************************} 57 58 procedure tavrnotnode.second_boolean; 59 var 60 tmpreg,lreg : tregister; 61 i : longint; 62 falselabel,truelabel,skiplabel: TAsmLabel; 63 begin 64 if not handle_locjump then 65 begin 66 secondpass(left); 67 { short code? } 68 if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG]) and 69 (left.location.sreg.bitlen=1) then 70 begin 71 current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,left.location.sreg.subsetreg,left.location.sreg.startbit)); 72 current_asmdata.getjumplabel(truelabel); 73 current_asmdata.getjumplabel(falselabel); 74 { sbrc does a jump without an explicit label, 75 if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether } 76 current_asmdata.getjumplabel(skiplabel); 77 skiplabel.increfs; 78 location_reset_jump(location,truelabel,falselabel); 79 cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel); 80 cg.a_label(current_asmdata.CurrAsmList,skiplabel); 81 cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel); 82 end 83 else if (left.location.loc in [LOC_SUBSETREF,LOC_CSUBSETREF]) and 84 (left.location.sref.bitlen=1) and (left.location.sref.bitindexreg=NR_NO) then 85 begin 86 tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_8); 87 hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,u8inttype,osuinttype,left.location.sref.ref,tmpreg); 88 current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,tmpreg,left.location.sref.startbit)); 89 current_asmdata.getjumplabel(truelabel); 90 current_asmdata.getjumplabel(falselabel); 91 { sbrc does a jump without an explicit label, 92 if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether } 93 current_asmdata.getjumplabel(skiplabel); 94 skiplabel.increfs; 95 location_reset_jump(location,truelabel,falselabel); 96 cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel); 97 cg.a_label(current_asmdata.CurrAsmList,skiplabel); 98 cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel); 99 end 100 else 101 case left.location.loc of 102 LOC_FLAGS : 103 begin 104 location_copy(location,left.location); 105 inverse_flags(location.resflags); 106 end; 107 LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF, 108 LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE : 109 begin 110 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); 111 current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0)); 112 113 tmpreg:=left.location.register; 114 for i:=2 to tcgsize2size[left.location.size] do 115 begin 116 if i=5 then 117 tmpreg:=left.location.registerhi 118 else 119 tmpreg:=cg.GetNextReg(tmpreg); 120 current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,NR_R1,tmpreg)); 121 end; 122 location_reset(location,LOC_FLAGS,OS_NO); 123 location.resflags:=F_EQ; 124 end; 125 else 126 internalerror(2003042401); 127 end; 128 end; 129 end; 130 131 132 procedure tavrshlshrnode.second_integer; 133 var 134 op : topcg; 135 opdef: tdef; 136 hcountreg : tregister; 137 opsize : tcgsize; 138 shiftval : longint; 139 begin 140 { determine operator } 141 case nodetype of 142 shln: op:=OP_SHL; 143 shrn: op:=OP_SHR; 144 else 145 internalerror(2013120102); 146 end; 147 opsize:=left.location.size; 148 opdef:=left.resultdef; 149 150 if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or 151 { location_force_reg can be also used to change the size of a register } 152 (left.location.size<>opsize) then 153 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true); 154 location_reset(location,LOC_REGISTER,opsize); 155 location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 156 157 { shifting by a constant directly coded: } 158 if (right.nodetype=ordconstn) then 159 begin 160 { shl/shr must "wrap around", so use ... and 31 } 161 { In TP, "byte/word shl 16 = 0", so no "and 15" in case of 162 a 16 bit ALU } 163 if tcgsize2size[opsize]<=4 then 164 shiftval:=tordconstnode(right).value.uvalue and 31 165 else 166 shiftval:=tordconstnode(right).value.uvalue and 63; 167 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef, 168 shiftval,left.location.register,location.register); 169 end 170 else 171 begin 172 { load right operators in a register - this 173 is done since most target cpu which will use this 174 node do not support a shift count in a mem. location (cec) 175 } 176 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,sinttype,true); 177 hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,right.location.register,left.location.register,location.register); 178 end; 179 { shl/shr nodes return the same type as left, which can be different 180 from opdef } 181 if opdef<>resultdef then 182 begin 183 hcountreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 184 hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,opdef,resultdef,location.register,hcountreg); 185 location.register:=hcountreg; 186 end; 187 end; 188 189 begin 190 cnotnode:=tavrnotnode; 191 cshlshrnode:=tavrshlshrnode; 192 end. 193