n68kmat.pas 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate 680x0 assembler for math 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 n68kmat;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,nmat,ncgmat,cpubase,cgbase;
  22. type
  23. tm68knotnode = class(tnotnode)
  24. procedure pass_2;override;
  25. end;
  26. tm68kmoddivnode = class(tcgmoddivnode)
  27. procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);override;
  28. procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);override;
  29. end;
  30. implementation
  31. uses
  32. globtype,systems,
  33. cutils,verbose,globals,
  34. symconst,symdef,aasmbase,aasmtai,aasmcpu,
  35. pass_1,pass_2,
  36. ncon,
  37. cpuinfo,paramgr,defutil,parabase,
  38. tgobj,ncgutil,cgobj,cgutils,rgobj,rgcpu,cgcpu,cg64f32;
  39. {*****************************************************************************
  40. TM68KNOTNODE
  41. *****************************************************************************}
  42. procedure tm68knotnode.pass_2;
  43. var
  44. hl : tasmlabel;
  45. opsize : tcgsize;
  46. begin
  47. opsize:=def_cgsize(resulttype.def);
  48. if is_boolean(resulttype.def) then
  49. begin
  50. { the second pass could change the location of left }
  51. { if it is a register variable, so we've to do }
  52. { this before the case statement }
  53. if left.location.loc<>LOC_JUMP then
  54. secondpass(left);
  55. case left.location.loc of
  56. LOC_JUMP :
  57. begin
  58. location_reset(location,LOC_JUMP,OS_NO);
  59. hl:=truelabel;
  60. truelabel:=falselabel;
  61. falselabel:=hl;
  62. secondpass(left);
  63. maketojumpbool(exprasmlist,left,lr_load_regvars);
  64. hl:=truelabel;
  65. truelabel:=falselabel;
  66. falselabel:=hl;
  67. end;
  68. LOC_FLAGS :
  69. begin
  70. location_copy(location,left.location);
  71. // location_release(exprasmlist,left.location);
  72. inverse_flags(location.resflags);
  73. end;
  74. LOC_CONSTANT,
  75. LOC_REGISTER,
  76. LOC_CREGISTER,
  77. LOC_REFERENCE,
  78. LOC_CREFERENCE :
  79. begin
  80. location_force_reg(exprasmlist,left.location,def_cgsize(resulttype.def),true);
  81. exprasmlist.concat(taicpu.op_reg(A_TST,tcgsize2opsize[opsize],left.location.register));
  82. // location_release(exprasmlist,left.location);
  83. location_reset(location,LOC_FLAGS,OS_NO);
  84. location.resflags:=F_E;
  85. end;
  86. else
  87. internalerror(200203224);
  88. end;
  89. end
  90. else if is_64bitint(left.resulttype.def) then
  91. begin
  92. secondpass(left);
  93. location_copy(location,left.location);
  94. location_force_reg(exprasmlist,location,OS_64,false);
  95. cg64.a_op64_loc_reg(exprasmlist,OP_NOT,OS_64,location,
  96. joinreg64(location.register64.reglo,location.register64.reghi));
  97. end
  98. else
  99. begin
  100. secondpass(left);
  101. location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
  102. location_copy(location,left.location);
  103. if location.loc=LOC_CREGISTER then
  104. location.register := cg.getintregister(exprasmlist,opsize);
  105. { perform the NOT operation }
  106. cg.a_op_reg_reg(exprasmlist,OP_NOT,opsize,location.register,left.location.register);
  107. end;
  108. end;
  109. {*****************************************************************************
  110. TM68KMODDIVNODE
  111. *****************************************************************************}
  112. procedure tm68kmoddivnode.emit_div_reg_reg(signed: boolean;denum,num : tregister);
  113. var
  114. continuelabel : tasmlabel;
  115. reg_d0,reg_d1 : tregister;
  116. paraloc1 : tcgpara;
  117. begin
  118. { no RTL call, so inline a zero denominator verification }
  119. if aktoptprocessor <> MC68000 then
  120. begin
  121. { verify if denominator is zero }
  122. objectlibrary.getjumplabel(continuelabel);
  123. { compare against zero, if not zero continue }
  124. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_NE,0,denum,continuelabel);
  125. // paraloc1.init;
  126. // cg.a_param_const(exprasmlist,OS_S32,200,paramanager.getintparaloc(pocall_default,1,paraloc1));
  127. cg.a_call_name(exprasmlist,'FPC_HANDLEERROR');
  128. cg.a_label(exprasmlist, continuelabel);
  129. if signed then
  130. exprasmlist.concat(taicpu.op_reg_reg(A_DIVS,S_L,denum,num))
  131. else
  132. exprasmlist.concat(taicpu.op_reg_reg(A_DIVU,S_L,denum,num));
  133. { result should be in denuminator }
  134. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,denum);
  135. end
  136. else
  137. begin
  138. { On MC68000/68010 mw must pass through RTL routines }
  139. reg_d0:=NR_D0;
  140. cg.getcpuregister(exprasmlist,NR_D0);
  141. reg_d1:=NR_D1;
  142. cg.getcpuregister(exprasmlist,NR_D1);
  143. { put numerator in d0 }
  144. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,reg_d0);
  145. { put denum in D1 }
  146. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,denum,reg_d1);
  147. if signed then
  148. cg.a_call_name(exprasmlist,'FPC_DIV_LONGINT')
  149. else
  150. cg.a_call_name(exprasmlist,'FPC_DIV_CARDINAL');
  151. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,reg_d0,denum);
  152. cg.ungetcpuregister(exprasmlist,reg_d0);
  153. cg.ungetcpuregister(exprasmlist,reg_d1);
  154. end;
  155. end;
  156. procedure tm68kmoddivnode.emit_mod_reg_reg(signed: boolean;denum,num : tregister);
  157. var tmpreg : tregister;
  158. continuelabel : tasmlabel;
  159. signlabel : tasmlabel;
  160. reg_d0,reg_d1 : tregister;
  161. begin
  162. { no RTL call, so inline a zero denominator verification }
  163. if aktoptprocessor <> MC68000 then
  164. begin
  165. { verify if denominator is zero }
  166. objectlibrary.getjumplabel(continuelabel);
  167. { compare against zero, if not zero continue }
  168. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_NE,0,denum,continuelabel);
  169. // cg.a_param_const(exprasmlist, OS_S32,200,paramanager.getintparaloc(pocall_default,1));
  170. cg.a_call_name(exprasmlist,'FPC_HANDLEERROR');
  171. cg.a_label(exprasmlist, continuelabel);
  172. tmpreg:=cg.getintregister(exprasmlist,OS_INT);
  173. { we have to prepare the high register with the }
  174. { correct sign. i.e we clear it, check if the low dword reg }
  175. { which will participate in the division is signed, if so we}
  176. { we extend the sign to the high doword register by inverting }
  177. { all the bits. }
  178. exprasmlist.concat(taicpu.op_reg(A_CLR,S_L,tmpreg));
  179. objectlibrary.getjumplabel(signlabel);
  180. exprasmlist.concat(taicpu.op_reg(A_TST,S_L,tmpreg));
  181. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_A,0,tmpreg,signlabel);
  182. { its a negative value, therefore change sign }
  183. cg.a_label(exprasmlist,signlabel);
  184. { tmpreg:num / denum }
  185. if signed then
  186. exprasmlist.concat(taicpu.op_reg_reg_reg(A_DIVSL,S_L,denum,tmpreg,num))
  187. else
  188. exprasmlist.concat(taicpu.op_reg_reg_reg(A_DIVUL,S_L,denum,tmpreg,num));
  189. { remainder in tmpreg }
  190. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,tmpreg,denum);
  191. cg.ungetcpuregister(exprasmlist,tmpreg);
  192. end
  193. else
  194. begin
  195. { On MC68000/68010 mw must pass through RTL routines }
  196. Reg_d0:=NR_D0;
  197. cg.getcpuregister(exprasmlist,NR_D0);
  198. Reg_d1:=NR_D1;
  199. cg.getcpuregister(exprasmlist,NR_D1);
  200. { put numerator in d0 }
  201. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,Reg_D0);
  202. { put denum in D1 }
  203. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,denum,Reg_D1);
  204. if signed then
  205. cg.a_call_name(exprasmlist,'FPC_MOD_LONGINT')
  206. else
  207. cg.a_call_name(exprasmlist,'FPC_MOD_CARDINAL');
  208. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,Reg_D0,denum);
  209. cg.ungetcpuregister(exprasmlist,Reg_D0);
  210. cg.ungetcpuregister(exprasmlist,Reg_D1);
  211. end;
  212. end;
  213. begin
  214. cnotnode:=tm68knotnode;
  215. cmoddivnode:=tm68kmoddivnode;
  216. end.