navrmat.pas 9.3 KB

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