ncpucnv.pas 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. {
  2. Copyright (c) 1998-2019 by Florian Klaempfl
  3. Generate Xtensa assembler for type converting 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 ncpucnv;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,ncnv,ncgcnv;
  22. type
  23. tcputypeconvnode = class(tcgtypeconvnode)
  24. protected
  25. function first_real_to_real: tnode;override;
  26. procedure second_int_to_bool;override;
  27. procedure second_int_to_real;override;
  28. function first_int_to_real: tnode;override;
  29. end;
  30. implementation
  31. uses
  32. verbose,globtype,globals,symdef,aasmbase,aasmtai,aasmdata,symtable,
  33. defutil,
  34. cgbase,cgutils,
  35. pass_1,pass_2,procinfo,ncal,
  36. ncgutil,
  37. cpubase,cpuinfo,aasmcpu,cgobj,hlcgobj,cgcpu;
  38. {*****************************************************************************
  39. tcputypeconvnode
  40. *****************************************************************************}
  41. function tcputypeconvnode.first_real_to_real: tnode;
  42. begin
  43. if (FPUXTENSA_SINGLE in fpu_capabilities[current_settings.fputype]) and
  44. not(FPUXTENSA_DOUBLE in fpu_capabilities[current_settings.fputype]) then
  45. begin
  46. case tfloatdef(left.resultdef).floattype of
  47. s32real:
  48. case tfloatdef(resultdef).floattype of
  49. s64real:
  50. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float32_to_float64',ccallparanode.create(
  51. ctypeconvnode.create_internal(left,search_system_type('FLOAT32REC').typedef),nil)),resultdef);
  52. s32real:
  53. begin
  54. result:=left;
  55. left:=nil;
  56. end;
  57. else
  58. internalerror(2020092603);
  59. end;
  60. s64real:
  61. case tfloatdef(resultdef).floattype of
  62. s32real:
  63. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float64_to_float32',ccallparanode.create(
  64. ctypeconvnode.create_internal(left,search_system_type('FLOAT64').typedef),nil)),resultdef);
  65. s64real:
  66. begin
  67. result:=left;
  68. left:=nil;
  69. end;
  70. else
  71. internalerror(2020092602);
  72. end;
  73. else
  74. internalerror(2020092601);
  75. end;
  76. left:=nil;
  77. firstpass(result);
  78. exit;
  79. end
  80. else
  81. Result := inherited first_real_to_real;
  82. end;
  83. procedure tcputypeconvnode.second_int_to_bool;
  84. var
  85. hreg1, onereg: tregister;
  86. href : treference;
  87. hlabel : tasmlabel;
  88. newsize : tcgsize;
  89. begin
  90. secondpass(left);
  91. if codegenerror then
  92. exit;
  93. { Explicit typecasts from any ordinal type to a boolean type
  94. must not change the ordinal value }
  95. if (nf_explicit in flags) and
  96. not(left.location.loc in [LOC_JUMP]) then
  97. begin
  98. location_copy(location,left.location);
  99. newsize:=def_cgsize(resultdef);
  100. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  101. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  102. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  103. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  104. else
  105. location.size:=newsize;
  106. exit;
  107. end;
  108. if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then
  109. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  110. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  111. onereg:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  112. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,1,onereg);
  113. hreg1:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  114. case left.location.loc of
  115. LOC_CREFERENCE,
  116. LOC_REFERENCE :
  117. begin
  118. if left.location.size in [OS_64,OS_S64] then
  119. begin
  120. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hreg1);
  121. href:=left.location.reference;
  122. inc(href.offset,4);
  123. cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hreg1);
  124. end
  125. else
  126. cg.a_load_ref_reg(current_asmdata.CurrAsmList,left.location.size,OS_32,left.location.reference,hreg1);
  127. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_MOVNEZ,hreg1,onereg,hreg1));
  128. end;
  129. LOC_REGISTER,LOC_CREGISTER :
  130. begin
  131. if left.location.size in [OS_64,OS_S64] then
  132. cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reglo,left.location.register64.reghi,hreg1)
  133. else
  134. cg.a_load_reg_reg(current_asmdata.CurrAsmList,left.location.size,OS_32,left.location.register,hreg1);
  135. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_MOVNEZ,hreg1,onereg,hreg1));
  136. end;
  137. LOC_JUMP :
  138. begin
  139. current_asmdata.getjumplabel(hlabel);
  140. cg.a_label(current_asmdata.CurrAsmList,left.location.truelabel);
  141. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hreg1);
  142. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  143. cg.a_label(current_asmdata.CurrAsmList,left.location.falselabel);
  144. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hreg1);
  145. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  146. end;
  147. else
  148. internalerror(2020031504);
  149. end;
  150. if (is_cbool(resultdef)) then
  151. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,hreg1,hreg1);
  152. {$ifndef cpu64bitalu}
  153. if (location.size in [OS_64,OS_S64]) then
  154. begin
  155. location.register64.reglo:=hreg1;
  156. location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  157. if (is_cbool(resultdef)) then
  158. { reglo is either 0 or -1 -> reghi has to become the same }
  159. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
  160. else
  161. { unsigned }
  162. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
  163. end
  164. else
  165. {$endif cpu64bitalu}
  166. location.register:=hreg1;
  167. end;
  168. function tcputypeconvnode.first_int_to_real: tnode;
  169. var
  170. fname: string[19];
  171. begin
  172. if (cs_fp_emulation in current_settings.moduleswitches) or
  173. (current_settings.fputype=fpu_soft) or
  174. not(FPUXTENSA_SINGLE in fpu_capabilities[current_settings.fputype]) or
  175. ((is_double(resultdef)) and not(FPUXTENSA_DOUBLE in fpu_capabilities[current_settings.fputype])) or
  176. is_64bitint(left.resultdef) or
  177. is_currency(left.resultdef) or
  178. (is_32bit(left.resultdef) and not(is_signed(left.resultdef))) then
  179. result:=inherited first_int_to_real
  180. else
  181. begin
  182. { other integers are supposed to be 32 bit }
  183. inserttypeconv(left,s32inttype);
  184. firstpass(left);
  185. result:=nil;
  186. expectloc:=LOC_FPUREGISTER;
  187. end;
  188. end;
  189. procedure tcputypeconvnode.second_int_to_real;
  190. var
  191. ai: taicpu;
  192. begin
  193. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  194. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  195. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,s32inttype,true);
  196. ai:=taicpu.op_reg_reg_const(A_FLOAT,location.register,left.location.register,0);
  197. ai.oppostfix:=PF_S;
  198. current_asmdata.CurrAsmList.concat(ai);
  199. end;
  200. begin
  201. ctypeconvnode:=tcputypeconvnode;
  202. end.