aasmcpu.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. {
  2. Copyright (C) 2022 Loongson Technology Corporation Limited.
  3. Contains the assembler object for the LoongArch64
  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 aasmcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,verbose,
  22. aasmbase,aasmtai,aasmdata,aasmsym,
  23. cpubase,cgbase,cgutils;
  24. const
  25. { "move reg,reg" source operand number }
  26. O_MOV_SOURCE = 1;
  27. { "move reg,reg" source operand number }
  28. O_MOV_DEST = 0;
  29. type
  30. { TODO: Branch condition? TRefernece and Symbol? }
  31. { taicpu }
  32. taicpu = class(tai_cpu_abstract_sym)
  33. { NOP,TLBSRCH,TLBRD,TLBWR,TLBFILL,TLBCLR,TLBFLUSH,ERTN, }
  34. constructor op_none(op : tasmop);
  35. { DBAR,IBAR,SYSCALL,BREAK,DBCL,IDLE, }
  36. constructor op_const(op : tasmop;_op1 : aint);
  37. { B,BL,JR, }
  38. constructor op_ref(op : tasmop; const _op1 : treference);
  39. { EXT,CLO,CLZ,CTO,CTZ,REVB,REVH,BITREV,ASRTLE,ASRTGT,RDTIMEL,RDTIMEH,
  40. RDTIME,CPUCFG,FABS,FNEG,FSQRT,FRECIP,FRSQRT,FLOGB,FCLASS,FCVT,FFINT,
  41. FTINT,FTINTRM,FTINTRP,FTINTRZ,FTINTRNE,FRINT,FMOV,MOVGR2FR,MOVGR2FRH,
  42. MOVFR2GR,MOVFRH2GR,MOVGR2FCSR,MOVFCSR2GR,MOVFR2CF,MOVCF2FR,MOVGR2CF,
  43. MOVCF2GR,IOCSRRD,IOCSRWR,MOVE,}
  44. constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  45. { BEQZ,BNEZ,BCEQZ,BCNEZ,LA,BLTZ,BGTZ,BGEZ,BLEZ,LD,ST,LDX,STX,LDPTR,
  46. STPTR,FLD,FST,FLDX,FSTX, }
  47. constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  48. { LU12I,LU32I,PCADDI,PCADDU12I,PCADDU18I,PCALAU12I,CSRRD,CSRWR,LDPTE,LI, }
  49. constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  50. { BSTRINS,BSTRPICK, }
  51. constructor op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
  52. { ADD,SUB,SLT,AND,OR,NOR,XOR,ANDN,ORN,MUL,MULH,MULW,DIV,MOD,SLL,SRL,SRA,
  53. RTOR,MASKEQZ,MASKNEZ,LDGT,LDLE,STGT,STLE,AMSWAP,AMSWAP_DB,AMADD,AMADD_DB,
  54. AMAND,AMAND_DB,AMOR,AMOR_DB,AMXOR,AMXOR_DB,AMMAX,AMMAX_DB,AMMIN,AMMIN_DB,
  55. CRC,CRCC,FADD,FSUB,FMUL,FDIV,FMAX,FMIN,FMAXA,FMINA,FCALEB,FCOPYSIGN,FCMP,
  56. FLDGT,FLDLE,FSTGT,FSTLE,}
  57. constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  58. { ADDI,ADDU16I,LU52I,SLTI,ANDI,ORI,XORI,SLLI,SRLI,SRAI,ROTRI,JIRL,LL,SC,
  59. CSRXCHG,LDDIR,}
  60. constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  61. { BEQ,BNE,BLT,BGE,BLTU,BGEU,BGT,BLE,BGTU,BLEU, }
  62. constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  63. { PRELD,CACOP, }
  64. constructor op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
  65. { PRELDX,INVTLB }
  66. constructor op_const_reg_reg(op : tasmop; _op1 : aint; _op2,_op3 : tregister);
  67. { FMADD,FMSUB,FNMADD,FNMSUB,FSEL,}
  68. constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  69. { ALSL,BYTEPICK, }
  70. constructor op_reg_reg_reg_const(op : tasmop; _op1, _op2, _op3 : tregister; _op4 : aint);
  71. function is_same_reg_move(regtype: Tregistertype):boolean; override;
  72. { register spilling code }
  73. function spilling_get_operation_type(opnr: longint): topertype;override;
  74. function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
  75. end;
  76. tai_align = class(tai_align_abstract)
  77. { nothing to add }
  78. end;
  79. procedure InitAsm;
  80. procedure DoneAsm;
  81. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  82. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  83. implementation
  84. uses cutils, cclasses;
  85. {*****************************************************************************
  86. taicpu Constructors
  87. *****************************************************************************}
  88. constructor taicpu.op_none(op : tasmop);
  89. begin
  90. inherited create(op);
  91. end;
  92. constructor taicpu.op_const(op : tasmop;_op1 : aint);
  93. begin
  94. inherited create(op);
  95. ops:=1;
  96. loadconst(0,_op1);
  97. end;
  98. constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
  99. begin
  100. inherited create(op);
  101. ops:=1;
  102. loadref(0,_op1);
  103. end;
  104. constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  105. begin
  106. inherited create(op);
  107. ops:=2;
  108. loadreg(0,_op1);
  109. loadreg(1,_op2);
  110. end;
  111. constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  112. begin
  113. inherited create(op);
  114. ops:=2;
  115. loadreg(0,_op1);
  116. loadref(1,_op2);
  117. end;
  118. constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  119. begin
  120. inherited create(op);
  121. ops:=2;
  122. loadreg(0,_op1);
  123. loadconst(1,_op2);
  124. end;
  125. constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
  126. begin
  127. inherited create(op);
  128. ops := 4;
  129. loadreg(0, _op1);
  130. loadreg(1, _op2);
  131. loadconst(2, _op3);
  132. loadconst(3, _op4);
  133. end;
  134. constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  135. begin
  136. inherited create(op);
  137. ops:=3;
  138. loadreg(0,_op1);
  139. loadreg(1,_op2);
  140. loadreg(2,_op3);
  141. end;
  142. constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  143. begin
  144. inherited create(op);
  145. ops:=3;
  146. loadreg(0,_op1);
  147. loadreg(1,_op2);
  148. loadconst(2,_op3);
  149. end;
  150. constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  151. begin
  152. inherited create(op);
  153. ops:=3;
  154. loadreg(0,_op1);
  155. loadreg(1,_op2);
  156. loadref(2,_op3);
  157. end;
  158. constructor taicpu.op_const_reg_reg(op : tasmop;_op1 : aint;_op2, _op3 : tregister);
  159. begin
  160. inherited create(op);
  161. ops:=3;
  162. loadconst(0,_op1);
  163. loadreg(1,_op2);
  164. loadreg(2,_op3);
  165. end;
  166. constructor taicpu.op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
  167. begin
  168. inherited create(op);
  169. ops:=3;
  170. loadconst(0,_op1);
  171. loadreg(1,_op2);
  172. loadconst(2,_op3);
  173. end;
  174. constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  175. begin
  176. inherited create(op);
  177. ops:=4;
  178. loadreg(0,_op1);
  179. loadreg(1,_op2);
  180. loadreg(2,_op3);
  181. loadreg(3,_op4);
  182. end;
  183. constructor taicpu.op_reg_reg_reg_const(op : tasmop; _op1, _op2, _op3 : tregister; _op4 : aint);
  184. begin
  185. inherited create(op);
  186. ops := 4;
  187. loadreg(0, _op1);
  188. loadreg(1, _op2);
  189. loadreg(2, _op3);
  190. loadconst(3, cardinal(_op4));
  191. end;
  192. { ****************************** newra stuff *************************** }
  193. function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
  194. begin
  195. case regtype of
  196. R_INTREGISTER:
  197. result:=
  198. (opcode=A_MOVE) and (oper[0]^.reg=oper[1]^.reg);
  199. R_FPUREGISTER:
  200. result:=
  201. ((opcode=A_FMOV_S) or (opcode=A_FMOV_D)) and
  202. (oper[0]^.reg=oper[1]^.reg);
  203. else
  204. result:=false;
  205. end;
  206. end;
  207. { Mant of case is set opnr0 and read from opnr(others). }
  208. function normal_oper_type(opnr: longint): topertype;
  209. begin
  210. if opnr=0 then
  211. result:=operand_write
  212. else
  213. result:=operand_read;
  214. end;
  215. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  216. begin
  217. case opcode of
  218. A_ST_B,A_ST_D,A_ST_W,A_ST_H,A_STX_B,A_STX_D,A_STX_W,A_STX_H,
  219. A_STPTR_W,A_STPTR_D,A_STGT_B,A_STGT_D,A_STGT_W,A_STGT_H,
  220. A_STLE_B,A_STLE_D,A_STLE_W,A_STLE_H,A_FST_S,A_FST_D,A_FSTX_S,
  221. A_FSTX_D,A_FSTGT_S,A_FSTGT_D,A_FSTLE_S,A_FSTLE_D,A_CSRWR,
  222. A_IOCSRWR_B,A_IOCSRWR_D,A_IOCSRWR_W,A_IOCSRWR_H:
  223. result:=operand_read;
  224. A_RDTIME_D,A_RDTIMEL_W,A_RDTIMEH_W:
  225. result:=operand_write;
  226. A_PRELD,A_PRELDX,A_DBAR,A_IBAR,A_SYSCALL,A_BREAK,A_ASRTLE_D,
  227. A_ASRTGT_D,A_CACOP,A_INVTLB,A_DBCL,A_IDLE,A_BEQ,A_BNE,A_BLT,
  228. A_BLTU,A_BGE,A_BGEU,A_BEQZ,A_BNEZ,A_B,A_BL,A_BCEQZ,A_BCNEZ,
  229. A_BLTZ,A_BGTZ,A_BGEZ,A_BLEZ,A_BGT,A_BLE,A_BGTU,A_BLEU,A_JR,
  230. A_NOP,A_BXX:
  231. result:=operand_read;
  232. A_AMSWAP_W,A_AMSWAP_D,A_AMSWAP_DB_W,A_AMSWAP_DB_D,A_AMADD_W,
  233. A_AMADD_D,A_AMADD_DB_W,A_AMADD_DB_D,A_AMAND_W,A_AMAND_D,
  234. A_AMAND_DB_W,A_AMAND_DB_D,A_AMOR_W,A_AMOR_D,A_AMOR_DB_W,
  235. A_AMOR_DB_D,A_AMXOR_W,A_AMXOR_D,A_AMXOR_DB_W,A_AMXOR_DB_D,
  236. A_AMMAX_W,A_AMMAX_DU,A_AMMAX_D,A_AMMAX_WU,A_AMMAX_DB_W,
  237. A_AMMAX_DB_DU,A_AMMAX_DB_D,A_AMMAX_DB_WU,A_AMMIN_W,A_AMMIN_DU,
  238. A_AMMIN_D,A_AMMIN_WU,A_AMMIN_DB_W,A_AMMIN_DB_DU,A_AMMIN_DB_D,
  239. A_AMMIN_DB_WU,A_SC_W,A_SC_D:
  240. result:=operand_readwrite;
  241. else
  242. result:=normal_oper_type(opnr);
  243. end;
  244. end;
  245. function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
  246. begin
  247. result := operand_read;
  248. end;
  249. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  250. var
  251. href : treference;
  252. begin
  253. href:=ref;
  254. href.refaddr:=addr_reg_12i;
  255. case getregtype(r) of
  256. R_INTREGISTER: result:=taicpu.op_reg_ref(A_LD_D,r,href);
  257. R_FPUREGISTER: result:=taicpu.op_reg_ref(A_FLD_D,r,href);
  258. else
  259. internalerror(2022111904);
  260. end;
  261. end;
  262. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  263. var
  264. href : treference;
  265. begin
  266. href:=ref;
  267. href.refaddr:=addr_reg_12i;
  268. case getregtype(r) of
  269. R_INTREGISTER: result:=taicpu.op_reg_ref(A_ST_D,r,href);
  270. R_FPUREGISTER: result:=taicpu.op_reg_ref(A_FST_D,r,href);
  271. else
  272. internalerror(2022111905);
  273. end;
  274. end;
  275. procedure InitAsm;
  276. begin
  277. end;
  278. procedure DoneAsm;
  279. begin
  280. end;
  281. begin
  282. cai_align:=tai_align;
  283. cai_cpu:=taicpu;
  284. end.