nppcset.pas 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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,cgbase,cgobj,aasmbase,aasmtai;
  23. type
  24. tppccasenode = class(tcgcasenode)
  25. protected
  26. procedure genlinearlist(hp : pcaselabel); 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. tgobj,ncgutil,regvars,rgobj,aasmcpu;
  38. {*****************************************************************************
  39. TCGCASENODE
  40. *****************************************************************************}
  41. procedure tppccasenode.genlinearlist(hp : pcaselabel);
  42. var
  43. first, lastrange : boolean;
  44. last : TConstExprInt;
  45. procedure genitem(t : pcaselabel);
  46. var r:Tregister;
  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.getintregister(exprasmlist,OS_INT);
  59. cg.a_load_const_reg(exprasmlist,OS_INT,value,tmpreg);
  60. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD_,hregister,
  61. hregister,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,aword(t^._low),hregister,elselabel);
  71. end;
  72. if t^._low=t^._high then
  73. begin
  74. if t^._low-last=0 then
  75. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid))
  76. else
  77. gensub(longint(t^._low-last));
  78. tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,blocklabel(t^.blockid));
  79. last:=t^._low;
  80. lastrange := false;
  81. end
  82. else
  83. begin
  84. { it begins with the smallest label, if the value }
  85. { is even smaller then jump immediately to the }
  86. { ELSE-label }
  87. if first then
  88. begin
  89. { have we to ajust the first value ? }
  90. if (t^._low>get_min_value(left.resulttype.def)) then
  91. gensub(longint(t^._low));
  92. end
  93. else
  94. begin
  95. { if there is no unused label between the last and the }
  96. { present label then the lower limit can be checked }
  97. { immediately. else check the range in between: }
  98. gensub(longint(t^._low-last));
  99. if ((t^._low-last) <> 1) or
  100. (not lastrange) then
  101. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_lt,elselabel);
  102. end;
  103. gensub(longint(t^._high-t^._low));
  104. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_le,blocklabel(t^.blockid));
  105. last:=t^._high;
  106. lastrange := true;
  107. end;
  108. first:=false;
  109. if assigned(t^.greater) then
  110. genitem(t^.greater);
  111. end;
  112. begin
  113. { do we need to generate cmps? }
  114. if (with_sign and (min_label<0)) or
  115. (opsize = OS_32) then
  116. genlinearcmplist(hp)
  117. else
  118. begin
  119. last:=0;
  120. lastrange:=false;
  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.17 2004-11-30 18:13:39 jonas
  132. * patch from Peter to fix inlining of case statements
  133. Revision 1.16 2004/10/25 15:36:47 peter
  134. * save standard registers moved to tcgobj
  135. Revision 1.15 2004/09/25 14:23:55 peter
  136. * ungetregister is now only used for cpuregisters, renamed to
  137. ungetcpuregister
  138. * renamed (get|unget)explicitregister(s) to ..cpuregister
  139. * removed location-release/reference_release
  140. Revision 1.14 2004/06/20 08:55:32 florian
  141. * logs truncated
  142. }