cgrv.pas 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250
  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,OP_IDIV,OP_NEG]) 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. if setflags then
  204. begin
  205. { if dst and src are equal, an overflow happened }
  206. a_cmp_reg_reg_label(list,OS_INT,OC_NE,dst,src1,ovloc.falselabel);
  207. a_jmp_always(list,ovloc.truelabel);
  208. end;
  209. maybeadjustresult(list,op,size,dst);
  210. end
  211. else
  212. case op of
  213. OP_MOVE:
  214. a_load_reg_reg(list,size,size,src1,dst);
  215. else
  216. {$ifdef RISCV64}
  217. if (op=OP_SHL) and
  218. (size=OS_S32) then
  219. begin
  220. list.concat(taicpu.op_reg_reg_reg(A_SLLW,dst,src2,src1));
  221. maybeadjustresult(list,op,size,dst);
  222. end
  223. else if (op=OP_SHR) and
  224. (size=OS_S32) then
  225. begin
  226. list.concat(taicpu.op_reg_reg_reg(A_SRLW,dst,src2,src1));
  227. maybeadjustresult(list,op,size,dst);
  228. end
  229. else if (op=OP_SAR) and
  230. (size=OS_S32) then
  231. begin
  232. list.concat(taicpu.op_reg_reg_reg(A_SRAW,dst,src2,src1));
  233. maybeadjustresult(list,op,size,dst);
  234. end
  235. else if (op=OP_SUB) and
  236. (size in [OS_32,OS_S32]) then
  237. begin
  238. list.concat(taicpu.op_reg_reg_reg(A_SUBW,dst,src2,src1));
  239. maybeadjustresult(list,op,size,dst);
  240. end
  241. else
  242. {$endif RISCV64}
  243. if (op in [OP_IMUL,OP_MUL]) and ([CPURV_HAS_MUL,CPURV_HAS_ZMMUL]*cpu_capabilities[current_settings.cputype]=[]) then
  244. begin
  245. case size of
  246. OS_8:
  247. name:='fpc_mul_byte';
  248. OS_S8:
  249. name:='fpc_mul_shortint';
  250. OS_16:
  251. name:='fpc_mul_word';
  252. OS_S16:
  253. name:='fpc_mul_integer';
  254. OS_32:
  255. name:='fpc_mul_dword';
  256. OS_S32:
  257. name:='fpc_mul_longint';
  258. else
  259. Internalerror(2021030601);
  260. end;
  261. // if check_overflow then
  262. // name:=name+'_checkoverflow';
  263. pd:=search_system_proc(name);
  264. paraloc1.init;
  265. paraloc2.init;
  266. paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  267. paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  268. a_load_reg_cgpara(list,OS_8,src1,paraloc2);
  269. a_load_reg_cgpara(list,OS_8,src2,paraloc1);
  270. paramanager.freecgpara(list,paraloc2);
  271. paramanager.freecgpara(list,paraloc1);
  272. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  273. a_call_name(list,upper(name),false);
  274. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  275. cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
  276. cg.a_load_reg_reg(list,size,size,NR_FUNCTION_RESULT_REG,dst);
  277. cg.a_reg_dealloc(list,NR_FUNCTION_RESULT_REG);
  278. paraloc2.done;
  279. paraloc1.done;
  280. end
  281. else
  282. begin
  283. if setflags and (op=OP_MUL) and (size=OS_32) then
  284. begin
  285. tmpreg1:=getintregister(list,size);
  286. list.concat(taicpu.op_reg_reg_reg(A_MULH,tmpreg1,src2,src1));
  287. end
  288. else
  289. tmpreg1:=NR_NO;
  290. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src2,src1));
  291. if setflags and (size in [OS_S32,OS_32]) then
  292. begin
  293. case op of
  294. OP_ADD:
  295. begin
  296. if size=OS_S32 then
  297. begin
  298. tmpreg1:=getintregister(list,size);
  299. list.concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg1,dst,src2));
  300. tmpreg2:=getintregister(list,size);
  301. list.concat(taicpu.op_reg_reg_const(A_SLTI,tmpreg2,src1,0));
  302. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,tmpreg2,ovloc.falselabel,0);
  303. ai.condition:=C_EQ;
  304. end
  305. else if size=OS_32 then
  306. begin
  307. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,dst,src2,ovloc.falselabel,0);
  308. ai.condition:=C_GEU;
  309. end
  310. else
  311. Internalerror(2025102003);
  312. list.concat(ai);
  313. a_jmp_always(list,ovloc.truelabel);
  314. end;
  315. OP_SUB:
  316. begin
  317. if size=OS_S32 then
  318. begin
  319. tmpreg1:=getintregister(list,size);
  320. list.concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg1,src2,dst));
  321. tmpreg2:=getintregister(list,size);
  322. list.concat(taicpu.op_reg_reg_const(A_SLTI,tmpreg2,src1,0));
  323. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,tmpreg2,ovloc.falselabel,0);
  324. ai.condition:=C_EQ;
  325. end
  326. else if size=OS_32 then
  327. begin
  328. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,src2,dst,ovloc.falselabel,0);
  329. ai.condition:=C_GEU;
  330. end
  331. else
  332. Internalerror(2025102002);
  333. list.concat(ai);
  334. a_jmp_always(list,ovloc.truelabel);
  335. end;
  336. OP_MUL:
  337. begin
  338. if size=OS_32 then
  339. begin
  340. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,NR_X0,ovloc.falselabel,0);
  341. ai.condition:=C_EQ;
  342. end
  343. else
  344. Internalerror(2025102002);
  345. list.concat(ai);
  346. a_jmp_always(list,ovloc.truelabel);
  347. end;
  348. OP_IMUL:
  349. begin
  350. if size=OS_S32 then
  351. begin
  352. tmpreg1:=getintregister(list,size);
  353. list.concat(taicpu.op_reg_reg_reg(A_MULH,tmpreg1,src2,src1));
  354. tmpreg2:=getintregister(list,size);
  355. list.concat(taicpu.op_reg_reg_const(A_SRAI,tmpreg2,dst,31));
  356. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg1,tmpreg2,ovloc.falselabel,0);
  357. ai.condition:=C_EQ;
  358. end
  359. else
  360. Internalerror(2025102004);
  361. list.concat(ai);
  362. a_jmp_always(list,ovloc.truelabel);
  363. end;
  364. OP_IDIV:
  365. begin
  366. { Only overflow if dst is all 1's }
  367. tmpreg1:=getintregister(list,OS_INT);
  368. list.Concat(taicpu.op_reg_reg_const(A_ADDI,tmpreg1,dst,1));
  369. a_cmp_reg_reg_label(list,OS_INT,OC_NE,tmpreg1,NR_X0,ovloc.falselabel);
  370. a_jmp_always(list,ovloc.truelabel);
  371. end;
  372. else
  373. ;
  374. end
  375. end;
  376. maybeadjustresult(list,op,size,dst);
  377. end;
  378. end;
  379. end;
  380. procedure tcgrv.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
  381. var
  382. ovloc: tlocation;
  383. begin
  384. a_op_reg_reg_reg_checkoverflow(list, op, size, src1, src2, dst, false, ovloc);
  385. end;
  386. procedure tcgrv.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean;
  387. var ovloc: tlocation);
  388. var
  389. tmpreg: TRegister;
  390. begin
  391. optimize_op_const(size,op,a);
  392. if op=OP_NONE then
  393. begin
  394. a_load_reg_reg(list,size,size,src,dst);
  395. exit;
  396. end;
  397. if op=OP_SUB then
  398. begin
  399. op:=OP_ADD;
  400. a:=-a;
  401. end;
  402. {$ifdef RISCV64}
  403. if (op=OP_SHL) and
  404. (size=OS_S32) then
  405. begin
  406. list.concat(taicpu.op_reg_reg_const(A_SLLIW,dst,src,a));
  407. maybeadjustresult(list,op,size,dst);
  408. end
  409. else if (op=OP_SHR) and
  410. (size=OS_S32) then
  411. begin
  412. list.concat(taicpu.op_reg_reg_const(A_SRLIW,dst,src,a));
  413. maybeadjustresult(list,op,size,dst);
  414. end
  415. else if (op=OP_SAR) and
  416. (size=OS_S32) then
  417. begin
  418. list.concat(taicpu.op_reg_reg_const(A_SRAIW,dst,src,a));
  419. maybeadjustresult(list,op,size,dst);
  420. end
  421. else
  422. {$endif RISCV64}
  423. if (TOpCG2AsmConstOp[op]<>A_None) and
  424. is_imm12(a) and not(setflags) then
  425. begin
  426. list.concat(taicpu.op_reg_reg_const(TOpCG2AsmConstOp[op],dst,src,a));
  427. maybeadjustresult(list,op,size,dst);
  428. end
  429. else if setflags then
  430. begin
  431. tmpreg:=getintregister(list,size);
  432. a_load_const_reg(list,size,a,tmpreg);
  433. a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,true,ovloc);
  434. end
  435. else
  436. begin
  437. tmpreg:=getintregister(list,size);
  438. a_load_const_reg(list,size,a,tmpreg);
  439. a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
  440. end;
  441. end;
  442. procedure tcgrv.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  443. var
  444. href: treference;
  445. b, tmpreg: TRegister;
  446. l: TAsmLabel;
  447. begin
  448. href:=ref;
  449. fixref(list,href);
  450. if (not assigned(href.symbol)) and
  451. (href.offset=0) then
  452. a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r)
  453. else if (assigned(href.symbol) or
  454. (not is_imm12(href.offset))) and
  455. (href.base<>NR_NO) then
  456. begin
  457. b:= href.base;
  458. current_asmdata.getjumplabel(l);
  459. a_label(list,l);
  460. href.base:=NR_NO;
  461. href.refaddr:=addr_pcrel_hi20;
  462. list.concat(taicpu.op_reg_ref(A_AUIPC,r,href));
  463. reference_reset_symbol(href,l,0,0,ref.volatility);
  464. href.refaddr:=addr_pcrel_lo12;
  465. list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,href));
  466. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
  467. end
  468. else if is_imm12(href.offset) and
  469. (href.base<>NR_NO) then
  470. begin
  471. list.concat(taicpu.op_reg_reg_const(A_ADDI,r,href.base,href.offset));
  472. end
  473. else if (href.refaddr=addr_pcrel) then
  474. begin
  475. tmpreg:=getintregister(list,OS_ADDR);
  476. b:=href.base;
  477. href.base:=NR_NO;
  478. current_asmdata.getjumplabel(l);
  479. a_label(list,l);
  480. href.refaddr:=addr_pcrel_hi20;
  481. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  482. reference_reset_symbol(href,l,0,0,ref.volatility);
  483. href.refaddr:=addr_pcrel_lo12;
  484. list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,tmpreg,href));
  485. if b<>NR_NO then
  486. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
  487. end
  488. else
  489. internalerror(2016060504);
  490. end;
  491. procedure tcgrv.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
  492. begin
  493. if a=0 then
  494. a_cmp_reg_reg_label(list,size,cmp_op,NR_X0,reg,l)
  495. else
  496. inherited;
  497. end;
  498. procedure tcgrv.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; reg1,reg2 : tregister;l : tasmlabel);
  499. var
  500. tmpreg: TRegister;
  501. ai: taicpu;
  502. begin
  503. if TOpCmp2AsmCond[cmp_op]=C_None then
  504. begin
  505. cmp_op:=swap_opcmp(cmp_op);
  506. tmpreg:=reg1;
  507. reg1:=reg2;
  508. reg2:=tmpreg;
  509. end;
  510. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,reg2,reg1,l,0);
  511. ai.is_jmp:=true;
  512. ai.condition:=TOpCmp2AsmCond[cmp_op];
  513. list.concat(ai);
  514. end;
  515. procedure tcgrv.a_jmp_name(list : TAsmList;const s : string);
  516. var
  517. ai: taicpu;
  518. href: treference;
  519. tmpreg: TRegister;
  520. l: TAsmLabel;
  521. begin
  522. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),0,0,[]);
  523. tmpreg:=getintregister(list,OS_ADDR);
  524. current_asmdata.getjumplabel(l);
  525. a_label(list,l);
  526. href.refaddr:=addr_pcrel_hi20;
  527. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  528. reference_reset_symbol(href,l,0,0,[]);
  529. href.refaddr:=addr_pcrel_lo12;
  530. ai:=taicpu.op_reg_reg_ref(A_JALR,NR_X0,tmpreg,href);
  531. ai.is_jmp:=true;
  532. list.concat(ai);
  533. //ai:=taicpu.op_reg_sym(A_JAL,NR_X0,current_asmdata.RefAsmSymbol(s));
  534. //ai.is_jmp:=true;
  535. end;
  536. procedure tcgrv.a_jmp_always(list : TAsmList;l: tasmlabel);
  537. var
  538. ai: taicpu;
  539. {href: treference;
  540. tmpreg: TRegister;}
  541. begin
  542. {reference_reset_symbol(href,l,0,0);
  543. tmpreg:=getintregister(list,OS_ADDR);
  544. current_asmdata.getjumplabel(l);
  545. a_label(list,l);
  546. href.refaddr:=addr_pcrel_hi20;
  547. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  548. reference_reset_symbol(href,l,0,0);
  549. href.refaddr:=addr_pcrel_lo12;
  550. ai:=taicpu.op_reg_reg_ref(A_JALR,NR_X0,tmpreg,href);
  551. ai.is_jmp:=true;
  552. list.concat(ai);}
  553. ai:=taicpu.op_reg_sym(A_JAL,NR_X0,l);
  554. ai.is_jmp:=true;
  555. list.concat(ai);
  556. end;
  557. procedure tcgrv.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
  558. const
  559. {$ifdef cpu64bitalu}
  560. store_int_op = A_SD;
  561. {$else cpu64bitalu}
  562. store_int_op = A_SW;
  563. {$endif cpu64bitalu}
  564. var
  565. regs, fregs: tcpuregisterset;
  566. r: TSuperRegister;
  567. href: treference;
  568. stackcount, stackAdjust: longint;
  569. begin
  570. if not(nostackframe) then
  571. begin
  572. a_reg_alloc(list,NR_STACK_POINTER_REG);
  573. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  574. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  575. { Int registers }
  576. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  577. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  578. regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
  579. if (pi_do_call in current_procinfo.flags) then
  580. regs:=regs+[RS_RETURN_ADDRESS_REG];
  581. stackcount:=0;
  582. for r:=RS_X0 to RS_X31 do
  583. if r in regs then
  584. inc(stackcount,sizeof(pint));
  585. { Float registers }
  586. fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
  587. for r:=RS_F0 to RS_F31 do
  588. if r in fregs then
  589. inc(stackcount,8);
  590. inc(localsize,stackcount);
  591. if not is_imm12(-localsize) then
  592. begin
  593. if not (RS_RETURN_ADDRESS_REG in regs) then
  594. begin
  595. include(regs,RS_RETURN_ADDRESS_REG);
  596. inc(localsize,sizeof(pint));
  597. end;
  598. end;
  599. reference_reset_base(href,NR_STACK_POINTER_REG,stackcount,ctempposinvalid,0,[]);
  600. stackAdjust:=0;
  601. if stackcount>0 then
  602. begin
  603. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-stackcount));
  604. stackAdjust:=stackcount;
  605. dec(localsize,stackcount);
  606. end;
  607. for r:=RS_X0 to RS_X31 do
  608. if r in regs then
  609. begin
  610. dec(href.offset,sizeof(pint));
  611. list.concat(taicpu.op_reg_ref(store_int_op,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
  612. end;
  613. { Float registers }
  614. for r:=RS_F0 to RS_F31 do
  615. if r in fregs then
  616. begin
  617. dec(href.offset,8);
  618. list.concat(taicpu.op_reg_ref(A_FSD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
  619. end;
  620. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  621. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG,stackAdjust));
  622. if localsize>0 then
  623. begin
  624. localsize:=align(localsize,sizeof(pint));
  625. if is_imm12(-localsize) then
  626. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize))
  627. else
  628. begin
  629. a_load_const_reg(list,OS_INT,localsize,NR_RETURN_ADDRESS_REG);
  630. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_RETURN_ADDRESS_REG));
  631. end;
  632. end;
  633. end;
  634. end;
  635. procedure tcgrv.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
  636. const
  637. {$ifdef cpu64bitalu}
  638. load_op = A_LD;
  639. {$else cpu64bitalu}
  640. load_op = A_LW;
  641. {$endif cpu64bitalu}
  642. var
  643. r: tsuperregister;
  644. regs, fregs: tcpuregisterset;
  645. stacksize, localsize, precompensation, postcompensation: longint;
  646. href: treference;
  647. begin
  648. if not(nostackframe) then
  649. begin
  650. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  651. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  652. regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
  653. if (pi_do_call in current_procinfo.flags) then
  654. regs:=regs+[RS_RETURN_ADDRESS_REG];
  655. stacksize:=0;
  656. for r:=RS_X31 downto RS_X0 do
  657. if r in regs then
  658. inc(stacksize,sizeof(pint));
  659. { Float registers }
  660. fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
  661. for r:=RS_F0 to RS_F31 do
  662. if r in fregs then
  663. inc(stacksize,8);
  664. localsize:=current_procinfo.calc_stackframe_size+stacksize;
  665. if localsize>0 then
  666. begin
  667. localsize:=align(localsize,sizeof(pint));
  668. if not is_imm12(-localsize) then
  669. begin
  670. if not (RS_RETURN_ADDRESS_REG in regs) then
  671. begin
  672. include(regs,RS_RETURN_ADDRESS_REG);
  673. inc(localsize,sizeof(pint));
  674. inc(stacksize,sizeof(pint));
  675. end;
  676. end;
  677. end;
  678. if not is_imm12(localsize) then
  679. begin
  680. precompensation:=localsize-2032;
  681. postcompensation:=localsize-precompensation;
  682. end
  683. else
  684. begin
  685. precompensation:=0;
  686. postcompensation:=localsize;
  687. end;
  688. reference_reset_base(href,NR_STACK_POINTER_REG,postcompensation-stacksize,ctempposinvalid,0,[]);
  689. if precompensation>0 then
  690. begin
  691. if is_imm12(precompensation) then
  692. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,precompensation))
  693. else
  694. begin
  695. { use X12 as temporary register as it is not callee-saved }
  696. a_load_const_reg(list,OS_INT,precompensation,NR_X12);
  697. list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_X12));
  698. end;
  699. end;
  700. { Float registers }
  701. for r:=RS_F31 downto RS_F0 do
  702. if r in fregs then
  703. begin
  704. list.concat(taicpu.op_reg_ref(A_FLD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
  705. inc(href.offset,8);
  706. end;
  707. for r:=RS_X31 downto RS_X0 do
  708. if r in regs then
  709. begin
  710. list.concat(taicpu.op_reg_ref(load_op,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
  711. inc(href.offset,sizeof(pint));
  712. end;
  713. if postcompensation>0 then
  714. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,postcompensation));
  715. end;
  716. if (target_info.system in (systems_freertos+systems_embedded)) and (po_interrupt in current_procinfo.procdef.procoptions) then
  717. begin
  718. list.concat(Taicpu.Op_none(A_MRET));
  719. end
  720. else
  721. list.concat(taicpu.op_reg_reg(A_JALR,NR_X0,NR_RETURN_ADDRESS_REG));
  722. end;
  723. procedure tcgrv.g_save_registers(list: TAsmList);
  724. begin
  725. end;
  726. procedure tcgrv.g_restore_registers(list: TAsmList);
  727. begin
  728. end;
  729. procedure tcgrv.g_profilecode(list: TAsmList);
  730. begin
  731. if target_info.system in [system_riscv32_linux,system_riscv64_linux] then
  732. begin
  733. list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_X10,NR_RETURN_ADDRESS_REG,0));
  734. a_call_name(list,'_mcount',false);
  735. end
  736. else
  737. internalerror(2018092201);
  738. end;
  739. procedure tcgrv.g_overflowcheck_loc(list: TAsmList; const Loc: tlocation; def: tdef; ovloc: tlocation);
  740. begin
  741. if not(cs_check_overflow in current_settings.localswitches) then
  742. exit;
  743. { no overflow checking yet generated }
  744. if ovloc.loc=LOC_VOID then
  745. exit;
  746. if ovloc.loc<>LOC_JUMP then
  747. Internalerror(2025102001);
  748. a_label(list,ovloc.truelabel);
  749. a_call_name(list,'FPC_OVERFLOW',false);
  750. a_label(list,ovloc.falselabel);
  751. end;
  752. procedure tcgrv.a_call_reg(list : TAsmList;reg: tregister);
  753. begin
  754. list.concat(taicpu.op_reg_reg(A_JALR,NR_RETURN_ADDRESS_REG,reg));
  755. include(current_procinfo.flags,pi_do_call);
  756. end;
  757. procedure tcgrv.a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
  758. reg: tregister; const ref: treference);
  759. const
  760. StoreInstr: array[OS_8..OS_INT] of TAsmOp =
  761. (A_SB,A_SH,A_SW
  762. {$ifdef cpu64bitalu}
  763. ,
  764. A_SD
  765. {$endif cpu64bitalu}
  766. );
  767. var
  768. ref2: TReference;
  769. tmpreg: tregister;
  770. op: TAsmOp;
  771. begin
  772. if not (fromsize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
  773. internalerror(2002090904);
  774. if not (tosize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
  775. internalerror(2002090905);
  776. tosize:=tcgsize2unsigned[tosize];
  777. ref2 := ref;
  778. fixref(list, ref2);
  779. op := storeinstr[tcgsize2unsigned[tosize]];
  780. list.concat(taicpu.op_reg_ref(op, reg,ref2));
  781. end;
  782. procedure tcgrv.a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
  783. var
  784. href: treference;
  785. op: TAsmOp;
  786. tmpreg: TRegister;
  787. begin
  788. href:=ref;
  789. fixref(list,href);
  790. if href.refaddr=addr_pcrel then
  791. begin
  792. tmpreg:=getintregister(list,OS_ADDR);
  793. a_loadaddr_ref_reg(list,href,tmpreg);
  794. reference_reset_base(href,tmpreg,0,ctempposinvalid,0,ref.volatility);
  795. end;
  796. case fromsize of
  797. OS_8: op:=A_LBU;
  798. OS_16: op:=A_LHU;
  799. OS_S8: op:=A_LB;
  800. OS_S16: op:=A_LH;
  801. {$ifdef RISCV64}
  802. OS_32: op:=A_LWU;
  803. OS_S32: op:=A_LW;
  804. OS_64,
  805. OS_S64: op:=A_LD;
  806. {$else}
  807. OS_64,OS_S64, { This only happens if tosize is smaller than fromsize }
  808. { We can therefore only consider the low 32-bit of the 64bit value }
  809. OS_32,
  810. OS_S32: op:=A_LW;
  811. {$endif}
  812. else
  813. internalerror(2016060502);
  814. end;
  815. list.concat(taicpu.op_reg_ref(op,reg,href));
  816. if (fromsize<>tosize) and (not (tosize in [OS_SINT,OS_INT])) then
  817. a_load_reg_reg(list,fromsize,tosize,reg,reg);
  818. end;
  819. procedure tcgrv.a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; register: tregister);
  820. begin
  821. if a=0 then
  822. a_load_reg_reg(list,size,size,NR_X0,register)
  823. else
  824. begin
  825. if is_imm12(a) then
  826. list.concat(taicpu.op_reg_reg_const(A_ADDI,register,NR_X0,a))
  827. else if is_lui_imm(a) then
  828. list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF))
  829. else
  830. begin
  831. if (a and $800)<>0 then
  832. list.concat(taicpu.op_reg_const(A_LUI,register,((a shr 12)+1) and $FFFFF))
  833. else
  834. list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF));
  835. list.concat(taicpu.op_reg_reg_const(A_ADDI,register,register,SarSmallint(smallint(a shl 4),4)));
  836. end;
  837. end;
  838. end;
  839. procedure tcgrv.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  840. var
  841. op: TAsmOp;
  842. ai: taicpu;
  843. const
  844. convOp: array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
  845. ((A_None,A_FCVT_D_S),
  846. (A_FCVT_S_D,A_None));
  847. begin
  848. if fromsize<>tosize then
  849. begin
  850. list.concat(taicpu.op_reg_reg(convOp[fromsize,tosize],reg2,reg1));
  851. maybe_check_for_fpu_exception(list);
  852. end
  853. else
  854. begin
  855. if tosize=OS_F32 then
  856. op:=A_FSGNJ_S
  857. else
  858. op:=A_FSGNJ_D;
  859. ai:=taicpu.op_reg_reg_reg(op,reg2,reg1,reg1);
  860. list.concat(ai);
  861. rg[R_FPUREGISTER].add_move_instruction(ai);
  862. end;
  863. end;
  864. procedure tcgrv.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
  865. var
  866. href: treference;
  867. op: TAsmOp;
  868. tmpreg: TRegister;
  869. l: TAsmLabel;
  870. begin
  871. href:=ref;
  872. { can we use the fl* rd,symbol,rd pseudoinstruction? }
  873. if (assigned(href.symbol) or (href.offset<>0)) then
  874. begin
  875. if (href.base<>NR_NO) or (href.index<>NR_NO) then
  876. fixref(list,href)
  877. else
  878. href.refaddr:=addr_full;
  879. end
  880. else
  881. fixref(list,href);
  882. if fromsize=OS_F32 then
  883. op:=A_FLW
  884. else if fromsize=OS_F64 then
  885. op:=A_FLD
  886. else if fromsize=OS_F128 then
  887. op:=A_FLQ
  888. else
  889. Internalerror(2025011101);
  890. if href.refaddr in [addr_pcrel,addr_full] then
  891. begin
  892. tmpreg:=getintregister(list,OS_ADDR);
  893. list.concat(taicpu.op_reg_ref_reg(op,reg,href,tmpreg));
  894. end
  895. else
  896. list.concat(taicpu.op_reg_ref(op,reg,href));
  897. if fromsize<>tosize then
  898. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  899. end;
  900. procedure tcgrv.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  901. var
  902. href: treference;
  903. op: TAsmOp;
  904. tmpreg: TRegister;
  905. begin
  906. href:=ref;
  907. fixref(list,href);
  908. if href.refaddr=addr_pcrel then
  909. begin
  910. tmpreg:=getintregister(list,OS_ADDR);
  911. a_loadaddr_ref_reg(list,href,tmpreg);
  912. reference_reset_base(href,tmpreg,0,ctempposinvalid,0,ref.volatility);
  913. end;
  914. if fromsize<>tosize then
  915. begin
  916. tmpreg:=getfpuregister(list,tosize);
  917. a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
  918. reg:=tmpreg;
  919. end;
  920. if tosize=OS_F32 then
  921. op:=A_FSW
  922. else
  923. op:=A_FSD;
  924. list.concat(taicpu.op_reg_ref(op,reg,href));
  925. end;
  926. function tcgrv.fixref(list: TAsmList; var ref: treference): boolean;
  927. var
  928. tmpreg: TRegister;
  929. href: treference;
  930. l: TAsmLabel;
  931. begin
  932. result:=true;
  933. if ref.refaddr=addr_pcrel then
  934. exit;
  935. if assigned(ref.symbol) then
  936. begin
  937. {$ifdef unsed}
  938. { keeping the code for reference
  939. we use the pseudo instruction LA below which is expanded by the assembler, doing
  940. so results in more readable assembler and easier optimization of the assembler code
  941. }
  942. if cs_create_pic in current_settings.moduleswitches then
  943. begin
  944. reference_reset_symbol(href,ref.symbol,0,0,[]);
  945. ref.symbol:=nil;
  946. tmpreg:=getintregister(list,OS_INT);
  947. current_asmdata.getaddrlabel(l);
  948. a_label(list,l);
  949. href.refaddr:=addr_got_pcrel_hi;
  950. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  951. reference_reset_symbol(href,l,0,0,[]);
  952. href.refaddr:=addr_pcrel_lo12;
  953. href.base:=tmpreg;
  954. {$ifdef RISCV64}
  955. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,href));
  956. {$else}
  957. list.concat(taicpu.op_reg_ref(A_LW,tmpreg,href));
  958. {$endif}
  959. end
  960. else
  961. begin
  962. reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment,ref.volatility);
  963. ref.symbol:=nil;
  964. ref.offset:=0;
  965. tmpreg:=getintregister(list,OS_INT);
  966. current_asmdata.getaddrlabel(l);
  967. a_label(list,l);
  968. href.refaddr:=addr_pcrel_hi20;
  969. list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
  970. reference_reset_symbol(href,l,0,0,ref.volatility);
  971. href.refaddr:=addr_pcrel_lo12;
  972. list.concat(taicpu.op_reg_reg_ref(A_ADDI,tmpreg,tmpreg,href));
  973. end;
  974. {$endif unsed}
  975. reference_reset_symbol(href,ref.symbol,0,0,[]);
  976. href.refaddr:=addr_full;
  977. ref.symbol:=nil;
  978. tmpreg:=getintregister(list,OS_ADDR);
  979. list.concat(taicpu.op_reg_ref(A_LA,tmpreg,href));
  980. if (ref.index<>NR_NO) and
  981. (ref.base<>NR_NO) then
  982. begin
  983. a_op_reg_reg(list,OP_ADD,OS_INT,ref.base,tmpreg);
  984. ref.base:=tmpreg;
  985. end
  986. else if (ref.index=NR_NO) and
  987. (ref.base<>NR_NO) then
  988. ref.index:=tmpreg
  989. else
  990. ref.base:=tmpreg;
  991. end
  992. else if (ref.index=NR_NO) and
  993. (ref.base=NR_NO) then
  994. begin
  995. tmpreg:=getintregister(list,OS_INT);
  996. a_load_const_reg(list, OS_ADDR,ref.offset,tmpreg);
  997. reference_reset_base(ref,tmpreg,0,ctempposinvalid,ref.alignment,ref.volatility);
  998. end;
  999. if (ref.index<>NR_NO) and
  1000. (ref.base=NR_NO) then
  1001. begin
  1002. ref.base:=ref.index;
  1003. ref.index:=NR_NO;
  1004. end;
  1005. if not is_imm12(ref.offset) then
  1006. begin
  1007. tmpreg:=getintregister(list,OS_INT);
  1008. a_load_const_reg(list,OS_INT,ref.offset,tmpreg);
  1009. ref.offset:=0;
  1010. if (ref.index<>NR_NO) and
  1011. (ref.base<>NR_NO) then
  1012. begin
  1013. a_op_reg_reg(list,OP_ADD,OS_INT,ref.index,tmpreg);
  1014. ref.index:=tmpreg;
  1015. end
  1016. else
  1017. ref.index:=tmpreg;
  1018. end;
  1019. if (ref.index<>NR_NO) and
  1020. (ref.base<>NR_NO) then
  1021. begin
  1022. tmpreg:=getaddressregister(list);
  1023. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
  1024. ref.base:=tmpreg;
  1025. ref.index:=NR_NO;
  1026. end;
  1027. end;
  1028. procedure tcgrv.maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
  1029. const
  1030. overflowops = [OP_MUL,OP_IMUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
  1031. begin
  1032. if (op in overflowops) and
  1033. (size in [OS_8,OS_S8,OS_16,OS_S16{$ifdef RISCV64},OS_32,OS_S32{$endif RISCV64}]) then
  1034. a_load_reg_reg(list,OS_INT,size,dst,dst)
  1035. end;
  1036. procedure tcgrv.g_check_for_fpu_exception(list: TAsmList;force,clear : boolean);
  1037. var
  1038. r : TRegister;
  1039. ai: taicpu;
  1040. l: TAsmLabel;
  1041. begin
  1042. if (CPURV_HAS_F in cpu_capabilities[current_settings.cputype]) and
  1043. needs_check_for_fpu_exceptions then
  1044. begin
  1045. r:=getintregister(list,OS_INT);
  1046. list.concat(taicpu.op_reg(A_FRFLAGS,r));
  1047. current_asmdata.getjumplabel(l);
  1048. ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,r,NR_X0,l,0);
  1049. ai.is_jmp:=true;
  1050. ai.condition:=C_EQ;
  1051. list.concat(ai);
  1052. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1053. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_THROWFPUEXCEPTION',false);
  1054. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1055. a_label(list,l);
  1056. end;
  1057. end;
  1058. end.