hlcgcpu.pas 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. {
  2. Copyright (c) 1998-2010 by Florian Klaempfl and Jonas Maebe
  3. Member of the Free Pascal development team
  4. This unit contains routines high-level cg support LoongArch64
  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 hlcgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globals,
  23. aasmdata,
  24. symtype,symdef,
  25. cgbase,cgutils,hlcgobj,hlcg2ll, parabase;
  26. type
  27. thlcgloongarch64 = class(thlcg2ll)
  28. protected
  29. public
  30. procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  31. end;
  32. implementation
  33. uses
  34. verbose,
  35. systems,fmodule,
  36. symconst, symsym,
  37. aasmbase,aasmtai,aasmcpu,
  38. cpubase,globtype,
  39. procinfo,cpupi,cgobj,cgcpu,
  40. defutil;
  41. procedure thlcgloongarch64.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
  42. procedure loadvmttor12;
  43. var
  44. tmpref,
  45. href : treference;
  46. l : TAsmLabel;
  47. begin
  48. reference_reset_base(href,voidpointertype,NR_R4,0,ctempposinvalid,sizeof(pint),[]);
  49. href.refaddr:=addr_reg_12i;
  50. list.concat(taicpu.op_reg_ref(A_LD_D,NR_R12,href));
  51. end;
  52. procedure op_onr12methodaddr;
  53. var
  54. tmpref,
  55. href : treference;
  56. l : TAsmLabel;
  57. offset: longint;
  58. begin
  59. if (procdef.extnumber=$ffff) then
  60. Internalerror(2022111915);
  61. offset:=tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber);
  62. if not is_simm12(offset) then
  63. begin
  64. list.concat(taicpu.op_reg_const(A_LI_D,NR_R15,offset));
  65. list.concat(taicpu.op_reg_reg_reg(A_ADD_D,NR_R12,NR_R12,NR_R15));
  66. offset:=0;
  67. end;
  68. reference_reset_base(href,voidpointertype,NR_R12,offset,ctempposinvalid, sizeof(pint),[]);
  69. href.refaddr:=addr_reg_12i;
  70. cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
  71. reference_reset_base(href,voidpointertype,NR_R12,0,ctempposinvalid,0,[]);
  72. href.refaddr:=addr_reg;
  73. list.concat(taicpu.op_ref(A_JR,href));
  74. end;
  75. var
  76. make_global : boolean;
  77. tmpref , href: treference;
  78. l : TAsmLabel;
  79. hsym: tsym;
  80. paraloc: PCGParaLocation;
  81. tmpreg: TRegister;
  82. begin
  83. if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
  84. Internalerror(2022111909);
  85. if not assigned(procdef.struct) or
  86. (procdef.procoptions*[po_classmethod, po_staticmethod,
  87. po_methodpointer, po_interrupt, po_iocheck]<>[]) then
  88. Internalerror(2022111910);
  89. if procdef.owner.symtabletype<>ObjectSymtable then
  90. Internalerror(2022111911);
  91. make_global:=false;
  92. if (not current_module.is_unit) or
  93. create_smartlink or
  94. (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
  95. make_global:=true;
  96. if make_global then
  97. list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0,voidcodepointertype))
  98. else
  99. list.concat(Tai_symbol.Createname_hidden(labelname,AT_FUNCTION,0,voidcodepointertype));
  100. { the wrapper might need aktlocaldata for the additional data to
  101. load the constant }
  102. current_procinfo:=cprocinfo.create(nil);
  103. { set param1 interface to self }
  104. procdef.init_paraloc_info(callerside);
  105. hsym:=tsym(procdef.parast.Find('self'));
  106. if not(assigned(hsym) and
  107. (hsym.typ=paravarsym)) then
  108. internalerror(2022111912);
  109. paraloc:=tparavarsym(hsym).paraloc[callerside].location;
  110. if assigned(paraloc^.next) then
  111. InternalError(2022111913);
  112. case paraloc^.loc of
  113. LOC_REGISTER:
  114. begin
  115. if is_simm12(ioffset) then
  116. cg.a_op_const_reg(list,OP_SUB, paraloc^.size,ioffset,paraloc^.register)
  117. else
  118. begin
  119. cg.a_load_const_reg(list, paraloc^.size, ioffset, NR_R13);
  120. cg.a_op_reg_reg(list, OP_SUB, paraloc^.size, NR_R13, paraloc^.register);
  121. end;
  122. end;
  123. else
  124. internalerror(2022111914);
  125. end;
  126. { case 4 }
  127. if (po_virtualmethod in procdef.procoptions) and
  128. not is_objectpascal_helper(procdef.struct) then
  129. begin
  130. loadvmttor12;
  131. op_onr12methodaddr;
  132. end
  133. else
  134. begin
  135. tmpreg:=NR_R12;
  136. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION),0,0,[]);
  137. href.refaddr:=addr_pc_hi20;
  138. list.concat(taicpu.op_reg_ref(A_PCALAU12I,tmpreg,href));
  139. href.refaddr:=addr_pc_lo12;
  140. list.concat(taicpu.op_reg_reg_ref(A_ADDI_D,tmpreg,tmpreg,href));
  141. reference_reset_base(href,voidpointertype,tmpreg,0,ctempposinvalid,0,[]);
  142. href.refaddr:=addr_reg;
  143. list.concat(taicpu.op_ref(A_JR,href));
  144. end;
  145. list.concatlist(current_procinfo.aktlocaldata);
  146. current_procinfo.Free;
  147. current_procinfo:=nil;
  148. list.concat(Tai_symbol_end.Createname(labelname));
  149. end;
  150. procedure create_hlcodegen_cpu;
  151. begin
  152. hlcg:=thlcgloongarch64.create;
  153. create_codegen;
  154. end;
  155. begin
  156. chlcgobj:=thlcgloongarch64;
  157. create_hlcodegen:=@create_hlcodegen_cpu;
  158. end.