nppcset.pas 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
  4. Generate PowerPC assembler for in set/case nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit nppcset;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nset,ncgset,cpubase,cginfo,cgbase,cgobj,aasmbase,aasmtai;
  23. type
  24. tppccasenode = class(tcgcasenode)
  25. protected
  26. procedure genlinearlist(hp : pcaserecord); override;
  27. end;
  28. implementation
  29. uses
  30. globtype,systems,
  31. verbose,globals,
  32. symconst,symdef,defutil,
  33. paramgr,
  34. cpuinfo,
  35. pass_2,cgcpu,
  36. ncon,
  37. cga,tgobj,ncgutil,regvars,rgobj,aasmcpu;
  38. {*****************************************************************************
  39. TCGCASENODE
  40. *****************************************************************************}
  41. procedure tppccasenode.genlinearlist(hp : pcaserecord);
  42. var
  43. first : boolean;
  44. last : TConstExprInt;
  45. resflags: tresflags;
  46. procedure genitem(t : pcaserecord);
  47. procedure gensub(value:longint);
  48. var
  49. tmpreg: tregister;
  50. begin
  51. value := -value;
  52. if (value >= low(smallint)) and
  53. (value <= high(smallint)) then
  54. exprasmlist.concat(taicpu.op_reg_reg_const(A_ADDIC_,hregister,
  55. hregister,value))
  56. else
  57. begin
  58. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  59. cg.a_load_const_reg(exprasmlist,OS_INT,aword(value),tmpreg);
  60. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD_,hregister,
  61. hregister,tmpreg));
  62. cg.free_scratch_reg(exprasmlist,tmpreg);
  63. end;
  64. end;
  65. begin
  66. if assigned(t^.less) then
  67. genitem(t^.less);
  68. { need we to test the first value }
  69. if first and (t^._low>get_min_value(left.resulttype.def)) then
  70. begin
  71. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,
  72. aword(t^._low),hregister,elselabel);
  73. end;
  74. if t^._low=t^._high then
  75. begin
  76. if t^._low-last=0 then
  77. exprasmlist.concat(taicpu.op_reg_reg_const(A_CMPWI,R_CR0,
  78. hregister,0))
  79. else
  80. gensub(longint(t^._low-last));
  81. last:=t^._low;
  82. resflags.cr := R_CR0;
  83. resflags.flag := F_EQ;
  84. cg.a_jmp_flags(exprasmlist,resflags,t^.statement);
  85. end
  86. else
  87. begin
  88. { it begins with the smallest label, if the value }
  89. { is even smaller then jump immediately to the }
  90. { ELSE-label }
  91. if first then
  92. begin
  93. { have we to ajust the first value ? }
  94. if (t^._low>get_min_value(left.resulttype.def)) then
  95. gensub(longint(t^._low));
  96. end
  97. else
  98. begin
  99. { if there is no unused label between the last and the }
  100. { present label then the lower limit can be checked }
  101. { immediately. else check the range in between: }
  102. gensub(longint(t^._low-last));
  103. if (t^._low-last) <> 1 then
  104. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_lt,elselabel);
  105. end;
  106. gensub(longint(t^._high-t^._low));
  107. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_le,t^.statement);
  108. last:=t^._high;
  109. end;
  110. first:=false;
  111. if assigned(t^.greater) then
  112. genitem(t^.greater);
  113. end;
  114. begin
  115. { do we need to generate cmps? }
  116. if (with_sign and (min_label<0)) or
  117. (opsize = OS_32) then
  118. genlinearcmplist(hp)
  119. else
  120. begin
  121. last:=0;
  122. first:=true;
  123. genitem(hp);
  124. cg.a_jmp_always(exprasmlist,elselabel);
  125. end;
  126. end;
  127. begin
  128. ccasenode:=tppccasenode;
  129. end.
  130. {
  131. $Log$
  132. Revision 1.5 2002-11-25 17:43:28 peter
  133. * splitted defbase in defutil,symutil,defcmp
  134. * merged isconvertable and is_equal into compare_defs(_ext)
  135. * made operator search faster by walking the list only once
  136. Revision 1.4 2002/10/21 18:08:05 jonas
  137. * some range errors fixed
  138. Revision 1.3 2002/09/09 13:57:45 jonas
  139. * small optimization to case genlist() case statements
  140. Revision 1.2 2002/09/08 20:14:33 jonas
  141. * use genlinearcmplist() for unsigned 32bit case statements instead
  142. of genlinearlist(), because the addic. instruction always sets the
  143. flags as if the arguments are signed 32bits (for smaller unsigned
  144. types, this doesn't matter since they fit in s32bit)
  145. Revision 1.1 2002/08/11 11:39:12 jonas
  146. + powerpc-specific genlinearlist
  147. Revision 1.13 2002/08/11 06:14:40 florian
  148. * fixed powerpc compilation problems
  149. Revision 1.12 2002/08/10 17:15:12 jonas
  150. * optimizations and bugfix
  151. Revision 1.11 2002/07/28 09:24:18 carl
  152. + generic case node
  153. Revision 1.10 2002/07/23 14:31:00 daniel
  154. * Added internal error when asked to generate code for 'if expr in []'
  155. Revision 1.9 2002/07/23 12:34:30 daniel
  156. * Readded old set code. To use it define 'oldset'. Activated by default
  157. for ppc.
  158. Revision 1.8 2002/07/22 11:48:04 daniel
  159. * Sets are now internally sets.
  160. Revision 1.7 2002/07/21 16:58:20 jonas
  161. * fixed some bugs in tcginnode.pass_2() and optimized the bit test
  162. Revision 1.6 2002/07/20 11:57:54 florian
  163. * types.pas renamed to defbase.pas because D6 contains a types
  164. unit so this would conflicts if D6 programms are compiled
  165. + Willamette/SSE2 instructions to assembler added
  166. Revision 1.5 2002/07/11 14:41:28 florian
  167. * start of the new generic parameter handling
  168. Revision 1.4 2002/07/07 10:16:29 florian
  169. * problems with last commit fixed
  170. Revision 1.3 2002/07/06 20:19:25 carl
  171. + generic set handling
  172. Revision 1.2 2002/07/01 16:23:53 peter
  173. * cg64 patch
  174. * basics for currency
  175. * asnode updates for class and interface (not finished)
  176. Revision 1.1 2002/06/16 08:14:56 carl
  177. + generic sets
  178. }