cgcpu.pas 73 KB

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