cgrv.pas 44 KB

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