navrmat.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. procedure second_integer;override;
  28. end;
  29. implementation
  30. uses
  31. globtype,systems,
  32. cutils,verbose,globals,constexp,
  33. symtype,symdef,
  34. aasmbase,aasmcpu,aasmtai,aasmdata,
  35. defutil,
  36. cgbase,cgobj,hlcgobj,cgutils,
  37. pass_2,procinfo,
  38. ncon,
  39. cpubase,
  40. ncgutil,cgcpu;
  41. {*****************************************************************************
  42. TAVRNOTNODE
  43. *****************************************************************************}
  44. procedure tavrnotnode.second_boolean;
  45. var
  46. tmpreg,lreg : tregister;
  47. i : longint;
  48. falselabel,truelabel,skiplabel: TAsmLabel;
  49. begin
  50. if not handle_locjump then
  51. begin
  52. secondpass(left);
  53. { short code? }
  54. if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG]) and
  55. (left.location.sreg.bitlen=1) then
  56. begin
  57. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,left.location.sreg.subsetreg,left.location.sreg.startbit));
  58. current_asmdata.getjumplabel(truelabel);
  59. current_asmdata.getjumplabel(falselabel);
  60. { sbrc does a jump without an explicit label,
  61. if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether }
  62. current_asmdata.getjumplabel(skiplabel);
  63. skiplabel.increfs;
  64. location_reset_jump(location,truelabel,falselabel);
  65. cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
  66. cg.a_label(current_asmdata.CurrAsmList,skiplabel);
  67. cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel);
  68. end
  69. else if (left.location.loc in [LOC_SUBSETREF,LOC_CSUBSETREF]) and
  70. (left.location.sref.bitlen=1) and (left.location.sref.bitindexreg=NR_NO) then
  71. begin
  72. tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_8);
  73. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,u8inttype,osuinttype,left.location.sref.ref,tmpreg);
  74. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,tmpreg,left.location.sref.startbit));
  75. current_asmdata.getjumplabel(truelabel);
  76. current_asmdata.getjumplabel(falselabel);
  77. { sbrc does a jump without an explicit label,
  78. if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether }
  79. current_asmdata.getjumplabel(skiplabel);
  80. skiplabel.increfs;
  81. location_reset_jump(location,truelabel,falselabel);
  82. cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
  83. cg.a_label(current_asmdata.CurrAsmList,skiplabel);
  84. cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel);
  85. end
  86. else
  87. case left.location.loc of
  88. LOC_FLAGS :
  89. begin
  90. location_copy(location,left.location);
  91. inverse_flags(location.resflags);
  92. end;
  93. LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF,
  94. LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE :
  95. begin
  96. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  97. current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0));
  98. tmpreg:=left.location.register;
  99. for i:=2 to tcgsize2size[left.location.size] do
  100. begin
  101. if i=5 then
  102. tmpreg:=left.location.registerhi
  103. else
  104. tmpreg:=cg.GetNextReg(tmpreg);
  105. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,NR_R1,tmpreg));
  106. end;
  107. location_reset(location,LOC_FLAGS,OS_NO);
  108. location.resflags:=F_EQ;
  109. end;
  110. else
  111. internalerror(2003042401);
  112. end;
  113. end;
  114. end;
  115. procedure tavrshlshrnode.second_integer;
  116. var
  117. op : topcg;
  118. opdef: tdef;
  119. hcountreg : tregister;
  120. opsize : tcgsize;
  121. shiftval : longint;
  122. begin
  123. { determine operator }
  124. case nodetype of
  125. shln: op:=OP_SHL;
  126. shrn: op:=OP_SHR;
  127. else
  128. internalerror(2013120102);
  129. end;
  130. opsize:=left.location.size;
  131. opdef:=left.resultdef;
  132. if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
  133. { location_force_reg can be also used to change the size of a register }
  134. (left.location.size<>opsize) then
  135. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
  136. location_reset(location,LOC_REGISTER,opsize);
  137. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  138. { shifting by a constant directly coded: }
  139. if (right.nodetype=ordconstn) then
  140. begin
  141. { shl/shr must "wrap around", so use ... and 31 }
  142. { In TP, "byte/word shl 16 = 0", so no "and 15" in case of
  143. a 16 bit ALU }
  144. if tcgsize2size[opsize]<=4 then
  145. shiftval:=tordconstnode(right).value.uvalue and 31
  146. else
  147. shiftval:=tordconstnode(right).value.uvalue and 63;
  148. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef,
  149. shiftval,left.location.register,location.register);
  150. end
  151. else
  152. begin
  153. { load right operators in a register - this
  154. is done since most target cpu which will use this
  155. node do not support a shift count in a mem. location (cec)
  156. }
  157. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,sinttype,true);
  158. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,right.location.register,left.location.register,location.register);
  159. end;
  160. { shl/shr nodes return the same type as left, which can be different
  161. from opdef }
  162. if opdef<>resultdef then
  163. begin
  164. hcountreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  165. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,opdef,resultdef,location.register,hcountreg);
  166. location.register:=hcountreg;
  167. end;
  168. end;
  169. begin
  170. cnotnode:=tavrnotnode;
  171. cshlshrnode:=tavrshlshrnode;
  172. end.