navrmat.pas 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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. location_copy(location,left.location);
  93. inverse_flags(location.resflags);
  94. end;
  95. LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF,
  96. LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE :
  97. begin
  98. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  99. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,GetDefaultZeroReg,left.location.register));
  100. tmpreg:=left.location.register;
  101. for i:=2 to tcgsize2size[left.location.size] do
  102. begin
  103. if i=5 then
  104. tmpreg:=left.location.registerhi
  105. else
  106. tmpreg:=cg.GetNextReg(tmpreg);
  107. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,GetDefaultZeroReg,tmpreg));
  108. end;
  109. location_reset(location,LOC_FLAGS,OS_NO);
  110. location.resflags:=F_EQ;
  111. end;
  112. else
  113. internalerror(2003042401);
  114. end;
  115. end;
  116. end;
  117. {*****************************************************************************
  118. TAVRSHLSHRNODE
  119. *****************************************************************************}
  120. function tavrshlshrnode.pass_1 : tnode;
  121. begin
  122. { the avr code generator can handle 64 bit shifts by constants directly }
  123. if is_constintnode(right) and is_64bit(resultdef) then
  124. begin
  125. result:=nil;
  126. firstpass(left);
  127. firstpass(right);
  128. if codegenerror then
  129. exit;
  130. expectloc:=LOC_REGISTER;
  131. end
  132. else
  133. Result:=inherited pass_1;
  134. end;
  135. procedure tavrshlshrnode.second_integer;
  136. var
  137. op : topcg;
  138. opdef: tdef;
  139. hcountreg : tregister;
  140. opsize : tcgsize;
  141. shiftval : longint;
  142. begin
  143. { determine operator }
  144. case nodetype of
  145. shln: op:=OP_SHL;
  146. shrn: op:=OP_SHR;
  147. else
  148. internalerror(2013120109);
  149. end;
  150. opsize:=left.location.size;
  151. opdef:=left.resultdef;
  152. if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
  153. { location_force_reg can be also used to change the size of a register }
  154. (left.location.size<>opsize) then
  155. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
  156. location_reset(location,LOC_REGISTER,opsize);
  157. if is_64bit(resultdef) then
  158. begin
  159. location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  160. location.registerhi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  161. end
  162. else
  163. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  164. { shifting by a constant directly coded: }
  165. if (right.nodetype=ordconstn) then
  166. begin
  167. { shl/shr must "wrap around", so use ... and 31 }
  168. { In TP, "byte/word shl 16 = 0", so no "and 15" in case of
  169. a 16 bit ALU }
  170. if tcgsize2size[opsize]<=4 then
  171. shiftval:=tordconstnode(right).value.uvalue and 31
  172. else
  173. shiftval:=tordconstnode(right).value.uvalue and 63;
  174. if is_64bit(resultdef) then
  175. cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,location.size,
  176. shiftval,left.location.register64,location.register64)
  177. else
  178. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef,
  179. shiftval,left.location.register,location.register);
  180. end
  181. else
  182. begin
  183. { load right operators in a register - this
  184. is done since most target cpu which will use this
  185. node do not support a shift count in a mem. location (cec)
  186. }
  187. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,sinttype,true);
  188. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,right.location.register,left.location.register,location.register);
  189. end;
  190. { shl/shr nodes return the same type as left, which can be different
  191. from opdef }
  192. if opdef<>resultdef then
  193. begin
  194. hcountreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  195. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,opdef,resultdef,location.register,hcountreg);
  196. location.register:=hcountreg;
  197. end;
  198. end;
  199. procedure tavrshlshrnode.second_64bit;
  200. begin
  201. second_integer;
  202. // inherited second_64bit;
  203. end;
  204. begin
  205. cnotnode:=tavrnotnode;
  206. cshlshrnode:=tavrshlshrnode;
  207. end.