nppcset.pas 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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,defbase,
  33. paramgr,
  34. pass_2,cgcpu,
  35. ncon,
  36. cga,tgobj,ncgutil,regvars,rgobj,aasmcpu;
  37. {*****************************************************************************
  38. TCGCASENODE
  39. *****************************************************************************}
  40. procedure tppccasenode.genlinearlist(hp : pcaserecord);
  41. var
  42. first : boolean;
  43. last : TConstExprInt;
  44. resflags: tresflags;
  45. procedure genitem(t : pcaserecord);
  46. procedure gensub(value:longint);
  47. var
  48. tmpreg: tregister;
  49. begin
  50. value := -value;
  51. if (value >= low(smallint)) and
  52. (value <= high(smallint)) then
  53. exprasmlist.concat(taicpu.op_reg_reg_const(A_ADDIC_,hregister,
  54. hregister,value))
  55. else
  56. begin
  57. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  58. cg.a_load_const_reg(exprasmlist,OS_INT,value,tmpreg);
  59. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD_,hregister,
  60. hregister,tmpreg));
  61. cg.free_scratch_reg(exprasmlist,tmpreg);
  62. end;
  63. end;
  64. begin
  65. if assigned(t^.less) then
  66. genitem(t^.less);
  67. { need we to test the first value }
  68. if first and (t^._low>get_min_value(left.resulttype.def)) then
  69. begin
  70. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,
  71. longint(t^._low),hregister,elselabel);
  72. end;
  73. if t^._low=t^._high then
  74. begin
  75. if t^._low-last=0 then
  76. exprasmlist.concat(taicpu.op_reg_reg_const(A_CMPWI,R_CR0,
  77. hregister,0))
  78. else
  79. gensub(longint(t^._low-last));
  80. last:=t^._low;
  81. resflags.cr := R_CR0;
  82. resflags.flag := F_EQ;
  83. cg.a_jmp_flags(exprasmlist,resflags,t^.statement);
  84. end
  85. else
  86. begin
  87. { it begins with the smallest label, if the value }
  88. { is even smaller then jump immediately to the }
  89. { ELSE-label }
  90. if first then
  91. begin
  92. { have we to ajust the first value ? }
  93. if (t^._low>get_min_value(left.resulttype.def)) then
  94. gensub(longint(t^._low));
  95. end
  96. else
  97. begin
  98. { if there is no unused label between the last and the }
  99. { present label then the lower limit can be checked }
  100. { immediately. else check the range in between: }
  101. gensub(longint(t^._low-last));
  102. if (t^._low-last) <> 1 then
  103. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_lt,elselabel);
  104. end;
  105. gensub(longint(t^._high-t^._low));
  106. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_le,t^.statement);
  107. last:=t^._high;
  108. end;
  109. first:=false;
  110. if assigned(t^.greater) then
  111. genitem(t^.greater);
  112. end;
  113. begin
  114. { do we need to generate cmps? }
  115. if (with_sign and (min_label<0)) or
  116. (opsize = OS_32) then
  117. genlinearcmplist(hp)
  118. else
  119. begin
  120. last:=0;
  121. first:=true;
  122. genitem(hp);
  123. cg.a_jmp_always(exprasmlist,elselabel);
  124. end;
  125. end;
  126. begin
  127. ccasenode:=tppccasenode;
  128. end.
  129. {
  130. $Log$
  131. Revision 1.3 2002-09-09 13:57:45 jonas
  132. * small optimization to case genlist() case statements
  133. Revision 1.2 2002/09/08 20:14:33 jonas
  134. * use genlinearcmplist() for unsigned 32bit case statements instead
  135. of genlinearlist(), because the addic. instruction always sets the
  136. flags as if the arguments are signed 32bits (for smaller unsigned
  137. types, this doesn't matter since they fit in s32bit)
  138. Revision 1.1 2002/08/11 11:39:12 jonas
  139. + powerpc-specific genlinearlist
  140. Revision 1.13 2002/08/11 06:14:40 florian
  141. * fixed powerpc compilation problems
  142. Revision 1.12 2002/08/10 17:15:12 jonas
  143. * optimizations and bugfix
  144. Revision 1.11 2002/07/28 09:24:18 carl
  145. + generic case node
  146. Revision 1.10 2002/07/23 14:31:00 daniel
  147. * Added internal error when asked to generate code for 'if expr in []'
  148. Revision 1.9 2002/07/23 12:34:30 daniel
  149. * Readded old set code. To use it define 'oldset'. Activated by default
  150. for ppc.
  151. Revision 1.8 2002/07/22 11:48:04 daniel
  152. * Sets are now internally sets.
  153. Revision 1.7 2002/07/21 16:58:20 jonas
  154. * fixed some bugs in tcginnode.pass_2() and optimized the bit test
  155. Revision 1.6 2002/07/20 11:57:54 florian
  156. * types.pas renamed to defbase.pas because D6 contains a types
  157. unit so this would conflicts if D6 programms are compiled
  158. + Willamette/SSE2 instructions to assembler added
  159. Revision 1.5 2002/07/11 14:41:28 florian
  160. * start of the new generic parameter handling
  161. Revision 1.4 2002/07/07 10:16:29 florian
  162. * problems with last commit fixed
  163. Revision 1.3 2002/07/06 20:19:25 carl
  164. + generic set handling
  165. Revision 1.2 2002/07/01 16:23:53 peter
  166. * cg64 patch
  167. * basics for currency
  168. * asnode updates for class and interface (not finished)
  169. Revision 1.1 2002/06/16 08:14:56 carl
  170. + generic sets
  171. }