nppcset.pas 7.7 KB

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