cgrv.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. {
  2. Copyright (c) 2006 by Florian Klaempfl
  3. This unit implements the common part of the code generator for the Risc-V
  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 cgrv;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,symtype,symdef,
  22. cgbase,cgobj,
  23. aasmbase,aasmcpu,aasmtai,aasmdata,
  24. cpubase,cpuinfo,cgutils,rgcpu,
  25. parabase;
  26. type
  27. tcgrv = class(tcg)
  28. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara); override;
  29. procedure a_bit_scan_reg_reg(list: TAsmList; reverse,not_zero: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override;
  30. procedure a_call_reg(list : TAsmList;reg: tregister); override;
  31. procedure a_call_name(list : TAsmList;const s : string; weak: boolean); override;
  32. procedure a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference); override;
  33. procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize; reg: tregister; const ref: treference); override;
  34. procedure a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
  35. procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; register: tregister); override;
  36. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
  37. procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  38. procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); override;
  39. procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); override;
  40. procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation); override;
  41. procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation); override;
  42. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  43. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister; l : tasmlabel); override;
  44. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  45. procedure a_jmp_name(list : TAsmList;const s : string); override;
  46. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  47. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  48. procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
  49. procedure g_save_registers(list: TAsmList); override;
  50. procedure g_restore_registers(list: TAsmList); override;
  51. procedure g_profilecode(list: TAsmList); override;
  52. procedure g_overflowcheck_loc(list: TAsmList; const Loc: tlocation; def: tdef; ovloc: tlocation); override;
  53. { fpu move instructions }
  54. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
  55. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
  56. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
  57. procedure g_check_for_fpu_exception(list: TAsmList;force,clear : boolean); override;
  58. protected
  59. function fixref(list: TAsmList; var ref: treference): boolean;
  60. procedure maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
  61. end;
  62. const
  63. TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_NONE,
  64. C_LT,C_GE,C_None,C_NE,C_NONE,C_LTU,C_GEU,C_NONE);
  65. const
  66. TOpCG2AsmConstOp: Array[topcg] of TAsmOp = (A_NONE,
  67. A_NONE,A_ADDI,A_ANDI,A_NONE,A_NONE,A_NONE,A_NONE,
  68. A_None,A_None,A_ORI,A_SRAI,A_SLLI,A_SRLI,A_NONE,A_XORI,A_None,A_RORI);
  69. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,
  70. A_NONE,A_ADD,A_AND,A_DIVU,A_DIV,A_MUL,A_MUL,
  71. A_None,A_None,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR,A_ROL,A_ROR);
  72. {$ifdef extdebug}
  73. function ref2string(const ref : treference) : string;
  74. function cgop2string(const op : TOpCg) : String;
  75. {$endif extdebug}
  76. implementation
  77. uses
  78. {$ifdef extdebug}sysutils,{$endif}
  79. globals,verbose,systems,cutils,
  80. symconst,symsym,symtable,fmodule,
  81. rgobj,tgobj,cpupi,procinfo,paramgr;
  82. {$ifdef extdebug}
  83. function ref2string(const ref : treference) : string;
  84. begin
  85. result := 'base : ' + inttostr(ord(ref.base)) + ' index : ' + inttostr(ord(ref.index)) + ' refaddr : ' + inttostr(ord(ref.refaddr)) + ' offset : ' + inttostr(ref.offset) + ' symbol : ';
  86. if (assigned(ref.symbol)) then
  87. result := result + ref.symbol.name;
  88. end;
  89. function cgop2string(const op : TOpCg) : String;
  90. const
  91. opcg_strings : array[TOpCg] of string[6] = (
  92. 'None', 'Move', 'Add', 'And', 'Div', 'IDiv', 'IMul', 'Mul',
  93. 'Neg', 'Not', 'Or', 'Sar', 'Shl', 'Shr', 'Sub', 'Xor', 'Rol', 'Ror'
  94. );
  95. begin
  96. result := opcg_strings[op];
  97. end;
  98. {$endif extdebug}
  99. procedure tcgrv.a_call_name(list : TAsmList;const s : string; weak: boolean);
  100. var
  101. href: treference;
  102. l: TAsmLabel;
  103. ai: taicpu;
  104. begin
  105. if not(weak) then
  106. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),0,0,[])
  107. else
  108. reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION),0,0,[]);
  109. if cs_create_pic in current_settings.moduleswitches then
  110. begin
  111. href.refaddr:=addr_plt;
  112. list.concat(taicpu.op_ref(A_CALL,href));
  113. end
  114. else
  115. begin
  116. current_asmdata.getjumplabel(l);
  117. a_label(list,l);
  118. href.refaddr:=addr_pcrel_hi20;
  119. list.concat(taicpu.op_reg_ref(A_AUIPC,NR_RETURN_ADDRESS_REG,href));
  120. reference_reset_symbol(href,l,0,0,[]);
  121. href.refaddr:=addr_pcrel_lo12;
  122. ai:=taicpu.op_reg_reg_ref(A_JALR,NR_RETURN_ADDRESS_REG,NR_RETURN_ADDRESS_REG,href);
  123. ai.is_jmp:=true;
  124. list.concat(ai);
  125. end;
  126. { not assigned while generating external wrappers }
  127. if assigned(current_procinfo) then
  128. include(current_procinfo.flags,pi_do_call);
  129. end;
  130. procedure tcgrv.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
  131. begin
  132. if a=0 then
  133. a_load_reg_ref(list,size,size,NR_X0,ref)
  134. else
  135. inherited a_load_const_ref(list, size, a, ref);
  136. end;
  137. procedure tcgrv.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
  138. var
  139. ref: treference;
  140. tmpreg: tregister;
  141. begin
  142. paraloc.check_simple_location;
  143. paramanager.allocparaloc(list,paraloc.location);
  144. case paraloc.location^.loc of
  145. LOC_REGISTER,LOC_CREGISTER:
  146. a_loadaddr_ref_reg(list,r,paraloc.location^.register);
  147. LOC_REFERENCE:
  148. begin
  149. reference_reset(ref,paraloc.alignment,[]);
  150. ref.base := paraloc.location^.reference.index;
  151. ref.offset := paraloc.location^.reference.offset;
  152. tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
  153. a_loadaddr_ref_reg(list,r,tmpreg);
  154. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  155. end;
  156. else
  157. internalerror(2002080701);
  158. end;
  159. end;
  160. procedure tcgrv.a_bit_scan_reg_reg(list: TAsmList; reverse,not_zero: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
  161. begin
  162. internalerror(2016060401);
  163. end;
  164. procedure tcgrv.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
  165. begin
  166. a_op_const_reg_reg(list,op,size,a,reg,reg);
  167. end;
  168. procedure tcgrv.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  169. begin
  170. a_op_reg_reg_reg(list,op,size,src,dst,dst);
  171. end;
  172. procedure tcgrv.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
  173. var
  174. ovloc: tlocation;
  175. begin
  176. a_op_const_reg_reg_checkoverflow(list, op, size, a, src, dst, false, ovloc);
  177. end;
  178. procedure tcgrv.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
  179. var
  180. name: String;
  181. pd: tprocdef;
  182. paraloc1, paraloc2: tcgpara;
  183. ai: taicpu;
  184. tmpreg1, tmpreg2: TRegister;
  185. begin
  186. if setflags and
  187. { do we know overflow checking for this operation? fix me! }(size in [OS_32,OS_S32]) and (op in [OP_ADD,OP_SUB,OP_MUL,OP_IMUL]) then
  188. begin
  189. ovloc.loc:=LOC_JUMP;
  190. current_asmdata.getjumplabel(ovloc.truelabel);
  191. current_asmdata.getjumplabel(ovloc.falselabel);
  192. end
  193. else
  194. ovloc.loc:=LOC_VOID;
  195. if op=OP_NOT then
  196. begin
  197. list.concat(taicpu.op_reg_reg_const(A_XORI,dst,src1,-1));
  198. maybeadjustresult(list,op,size,dst);
  199. end
  200. else if op=OP_NEG then
  201. begin
  202. list.concat(taicpu.op_reg_reg_reg(A_SUB,dst,NR_X0,src1));
  203. maybeadjustresult(list,op,size,dst);
  204. end
  205. else
  206. case op of
  207. OP_MOVE:
  208. a_load_reg_reg(list,size,size,src1,dst);
  209. else
  210. {$ifdef RISCV64}
  211. if (op=OP_SHL) and
  212. (size=OS_S32) then
  213. begin
  214. list.concat(taicpu.op_reg_reg_reg(A_SLLW,dst,src2,src1));
  215. maybeadjustresult(list,op,size,dst);
  216. end
  217. else if (op=OP_SHR) and
  218. (size=OS_S32) then
  219. begin
  220. list.concat(taicpu.op_reg_reg_reg(A_SRLW,dst,src2,src1));
  221. maybeadjustresult(list,op,size,dst);
  222. end
  223. else if (op=OP_SAR) and
  224. (size=OS_S32) then
  225. begin
  226. list.concat(taicpu.op_reg_reg_reg(A_SRAW,dst,src2,src1));
  227. maybeadjustresult(list,op,size,dst);
  228. end
  229. else if (op=OP_SUB) and
  230. (size in [OS_32,OS_S32]) then
  231. begin
  232. list.concat(taicpu.op_reg_reg_reg(A_SUBW,dst,src2,src1));
  233. maybeadjustresult(list,op,size,dst);
  234. end
  235. else
  236. {$endif RISCV64}
  237. if (op in [OP_IMUL,OP_MUL]) and ([CPURV_HAS_MUL,CPURV_HAS_ZMMUL]*cpu_capabilities[current_settings.cputype]=[]) then
  238. begin
  239. case size of
  240. OS_8:
  241. name:='fpc_mul_byte';
  242. OS_S8:
  243. name:='fpc_mul_shortint';
  244. OS_16:
  245. name:='fpc_mul_word';
  246. OS_S16:
  247. name:='fpc_mul_integer';
  248. OS_32:
  249. name:='fpc_mul_dword';
  250. OS_S32:
  251. name:='fpc_mul_longint';
  252. else
  253. Internalerror(2021030601);
  254. end;
  255. // if check_overflow then
  256. // name:=name+'_checkoverflow';
  257. pd:=search_system_proc(name);
  258. paraloc1.init;
  259. paraloc2.init;
  260. paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  261. paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  262. a_load_reg_cgpara(list,OS_8,src1,paraloc2);
  263. a_load_reg_cgpara(list,OS_8,src2,paraloc1);
  264. paramanager.freecgpara(list,paraloc2);
  265. paramanager.freecgpara(list,paraloc1);
  266. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  267. a_call_name(list,upper(name),false);
  268. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  269. cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
  270. cg.a_load_reg_reg(list,size,size,NR_FUNCTION_RESULT_REG,dst);
  271. cg.a_reg_dealloc(list,NR_FUNCTION_RESULT_REG);
  272. paraloc2.done;
  273. paraloc1.done;
  274. end
  275. else
  276. begin
  277. if setflags and (op=OP_MUL) and (size=OS_32) then
  278. begin
  279. tmpreg1:=getintregister(list,size);
  280. list.concat(taicpu.op_reg_reg_reg(A_MULH,tmpreg1,src2,src1));
  281. end
  282. else
  283. tmpreg1:=NR_NO;
  284. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src2,src1));
  285. if setflags and (size in [OS_S32,OS_32]) then
  286. begin
  287. case op of
  288. OP_ADD:
  289. begin
  290. if size=OS_S32 then
  291. begin
  292. tmpreg1:=getintregister(list,size);
  293. list.concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg1,dst,src2));
  294. tmpreg2:=getintregister(list,size);
  295. list.concat(taicpu.op_reg_reg_const(A_SLTI,tmpreg2,src1,0));
  296. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,tmpreg2,ovloc.falselabel,0);
  297. ai.condition:=C_EQ;
  298. end
  299. else if size=OS_32 then
  300. begin
  301. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,dst,src2,ovloc.falselabel,0);
  302. ai.condition:=C_GEU;
  303. end
  304. else
  305. Internalerror(2025102003);
  306. list.concat(ai);
  307. a_jmp_always(list,ovloc.truelabel);
  308. end;
  309. OP_SUB:
  310. begin
  311. if size=OS_S32 then
  312. begin
  313. tmpreg1:=getintregister(list,size);
  314. list.concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg1,src2,dst));
  315. tmpreg2:=getintregister(list,size);
  316. list.concat(taicpu.op_reg_reg_const(A_SLTI,tmpreg2,src1,0));
  317. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,tmpreg2,ovloc.falselabel,0);
  318. ai.condition:=C_EQ;
  319. end
  320. else if size=OS_32 then
  321. begin
  322. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,src2,dst,ovloc.falselabel,0);
  323. ai.condition:=C_GEU;
  324. end
  325. else
  326. Internalerror(2025102002);
  327. list.concat(ai);
  328. a_jmp_always(list,ovloc.truelabel);
  329. end;
  330. OP_MUL:
  331. begin
  332. if size=OS_32 then
  333. begin
  334. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,NR_X0,ovloc.falselabel,0);
  335. ai.condition:=C_EQ;
  336. end
  337. else
  338. Internalerror(2025102002);
  339. list.concat(ai);
  340. a_jmp_always(list,ovloc.truelabel);
  341. end;
  342. OP_IMUL:
  343. begin
  344. if size=OS_S32 then
  345. begin
  346. tmpreg1:=getintregister(list,size);
  347. list.concat(taicpu.op_reg_reg_reg(A_MULH,tmpreg1,src2,src1));
  348. tmpreg2:=getintregister(list,size);
  349. list.concat(taicpu.op_reg_reg_const(A_SRAI,tmpreg2,dst,31));
  350. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,tmpreg2,ovloc.falselabel,0);
  351. ai.condition:=C_EQ;
  352. end
  353. else
  354. Internalerror(2025102004);
  355. list.concat(ai);
  356. a_jmp_always(list,ovloc.truelabel);
  357. end;
  358. else
  359. ;
  360. end
  361. end;
  362. maybeadjustresult(list,op,size,dst);
  363. end;
  364. end;
  365. end;
  366. procedure tcgrv.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
  367. var
  368. ovloc: tlocation;
  369. begin
  370. a_op_reg_reg_reg_checkoverflow(list, op, size, src1, src2, dst, false, ovloc);
  371. end;
  372. procedure tcgrv.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean;
  373. var ovloc: tlocation);
  374. var
  375. tmpreg: TRegister;
  376. begin
  377. optimize_op_const(size,op,a);
  378. if op=OP_NONE then
  379. begin
  380. a_load_reg_reg(list,size,size,src,dst);
  381. exit;
  382. end;
  383. if op=OP_SUB then
  384. begin
  385. op:=OP_ADD;
  386. a:=-a;
  387. end;
  388. {$ifdef RISCV64}
  389. if (op=OP_SHL) and
  390. (size=OS_S32) then
  391. begin
  392. list.concat(taicpu.op_reg_reg_const(A_SLLIW,dst,src,a));
  393. maybeadjustresult(list,op,size,dst);
  394. end
  395. else if (op=OP_SHR) and
  396. (size=OS_S32) then
  397. begin
  398. list.concat(taicpu.op_reg_reg_const(A_SRLIW,dst,src,a));
  399. maybeadjustresult(list,op,size,dst);
  400. end
  401. else if (op=OP_SAR) and
  402. (size=OS_S32) then
  403. begin
  404. list.concat(taicpu.op_reg_reg_const(A_SRAIW,dst,src,a));
  405. maybeadjustresult(list,op,size,dst);
  406. end
  407. else
  408. {$endif RISCV64}
  409. if (TOpCG2AsmConstOp[op]<>A_None) and
  410. is_imm12(a) and not(setflags) then
  411. begin
  412. list.concat(taicpu.op_reg_reg_const(TOpCG2AsmConstOp[op],dst,src,a));
  413. maybeadjustresult(list,op,size,dst);
  414. end
  415. else if setflags then
  416. begin
  417. tmpreg:=getintregister(list,size);
  418. a_load_const_reg(list,size,a,tmpreg);
  419. a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,true,ovloc);
  420. end
  421. else
  422. begin
  423. tmpreg:=getintregister(list,size);
  424. a_load_const_reg(list,size,a,tmpreg);
  425. a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
  426. end;
  427. end;
  428. procedure tcgrv.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  429. var
  430. href: treference;
  431. b, tmpreg: TRegister;
  432. l: TAsmLabel;
  433. begin
  434. href:=ref;
  435. fixref(list,href);
  436. if (not assigned(href.symbol)) and
  437. (href.offset=0) then
  438. a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r)
  439. else if (assigned(href.symbol) or
  440. (not is_imm12(href.offset))) and
  441. (href.base<>NR_NO) then
  442. begin
  443. b:= href.base;
  444. current_asmdata.getjumplabel(l);
  445. a_label(list,l);
  446. href.base:=NR_NO;
  447. href.refaddr:=addr_pcrel_hi20;
  448. list.concat(taicpu.op_reg_ref(A_AUIPC,r,href));
  449. reference_reset_symbol(href,l,0,0,ref.volatility);
  450. href.refaddr:=addr_pcrel_lo12;
  451. list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,href));
  452. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
  453. end
  454. else if is_imm12(href.offset) and
  455. (href.base<>NR_NO) then
  456. begin
  457. list.concat(taicpu.op_reg_reg_const(A_ADDI,r,href.base,href.offset));
  458. end
  459. else if (href.refaddr=addr_pcrel) then
  460. begin
  461. tmpreg:=getintregister(list,OS_ADDR);
  462. b:=href.base;
  463. href.base:=NR_NO;
  464. current_asmdata.getjumplabel(l);
  465. a_label(list,l);
  466. href.refaddr:=addr_pcrel_hi20;
  467. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  468. reference_reset_symbol(href,l,0,0,ref.volatility);
  469. href.refaddr:=addr_pcrel_lo12;
  470. list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,tmpreg,href));
  471. if b<>NR_NO then
  472. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
  473. end
  474. else
  475. internalerror(2016060504);
  476. end;
  477. procedure tcgrv.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
  478. begin
  479. if a=0 then
  480. a_cmp_reg_reg_label(list,size,cmp_op,NR_X0,reg,l)
  481. else
  482. inherited;
  483. end;
  484. procedure tcgrv.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; reg1,reg2 : tregister;l : tasmlabel);
  485. var
  486. tmpreg: TRegister;
  487. ai: taicpu;
  488. begin
  489. if TOpCmp2AsmCond[cmp_op]=C_None then
  490. begin
  491. cmp_op:=swap_opcmp(cmp_op);
  492. tmpreg:=reg1;
  493. reg1:=reg2;
  494. reg2:=tmpreg;
  495. end;
  496. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,reg2,reg1,l,0);
  497. ai.is_jmp:=true;
  498. ai.condition:=TOpCmp2AsmCond[cmp_op];
  499. list.concat(ai);
  500. end;
  501. procedure tcgrv.a_jmp_name(list : TAsmList;const s : string);
  502. var
  503. ai: taicpu;
  504. href: treference;
  505. tmpreg: TRegister;
  506. l: TAsmLabel;
  507. begin
  508. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),0,0,[]);
  509. tmpreg:=getintregister(list,OS_ADDR);
  510. current_asmdata.getjumplabel(l);
  511. a_label(list,l);
  512. href.refaddr:=addr_pcrel_hi20;
  513. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  514. reference_reset_symbol(href,l,0,0,[]);
  515. href.refaddr:=addr_pcrel_lo12;
  516. ai:=taicpu.op_reg_reg_ref(A_JALR,NR_X0,tmpreg,href);
  517. ai.is_jmp:=true;
  518. list.concat(ai);
  519. //ai:=taicpu.op_reg_sym(A_JAL,NR_X0,current_asmdata.RefAsmSymbol(s));
  520. //ai.is_jmp:=true;
  521. end;
  522. procedure tcgrv.a_jmp_always(list : TAsmList;l: tasmlabel);
  523. var
  524. ai: taicpu;
  525. {href: treference;
  526. tmpreg: TRegister;}
  527. begin
  528. {reference_reset_symbol(href,l,0,0);
  529. tmpreg:=getintregister(list,OS_ADDR);
  530. current_asmdata.getjumplabel(l);
  531. a_label(list,l);
  532. href.refaddr:=addr_pcrel_hi20;
  533. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  534. reference_reset_symbol(href,l,0,0);
  535. href.refaddr:=addr_pcrel_lo12;
  536. ai:=taicpu.op_reg_reg_ref(A_JALR,NR_X0,tmpreg,href);
  537. ai.is_jmp:=true;
  538. list.concat(ai);}
  539. ai:=taicpu.op_reg_sym(A_JAL,NR_X0,l);
  540. ai.is_jmp:=true;
  541. list.concat(ai);
  542. end;
  543. procedure tcgrv.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
  544. const
  545. {$ifdef cpu64bitalu}
  546. store_int_op = A_SD;
  547. {$else cpu64bitalu}
  548. store_int_op = A_SW;
  549. {$endif cpu64bitalu}
  550. var
  551. regs, fregs: tcpuregisterset;
  552. r: TSuperRegister;
  553. href: treference;
  554. stackcount, stackAdjust: longint;
  555. begin
  556. if not(nostackframe) then
  557. begin
  558. a_reg_alloc(list,NR_STACK_POINTER_REG);
  559. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  560. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  561. { Int registers }
  562. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  563. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  564. regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
  565. if (pi_do_call in current_procinfo.flags) then
  566. regs:=regs+[RS_RETURN_ADDRESS_REG];
  567. stackcount:=0;
  568. for r:=RS_X0 to RS_X31 do
  569. if r in regs then
  570. inc(stackcount,sizeof(pint));
  571. { Float registers }
  572. fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
  573. for r:=RS_F0 to RS_F31 do
  574. if r in fregs then
  575. inc(stackcount,8);
  576. inc(localsize,stackcount);
  577. if not is_imm12(-localsize) then
  578. begin
  579. if not (RS_RETURN_ADDRESS_REG in regs) then
  580. begin
  581. include(regs,RS_RETURN_ADDRESS_REG);
  582. inc(localsize,sizeof(pint));
  583. end;
  584. end;
  585. reference_reset_base(href,NR_STACK_POINTER_REG,stackcount,ctempposinvalid,0,[]);
  586. stackAdjust:=0;
  587. if stackcount>0 then
  588. begin
  589. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-stackcount));
  590. stackAdjust:=stackcount;
  591. dec(localsize,stackcount);
  592. end;
  593. for r:=RS_X0 to RS_X31 do
  594. if r in regs then
  595. begin
  596. dec(href.offset,sizeof(pint));
  597. list.concat(taicpu.op_reg_ref(store_int_op,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
  598. end;
  599. { Float registers }
  600. for r:=RS_F0 to RS_F31 do
  601. if r in fregs then
  602. begin
  603. dec(href.offset,8);
  604. list.concat(taicpu.op_reg_ref(A_FSD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
  605. end;
  606. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  607. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG,stackAdjust));
  608. if localsize>0 then
  609. begin
  610. localsize:=align(localsize,sizeof(pint));
  611. if is_imm12(-localsize) then
  612. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize))
  613. else
  614. begin
  615. a_load_const_reg(list,OS_INT,localsize,NR_RETURN_ADDRESS_REG);
  616. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_RETURN_ADDRESS_REG));
  617. end;
  618. end;
  619. end;
  620. end;
  621. procedure tcgrv.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
  622. const
  623. {$ifdef cpu64bitalu}
  624. load_op = A_LD;
  625. {$else cpu64bitalu}
  626. load_op = A_LW;
  627. {$endif cpu64bitalu}
  628. var
  629. r: tsuperregister;
  630. regs, fregs: tcpuregisterset;
  631. stacksize, localsize, precompensation, postcompensation: longint;
  632. href: treference;
  633. begin
  634. if not(nostackframe) then
  635. begin
  636. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  637. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  638. regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
  639. if (pi_do_call in current_procinfo.flags) then
  640. regs:=regs+[RS_RETURN_ADDRESS_REG];
  641. stacksize:=0;
  642. for r:=RS_X31 downto RS_X0 do
  643. if r in regs then
  644. inc(stacksize,sizeof(pint));
  645. { Float registers }
  646. fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
  647. for r:=RS_F0 to RS_F31 do
  648. if r in fregs then
  649. inc(stacksize,8);
  650. localsize:=current_procinfo.calc_stackframe_size+stacksize;
  651. if localsize>0 then
  652. begin
  653. localsize:=align(localsize,sizeof(pint));
  654. if not is_imm12(-localsize) then
  655. begin
  656. if not (RS_RETURN_ADDRESS_REG in regs) then
  657. begin
  658. include(regs,RS_RETURN_ADDRESS_REG);
  659. inc(localsize,sizeof(pint));
  660. inc(stacksize,sizeof(pint));
  661. end;
  662. end;
  663. end;
  664. if not is_imm12(localsize) then
  665. begin
  666. precompensation:=localsize-2032;
  667. postcompensation:=localsize-precompensation;
  668. end
  669. else
  670. begin
  671. precompensation:=0;
  672. postcompensation:=localsize;
  673. end;
  674. reference_reset_base(href,NR_STACK_POINTER_REG,postcompensation-stacksize,ctempposinvalid,0,[]);
  675. if precompensation>0 then
  676. begin
  677. if is_imm12(precompensation) then
  678. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,precompensation))
  679. else
  680. begin
  681. { use X12 as temporary register as it is not callee-saved }
  682. a_load_const_reg(list,OS_INT,precompensation,NR_X12);
  683. list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_X12));
  684. end;
  685. end;
  686. { Float registers }
  687. for r:=RS_F31 downto RS_F0 do
  688. if r in fregs then
  689. begin
  690. list.concat(taicpu.op_reg_ref(A_FLD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
  691. inc(href.offset,8);
  692. end;
  693. for r:=RS_X31 downto RS_X0 do
  694. if r in regs then
  695. begin
  696. list.concat(taicpu.op_reg_ref(load_op,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
  697. inc(href.offset,sizeof(pint));
  698. end;
  699. if postcompensation>0 then
  700. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,postcompensation));
  701. end;
  702. if (target_info.system in (systems_freertos+systems_embedded)) and (po_interrupt in current_procinfo.procdef.procoptions) then
  703. begin
  704. list.concat(Taicpu.Op_none(A_MRET));
  705. end
  706. else
  707. list.concat(taicpu.op_reg_reg(A_JALR,NR_X0,NR_RETURN_ADDRESS_REG));
  708. end;
  709. procedure tcgrv.g_save_registers(list: TAsmList);
  710. begin
  711. end;
  712. procedure tcgrv.g_restore_registers(list: TAsmList);
  713. begin
  714. end;
  715. procedure tcgrv.g_profilecode(list: TAsmList);
  716. begin
  717. if target_info.system in [system_riscv32_linux,system_riscv64_linux] then
  718. begin
  719. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_X10,NR_RETURN_ADDRESS_REG,0));
  720. a_call_name(list,'_mcount',false);
  721. end
  722. else
  723. internalerror(2018092201);
  724. end;
  725. procedure tcgrv.g_overflowcheck_loc(list: TAsmList; const Loc: tlocation; def: tdef; ovloc: tlocation);
  726. begin
  727. if not(cs_check_overflow in current_settings.localswitches) then
  728. exit;
  729. { no overflow checking yet generated }
  730. if ovloc.loc=LOC_VOID then
  731. exit;
  732. if ovloc.loc<>LOC_JUMP then
  733. Internalerror(2025102001);
  734. a_label(list,ovloc.truelabel);
  735. a_call_name(list,'FPC_OVERFLOW',false);
  736. a_label(list,ovloc.falselabel);
  737. end;
  738. procedure tcgrv.a_call_reg(list : TAsmList;reg: tregister);
  739. begin
  740. list.concat(taicpu.op_reg_reg(A_JALR,NR_RETURN_ADDRESS_REG,reg));
  741. include(current_procinfo.flags,pi_do_call);
  742. end;
  743. procedure tcgrv.a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
  744. reg: tregister; const ref: treference);
  745. const
  746. StoreInstr: array[OS_8..OS_INT] of TAsmOp =
  747. (A_SB,A_SH,A_SW
  748. {$ifdef cpu64bitalu}
  749. ,
  750. A_SD
  751. {$endif cpu64bitalu}
  752. );
  753. var
  754. ref2: TReference;
  755. tmpreg: tregister;
  756. op: TAsmOp;
  757. begin
  758. if not (fromsize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
  759. internalerror(2002090904);
  760. if not (tosize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
  761. internalerror(2002090905);
  762. tosize:=tcgsize2unsigned[tosize];
  763. ref2 := ref;
  764. fixref(list, ref2);
  765. op := storeinstr[tcgsize2unsigned[tosize]];
  766. list.concat(taicpu.op_reg_ref(op, reg,ref2));
  767. end;
  768. procedure tcgrv.a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
  769. var
  770. href: treference;
  771. op: TAsmOp;
  772. tmpreg: TRegister;
  773. begin
  774. href:=ref;
  775. fixref(list,href);
  776. if href.refaddr=addr_pcrel then
  777. begin
  778. tmpreg:=getintregister(list,OS_ADDR);
  779. a_loadaddr_ref_reg(list,href,tmpreg);
  780. reference_reset_base(href,tmpreg,0,ctempposinvalid,0,ref.volatility);
  781. end;
  782. case fromsize of
  783. OS_8: op:=A_LBU;
  784. OS_16: op:=A_LHU;
  785. OS_S8: op:=A_LB;
  786. OS_S16: op:=A_LH;
  787. {$ifdef RISCV64}
  788. OS_32: op:=A_LWU;
  789. OS_S32: op:=A_LW;
  790. OS_64,
  791. OS_S64: op:=A_LD;
  792. {$else}
  793. OS_64,OS_S64, { This only happens if tosize is smaller than fromsize }
  794. { We can therefore only consider the low 32-bit of the 64bit value }
  795. OS_32,
  796. OS_S32: op:=A_LW;
  797. {$endif}
  798. else
  799. internalerror(2016060502);
  800. end;
  801. list.concat(taicpu.op_reg_ref(op,reg,href));
  802. if (fromsize<>tosize) and (not (tosize in [OS_SINT,OS_INT])) then
  803. a_load_reg_reg(list,fromsize,tosize,reg,reg);
  804. end;
  805. procedure tcgrv.a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; register: tregister);
  806. begin
  807. if a=0 then
  808. a_load_reg_reg(list,size,size,NR_X0,register)
  809. else
  810. begin
  811. if is_imm12(a) then
  812. list.concat(taicpu.op_reg_reg_const(A_ADDI,register,NR_X0,a))
  813. else if is_lui_imm(a) then
  814. list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF))
  815. else
  816. begin
  817. if (a and $800)<>0 then
  818. list.concat(taicpu.op_reg_const(A_LUI,register,((a shr 12)+1) and $FFFFF))
  819. else
  820. list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF));
  821. list.concat(taicpu.op_reg_reg_const(A_ADDI,register,register,SarSmallint(smallint(a shl 4),4)));
  822. end;
  823. end;
  824. end;
  825. procedure tcgrv.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  826. var
  827. op: TAsmOp;
  828. ai: taicpu;
  829. const
  830. convOp: array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
  831. ((A_None,A_FCVT_D_S),
  832. (A_FCVT_S_D,A_None));
  833. begin
  834. if fromsize<>tosize then
  835. begin
  836. list.concat(taicpu.op_reg_reg(convOp[fromsize,tosize],reg2,reg1));
  837. maybe_check_for_fpu_exception(list);
  838. end
  839. else
  840. begin
  841. if tosize=OS_F32 then
  842. op:=A_FSGNJ_S
  843. else
  844. op:=A_FSGNJ_D;
  845. ai:=taicpu.op_reg_reg_reg(op,reg2,reg1,reg1);
  846. list.concat(ai);
  847. rg[R_FPUREGISTER].add_move_instruction(ai);
  848. end;
  849. end;
  850. procedure tcgrv.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
  851. var
  852. href: treference;
  853. op: TAsmOp;
  854. tmpreg: TRegister;
  855. l: TAsmLabel;
  856. begin
  857. href:=ref;
  858. { can we use the fl* rd,symbol,rd pseudoinstruction? }
  859. if (assigned(href.symbol) or (href.offset<>0)) then
  860. begin
  861. if (href.base<>NR_NO) or (href.index<>NR_NO) then
  862. fixref(list,href)
  863. else
  864. href.refaddr:=addr_full;
  865. end
  866. else
  867. fixref(list,href);
  868. if fromsize=OS_F32 then
  869. op:=A_FLW
  870. else if fromsize=OS_F64 then
  871. op:=A_FLD
  872. else if fromsize=OS_F128 then
  873. op:=A_FLQ
  874. else
  875. Internalerror(2025011101);
  876. if href.refaddr in [addr_pcrel,addr_full] then
  877. begin
  878. tmpreg:=getintregister(list,OS_ADDR);
  879. list.concat(taicpu.op_reg_ref_reg(op,reg,href,tmpreg));
  880. end
  881. else
  882. list.concat(taicpu.op_reg_ref(op,reg,href));
  883. if fromsize<>tosize then
  884. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  885. end;
  886. procedure tcgrv.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  887. var
  888. href: treference;
  889. op: TAsmOp;
  890. tmpreg: TRegister;
  891. begin
  892. href:=ref;
  893. fixref(list,href);
  894. if href.refaddr=addr_pcrel then
  895. begin
  896. tmpreg:=getintregister(list,OS_ADDR);
  897. a_loadaddr_ref_reg(list,href,tmpreg);
  898. reference_reset_base(href,tmpreg,0,ctempposinvalid,0,ref.volatility);
  899. end;
  900. if fromsize<>tosize then
  901. begin
  902. tmpreg:=getfpuregister(list,tosize);
  903. a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
  904. reg:=tmpreg;
  905. end;
  906. if tosize=OS_F32 then
  907. op:=A_FSW
  908. else
  909. op:=A_FSD;
  910. list.concat(taicpu.op_reg_ref(op,reg,href));
  911. end;
  912. function tcgrv.fixref(list: TAsmList; var ref: treference): boolean;
  913. var
  914. tmpreg: TRegister;
  915. href: treference;
  916. l: TAsmLabel;
  917. begin
  918. result:=true;
  919. if ref.refaddr=addr_pcrel then
  920. exit;
  921. if assigned(ref.symbol) then
  922. begin
  923. {$ifdef unsed}
  924. { keeping the code for reference
  925. we use the pseudo instruction LA below which is expanded by the assembler, doing
  926. so results in more readable assembler and easier optimization of the assembler code
  927. }
  928. if cs_create_pic in current_settings.moduleswitches then
  929. begin
  930. reference_reset_symbol(href,ref.symbol,0,0,[]);
  931. ref.symbol:=nil;
  932. tmpreg:=getintregister(list,OS_INT);
  933. current_asmdata.getaddrlabel(l);
  934. a_label(list,l);
  935. href.refaddr:=addr_got_pcrel_hi;
  936. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  937. reference_reset_symbol(href,l,0,0,[]);
  938. href.refaddr:=addr_pcrel_lo12;
  939. href.base:=tmpreg;
  940. {$ifdef RISCV64}
  941. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,href));
  942. {$else}
  943. list.concat(taicpu.op_reg_ref(A_LW,tmpreg,href));
  944. {$endif}
  945. end
  946. else
  947. begin
  948. reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment,ref.volatility);
  949. ref.symbol:=nil;
  950. ref.offset:=0;
  951. tmpreg:=getintregister(list,OS_INT);
  952. current_asmdata.getaddrlabel(l);
  953. a_label(list,l);
  954. href.refaddr:=addr_pcrel_hi20;
  955. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  956. reference_reset_symbol(href,l,0,0,ref.volatility);
  957. href.refaddr:=addr_pcrel_lo12;
  958. list.concat(taicpu.op_reg_reg_ref(A_ADDI,tmpreg,tmpreg,href));
  959. end;
  960. {$endif unsed}
  961. reference_reset_symbol(href,ref.symbol,0,0,[]);
  962. href.refaddr:=addr_full;
  963. ref.symbol:=nil;
  964. tmpreg:=getintregister(list,OS_ADDR);
  965. list.concat(taicpu.op_reg_ref(A_LA,tmpreg,href));
  966. if (ref.index<>NR_NO) and
  967. (ref.base<>NR_NO) then
  968. begin
  969. a_op_reg_reg(list,OP_ADD,OS_INT,ref.base,tmpreg);
  970. ref.base:=tmpreg;
  971. end
  972. else if (ref.index=NR_NO) and
  973. (ref.base<>NR_NO) then
  974. ref.index:=tmpreg
  975. else
  976. ref.base:=tmpreg;
  977. end
  978. else if (ref.index=NR_NO) and
  979. (ref.base=NR_NO) then
  980. begin
  981. tmpreg:=getintregister(list,OS_INT);
  982. a_load_const_reg(list, OS_ADDR,ref.offset,tmpreg);
  983. reference_reset_base(ref,tmpreg,0,ctempposinvalid,ref.alignment,ref.volatility);
  984. end;
  985. if (ref.index<>NR_NO) and
  986. (ref.base=NR_NO) then
  987. begin
  988. ref.base:=ref.index;
  989. ref.index:=NR_NO;
  990. end;
  991. if not is_imm12(ref.offset) then
  992. begin
  993. tmpreg:=getintregister(list,OS_INT);
  994. a_load_const_reg(list,OS_INT,ref.offset,tmpreg);
  995. ref.offset:=0;
  996. if (ref.index<>NR_NO) and
  997. (ref.base<>NR_NO) then
  998. begin
  999. a_op_reg_reg(list,OP_ADD,OS_INT,ref.index,tmpreg);
  1000. ref.index:=tmpreg;
  1001. end
  1002. else
  1003. ref.index:=tmpreg;
  1004. end;
  1005. if (ref.index<>NR_NO) and
  1006. (ref.base<>NR_NO) then
  1007. begin
  1008. tmpreg:=getaddressregister(list);
  1009. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
  1010. ref.base:=tmpreg;
  1011. ref.index:=NR_NO;
  1012. end;
  1013. end;
  1014. procedure tcgrv.maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
  1015. const
  1016. overflowops = [OP_MUL,OP_IMUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
  1017. begin
  1018. if (op in overflowops) and
  1019. (size in [OS_8,OS_S8,OS_16,OS_S16{$ifdef RISCV64},OS_32,OS_S32{$endif RISCV64}]) then
  1020. a_load_reg_reg(list,OS_INT,size,dst,dst)
  1021. end;
  1022. procedure tcgrv.g_check_for_fpu_exception(list: TAsmList;force,clear : boolean);
  1023. var
  1024. r : TRegister;
  1025. ai: taicpu;
  1026. l: TAsmLabel;
  1027. begin
  1028. if (CPURV_HAS_F in cpu_capabilities[current_settings.cputype]) and
  1029. needs_check_for_fpu_exceptions then
  1030. begin
  1031. r:=getintregister(list,OS_INT);
  1032. list.concat(taicpu.op_reg(A_FRFLAGS,r));
  1033. current_asmdata.getjumplabel(l);
  1034. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,r,NR_X0,l,0);
  1035. ai.is_jmp:=true;
  1036. ai.condition:=C_EQ;
  1037. list.concat(ai);
  1038. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1039. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_THROWFPUEXCEPTION',false);
  1040. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1041. a_label(list,l);
  1042. end;
  1043. end;
  1044. end.