ncpucnv.pas 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. end;
  28. implementation
  29. uses
  30. verbose,globtype,globals,symdef,aasmbase,aasmtai,aasmdata,symtable,
  31. defutil,
  32. cgbase,cgutils,
  33. pass_1,pass_2,procinfo,ncal,
  34. ncgutil,
  35. cpubase,cpuinfo,aasmcpu,cgobj,hlcgobj,cgcpu;
  36. {*****************************************************************************
  37. tcputypeconvnode
  38. *****************************************************************************}
  39. function tcputypeconvnode.first_real_to_real: tnode;
  40. begin
  41. if (FPUXTENSA_SINGLE in fpu_capabilities[current_settings.fputype]) and
  42. not(FPUXTENSA_DOUBLE in fpu_capabilities[current_settings.fputype]) then
  43. begin
  44. case tfloatdef(left.resultdef).floattype of
  45. s32real:
  46. case tfloatdef(resultdef).floattype of
  47. s64real:
  48. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float32_to_float64',ccallparanode.create(
  49. ctypeconvnode.create_internal(left,search_system_type('FLOAT32REC').typedef),nil)),resultdef);
  50. s32real:
  51. begin
  52. result:=left;
  53. left:=nil;
  54. end;
  55. else
  56. internalerror(200610151);
  57. end;
  58. s64real:
  59. case tfloatdef(resultdef).floattype of
  60. s32real:
  61. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float64_to_float32',ccallparanode.create(
  62. ctypeconvnode.create_internal(left,search_system_type('FLOAT64').typedef),nil)),resultdef);
  63. s64real:
  64. begin
  65. result:=left;
  66. left:=nil;
  67. end;
  68. else
  69. internalerror(200610152);
  70. end;
  71. else
  72. internalerror(200610153);
  73. end;
  74. left:=nil;
  75. firstpass(result);
  76. exit;
  77. end
  78. else
  79. Result := inherited first_real_to_real;
  80. end;
  81. procedure tcputypeconvnode.second_int_to_bool;
  82. var
  83. hreg1, onereg: tregister;
  84. href : treference;
  85. hlabel : tasmlabel;
  86. newsize : tcgsize;
  87. begin
  88. secondpass(left);
  89. if codegenerror then
  90. exit;
  91. { Explicit typecasts from any ordinal type to a boolean type
  92. must not change the ordinal value }
  93. if (nf_explicit in flags) and
  94. not(left.location.loc in [LOC_JUMP]) then
  95. begin
  96. location_copy(location,left.location);
  97. newsize:=def_cgsize(resultdef);
  98. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  99. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  100. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  101. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  102. else
  103. location.size:=newsize;
  104. exit;
  105. end;
  106. if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then
  107. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  108. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  109. onereg:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  110. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,1,onereg);
  111. hreg1:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  112. case left.location.loc of
  113. LOC_CREFERENCE,
  114. LOC_REFERENCE :
  115. begin
  116. if left.location.size in [OS_64,OS_S64] then
  117. begin
  118. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hreg1);
  119. href:=left.location.reference;
  120. inc(href.offset,4);
  121. cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hreg1);
  122. end
  123. else
  124. cg.a_load_ref_reg(current_asmdata.CurrAsmList,left.location.size,OS_32,left.location.reference,hreg1);
  125. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_MOVNEZ,hreg1,onereg,hreg1));
  126. end;
  127. LOC_REGISTER,LOC_CREGISTER :
  128. begin
  129. if left.location.size in [OS_64,OS_S64] then
  130. cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reglo,left.location.register64.reghi,hreg1)
  131. else
  132. cg.a_load_reg_reg(current_asmdata.CurrAsmList,left.location.size,OS_32,left.location.register,hreg1);
  133. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_MOVNEZ,hreg1,onereg,hreg1));
  134. end;
  135. LOC_JUMP :
  136. begin
  137. current_asmdata.getjumplabel(hlabel);
  138. cg.a_label(current_asmdata.CurrAsmList,left.location.truelabel);
  139. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hreg1);
  140. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  141. cg.a_label(current_asmdata.CurrAsmList,left.location.falselabel);
  142. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hreg1);
  143. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  144. end;
  145. else
  146. internalerror(2020031504);
  147. end;
  148. if (is_cbool(resultdef)) then
  149. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,hreg1,hreg1);
  150. {$ifndef cpu64bitalu}
  151. if (location.size in [OS_64,OS_S64]) then
  152. begin
  153. location.register64.reglo:=hreg1;
  154. location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  155. if (is_cbool(resultdef)) then
  156. { reglo is either 0 or -1 -> reghi has to become the same }
  157. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
  158. else
  159. { unsigned }
  160. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
  161. end
  162. else
  163. {$endif cpu64bitalu}
  164. location.register:=hreg1;
  165. end;
  166. begin
  167. ctypeconvnode:=tcputypeconvnode;
  168. end.