nppcset.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
  3. Generate PowerPC assembler for in set/case 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 nppcset;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai;
  22. type
  23. tppccasenode = class(tcgcasenode)
  24. protected
  25. procedure genlinearlist(hp : pcaselabel); override;
  26. end;
  27. implementation
  28. uses
  29. globtype,systems,
  30. verbose,globals,
  31. symconst,symdef,defutil,
  32. paramgr,
  33. cpuinfo,
  34. pass_2,cgcpu,
  35. ncon,
  36. tgobj,ncgutil,regvars,rgobj,aasmcpu;
  37. {*****************************************************************************
  38. TCGCASENODE
  39. *****************************************************************************}
  40. procedure tppccasenode.genlinearlist(hp : pcaselabel);
  41. var
  42. first, lastrange : boolean;
  43. last : TConstExprInt;
  44. procedure genitem(t : pcaselabel);
  45. procedure gensub(value:longint);
  46. var
  47. tmpreg: tregister;
  48. begin
  49. value := -value;
  50. if (value >= low(smallint)) and
  51. (value <= high(smallint)) then
  52. exprasmlist.concat(taicpu.op_reg_reg_const(A_ADDIC_,hregister,
  53. hregister,value))
  54. else
  55. begin
  56. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  57. cg.a_load_const_reg(exprasmlist,OS_INT,value,tmpreg);
  58. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD_,hregister,
  59. hregister,tmpreg));
  60. end;
  61. end;
  62. begin
  63. if assigned(t^.less) then
  64. genitem(t^.less);
  65. { need we to test the first value }
  66. if first and (t^._low>get_min_value(left.resulttype.def)) then
  67. begin
  68. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,aword(t^._low),hregister,elselabel);
  69. end;
  70. if t^._low=t^._high then
  71. begin
  72. if t^._low-last=0 then
  73. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid))
  74. else
  75. gensub(longint(t^._low-last));
  76. tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,blocklabel(t^.blockid));
  77. last:=t^._low;
  78. lastrange := false;
  79. end
  80. else
  81. begin
  82. { it begins with the smallest label, if the value }
  83. { is even smaller then jump immediately to the }
  84. { ELSE-label }
  85. if first then
  86. begin
  87. { have we to ajust the first value ? }
  88. if (t^._low>get_min_value(left.resulttype.def)) then
  89. gensub(longint(t^._low));
  90. end
  91. else
  92. begin
  93. { if there is no unused label between the last and the }
  94. { present label then the lower limit can be checked }
  95. { immediately. else check the range in between: }
  96. gensub(longint(t^._low-last));
  97. if ((t^._low-last) <> 1) or
  98. (not lastrange) then
  99. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_lt,elselabel);
  100. end;
  101. gensub(longint(t^._high-t^._low));
  102. tcgppc(cg).a_jmp_cond(exprasmlist,jmp_le,blocklabel(t^.blockid));
  103. last:=t^._high;
  104. lastrange := true;
  105. end;
  106. first:=false;
  107. if assigned(t^.greater) then
  108. genitem(t^.greater);
  109. end;
  110. begin
  111. { do we need to generate cmps? }
  112. if (with_sign and (min_label<0)) or
  113. (opsize = OS_32) then
  114. genlinearcmplist(hp)
  115. else
  116. begin
  117. last:=0;
  118. lastrange:=false;
  119. first:=true;
  120. genitem(hp);
  121. cg.a_jmp_always(exprasmlist,elselabel);
  122. end;
  123. end;
  124. begin
  125. ccasenode:=tppccasenode;
  126. end.