cgcpu.pas 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150
  1. {
  2. Copyright (c) 1998-2012 by Florian Klaempfl and David Zhang
  3. This unit implements the code generator for MIPS
  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 cgcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype, parabase,
  22. cgbase, cgutils, cgobj, cg64f32, cpupara,
  23. aasmbase, aasmtai, aasmcpu, aasmdata,
  24. cpubase, cpuinfo,
  25. node, symconst, SymType, symdef,
  26. rgcpu;
  27. type
  28. TCGMIPS = class(tcg)
  29. public
  30. procedure init_register_allocators; override;
  31. procedure done_register_allocators; override;
  32. function getfpuregister(list: tasmlist; size: Tcgsize): Tregister; override;
  33. /// { needed by cg64 }
  34. procedure make_simple_ref(list: tasmlist; var ref: treference);
  35. procedure make_simple_ref_fpu(list: tasmlist; var ref: treference);
  36. procedure handle_load_store(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
  37. procedure handle_load_store_fpu(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
  38. procedure handle_reg_const_reg(list: tasmlist; op: Tasmop; src: tregister; a: tcgint; dst: tregister);
  39. procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
  40. { parameter }
  41. procedure a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara); override;
  42. procedure a_load_ref_cgpara(list: tasmlist; sz: tcgsize; const r: TReference; const paraloc: TCGPara); override;
  43. procedure a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara); override;
  44. procedure a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara); override;
  45. procedure a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); override;
  46. procedure a_call_name(list: tasmlist; const s: string; weak : boolean); override;
  47. procedure a_call_reg(list: tasmlist; Reg: TRegister); override;
  48. { General purpose instructions }
  49. procedure a_op_const_reg(list: tasmlist; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister); override;
  50. procedure a_op_reg_reg(list: tasmlist; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  51. procedure a_op_const_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); override;
  52. procedure a_op_reg_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); override;
  53. procedure a_op_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation); override;
  54. procedure a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation); override;
  55. { move instructions }
  56. procedure a_load_const_reg(list: tasmlist; size: tcgsize; a: tcgint; reg: tregister); override;
  57. procedure a_load_const_ref(list: tasmlist; size: tcgsize; a: tcgint; const ref: TReference); override;
  58. procedure a_load_reg_ref(list: tasmlist; FromSize, ToSize: TCgSize; reg: TRegister; const ref: TReference); override;
  59. procedure a_load_ref_reg(list: tasmlist; FromSize, ToSize: TCgSize; const ref: TReference; reg: tregister); override;
  60. procedure a_load_reg_reg(list: tasmlist; FromSize, ToSize: TCgSize; reg1, reg2: tregister); override;
  61. procedure a_loadaddr_ref_reg(list: tasmlist; const ref: TReference; r: tregister); override;
  62. { fpu move instructions }
  63. procedure a_loadfpu_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
  64. procedure a_loadfpu_ref_reg(list: tasmlist; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister); override;
  65. procedure a_loadfpu_reg_ref(list: tasmlist; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference); override;
  66. { comparison operations }
  67. procedure a_cmp_const_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel); override;
  68. procedure a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); override;
  69. procedure a_jmp_always(List: tasmlist; l: TAsmLabel); override;
  70. procedure a_jmp_name(list: tasmlist; const s: string); override;
  71. procedure a_jmp_cond(list: tasmlist; cond: TOpCmp; l: tasmlabel); { override;}
  72. procedure g_overflowCheck(List: tasmlist; const Loc: TLocation; def: TDef); override;
  73. procedure g_overflowCheck_loc(List: tasmlist; const Loc: TLocation; def: TDef; ovloc: tlocation); override;
  74. procedure g_proc_entry(list: tasmlist; localsize: longint; nostackframe: boolean); override;
  75. procedure g_proc_exit(list: tasmlist; parasize: longint; nostackframe: boolean); override;
  76. procedure g_concatcopy(list: tasmlist; const Source, dest: treference; len: tcgint); override;
  77. procedure g_concatcopy_unaligned(list: tasmlist; const Source, dest: treference; len: tcgint); override;
  78. procedure g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
  79. procedure g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labelname: string; ioffset: longint); override;
  80. { Transform unsupported methods into Internal errors }
  81. procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
  82. procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
  83. end;
  84. TCg64MPSel = class(tcg64f32)
  85. public
  86. procedure a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference); override;
  87. procedure a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64); override;
  88. procedure a_load64_ref_cgpara(list: tasmlist; const r: treference; const paraloc: tcgpara); override;
  89. procedure a_op64_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc, regdst: TRegister64); override;
  90. procedure a_op64_const_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regdst: TRegister64); override;
  91. procedure a_op64_const_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64); override;
  92. procedure a_op64_reg_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64); override;
  93. procedure a_op64_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override;
  94. procedure a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override;
  95. end;
  96. procedure create_codegen;
  97. const
  98. TOpCmp2AsmCond : array[topcmp] of TAsmCond=(C_NONE,
  99. C_EQ,C_GT,C_LT,C_GE,C_LE,C_NE,C_LEU,C_LTU,C_GEU,C_GTU
  100. );
  101. implementation
  102. uses
  103. globals, verbose, systems, cutils,
  104. paramgr, fmodule,
  105. symtable,
  106. tgobj,
  107. procinfo, cpupi;
  108. var
  109. cgcpu_calc_stackframe_size: aint;
  110. function f_TOpCG2AsmOp(op: TOpCG; size: tcgsize): TAsmOp;
  111. begin
  112. if size = OS_32 then
  113. case op of
  114. OP_ADD: { simple addition }
  115. f_TOpCG2AsmOp := A_ADDU;
  116. OP_AND: { simple logical and }
  117. f_TOpCG2AsmOp := A_AND;
  118. OP_DIV: { simple unsigned division }
  119. f_TOpCG2AsmOp := A_DIVU;
  120. OP_IDIV: { simple signed division }
  121. f_TOpCG2AsmOp := A_DIV;
  122. OP_IMUL: { simple signed multiply }
  123. f_TOpCG2AsmOp := A_MULT;
  124. OP_MUL: { simple unsigned multiply }
  125. f_TOpCG2AsmOp := A_MULTU;
  126. OP_NEG: { simple negate }
  127. f_TOpCG2AsmOp := A_NEGU;
  128. OP_NOT: { simple logical not }
  129. f_TOpCG2AsmOp := A_NOT;
  130. OP_OR: { simple logical or }
  131. f_TOpCG2AsmOp := A_OR;
  132. OP_SAR: { arithmetic shift-right }
  133. f_TOpCG2AsmOp := A_SRA;
  134. OP_SHL: { logical shift left }
  135. f_TOpCG2AsmOp := A_SLL;
  136. OP_SHR: { logical shift right }
  137. f_TOpCG2AsmOp := A_SRL;
  138. OP_SUB: { simple subtraction }
  139. f_TOpCG2AsmOp := A_SUBU;
  140. OP_XOR: { simple exclusive or }
  141. f_TOpCG2AsmOp := A_XOR;
  142. else
  143. InternalError(2007070401);
  144. end{ case }
  145. else
  146. case op of
  147. OP_ADD: { simple addition }
  148. f_TOpCG2AsmOp := A_ADDU;
  149. OP_AND: { simple logical and }
  150. f_TOpCG2AsmOp := A_AND;
  151. OP_DIV: { simple unsigned division }
  152. f_TOpCG2AsmOp := A_DIVU;
  153. OP_IDIV: { simple signed division }
  154. f_TOpCG2AsmOp := A_DIV;
  155. OP_IMUL: { simple signed multiply }
  156. f_TOpCG2AsmOp := A_MULT;
  157. OP_MUL: { simple unsigned multiply }
  158. f_TOpCG2AsmOp := A_MULTU;
  159. OP_NEG: { simple negate }
  160. f_TOpCG2AsmOp := A_NEGU;
  161. OP_NOT: { simple logical not }
  162. f_TOpCG2AsmOp := A_NOT;
  163. OP_OR: { simple logical or }
  164. f_TOpCG2AsmOp := A_OR;
  165. OP_SAR: { arithmetic shift-right }
  166. f_TOpCG2AsmOp := A_SRA;
  167. OP_SHL: { logical shift left }
  168. f_TOpCG2AsmOp := A_SLL;
  169. OP_SHR: { logical shift right }
  170. f_TOpCG2AsmOp := A_SRL;
  171. OP_SUB: { simple subtraction }
  172. f_TOpCG2AsmOp := A_SUBU;
  173. OP_XOR: { simple exclusive or }
  174. f_TOpCG2AsmOp := A_XOR;
  175. else
  176. InternalError(2007010701);
  177. end;{ case }
  178. end;
  179. function f_TOpCG2AsmOp_ovf(op: TOpCG; size: tcgsize): TAsmOp;
  180. begin
  181. if size = OS_32 then
  182. case op of
  183. OP_ADD: { simple addition }
  184. f_TOpCG2AsmOp_ovf := A_ADD;
  185. OP_AND: { simple logical and }
  186. f_TOpCG2AsmOp_ovf := A_AND;
  187. OP_DIV: { simple unsigned division }
  188. f_TOpCG2AsmOp_ovf := A_DIVU;
  189. OP_IDIV: { simple signed division }
  190. f_TOpCG2AsmOp_ovf := A_DIV;
  191. OP_IMUL: { simple signed multiply }
  192. f_TOpCG2AsmOp_ovf := A_MULO;
  193. OP_MUL: { simple unsigned multiply }
  194. f_TOpCG2AsmOp_ovf := A_MULOU;
  195. OP_NEG: { simple negate }
  196. f_TOpCG2AsmOp_ovf := A_NEG;
  197. OP_NOT: { simple logical not }
  198. f_TOpCG2AsmOp_ovf := A_NOT;
  199. OP_OR: { simple logical or }
  200. f_TOpCG2AsmOp_ovf := A_OR;
  201. OP_SAR: { arithmetic shift-right }
  202. f_TOpCG2AsmOp_ovf := A_SRA;
  203. OP_SHL: { logical shift left }
  204. f_TOpCG2AsmOp_ovf := A_SLL;
  205. OP_SHR: { logical shift right }
  206. f_TOpCG2AsmOp_ovf := A_SRL;
  207. OP_SUB: { simple subtraction }
  208. f_TOpCG2AsmOp_ovf := A_SUB;
  209. OP_XOR: { simple exclusive or }
  210. f_TOpCG2AsmOp_ovf := A_XOR;
  211. else
  212. InternalError(2007070403);
  213. end{ case }
  214. else
  215. case op of
  216. OP_ADD: { simple addition }
  217. f_TOpCG2AsmOp_ovf := A_ADD;
  218. OP_AND: { simple logical and }
  219. f_TOpCG2AsmOp_ovf := A_AND;
  220. OP_DIV: { simple unsigned division }
  221. f_TOpCG2AsmOp_ovf := A_DIVU;
  222. OP_IDIV: { simple signed division }
  223. f_TOpCG2AsmOp_ovf := A_DIV;
  224. OP_IMUL: { simple signed multiply }
  225. f_TOpCG2AsmOp_ovf := A_MULO;
  226. OP_MUL: { simple unsigned multiply }
  227. f_TOpCG2AsmOp_ovf := A_MULOU;
  228. OP_NEG: { simple negate }
  229. f_TOpCG2AsmOp_ovf := A_NEG;
  230. OP_NOT: { simple logical not }
  231. f_TOpCG2AsmOp_ovf := A_NOT;
  232. OP_OR: { simple logical or }
  233. f_TOpCG2AsmOp_ovf := A_OR;
  234. OP_SAR: { arithmetic shift-right }
  235. f_TOpCG2AsmOp_ovf := A_SRA;
  236. OP_SHL: { logical shift left }
  237. f_TOpCG2AsmOp_ovf := A_SLL;
  238. OP_SHR: { logical shift right }
  239. f_TOpCG2AsmOp_ovf := A_SRL;
  240. OP_SUB: { simple subtraction }
  241. f_TOpCG2AsmOp_ovf := A_SUB;
  242. OP_XOR: { simple exclusive or }
  243. f_TOpCG2AsmOp_ovf := A_XOR;
  244. else
  245. InternalError(2007010703);
  246. end;{ case }
  247. end;
  248. function f_TOp64CG2AsmOp(op: TOpCG): TAsmOp;
  249. begin
  250. case op of
  251. OP_ADD: { simple addition }
  252. f_TOp64CG2AsmOp := A_DADDU;
  253. OP_AND: { simple logical and }
  254. f_TOp64CG2AsmOp := A_AND;
  255. OP_DIV: { simple unsigned division }
  256. f_TOp64CG2AsmOp := A_DDIVU;
  257. OP_IDIV: { simple signed division }
  258. f_TOp64CG2AsmOp := A_DDIV;
  259. OP_IMUL: { simple signed multiply }
  260. f_TOp64CG2AsmOp := A_DMULO;
  261. OP_MUL: { simple unsigned multiply }
  262. f_TOp64CG2AsmOp := A_DMULOU;
  263. OP_NEG: { simple negate }
  264. f_TOp64CG2AsmOp := A_DNEGU;
  265. OP_NOT: { simple logical not }
  266. f_TOp64CG2AsmOp := A_NOT;
  267. OP_OR: { simple logical or }
  268. f_TOp64CG2AsmOp := A_OR;
  269. OP_SAR: { arithmetic shift-right }
  270. f_TOp64CG2AsmOp := A_DSRA;
  271. OP_SHL: { logical shift left }
  272. f_TOp64CG2AsmOp := A_DSLL;
  273. OP_SHR: { logical shift right }
  274. f_TOp64CG2AsmOp := A_DSRL;
  275. OP_SUB: { simple subtraction }
  276. f_TOp64CG2AsmOp := A_DSUBU;
  277. OP_XOR: { simple exclusive or }
  278. f_TOp64CG2AsmOp := A_XOR;
  279. else
  280. InternalError(2007010702);
  281. end;{ case }
  282. end;
  283. procedure TCGMIPS.make_simple_ref(list: tasmlist; var ref: treference);
  284. var
  285. tmpreg, tmpreg1: tregister;
  286. tmpref: treference;
  287. begin
  288. tmpreg := NR_NO;
  289. { Be sure to have a base register }
  290. if (ref.base = NR_NO) then
  291. begin
  292. ref.base := ref.index;
  293. ref.index := NR_NO;
  294. end;
  295. if (cs_create_pic in current_settings.moduleswitches) and
  296. assigned(ref.symbol) then
  297. begin
  298. tmpreg := cg.GetIntRegister(list, OS_INT);
  299. reference_reset(tmpref,sizeof(aint));
  300. tmpref.symbol := ref.symbol;
  301. tmpref.refaddr := addr_pic;
  302. if not (pi_needs_got in current_procinfo.flags) then
  303. internalerror(200501161);
  304. tmpref.index := current_procinfo.got;
  305. list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
  306. ref.symbol := nil;
  307. if (ref.index <> NR_NO) then
  308. begin
  309. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg));
  310. ref.index := tmpreg;
  311. end
  312. else
  313. begin
  314. if ref.base <> NR_NO then
  315. ref.index := tmpreg
  316. else
  317. ref.base := tmpreg;
  318. end;
  319. end;
  320. { When need to use LUI, do it first }
  321. if assigned(ref.symbol) or
  322. (ref.offset < simm16lo) or
  323. (ref.offset > simm16hi) then
  324. begin
  325. tmpreg := GetIntRegister(list, OS_INT);
  326. reference_reset(tmpref,sizeof(aint));
  327. tmpref.symbol := ref.symbol;
  328. tmpref.offset := ref.offset;
  329. tmpref.refaddr := addr_high;
  330. list.concat(taicpu.op_reg_ref(A_LUI, tmpreg, tmpref));
  331. if (ref.offset = 0) and (ref.index = NR_NO) and
  332. (ref.base = NR_NO) then
  333. begin
  334. ref.refaddr := addr_low;
  335. end
  336. else
  337. begin
  338. { Load the low part is left }
  339. tmpref.refaddr := addr_low;
  340. list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg, tmpreg, tmpref));
  341. ref.offset := 0;
  342. { symbol is loaded }
  343. ref.symbol := nil;
  344. end;
  345. if (ref.index <> NR_NO) then
  346. begin
  347. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg));
  348. ref.index := tmpreg;
  349. end
  350. else
  351. begin
  352. if ref.base <> NR_NO then
  353. ref.index := tmpreg
  354. else
  355. ref.base := tmpreg;
  356. end;
  357. end;
  358. if (ref.base <> NR_NO) then
  359. begin
  360. if (ref.index <> NR_NO) and (ref.offset = 0) then
  361. begin
  362. tmpreg1 := GetIntRegister(list, OS_INT);
  363. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.base, ref.index));
  364. ref.base := tmpreg1;
  365. ref.index := NR_NO;
  366. end
  367. else if (ref.index <> NR_NO) and
  368. ((ref.offset <> 0) or assigned(ref.symbol)) then
  369. begin
  370. if tmpreg = NR_NO then
  371. tmpreg := GetIntRegister(list, OS_INT);
  372. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.base, ref.index));
  373. ref.base := tmpreg;
  374. ref.index := NR_NO;
  375. end;
  376. end;
  377. end;
  378. procedure TCGMIPS.make_simple_ref_fpu(list: tasmlist; var ref: treference);
  379. var
  380. tmpreg, tmpreg1: tregister;
  381. tmpref: treference;
  382. begin
  383. tmpreg := NR_NO;
  384. { Be sure to have a base register }
  385. if (ref.base = NR_NO) then
  386. begin
  387. ref.base := ref.index;
  388. ref.index := NR_NO;
  389. end;
  390. if (cs_create_pic in current_settings.moduleswitches) and
  391. assigned(ref.symbol) then
  392. begin
  393. tmpreg := GetIntRegister(list, OS_INT);
  394. reference_reset(tmpref,sizeof(aint));
  395. tmpref.symbol := ref.symbol;
  396. tmpref.refaddr := addr_pic;
  397. if not (pi_needs_got in current_procinfo.flags) then
  398. internalerror(200501161);
  399. tmpref.index := current_procinfo.got;
  400. list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
  401. ref.symbol := nil;
  402. if (ref.index <> NR_NO) then
  403. begin
  404. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg));
  405. ref.index := tmpreg;
  406. end
  407. else
  408. begin
  409. if ref.base <> NR_NO then
  410. ref.index := tmpreg
  411. else
  412. ref.base := tmpreg;
  413. end;
  414. end;
  415. { When need to use LUI, do it first }
  416. if (not assigned(ref.symbol)) and (ref.index = NR_NO) and
  417. (ref.offset > simm16lo + 1000) and (ref.offset < simm16hi - 1000)
  418. then
  419. exit;
  420. tmpreg1 := GetIntRegister(list, OS_INT);
  421. if assigned(ref.symbol) then
  422. begin
  423. reference_reset(tmpref,sizeof(aint));
  424. tmpref.symbol := ref.symbol;
  425. tmpref.offset := ref.offset;
  426. tmpref.refaddr := addr_high;
  427. list.concat(taicpu.op_reg_ref(A_LUI, tmpreg1, tmpref));
  428. { Load the low part }
  429. tmpref.refaddr := addr_low;
  430. list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg1, tmpreg1, tmpref));
  431. { symbol is loaded }
  432. ref.symbol := nil;
  433. end
  434. else
  435. list.concat(taicpu.op_reg_const(A_LI, tmpreg1, ref.offset));
  436. if (ref.index <> NR_NO) then
  437. begin
  438. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.index, tmpreg1));
  439. ref.index := NR_NO
  440. end;
  441. if ref.base <> NR_NO then
  442. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.base, tmpreg1));
  443. ref.base := tmpreg1;
  444. ref.offset := 0;
  445. end;
  446. procedure TCGMIPS.handle_load_store(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
  447. begin
  448. make_simple_ref(list, ref);
  449. list.concat(taicpu.op_reg_ref(op, reg, ref));
  450. end;
  451. procedure TCGMIPS.handle_load_store_fpu(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
  452. begin
  453. make_simple_ref_fpu(list, ref);
  454. list.concat(taicpu.op_reg_ref(op, reg, ref));
  455. end;
  456. procedure TCGMIPS.handle_reg_const_reg(list: tasmlist; op: Tasmop; src: tregister; a: tcgint; dst: tregister);
  457. var
  458. tmpreg: tregister;
  459. begin
  460. if (a < simm16lo) or
  461. (a > simm16hi) then
  462. begin
  463. tmpreg := GetIntRegister(list, OS_INT);
  464. a_load_const_reg(list, OS_INT, a, tmpreg);
  465. list.concat(taicpu.op_reg_reg_reg(op, dst, src, tmpreg));
  466. end
  467. else
  468. list.concat(taicpu.op_reg_reg_const(op, dst, src, a));
  469. end;
  470. {****************************************************************************
  471. Assembler code
  472. ****************************************************************************}
  473. procedure TCGMIPS.init_register_allocators;
  474. begin
  475. inherited init_register_allocators;
  476. { Keep RS_R25, i.e. $t9 for PIC call }
  477. if (cs_create_pic in current_settings.moduleswitches) and assigned(current_procinfo) and
  478. (pi_needs_got in current_procinfo.flags) then
  479. begin
  480. current_procinfo.got := NR_GP;
  481. rg[R_INTREGISTER] := Trgcpu.Create(R_INTREGISTER, R_SUBD,
  482. [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
  483. RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
  484. RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
  485. first_int_imreg, []);
  486. end
  487. else
  488. rg[R_INTREGISTER] := trgcpu.Create(R_INTREGISTER, R_SUBD,
  489. [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
  490. RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
  491. RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
  492. first_int_imreg, []);
  493. {
  494. rg[R_FPUREGISTER] := trgcpu.Create(R_FPUREGISTER, R_SUBFS,
  495. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
  496. RS_F8,RS_F9,RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15,
  497. RS_F16,RS_F17,RS_F18,RS_F19,RS_F20,RS_F21,RS_F22,RS_F23,
  498. RS_F24,RS_F25,RS_F26,RS_F27,RS_F28,RS_F29,RS_F30,RS_F31],
  499. first_fpu_imreg, []);
  500. }
  501. rg[R_FPUREGISTER] := trgcpu.Create(R_FPUREGISTER, R_SUBFS,
  502. [RS_F0,RS_F2,RS_F4,RS_F6, RS_F8,RS_F10,RS_F12,RS_F14,
  503. RS_F16,RS_F18,RS_F20,RS_F22, RS_F24,RS_F26,RS_F28,RS_F30],
  504. first_fpu_imreg, []);
  505. { needs at least one element for rgobj not to crash }
  506. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
  507. [RS_R0],first_mm_imreg,[]);
  508. end;
  509. procedure TCGMIPS.done_register_allocators;
  510. begin
  511. rg[R_INTREGISTER].Free;
  512. rg[R_FPUREGISTER].Free;
  513. rg[R_MMREGISTER].Free;
  514. inherited done_register_allocators;
  515. end;
  516. function TCGMIPS.getfpuregister(list: tasmlist; size: Tcgsize): Tregister;
  517. begin
  518. if size = OS_F64 then
  519. Result := rg[R_FPUREGISTER].getregister(list, R_SUBFD)
  520. else
  521. Result := rg[R_FPUREGISTER].getregister(list, R_SUBFS);
  522. end;
  523. procedure TCGMIPS.a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara);
  524. var
  525. Ref: TReference;
  526. begin
  527. paraloc.check_simple_location;
  528. paramanager.allocparaloc(list,paraloc.location);
  529. case paraloc.location^.loc of
  530. LOC_REGISTER, LOC_CREGISTER:
  531. a_load_const_reg(list, size, a, paraloc.location^.Register);
  532. LOC_REFERENCE:
  533. begin
  534. with paraloc.location^.Reference do
  535. begin
  536. if (Index = NR_SP) and (Offset < 0) then
  537. InternalError(2002081104);
  538. reference_reset_base(ref, index, offset, sizeof(aint));
  539. end;
  540. a_load_const_ref(list, size, a, ref);
  541. end;
  542. else
  543. InternalError(2002122200);
  544. end;
  545. end;
  546. procedure TCGMIPS.a_load_ref_cgpara(list: tasmlist; sz: TCgSize; const r: TReference; const paraloc: TCGPara);
  547. var
  548. href, href2: treference;
  549. hloc: pcgparalocation;
  550. begin
  551. href := r;
  552. hloc := paraloc.location;
  553. while assigned(hloc) do
  554. begin
  555. paramanager.allocparaloc(list,hloc);
  556. case hloc^.loc of
  557. LOC_REGISTER,LOC_CREGISTER:
  558. a_load_ref_reg(list, hloc^.size, hloc^.size, href, hloc^.Register);
  559. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  560. a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
  561. LOC_REFERENCE:
  562. begin
  563. reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
  564. a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
  565. end
  566. else
  567. internalerror(200408241);
  568. end;
  569. Inc(href.offset, tcgsize2size[hloc^.size]);
  570. hloc := hloc^.Next;
  571. end;
  572. end;
  573. procedure TCGMIPS.a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara);
  574. var
  575. Ref: TReference;
  576. TmpReg: TRegister;
  577. begin
  578. paraloc.check_simple_location;
  579. paramanager.allocparaloc(list,paraloc.location);
  580. with paraloc.location^ do
  581. begin
  582. case loc of
  583. LOC_REGISTER, LOC_CREGISTER:
  584. a_loadaddr_ref_reg(list, r, Register);
  585. LOC_REFERENCE:
  586. begin
  587. reference_reset(ref,sizeof(aint));
  588. ref.base := reference.index;
  589. ref.offset := reference.offset;
  590. tmpreg := GetAddressRegister(list);
  591. a_loadaddr_ref_reg(list, r, tmpreg);
  592. a_load_reg_ref(list, OS_ADDR, OS_ADDR, tmpreg, ref);
  593. end;
  594. else
  595. internalerror(2002080701);
  596. end;
  597. end;
  598. end;
  599. procedure TCGMIPS.a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara);
  600. var
  601. href, href2: treference;
  602. hloc: pcgparalocation;
  603. begin
  604. href := ref;
  605. hloc := paraloc.location;
  606. while assigned(hloc) do
  607. begin
  608. paramanager.allocparaloc(list,hloc);
  609. case hloc^.loc of
  610. LOC_REGISTER:
  611. a_load_ref_reg(list, hloc^.size, hloc^.size, href, hloc^.Register);
  612. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  613. a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
  614. LOC_REFERENCE:
  615. begin
  616. reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
  617. a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
  618. end;
  619. else
  620. internalerror(200408241);
  621. end;
  622. Inc(href.offset, tcgsize2size[hloc^.size]);
  623. hloc := hloc^.Next;
  624. end;
  625. end;
  626. procedure TCGMIPS.a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara);
  627. var
  628. href: treference;
  629. begin
  630. tg.GetTemp(list, TCGSize2Size[size], TCGSize2Size[size], tt_normal, href);
  631. a_loadfpu_reg_ref(list, size, size, r, href);
  632. a_loadfpu_ref_cgpara(list, size, href, paraloc);
  633. tg.Ungettemp(list, href);
  634. end;
  635. procedure TCGMIPS.a_call_name(list: tasmlist; const s: string; weak: boolean);
  636. var
  637. href: treference;
  638. begin
  639. if (cs_create_pic in current_settings.moduleswitches) then
  640. begin
  641. reference_reset(href,sizeof(aint));
  642. href.symbol:=current_asmdata.RefAsmSymbol(s);
  643. a_loadaddr_ref_reg(list,href,NR_PIC_FUNC);
  644. list.concat(taicpu.op_reg(A_JALR,NR_PIC_FUNC));
  645. end
  646. else
  647. list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s)));
  648. { Delay slot }
  649. list.concat(taicpu.op_none(A_NOP));
  650. end;
  651. procedure TCGMIPS.a_call_reg(list: tasmlist; Reg: TRegister);
  652. begin
  653. if (cs_create_pic in current_settings.moduleswitches) and
  654. (Reg <> NR_PIC_FUNC) then
  655. list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_PIC_FUNC));
  656. list.concat(taicpu.op_reg(A_JALR, reg));
  657. { Delay slot }
  658. list.concat(taicpu.op_none(A_NOP));
  659. end;
  660. {********************** load instructions ********************}
  661. procedure TCGMIPS.a_load_const_reg(list: tasmlist; size: TCGSize; a: tcgint; reg: TRegister);
  662. begin
  663. if (a = 0) then
  664. list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_R0))
  665. { LUI allows to set the upper 16 bits, so we'll take full advantage of it }
  666. else if (a and aint($ffff)) = 0 then
  667. list.concat(taicpu.op_reg_const(A_LUI, reg, aint(a) shr 16))
  668. else if (a >= simm16lo) and (a <= simm16hi) then
  669. list.concat(taicpu.op_reg_reg_const(A_ADDIU, reg, NR_R0, a))
  670. else if (a>=0) and (a <= 65535) then
  671. list.concat(taicpu.op_reg_reg_const(A_ORI, reg, NR_R0, a))
  672. else
  673. begin
  674. list.concat(taicpu.op_reg_const(A_LI, reg, aint(a) ));
  675. end;
  676. end;
  677. procedure TCGMIPS.a_load_const_ref(list: tasmlist; size: tcgsize; a: tcgint; const ref: TReference);
  678. begin
  679. if a = 0 then
  680. a_load_reg_ref(list, size, size, NR_R0, ref)
  681. else
  682. inherited a_load_const_ref(list, size, a, ref);
  683. end;
  684. procedure TCGMIPS.a_load_reg_ref(list: tasmlist; FromSize, ToSize: TCGSize; reg: tregister; const Ref: TReference);
  685. var
  686. op: tasmop;
  687. begin
  688. if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
  689. fromsize := tosize;
  690. case fromsize of
  691. { signed integer registers }
  692. OS_8,
  693. OS_S8:
  694. Op := A_SB;
  695. OS_16,
  696. OS_S16:
  697. Op := A_SH;
  698. OS_32,
  699. OS_S32:
  700. Op := A_SW;
  701. else
  702. InternalError(2002122100);
  703. end;
  704. handle_load_store(list, True, op, reg, ref);
  705. end;
  706. procedure TCGMIPS.a_load_ref_reg(list: tasmlist; FromSize, ToSize: TCgSize; const ref: TReference; reg: tregister);
  707. var
  708. op: tasmop;
  709. begin
  710. if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
  711. fromsize := tosize;
  712. case fromsize of
  713. OS_S8:
  714. Op := A_LB;{Load Signed Byte}
  715. OS_8:
  716. Op := A_LBU;{Load Unsigned Byte}
  717. OS_S16:
  718. Op := A_LH;{Load Signed Halfword}
  719. OS_16:
  720. Op := A_LHU;{Load Unsigned Halfword}
  721. OS_S32:
  722. Op := A_LW;{Load Word}
  723. OS_32:
  724. Op := A_LW;//A_LWU;{Load Unsigned Word}
  725. OS_S64,
  726. OS_64:
  727. Op := A_LD;{Load a Long Word}
  728. else
  729. InternalError(2002122101);
  730. end;
  731. handle_load_store(list, False, op, reg, ref);
  732. if (fromsize=OS_S8) and (tosize=OS_16) then
  733. a_load_reg_reg(list,fromsize,tosize,reg,reg);
  734. end;
  735. procedure TCGMIPS.a_load_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  736. var
  737. instr: taicpu;
  738. begin
  739. if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
  740. (
  741. (tcgsize2size[tosize] = tcgsize2size[fromsize]) and (tosize <> fromsize)
  742. ) or ((fromsize = OS_S8) and
  743. (tosize = OS_16)) then
  744. begin
  745. case tosize of
  746. OS_8:
  747. a_op_const_reg_reg(list, OP_AND, tosize, $ff, reg1, reg2);
  748. OS_16:
  749. a_op_const_reg_reg(list, OP_AND, tosize, $ffff, reg1, reg2);
  750. OS_32,
  751. OS_S32:
  752. begin
  753. instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
  754. list.Concat(instr);
  755. { Notify the register allocator that we have written a move instruction so
  756. it can try to eliminate it. }
  757. add_move_instruction(instr);
  758. end;
  759. OS_S8:
  760. begin
  761. list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 24));
  762. list.concat(taicpu.op_reg_reg_const(A_SRA, reg2, reg2, 24));
  763. end;
  764. OS_S16:
  765. begin
  766. list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 16));
  767. list.concat(taicpu.op_reg_reg_const(A_SRA, reg2, reg2, 16));
  768. end;
  769. else
  770. internalerror(2002090901);
  771. end;
  772. end
  773. else
  774. begin
  775. if reg1 <> reg2 then
  776. begin
  777. { same size, only a register mov required }
  778. instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
  779. list.Concat(instr);
  780. // { Notify the register allocator that we have written a move instruction so
  781. // it can try to eliminate it. }
  782. add_move_instruction(instr);
  783. end;
  784. end;
  785. end;
  786. procedure TCGMIPS.a_loadaddr_ref_reg(list: tasmlist; const ref: TReference; r: tregister);
  787. var
  788. tmpref, href: treference;
  789. hreg, tmpreg: tregister;
  790. r_used: boolean;
  791. begin
  792. r_used := false;
  793. href := ref;
  794. if (href.base = NR_NO) and (href.index <> NR_NO) then
  795. internalerror(200306171);
  796. if ((cs_create_pic in current_settings.moduleswitches) or
  797. (ref.refaddr=addr_pic)) and
  798. assigned(href.symbol) then
  799. begin
  800. tmpreg := r; //GetIntRegister(list, OS_ADDR);
  801. r_used := true;
  802. reference_reset(tmpref,sizeof(aint));
  803. tmpref.symbol := href.symbol;
  804. tmpref.refaddr := addr_pic;
  805. if not (pi_needs_got in current_procinfo.flags) then
  806. internalerror(200501161);
  807. if current_procinfo.got=NR_NO then
  808. current_procinfo.got:=NR_GP;
  809. { for addr_pic NR_GP can be implicit or explicit }
  810. if (href.refaddr=addr_pic) and (href.base=current_procinfo.got) then
  811. href.base:=NR_NO;
  812. tmpref.base := current_procinfo.got;
  813. list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
  814. href.symbol := nil;
  815. if (href.index <> NR_NO) then
  816. begin
  817. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, href.index, tmpreg));
  818. href.index := tmpreg;
  819. end
  820. else
  821. begin
  822. if href.base <> NR_NO then
  823. href.index := tmpreg
  824. else
  825. href.base := tmpreg;
  826. end;
  827. if (href.base=NR_NO) and (href.offset=0) then
  828. exit;
  829. end;
  830. if assigned(href.symbol) or
  831. (href.offset < simm16lo) or
  832. (href.offset > simm16hi) then
  833. begin
  834. if (href.base = NR_NO) and (href.index = NR_NO) then
  835. hreg := r
  836. else
  837. hreg := GetAddressRegister(list);
  838. reference_reset(tmpref,sizeof(aint));
  839. tmpref.symbol := href.symbol;
  840. tmpref.offset := href.offset;
  841. tmpref.refaddr := addr_high;
  842. list.concat(taicpu.op_reg_ref(A_LUI, hreg, tmpref));
  843. { Only the low part is left }
  844. tmpref.refaddr := addr_low;
  845. list.concat(taicpu.op_reg_reg_ref(A_ADDIU, hreg, hreg, tmpref));
  846. if href.base <> NR_NO then
  847. begin
  848. if href.index <> NR_NO then
  849. begin
  850. list.concat(taicpu.op_reg_reg_reg(A_ADDU, hreg, href.base, hreg));
  851. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index));
  852. end
  853. else
  854. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.base));
  855. end;
  856. end
  857. else
  858. { At least small offset, maybe base and maybe index }
  859. if (href.offset >= simm16lo) and
  860. (href.offset <= simm16hi) then
  861. begin
  862. if href.index <> NR_NO then { Both base and index }
  863. begin
  864. if href.offset = 0 then
  865. begin
  866. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, href.base, href.index));
  867. end
  868. else
  869. begin
  870. if r_used then
  871. hreg := GetAddressRegister(list)
  872. else
  873. hreg := r;
  874. list.concat(taicpu.op_reg_reg_const(A_ADDIU, hreg, href.base, href.offset));
  875. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index));
  876. end
  877. end
  878. else if href.base <> NR_NO then { Only base }
  879. begin
  880. list.concat(taicpu.op_reg_reg_const(A_ADDIU, r, href.base, href.offset));
  881. end
  882. else
  883. { only offset, can be generated by absolute }
  884. a_load_const_reg(list, OS_ADDR, href.offset, r);
  885. end
  886. else
  887. internalerror(200703111);
  888. end;
  889. procedure TCGMIPS.a_loadfpu_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  890. const
  891. FpuMovInstr: array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
  892. ((A_MOV_S, A_CVT_D_S),(A_CVT_S_D,A_MOV_D));
  893. var
  894. instr: taicpu;
  895. begin
  896. if (reg1 <> reg2) or (fromsize<>tosize) then
  897. begin
  898. instr := taicpu.op_reg_reg(fpumovinstr[fromsize,tosize], reg2, reg1);
  899. list.Concat(instr);
  900. { Notify the register allocator that we have written a move instruction so
  901. it can try to eliminate it. }
  902. if (fromsize=tosize) then
  903. add_move_instruction(instr);
  904. end;
  905. end;
  906. procedure TCGMIPS.a_loadfpu_ref_reg(list: tasmlist; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister);
  907. var
  908. tmpref: treference;
  909. tmpreg: tregister;
  910. begin
  911. case fromsize of
  912. OS_F32:
  913. handle_load_store_fpu(list, False, A_LWC1, reg, ref);
  914. OS_F64:
  915. handle_load_store_fpu(list, False, A_LDC1, reg, ref);
  916. else
  917. InternalError(2007042701);
  918. end;
  919. if tosize<>fromsize then
  920. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  921. end;
  922. procedure TCGMIPS.a_loadfpu_reg_ref(list: tasmlist; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference);
  923. var
  924. tmpref: treference;
  925. tmpreg: tregister;
  926. begin
  927. if tosize<>fromsize then
  928. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  929. case tosize of
  930. OS_F32:
  931. handle_load_store_fpu(list, True, A_SWC1, reg, ref);
  932. OS_F64:
  933. handle_load_store_fpu(list, True, A_SDC1, reg, ref);
  934. else
  935. InternalError(2007042702);
  936. end;
  937. end;
  938. procedure TCGMIPS.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
  939. const
  940. overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
  941. begin
  942. if (op in overflowops) and
  943. (size in [OS_8,OS_S8,OS_16,OS_S16]) then
  944. a_load_reg_reg(list,OS_32,size,dst,dst);
  945. end;
  946. procedure TCGMIPS.a_op_const_reg(list: tasmlist; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister);
  947. var
  948. power: longint;
  949. tmpreg1: tregister;
  950. begin
  951. if ((op = OP_MUL) or (op = OP_IMUL)) then
  952. begin
  953. if ispowerof2(a, power) then
  954. begin
  955. { can be done with a shift }
  956. if power < 32 then
  957. begin
  958. list.concat(taicpu.op_reg_reg_const(A_SLL, reg, reg, power));
  959. exit;
  960. end;
  961. end;
  962. end;
  963. if ((op = OP_SUB) or (op = OP_ADD)) then
  964. begin
  965. if (a = 0) then
  966. exit;
  967. end;
  968. if Op in [OP_NEG, OP_NOT] then
  969. internalerror(200306011);
  970. if (a = 0) then
  971. begin
  972. if (Op = OP_IMUL) or (Op = OP_MUL) then
  973. list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_R0))
  974. else
  975. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), reg, reg, NR_R0))
  976. end
  977. else
  978. begin
  979. if op = OP_IMUL then
  980. begin
  981. tmpreg1 := GetIntRegister(list, OS_INT);
  982. a_load_const_reg(list, OS_INT, a, tmpreg1);
  983. list.concat(taicpu.op_reg_reg(A_MULT, reg, tmpreg1));
  984. list.concat(taicpu.op_reg(A_MFLO, reg));
  985. end
  986. else if op = OP_MUL then
  987. begin
  988. tmpreg1 := GetIntRegister(list, OS_INT);
  989. a_load_const_reg(list, OS_INT, a, tmpreg1);
  990. list.concat(taicpu.op_reg_reg(A_MULTU, reg, tmpreg1));
  991. list.concat(taicpu.op_reg(A_MFLO, reg));
  992. end
  993. else
  994. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), reg, a, reg);
  995. end;
  996. maybeadjustresult(list,op,size,reg);
  997. end;
  998. procedure TCGMIPS.a_op_reg_reg(list: tasmlist; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  999. var
  1000. a: aint;
  1001. begin
  1002. case Op of
  1003. OP_NEG:
  1004. { discard overflow checking }
  1005. list.concat(taicpu.op_reg_reg(A_NEGU{A_NEG}, dst, src));
  1006. OP_NOT:
  1007. begin
  1008. list.concat(taicpu.op_reg_reg(A_NOT, dst, src));
  1009. end;
  1010. else
  1011. begin
  1012. if op = OP_IMUL then
  1013. begin
  1014. list.concat(taicpu.op_reg_reg(A_MULT, dst, src));
  1015. list.concat(taicpu.op_reg(A_MFLO, dst));
  1016. end
  1017. else if op = OP_MUL then
  1018. begin
  1019. list.concat(taicpu.op_reg_reg(A_MULTU, dst, src));
  1020. list.concat(taicpu.op_reg(A_MFLO, dst));
  1021. end
  1022. else
  1023. begin
  1024. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, dst, src));
  1025. end;
  1026. end;
  1027. end;
  1028. maybeadjustresult(list,op,size,dst);
  1029. end;
  1030. procedure TCGMIPS.a_op_const_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
  1031. var
  1032. power: longint;
  1033. tmpreg1: tregister;
  1034. begin
  1035. case op of
  1036. OP_MUL,
  1037. OP_IMUL:
  1038. begin
  1039. if ispowerof2(a, power) then
  1040. begin
  1041. { can be done with a shift }
  1042. if power < 32 then
  1043. list.concat(taicpu.op_reg_reg_const(A_SLL, dst, src, power))
  1044. else
  1045. inherited a_op_const_reg_reg(list, op, size, a, src, dst);
  1046. exit;
  1047. end;
  1048. end;
  1049. OP_SUB,
  1050. OP_ADD:
  1051. begin
  1052. if (a = 0) then
  1053. begin
  1054. a_load_reg_reg(list, size, size, src, dst);
  1055. exit;
  1056. end;
  1057. end;
  1058. end;
  1059. if op = OP_IMUL then
  1060. begin
  1061. tmpreg1 := GetIntRegister(list, OS_INT);
  1062. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1063. list.concat(taicpu.op_reg_reg(A_MULT, src, tmpreg1));
  1064. list.concat(taicpu.op_reg(A_MFLO, dst));
  1065. end
  1066. else if op = OP_MUL then
  1067. begin
  1068. tmpreg1 := GetIntRegister(list, OS_INT);
  1069. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1070. list.concat(taicpu.op_reg_reg(A_MULTU, src, tmpreg1));
  1071. list.concat(taicpu.op_reg(A_MFLO, dst));
  1072. end
  1073. else
  1074. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
  1075. maybeadjustresult(list,op,size,dst);
  1076. end;
  1077. procedure TCGMIPS.a_op_reg_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
  1078. begin
  1079. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
  1080. maybeadjustresult(list,op,size,dst);
  1081. end;
  1082. procedure TCGMIPS.a_op_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation);
  1083. var
  1084. tmpreg1: tregister;
  1085. begin
  1086. ovloc.loc := LOC_VOID;
  1087. case op of
  1088. OP_SUB,
  1089. OP_ADD:
  1090. begin
  1091. if (a = 0) then
  1092. begin
  1093. a_load_reg_reg(list, size, size, src, dst);
  1094. exit;
  1095. end;
  1096. end;
  1097. end;{case}
  1098. case op of
  1099. OP_ADD:
  1100. begin
  1101. if setflags then
  1102. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1103. else
  1104. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
  1105. end;
  1106. OP_SUB:
  1107. begin
  1108. if setflags then
  1109. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1110. else
  1111. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
  1112. end;
  1113. OP_MUL:
  1114. begin
  1115. if setflags then
  1116. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1117. else
  1118. begin
  1119. tmpreg1 := GetIntRegister(list, OS_INT);
  1120. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1121. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size),src, tmpreg1));
  1122. list.concat(taicpu.op_reg(A_MFLO, dst));
  1123. end;
  1124. end;
  1125. OP_IMUL:
  1126. begin
  1127. if setflags then
  1128. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1129. else
  1130. begin
  1131. tmpreg1 := GetIntRegister(list, OS_INT);
  1132. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1133. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size),src, tmpreg1));
  1134. list.concat(taicpu.op_reg(A_MFLO, dst));
  1135. end;
  1136. end;
  1137. OP_XOR, OP_OR, OP_AND:
  1138. begin
  1139. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst);
  1140. end;
  1141. else
  1142. internalerror(2007012601);
  1143. end;
  1144. maybeadjustresult(list,op,size,dst);
  1145. end;
  1146. procedure TCGMIPS.a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
  1147. begin
  1148. ovloc.loc := LOC_VOID;
  1149. case op of
  1150. OP_ADD:
  1151. begin
  1152. if setflags then
  1153. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1154. else
  1155. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
  1156. end;
  1157. OP_SUB:
  1158. begin
  1159. if setflags then
  1160. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1161. else
  1162. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
  1163. end;
  1164. OP_MUL:
  1165. begin
  1166. if setflags then
  1167. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1168. else
  1169. begin
  1170. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size), src2, src1));
  1171. list.concat(taicpu.op_reg(A_MFLO, dst));
  1172. end;
  1173. end;
  1174. OP_IMUL:
  1175. begin
  1176. if setflags then
  1177. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1178. else
  1179. begin
  1180. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size), src2, src1));
  1181. list.concat(taicpu.op_reg(A_MFLO, dst));
  1182. end;
  1183. end;
  1184. OP_XOR, OP_OR, OP_AND:
  1185. begin
  1186. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1));
  1187. end;
  1188. else
  1189. internalerror(2007012602);
  1190. end;
  1191. maybeadjustresult(list,op,size,dst);
  1192. end;
  1193. {*************** compare instructructions ****************}
  1194. procedure TCGMIPS.a_cmp_const_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
  1195. var
  1196. tmpreg: tregister;
  1197. ai : Taicpu;
  1198. begin
  1199. if a = 0 then
  1200. tmpreg := NR_R0
  1201. else
  1202. begin
  1203. tmpreg := GetIntRegister(list, OS_INT);
  1204. list.concat(taicpu.op_reg_const(A_LI, tmpreg, a));
  1205. end;
  1206. ai := taicpu.op_reg_reg_sym(A_BC, reg, tmpreg, l);
  1207. ai.SetCondition(TOpCmp2AsmCond[cmp_op]);
  1208. list.concat(ai);
  1209. { Delay slot }
  1210. list.Concat(TAiCpu.Op_none(A_NOP));
  1211. end;
  1212. procedure TCGMIPS.a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  1213. var
  1214. ai : Taicpu;
  1215. begin
  1216. ai := taicpu.op_reg_reg_sym(A_BC, reg2, reg1, l);
  1217. ai.SetCondition(TOpCmp2AsmCond[cmp_op]);
  1218. list.concat(ai);
  1219. { Delay slot }
  1220. list.Concat(TAiCpu.Op_none(A_NOP));
  1221. end;
  1222. procedure TCGMIPS.a_jmp_always(List: tasmlist; l: TAsmLabel);
  1223. var
  1224. ai : Taicpu;
  1225. begin
  1226. ai := taicpu.op_sym(A_BA, l);
  1227. list.concat(ai);
  1228. { Delay slot }
  1229. list.Concat(TAiCpu.Op_none(A_NOP));
  1230. end;
  1231. procedure TCGMIPS.a_jmp_name(list: tasmlist; const s: string);
  1232. begin
  1233. List.Concat(TAiCpu.op_sym(A_BA, current_asmdata.RefAsmSymbol(s)));
  1234. { Delay slot }
  1235. list.Concat(TAiCpu.Op_none(A_NOP));
  1236. end;
  1237. procedure TCGMIPS.a_jmp_cond(list: tasmlist; cond: TOpCmp; l: TAsmLabel);
  1238. begin
  1239. internalerror(200701181);
  1240. end;
  1241. procedure TCGMIPS.g_overflowCheck(List: tasmlist; const Loc: TLocation; def: TDef);
  1242. begin
  1243. // this is an empty procedure
  1244. end;
  1245. procedure TCGMIPS.g_overflowCheck_loc(List: tasmlist; const Loc: TLocation; def: TDef; ovloc: tlocation);
  1246. begin
  1247. // this is an empty procedure
  1248. end;
  1249. { *********** entry/exit code and address loading ************ }
  1250. procedure TCGMIPS.g_proc_entry(list: tasmlist; localsize: longint; nostackframe: boolean);
  1251. var
  1252. lastintoffset,lastfpuoffset,
  1253. nextoffset : aint;
  1254. i : longint;
  1255. ra_save,framesave,gp_save : taicpu;
  1256. fmask,mask : dword;
  1257. saveregs : tcpuregisterset;
  1258. StoreOp : TAsmOp;
  1259. href: treference;
  1260. usesfpr, usesgpr, gotgot : boolean;
  1261. reg : Tsuperregister;
  1262. helplist : TAsmList;
  1263. begin
  1264. a_reg_alloc(list,NR_STACK_POINTER_REG);
  1265. if nostackframe then
  1266. exit;
  1267. if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
  1268. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  1269. helplist:=TAsmList.Create;
  1270. cgcpu_calc_stackframe_size := LocalSize;
  1271. reference_reset(href,0);
  1272. href.base:=NR_STACK_POINTER_REG;
  1273. usesfpr:=false;
  1274. fmask:=0;
  1275. nextoffset:=TMIPSProcInfo(current_procinfo).floatregstart;
  1276. lastfpuoffset:=LocalSize;
  1277. for reg := RS_F0 to RS_F31 do { to check: what if F30 is double? }
  1278. begin
  1279. if reg in (rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall)) then
  1280. begin
  1281. usesfpr:=true;
  1282. fmask:=fmask or (1 shl ord(reg));
  1283. href.offset:=nextoffset;
  1284. lastfpuoffset:=nextoffset;
  1285. if cs_asm_source in current_settings.globalswitches then
  1286. helplist.concat(tai_comment.Create(strpnew(std_regname(newreg(R_FPUREGISTER,reg,R_SUBFS))+' register saved.')));
  1287. helplist.concat(taicpu.op_reg_ref(A_SWC1,newreg(R_FPUREGISTER,reg,R_SUBFS),href));
  1288. inc(nextoffset,4);
  1289. { IEEE Double values are stored in floating point
  1290. register pairs f2X/f2X+1,
  1291. as the f2X+1 register is not correctly marked as used for now,
  1292. we simply assume it is also used if f2X is used
  1293. Should be fixed by a proper inclusion of f2X+1 into used_in_proc }
  1294. if (ord(reg)-ord(RS_F0)) mod 2 = 0 then
  1295. include(rg[R_FPUREGISTER].used_in_proc,succ(reg));
  1296. end;
  1297. end;
  1298. usesgpr:=false;
  1299. mask:=0;
  1300. nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
  1301. saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  1302. include(saveregs,RS_R31);
  1303. if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
  1304. include(saveregs,RS_FRAME_POINTER_REG);
  1305. if (cs_create_pic in current_settings.moduleswitches) and
  1306. (pi_needs_got in current_procinfo.flags) then
  1307. include(saveregs,RS_GP);
  1308. lastintoffset:=LocalSize;
  1309. framesave:=nil;
  1310. gp_save:=nil;
  1311. for reg:=RS_R1 to RS_R31 do
  1312. begin
  1313. if reg in saveregs then
  1314. begin
  1315. usesgpr:=true;
  1316. mask:=mask or (1 shl ord(reg));
  1317. href.offset:=nextoffset;
  1318. lastintoffset:=nextoffset;
  1319. if (reg=RS_FRAME_POINTER_REG) then
  1320. framesave:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
  1321. else if (reg=RS_R31) then
  1322. ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
  1323. else if (reg=RS_GP) and
  1324. (cs_create_pic in current_settings.moduleswitches) and
  1325. (pi_needs_got in current_procinfo.flags) then
  1326. gp_save:=taicpu.op_const(A_P_CPRESTORE,nextoffset)
  1327. else
  1328. begin
  1329. if cs_asm_source in current_settings.globalswitches then
  1330. helplist.concat(tai_comment.Create(strpnew(
  1331. std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))+' register saved.')));
  1332. helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
  1333. end;
  1334. inc(nextoffset,4);
  1335. end;
  1336. end;
  1337. //list.concat(Taicpu.Op_reg_reg_const(A_ADDIU,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG,current_procinfo.para_stack_size));
  1338. list.concat(Taicpu.op_none(A_P_SET_NOMIPS16));
  1339. list.concat(Taicpu.op_reg_const_reg(A_P_FRAME,current_procinfo.framepointer,LocalSize,NR_R31));
  1340. list.concat(Taicpu.op_const_const(A_P_MASK,mask,-(LocalSize-lastintoffset)));
  1341. list.concat(Taicpu.op_const_const(A_P_FMASK,Fmask,-(LocalSize-lastfpuoffset)));
  1342. if (cs_create_pic in current_settings.moduleswitches) and
  1343. (pi_needs_got in current_procinfo.flags) then
  1344. begin
  1345. list.concat(Taicpu.op_reg(A_P_CPLOAD,NR_PIC_FUNC));
  1346. end;
  1347. list.concat(Taicpu.op_none(A_P_SET_NOREORDER));
  1348. if (-LocalSize >= simm16lo) and (-LocalSize <= simm16hi) then
  1349. begin
  1350. list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
  1351. if cs_asm_source in current_settings.globalswitches then
  1352. begin
  1353. list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size')));
  1354. list.concat(tai_comment.Create(strpnew(' 0-'+
  1355. tostr(TMIPSProcInfo(current_procinfo).maxpushedparasize)+' for called function parameters')));
  1356. list.concat(tai_comment.Create(strpnew('Register save area at '+
  1357. tostr(TMIPSProcInfo(current_procinfo).intregstart))));
  1358. list.concat(tai_comment.Create(strpnew('FPU register save area at '+
  1359. tostr(TMIPSProcInfo(current_procinfo).floatregstart))));
  1360. end;
  1361. list.concat(Taicpu.Op_reg_reg_const(A_ADDIU,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-LocalSize));
  1362. if cs_asm_source in current_settings.globalswitches then
  1363. list.concat(tai_comment.Create(strpnew('RA register saved.')));
  1364. list.concat(ra_save);
  1365. if assigned(framesave) then
  1366. begin
  1367. if cs_asm_source in current_settings.globalswitches then
  1368. list.concat(tai_comment.Create(strpnew('Frame S8/FP register saved.')));
  1369. list.concat(framesave);
  1370. if cs_asm_source in current_settings.globalswitches then
  1371. list.concat(tai_comment.Create(strpnew('New frame FP register set to $sp+'+ToStr(LocalSize))));
  1372. list.concat(Taicpu.op_reg_reg_const(A_ADDIU,NR_FRAME_POINTER_REG,
  1373. NR_STACK_POINTER_REG,LocalSize));
  1374. end;
  1375. end
  1376. else
  1377. begin
  1378. if cs_asm_source in current_settings.globalswitches then
  1379. list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size using R9/t1 register')));
  1380. list.concat(Taicpu.Op_reg_const(A_LI,NR_R9,-LocalSize));
  1381. list.concat(Taicpu.Op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R9));
  1382. if cs_asm_source in current_settings.globalswitches then
  1383. list.concat(tai_comment.Create(strpnew('RA register saved.')));
  1384. list.concat(ra_save);
  1385. if assigned(framesave) then
  1386. begin
  1387. if cs_asm_source in current_settings.globalswitches then
  1388. list.concat(tai_comment.Create(strpnew('Frame register saved.')));
  1389. list.concat(framesave);
  1390. if cs_asm_source in current_settings.globalswitches then
  1391. list.concat(tai_comment.Create(strpnew('Frame register updated to $SP+R9 value')));
  1392. list.concat(Taicpu.op_reg_reg_reg(A_SUBU,NR_FRAME_POINTER_REG,
  1393. NR_STACK_POINTER_REG,NR_R9));
  1394. end;
  1395. { The instructions before are macros that can extend to multiple instructions,
  1396. the settings of R9 to -LocalSize surely does,
  1397. but the saving of RA and FP also might, and might
  1398. even use AT register, which is why we use R9 instead of AT here for -LocalSize }
  1399. list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
  1400. end;
  1401. if assigned(gp_save) then
  1402. begin
  1403. if cs_asm_source in current_settings.globalswitches then
  1404. list.concat(tai_comment.Create(strpnew('GOT register saved.')));
  1405. list.concat(Taicpu.op_none(A_P_SET_MACRO));
  1406. list.concat(gp_save);
  1407. list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
  1408. end;
  1409. with TMIPSProcInfo(current_procinfo) do
  1410. begin
  1411. href.offset:=0;
  1412. //if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  1413. href.base:=NR_FRAME_POINTER_REG;
  1414. for i:=0 to MIPS_MAX_REGISTERS_USED_IN_CALL-1 do
  1415. if (register_used[i]) then
  1416. begin
  1417. reg:=parasupregs[i];
  1418. if register_offset[i]=-1 then
  1419. comment(V_warning,'Register parameter has offset -1 in TCGMIPS.g_proc_entry');
  1420. //if current_procinfo.framepointer=NR_STACK_POINTER_REG then
  1421. // href.offset:=register_offset[i]+Localsize
  1422. //else
  1423. href.offset:=register_offset[i];
  1424. {$ifdef MIPSEL}
  1425. if cs_asm_source in current_settings.globalswitches then
  1426. list.concat(tai_comment.Create(strpnew('Var '+
  1427. register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
  1428. +' saved to offset '+tostr(href.offset))));
  1429. list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
  1430. {$else not MIPSEL, for big endian, size matters}
  1431. case register_size[i] of
  1432. OS_8,
  1433. OS_S8:
  1434. StoreOp := A_SB;
  1435. OS_16,
  1436. OS_S16:
  1437. StoreOp := A_SH;
  1438. OS_32,
  1439. OS_NO,
  1440. OS_F32,
  1441. OS_S32:
  1442. StoreOp := A_SW;
  1443. OS_F64,
  1444. OS_64,
  1445. OS_S64:
  1446. begin
  1447. {$ifdef cpu64bitalu}
  1448. StoreOp:=A_SD;
  1449. {$else not cpu64bitalu}
  1450. StoreOp:= A_SW;
  1451. {$endif not cpu64bitalu}
  1452. end
  1453. else
  1454. internalerror(2012061801);
  1455. end;
  1456. if cs_asm_source in current_settings.globalswitches then
  1457. list.concat(tai_comment.Create(strpnew('Var '+
  1458. register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
  1459. +' saved to offset '+tostr(href.offset))));
  1460. list.concat(taicpu.op_reg_ref(StoreOp, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
  1461. {$endif}
  1462. end;
  1463. end;
  1464. if (cs_create_pic in current_settings.moduleswitches) and
  1465. (pi_needs_got in current_procinfo.flags) then
  1466. begin
  1467. current_procinfo.got := NR_GP;
  1468. end;
  1469. list.concatList(helplist);
  1470. helplist.Free;
  1471. end;
  1472. procedure TCGMIPS.g_proc_exit(list: tasmlist; parasize: longint; nostackframe: boolean);
  1473. var
  1474. href : treference;
  1475. stacksize : aint;
  1476. saveregs : tcpuregisterset;
  1477. nextoffset : aint;
  1478. reg : Tsuperregister;
  1479. begin
  1480. stacksize:=current_procinfo.calc_stackframe_size;
  1481. if nostackframe then
  1482. begin
  1483. list.concat(taicpu.op_reg(A_JR, NR_R31));
  1484. list.concat(Taicpu.op_none(A_NOP));
  1485. list.concat(Taicpu.op_none(A_P_SET_MACRO));
  1486. list.concat(Taicpu.op_none(A_P_SET_REORDER));
  1487. end
  1488. else
  1489. begin
  1490. reference_reset(href,0);
  1491. href.base:=NR_STACK_POINTER_REG;
  1492. nextoffset:=TMIPSProcInfo(current_procinfo).floatregstart;
  1493. for reg := RS_F0 to RS_F31 do
  1494. begin
  1495. if reg in (rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall)) then
  1496. begin
  1497. href.offset:=nextoffset;
  1498. list.concat(taicpu.op_reg_ref(A_LWC1,newreg(R_FPUREGISTER,reg,R_SUBFS),href));
  1499. inc(nextoffset,4);
  1500. end;
  1501. end;
  1502. nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
  1503. saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  1504. include(saveregs,RS_R31);
  1505. if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
  1506. include(saveregs,RS_FRAME_POINTER_REG);
  1507. if (cs_create_pic in current_settings.moduleswitches) and
  1508. (pi_needs_got in current_procinfo.flags) then
  1509. include(saveregs,RS_GP);
  1510. for reg:=RS_R1 to RS_R31 do
  1511. begin
  1512. if reg in saveregs then
  1513. begin
  1514. href.offset:=nextoffset;
  1515. list.concat(taicpu.op_reg_ref(A_LW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
  1516. inc(nextoffset,sizeof(aint));
  1517. end;
  1518. end;
  1519. if (-stacksize >= simm16lo) and (-stacksize <= simm16hi) then
  1520. begin
  1521. list.concat(taicpu.op_reg(A_JR, NR_R31));
  1522. { correct stack pointer in the delay slot }
  1523. list.concat(Taicpu.Op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, stacksize));
  1524. end
  1525. else
  1526. begin
  1527. a_load_const_reg(list,OS_32,stacksize,NR_R1);
  1528. list.concat(taicpu.op_reg(A_JR, NR_R31));
  1529. { correct stack pointer in the delay slot }
  1530. list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R1));
  1531. end;
  1532. list.concat(Taicpu.op_none(A_P_SET_MACRO));
  1533. list.concat(Taicpu.op_none(A_P_SET_REORDER));
  1534. end;
  1535. end;
  1536. { ************* concatcopy ************ }
  1537. procedure TCGMIPS.g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
  1538. var
  1539. paraloc1, paraloc2, paraloc3: TCGPara;
  1540. pd: tprocdef;
  1541. begin
  1542. pd:=search_system_proc('MOVE');
  1543. paraloc1.init;
  1544. paraloc2.init;
  1545. paraloc3.init;
  1546. paramanager.getintparaloc(pd, 1, paraloc1);
  1547. paramanager.getintparaloc(pd, 2, paraloc2);
  1548. paramanager.getintparaloc(pd, 3, paraloc3);
  1549. a_load_const_cgpara(list, OS_SINT, len, paraloc3);
  1550. a_loadaddr_ref_cgpara(list, dest, paraloc2);
  1551. a_loadaddr_ref_cgpara(list, Source, paraloc1);
  1552. paramanager.freecgpara(list, paraloc3);
  1553. paramanager.freecgpara(list, paraloc2);
  1554. paramanager.freecgpara(list, paraloc1);
  1555. alloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
  1556. alloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
  1557. a_call_name(list, 'FPC_MOVE', false);
  1558. dealloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
  1559. dealloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
  1560. paraloc3.done;
  1561. paraloc2.done;
  1562. paraloc1.done;
  1563. end;
  1564. procedure TCGMIPS.g_concatcopy(list: tasmlist; const Source, dest: treference; len: tcgint);
  1565. var
  1566. tmpreg1, hreg, countreg: TRegister;
  1567. src, dst: TReference;
  1568. lab: tasmlabel;
  1569. Count, count2: aint;
  1570. ai : TaiCpu;
  1571. begin
  1572. if len > high(longint) then
  1573. internalerror(2002072704);
  1574. { anybody wants to determine a good value here :)? }
  1575. if len > 100 then
  1576. g_concatcopy_move(list, Source, dest, len)
  1577. else
  1578. begin
  1579. reference_reset(src,sizeof(aint));
  1580. reference_reset(dst,sizeof(aint));
  1581. { load the address of source into src.base }
  1582. src.base := GetAddressRegister(list);
  1583. a_loadaddr_ref_reg(list, Source, src.base);
  1584. { load the address of dest into dst.base }
  1585. dst.base := GetAddressRegister(list);
  1586. a_loadaddr_ref_reg(list, dest, dst.base);
  1587. { generate a loop }
  1588. Count := len div 4;
  1589. if Count > 4 then
  1590. begin
  1591. { the offsets are zero after the a_loadaddress_ref_reg and just }
  1592. { have to be set to 8. I put an Inc there so debugging may be }
  1593. { easier (should offset be different from zero here, it will be }
  1594. { easy to notice in the generated assembler }
  1595. countreg := GetIntRegister(list, OS_INT);
  1596. tmpreg1 := GetIntRegister(list, OS_INT);
  1597. a_load_const_reg(list, OS_INT, Count, countreg);
  1598. { explicitely allocate R_O0 since it can be used safely here }
  1599. { (for holding date that's being copied) }
  1600. current_asmdata.getjumplabel(lab);
  1601. a_label(list, lab);
  1602. list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
  1603. list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
  1604. list.concat(taicpu.op_reg_reg_const(A_ADDIU, src.base, src.base, 4));
  1605. list.concat(taicpu.op_reg_reg_const(A_ADDIU, dst.base, dst.base, 4));
  1606. list.concat(taicpu.op_reg_reg_const(A_ADDIU, countreg, countreg, -1));
  1607. //list.concat(taicpu.op_reg_sym(A_BGTZ, countreg, lab));
  1608. ai := taicpu.op_reg_reg_sym(A_BC,countreg, NR_R0, lab);
  1609. ai.setcondition(C_GT);
  1610. list.concat(ai);
  1611. list.concat(taicpu.op_none(A_NOP));
  1612. len := len mod 4;
  1613. end;
  1614. { unrolled loop }
  1615. Count := len div 4;
  1616. if Count > 0 then
  1617. begin
  1618. tmpreg1 := GetIntRegister(list, OS_INT);
  1619. for count2 := 1 to Count do
  1620. begin
  1621. list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
  1622. list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
  1623. Inc(src.offset, 4);
  1624. Inc(dst.offset, 4);
  1625. end;
  1626. len := len mod 4;
  1627. end;
  1628. if (len and 4) <> 0 then
  1629. begin
  1630. hreg := GetIntRegister(list, OS_INT);
  1631. a_load_ref_reg(list, OS_32, OS_32, src, hreg);
  1632. a_load_reg_ref(list, OS_32, OS_32, hreg, dst);
  1633. Inc(src.offset, 4);
  1634. Inc(dst.offset, 4);
  1635. end;
  1636. { copy the leftovers }
  1637. if (len and 2) <> 0 then
  1638. begin
  1639. hreg := GetIntRegister(list, OS_INT);
  1640. a_load_ref_reg(list, OS_16, OS_16, src, hreg);
  1641. a_load_reg_ref(list, OS_16, OS_16, hreg, dst);
  1642. Inc(src.offset, 2);
  1643. Inc(dst.offset, 2);
  1644. end;
  1645. if (len and 1) <> 0 then
  1646. begin
  1647. hreg := GetIntRegister(list, OS_INT);
  1648. a_load_ref_reg(list, OS_8, OS_8, src, hreg);
  1649. a_load_reg_ref(list, OS_8, OS_8, hreg, dst);
  1650. end;
  1651. end;
  1652. end;
  1653. procedure TCGMIPS.g_concatcopy_unaligned(list: tasmlist; const Source, dest: treference; len: tcgint);
  1654. var
  1655. src, dst: TReference;
  1656. tmpreg1, countreg: TRegister;
  1657. i: aint;
  1658. lab: tasmlabel;
  1659. ai : TaiCpu;
  1660. begin
  1661. if len > 31 then
  1662. g_concatcopy_move(list, Source, dest, len)
  1663. else
  1664. begin
  1665. reference_reset(src,sizeof(aint));
  1666. reference_reset(dst,sizeof(aint));
  1667. { load the address of source into src.base }
  1668. src.base := GetAddressRegister(list);
  1669. a_loadaddr_ref_reg(list, Source, src.base);
  1670. { load the address of dest into dst.base }
  1671. dst.base := GetAddressRegister(list);
  1672. a_loadaddr_ref_reg(list, dest, dst.base);
  1673. { generate a loop }
  1674. if len > 4 then
  1675. begin
  1676. { the offsets are zero after the a_loadaddress_ref_reg and just }
  1677. { have to be set to 8. I put an Inc there so debugging may be }
  1678. { easier (should offset be different from zero here, it will be }
  1679. { easy to notice in the generated assembler }
  1680. countreg := cg.GetIntRegister(list, OS_INT);
  1681. tmpreg1 := cg.GetIntRegister(list, OS_INT);
  1682. a_load_const_reg(list, OS_INT, len, countreg);
  1683. { explicitely allocate R_O0 since it can be used safely here }
  1684. { (for holding date that's being copied) }
  1685. current_asmdata.getjumplabel(lab);
  1686. a_label(list, lab);
  1687. list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
  1688. list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst));
  1689. list.concat(taicpu.op_reg_reg_const(A_ADDIU, src.base, src.base, 1));
  1690. list.concat(taicpu.op_reg_reg_const(A_ADDIU, dst.base, dst.base, 1));
  1691. list.concat(taicpu.op_reg_reg_const(A_ADDIU, countreg, countreg, -1));
  1692. //list.concat(taicpu.op_reg_sym(A_BGTZ, countreg, lab));
  1693. ai := taicpu.op_reg_reg_sym(A_BC,countreg, NR_R0, lab);
  1694. ai.setcondition(C_GT);
  1695. list.concat(ai);
  1696. list.concat(taicpu.op_none(A_NOP));
  1697. end
  1698. else
  1699. begin
  1700. { unrolled loop }
  1701. tmpreg1 := cg.GetIntRegister(list, OS_INT);
  1702. for i := 1 to len do
  1703. begin
  1704. list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
  1705. list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst));
  1706. Inc(src.offset);
  1707. Inc(dst.offset);
  1708. end;
  1709. end;
  1710. end;
  1711. end;
  1712. procedure TCGMIPS.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labelname: string; ioffset: longint);
  1713. procedure loadvmttorvmt;
  1714. var
  1715. href: treference;
  1716. begin
  1717. reference_reset_base(href, NR_R2, 0, sizeof(aint)); { return value }
  1718. cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_VMT);
  1719. end;
  1720. procedure op_onrvmtmethodaddr;
  1721. var
  1722. href : treference;
  1723. reg : tregister;
  1724. begin
  1725. if (procdef.extnumber=$ffff) then
  1726. Internalerror(200006139);
  1727. { call/jmp vmtoffs(%eax) ; method offs }
  1728. reference_reset_base(href, NR_VMT, tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber), sizeof(aint));
  1729. if (cs_create_pic in current_settings.moduleswitches) then
  1730. reg:=NR_PIC_FUNC
  1731. else
  1732. reg:=NR_VMT;
  1733. cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, reg);
  1734. list.concat(taicpu.op_reg(A_JR, reg));
  1735. end;
  1736. var
  1737. make_global: boolean;
  1738. href: treference;
  1739. begin
  1740. if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
  1741. Internalerror(200006137);
  1742. if not assigned(procdef.struct) or
  1743. (procdef.procoptions * [po_classmethod, po_staticmethod,
  1744. po_methodpointer, po_interrupt, po_iocheck] <> []) then
  1745. Internalerror(200006138);
  1746. if procdef.owner.symtabletype <> objectsymtable then
  1747. Internalerror(200109191);
  1748. make_global := False;
  1749. if (not current_module.is_unit) or create_smartlink or
  1750. (procdef.owner.defowner.owner.symtabletype = globalsymtable) then
  1751. make_global := True;
  1752. if make_global then
  1753. List.concat(Tai_symbol.Createname_global(labelname, AT_FUNCTION, 0))
  1754. else
  1755. List.concat(Tai_symbol.Createname(labelname, AT_FUNCTION, 0));
  1756. { set param1 interface to self }
  1757. g_adjust_self_value(list, procdef, ioffset);
  1758. if (po_virtualmethod in procdef.procoptions) and
  1759. not is_objectpascal_helper(procdef.struct) then
  1760. begin
  1761. loadvmttorvmt;
  1762. op_onrvmtmethodaddr;
  1763. end
  1764. else
  1765. list.concat(taicpu.op_sym(A_J,current_asmdata.RefAsmSymbol(procdef.mangledname)));
  1766. { Delay slot }
  1767. list.Concat(TAiCpu.Op_none(A_NOP));
  1768. List.concat(Tai_symbol_end.Createname(labelname));
  1769. end;
  1770. procedure TCGMIPS.g_stackpointer_alloc(list : TAsmList;localsize : longint);
  1771. begin
  1772. Comment(V_Error,'TCgMPSel.g_stackpointer_alloc method not implemented');
  1773. end;
  1774. procedure TCGMIPS.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
  1775. begin
  1776. Comment(V_Error,'TCgMPSel.a_bit_scan_reg_reg method not implemented');
  1777. end;
  1778. {****************************************************************************
  1779. TCG64_MIPSel
  1780. ****************************************************************************}
  1781. procedure TCg64MPSel.a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference);
  1782. var
  1783. tmpref: treference;
  1784. tmpreg: tregister;
  1785. begin
  1786. { Override this function to prevent loading the reference twice }
  1787. if target_info.endian = endian_big then
  1788. begin
  1789. tmpreg := reg.reglo;
  1790. reg.reglo := reg.reghi;
  1791. reg.reghi := tmpreg;
  1792. end;
  1793. tmpref := ref;
  1794. cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reglo, tmpref);
  1795. Inc(tmpref.offset, 4);
  1796. cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reghi, tmpref);
  1797. end;
  1798. procedure TCg64MPSel.a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64);
  1799. var
  1800. tmpref: treference;
  1801. tmpreg: tregister;
  1802. begin
  1803. { Override this function to prevent loading the reference twice }
  1804. if target_info.endian = endian_big then
  1805. begin
  1806. tmpreg := reg.reglo;
  1807. reg.reglo := reg.reghi;
  1808. reg.reghi := tmpreg;
  1809. end;
  1810. tmpref := ref;
  1811. cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reglo);
  1812. Inc(tmpref.offset, 4);
  1813. cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reghi);
  1814. end;
  1815. procedure TCg64MPSel.a_load64_ref_cgpara(list: tasmlist; const r: treference; const paraloc: tcgpara);
  1816. var
  1817. hreg64: tregister64;
  1818. begin
  1819. { Override this function to prevent loading the reference twice.
  1820. Use here some extra registers, but those are optimized away by the RA }
  1821. hreg64.reglo := cg.GetIntRegister(list, OS_S32);
  1822. hreg64.reghi := cg.GetIntRegister(list, OS_S32);
  1823. a_load64_ref_reg(list, r, hreg64);
  1824. a_load64_reg_cgpara(list, hreg64, paraloc);
  1825. end;
  1826. procedure TCg64MPSel.a_op64_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc, regdst: TRegister64);
  1827. var
  1828. op1, op2, op_call64: TAsmOp;
  1829. tmpreg1, tmpreg2: TRegister;
  1830. begin
  1831. tmpreg1 := cg.GetIntRegister(list, OS_INT);
  1832. tmpreg2 := cg.GetIntRegister(list, OS_INT);
  1833. case op of
  1834. OP_ADD:
  1835. begin
  1836. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reglo, regsrc.reglo, regdst.reglo));
  1837. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg1, regdst.reglo, regsrc.reglo));
  1838. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg2, regsrc.reghi, regdst.reghi));
  1839. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, tmpreg1, tmpreg2));
  1840. exit;
  1841. end;
  1842. OP_AND:
  1843. begin
  1844. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reglo, regsrc.reglo, regdst.reglo));
  1845. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reghi, regsrc.reghi, regdst.reghi));
  1846. exit;
  1847. end;
  1848. OP_NEG:
  1849. begin
  1850. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reglo, NR_R0, regsrc.reglo));
  1851. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg1, NR_R0, regdst.reglo));
  1852. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, NR_R0, regsrc.reghi));
  1853. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, tmpreg1));
  1854. exit;
  1855. end;
  1856. OP_NOT:
  1857. begin
  1858. list.concat(taicpu.op_reg_reg_reg(A_NOR, regdst.reglo, NR_R0, regsrc.reglo));
  1859. list.concat(taicpu.op_reg_reg_reg(A_NOR, regdst.reghi, NR_R0, regsrc.reghi));
  1860. exit;
  1861. end;
  1862. OP_OR:
  1863. begin
  1864. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reglo, regsrc.reglo, regdst.reglo));
  1865. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reghi, regsrc.reghi, regdst.reghi));
  1866. exit;
  1867. end;
  1868. OP_SUB:
  1869. begin
  1870. list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg1, regdst.reglo, regsrc.reglo));
  1871. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg2, regdst.reglo, tmpreg1));
  1872. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, regsrc.reghi));
  1873. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, tmpreg2));
  1874. list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
  1875. exit;
  1876. end;
  1877. OP_XOR:
  1878. begin
  1879. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reglo, regdst.reglo, regsrc.reglo));
  1880. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reghi, regsrc.reghi, regdst.reghi));
  1881. exit;
  1882. end;
  1883. else
  1884. internalerror(200306017);
  1885. end; {case}
  1886. end;
  1887. procedure TCg64MPSel.a_op64_const_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regdst: TRegister64);
  1888. begin
  1889. a_op64_const_reg_reg(list, op, size, value, regdst, regdst);
  1890. end;
  1891. procedure TCg64MPSel.a_op64_const_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64);
  1892. var
  1893. l: tlocation;
  1894. begin
  1895. a_op64_const_reg_reg_checkoverflow(list, op, size, Value, regsrc, regdst, False, l);
  1896. end;
  1897. procedure TCg64MPSel.a_op64_reg_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64);
  1898. var
  1899. l: tlocation;
  1900. begin
  1901. a_op64_reg_reg_reg_checkoverflow(list, op, size, regsrc1, regsrc2, regdst, False, l);
  1902. end;
  1903. procedure TCg64MPSel.a_op64_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64; setflags: boolean; var ovloc: tlocation);
  1904. var
  1905. tmpreg64: TRegister64;
  1906. begin
  1907. tmpreg64.reglo := cg.GetIntRegister(list, OS_S32);
  1908. tmpreg64.reghi := cg.GetIntRegister(list, OS_S32);
  1909. list.concat(taicpu.op_reg_const(A_LI, tmpreg64.reglo, aint(lo(Value))));
  1910. list.concat(taicpu.op_reg_const(A_LI, tmpreg64.reghi, aint(hi(Value))));
  1911. a_op64_reg_reg_reg_checkoverflow(list, op, size, tmpreg64, regsrc, regdst, False, ovloc);
  1912. end;
  1913. procedure TCg64MPSel.a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation);
  1914. var
  1915. op1, op2: TAsmOp;
  1916. tmpreg1, tmpreg2: TRegister;
  1917. begin
  1918. case op of
  1919. OP_ADD:
  1920. begin
  1921. tmpreg1 := cg.GetIntRegister(list,OS_S32);
  1922. tmpreg2 := cg.GetIntRegister(list,OS_S32);
  1923. // destreg.reglo could be regsrc1.reglo or regsrc2.reglo
  1924. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, regsrc2.reglo, regsrc1.reglo));
  1925. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg2, tmpreg1, regsrc2.reglo));
  1926. list.concat(taicpu.op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
  1927. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1928. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, regdst.reghi, tmpreg2));
  1929. exit;
  1930. end;
  1931. OP_AND:
  1932. begin
  1933. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
  1934. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1935. exit;
  1936. end;
  1937. OP_OR:
  1938. begin
  1939. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
  1940. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1941. exit;
  1942. end;
  1943. OP_SUB:
  1944. begin
  1945. tmpreg1 := cg.GetIntRegister(list,OS_S32);
  1946. tmpreg2 := cg.GetIntRegister(list,OS_S32);
  1947. // destreg.reglo could be regsrc1.reglo or regsrc2.reglo
  1948. list.concat(taicpu.op_reg_reg_reg(A_SUBU,tmpreg1, regsrc2.reglo, regsrc1.reglo));
  1949. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg2, regsrc2.reglo,tmpreg1));
  1950. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1951. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, tmpreg2));
  1952. list.concat(taicpu.op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
  1953. exit;
  1954. end;
  1955. OP_XOR:
  1956. begin
  1957. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
  1958. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1959. exit;
  1960. end;
  1961. else
  1962. internalerror(200306017);
  1963. end; {case}
  1964. end;
  1965. procedure create_codegen;
  1966. begin
  1967. cg:=TCGMIPS.Create;
  1968. cg64:=TCg64MPSel.Create;
  1969. end;
  1970. end.