cgcpu.pas 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170
  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 g_overflowCheck(List: tasmlist; const Loc: TLocation; def: TDef); override;
  72. procedure g_overflowCheck_loc(List: tasmlist; const Loc: TLocation; def: TDef; ovloc: tlocation); override;
  73. procedure g_proc_entry(list: tasmlist; localsize: longint; nostackframe: boolean); override;
  74. procedure g_proc_exit(list: tasmlist; parasize: longint; nostackframe: boolean); override;
  75. procedure g_concatcopy(list: tasmlist; const Source, dest: treference; len: tcgint); override;
  76. procedure g_concatcopy_unaligned(list: tasmlist; const Source, dest: treference; len: tcgint); override;
  77. procedure g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
  78. procedure g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labelname: string; ioffset: longint); override;
  79. { Transform unsupported methods into Internal errors }
  80. procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
  81. procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
  82. end;
  83. TCg64MPSel = class(tcg64f32)
  84. public
  85. procedure a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference); override;
  86. procedure a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64); override;
  87. procedure a_load64_ref_cgpara(list: tasmlist; const r: treference; const paraloc: tcgpara); override;
  88. procedure a_op64_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc, regdst: TRegister64); override;
  89. procedure a_op64_const_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regdst: TRegister64); override;
  90. procedure a_op64_const_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64); override;
  91. procedure a_op64_reg_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64); override;
  92. procedure a_op64_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override;
  93. procedure a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override;
  94. end;
  95. procedure create_codegen;
  96. const
  97. TOpCmp2AsmCond : array[topcmp] of TAsmCond=(C_NONE,
  98. C_EQ,C_GT,C_LT,C_GE,C_LE,C_NE,C_LEU,C_LTU,C_GEU,C_GTU
  99. );
  100. implementation
  101. uses
  102. globals, verbose, systems, cutils,
  103. paramgr, fmodule,
  104. symtable,
  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. if paraloc.Location^.next=nil then
  630. begin
  631. inherited a_loadfpu_reg_cgpara(list,size,r,paraloc);
  632. exit;
  633. end;
  634. tg.GetTemp(list, TCGSize2Size[size], TCGSize2Size[size], tt_normal, href);
  635. a_loadfpu_reg_ref(list, size, size, r, href);
  636. a_loadfpu_ref_cgpara(list, size, href, paraloc);
  637. tg.Ungettemp(list, href);
  638. end;
  639. procedure TCGMIPS.a_call_name(list: tasmlist; const s: string; weak: boolean);
  640. var
  641. href: treference;
  642. begin
  643. if (cs_create_pic in current_settings.moduleswitches) then
  644. begin
  645. reference_reset(href,sizeof(aint));
  646. href.symbol:=current_asmdata.RefAsmSymbol(s);
  647. a_loadaddr_ref_reg(list,href,NR_PIC_FUNC);
  648. list.concat(taicpu.op_reg(A_JALR,NR_PIC_FUNC));
  649. end
  650. else
  651. list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s)));
  652. { Delay slot }
  653. list.concat(taicpu.op_none(A_NOP));
  654. end;
  655. procedure TCGMIPS.a_call_reg(list: tasmlist; Reg: TRegister);
  656. begin
  657. if (cs_create_pic in current_settings.moduleswitches) and
  658. (Reg <> NR_PIC_FUNC) then
  659. list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_PIC_FUNC));
  660. list.concat(taicpu.op_reg(A_JALR, reg));
  661. { Delay slot }
  662. list.concat(taicpu.op_none(A_NOP));
  663. end;
  664. {********************** load instructions ********************}
  665. procedure TCGMIPS.a_load_const_reg(list: tasmlist; size: TCGSize; a: tcgint; reg: TRegister);
  666. begin
  667. if (a = 0) then
  668. list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_R0))
  669. { LUI allows to set the upper 16 bits, so we'll take full advantage of it }
  670. else if (a and aint($ffff)) = 0 then
  671. list.concat(taicpu.op_reg_const(A_LUI, reg, aint(a) shr 16))
  672. else if (a >= simm16lo) and (a <= simm16hi) then
  673. list.concat(taicpu.op_reg_reg_const(A_ADDIU, reg, NR_R0, a))
  674. else if (a>=0) and (a <= 65535) then
  675. list.concat(taicpu.op_reg_reg_const(A_ORI, reg, NR_R0, a))
  676. else
  677. begin
  678. list.concat(taicpu.op_reg_const(A_LI, reg, aint(a) ));
  679. end;
  680. end;
  681. procedure TCGMIPS.a_load_const_ref(list: tasmlist; size: tcgsize; a: tcgint; const ref: TReference);
  682. begin
  683. if a = 0 then
  684. a_load_reg_ref(list, size, size, NR_R0, ref)
  685. else
  686. inherited a_load_const_ref(list, size, a, ref);
  687. end;
  688. procedure TCGMIPS.a_load_reg_ref(list: tasmlist; FromSize, ToSize: TCGSize; reg: tregister; const Ref: TReference);
  689. var
  690. op: tasmop;
  691. begin
  692. if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
  693. fromsize := tosize;
  694. case fromsize of
  695. { signed integer registers }
  696. OS_8,
  697. OS_S8:
  698. Op := A_SB;
  699. OS_16,
  700. OS_S16:
  701. Op := A_SH;
  702. OS_32,
  703. OS_S32:
  704. Op := A_SW;
  705. else
  706. InternalError(2002122100);
  707. end;
  708. handle_load_store(list, True, op, reg, ref);
  709. end;
  710. procedure TCGMIPS.a_load_ref_reg(list: tasmlist; FromSize, ToSize: TCgSize; const ref: TReference; reg: tregister);
  711. var
  712. op: tasmop;
  713. begin
  714. if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
  715. fromsize := tosize;
  716. case fromsize of
  717. OS_S8:
  718. Op := A_LB;{Load Signed Byte}
  719. OS_8:
  720. Op := A_LBU;{Load Unsigned Byte}
  721. OS_S16:
  722. Op := A_LH;{Load Signed Halfword}
  723. OS_16:
  724. Op := A_LHU;{Load Unsigned Halfword}
  725. OS_S32:
  726. Op := A_LW;{Load Word}
  727. OS_32:
  728. Op := A_LW;//A_LWU;{Load Unsigned Word}
  729. OS_S64,
  730. OS_64:
  731. Op := A_LD;{Load a Long Word}
  732. else
  733. InternalError(2002122101);
  734. end;
  735. handle_load_store(list, False, op, reg, ref);
  736. if (fromsize=OS_S8) and (tosize=OS_16) then
  737. a_load_reg_reg(list,fromsize,tosize,reg,reg);
  738. end;
  739. procedure TCGMIPS.a_load_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  740. var
  741. instr: taicpu;
  742. begin
  743. if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
  744. (
  745. (tcgsize2size[tosize] = tcgsize2size[fromsize]) and (tosize <> fromsize)
  746. ) or ((fromsize = OS_S8) and
  747. (tosize = OS_16)) then
  748. begin
  749. case tosize of
  750. OS_8:
  751. a_op_const_reg_reg(list, OP_AND, tosize, $ff, reg1, reg2);
  752. OS_16:
  753. a_op_const_reg_reg(list, OP_AND, tosize, $ffff, reg1, reg2);
  754. OS_32,
  755. OS_S32:
  756. begin
  757. instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
  758. list.Concat(instr);
  759. { Notify the register allocator that we have written a move instruction so
  760. it can try to eliminate it. }
  761. add_move_instruction(instr);
  762. end;
  763. OS_S8:
  764. begin
  765. list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 24));
  766. list.concat(taicpu.op_reg_reg_const(A_SRA, reg2, reg2, 24));
  767. end;
  768. OS_S16:
  769. begin
  770. list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 16));
  771. list.concat(taicpu.op_reg_reg_const(A_SRA, reg2, reg2, 16));
  772. end;
  773. else
  774. internalerror(2002090901);
  775. end;
  776. end
  777. else
  778. begin
  779. if reg1 <> reg2 then
  780. begin
  781. { same size, only a register mov required }
  782. instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
  783. list.Concat(instr);
  784. // { Notify the register allocator that we have written a move instruction so
  785. // it can try to eliminate it. }
  786. add_move_instruction(instr);
  787. end;
  788. end;
  789. end;
  790. procedure TCGMIPS.a_loadaddr_ref_reg(list: tasmlist; const ref: TReference; r: tregister);
  791. var
  792. tmpref, href: treference;
  793. hreg, tmpreg: tregister;
  794. r_used: boolean;
  795. begin
  796. r_used := false;
  797. href := ref;
  798. if (href.base = NR_NO) and (href.index <> NR_NO) then
  799. internalerror(200306171);
  800. if ((cs_create_pic in current_settings.moduleswitches) or
  801. (ref.refaddr=addr_pic)) and
  802. assigned(href.symbol) then
  803. begin
  804. tmpreg := r; //GetIntRegister(list, OS_ADDR);
  805. r_used := true;
  806. reference_reset(tmpref,sizeof(aint));
  807. tmpref.symbol := href.symbol;
  808. tmpref.refaddr := addr_pic;
  809. if not (pi_needs_got in current_procinfo.flags) then
  810. internalerror(200501161);
  811. if current_procinfo.got=NR_NO then
  812. current_procinfo.got:=NR_GP;
  813. { for addr_pic NR_GP can be implicit or explicit }
  814. if (href.refaddr=addr_pic) and (href.base=current_procinfo.got) then
  815. href.base:=NR_NO;
  816. tmpref.base := current_procinfo.got;
  817. list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
  818. href.symbol := nil;
  819. if (href.index <> NR_NO) then
  820. begin
  821. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, href.index, tmpreg));
  822. href.index := tmpreg;
  823. end
  824. else
  825. begin
  826. if href.base <> NR_NO then
  827. href.index := tmpreg
  828. else
  829. href.base := tmpreg;
  830. end;
  831. if (href.base=NR_NO) and (href.offset=0) then
  832. exit;
  833. end;
  834. if assigned(href.symbol) or
  835. (href.offset < simm16lo) or
  836. (href.offset > simm16hi) then
  837. begin
  838. if (href.base = NR_NO) and (href.index = NR_NO) then
  839. hreg := r
  840. else
  841. hreg := GetAddressRegister(list);
  842. reference_reset(tmpref,sizeof(aint));
  843. tmpref.symbol := href.symbol;
  844. tmpref.offset := href.offset;
  845. tmpref.refaddr := addr_high;
  846. list.concat(taicpu.op_reg_ref(A_LUI, hreg, tmpref));
  847. { Only the low part is left }
  848. tmpref.refaddr := addr_low;
  849. list.concat(taicpu.op_reg_reg_ref(A_ADDIU, hreg, hreg, tmpref));
  850. if href.base <> NR_NO then
  851. begin
  852. if href.index <> NR_NO then
  853. begin
  854. list.concat(taicpu.op_reg_reg_reg(A_ADDU, hreg, href.base, hreg));
  855. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index));
  856. end
  857. else
  858. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.base));
  859. end;
  860. end
  861. else
  862. { At least small offset, maybe base and maybe index }
  863. if (href.offset >= simm16lo) and
  864. (href.offset <= simm16hi) then
  865. begin
  866. if href.index <> NR_NO then { Both base and index }
  867. begin
  868. if href.offset = 0 then
  869. begin
  870. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, href.base, href.index));
  871. end
  872. else
  873. begin
  874. if r_used then
  875. hreg := GetAddressRegister(list)
  876. else
  877. hreg := r;
  878. list.concat(taicpu.op_reg_reg_const(A_ADDIU, hreg, href.base, href.offset));
  879. list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index));
  880. end
  881. end
  882. else if href.base <> NR_NO then { Only base }
  883. begin
  884. list.concat(taicpu.op_reg_reg_const(A_ADDIU, r, href.base, href.offset));
  885. end
  886. else
  887. { only offset, can be generated by absolute }
  888. a_load_const_reg(list, OS_ADDR, href.offset, r);
  889. end
  890. else
  891. internalerror(200703111);
  892. end;
  893. procedure TCGMIPS.a_loadfpu_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  894. const
  895. FpuMovInstr: array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
  896. ((A_MOV_S, A_CVT_D_S),(A_CVT_S_D,A_MOV_D));
  897. var
  898. instr: taicpu;
  899. begin
  900. if (reg1 <> reg2) or (fromsize<>tosize) then
  901. begin
  902. instr := taicpu.op_reg_reg(fpumovinstr[fromsize,tosize], reg2, reg1);
  903. list.Concat(instr);
  904. { Notify the register allocator that we have written a move instruction so
  905. it can try to eliminate it. }
  906. if (fromsize=tosize) then
  907. add_move_instruction(instr);
  908. end;
  909. end;
  910. procedure TCGMIPS.a_loadfpu_ref_reg(list: tasmlist; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister);
  911. var
  912. tmpref: treference;
  913. tmpreg: tregister;
  914. begin
  915. case fromsize of
  916. OS_F32:
  917. handle_load_store_fpu(list, False, A_LWC1, reg, ref);
  918. OS_F64:
  919. handle_load_store_fpu(list, False, A_LDC1, reg, ref);
  920. else
  921. InternalError(2007042701);
  922. end;
  923. if tosize<>fromsize then
  924. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  925. end;
  926. procedure TCGMIPS.a_loadfpu_reg_ref(list: tasmlist; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference);
  927. var
  928. tmpref: treference;
  929. tmpreg: tregister;
  930. begin
  931. if tosize<>fromsize then
  932. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  933. case tosize of
  934. OS_F32:
  935. handle_load_store_fpu(list, True, A_SWC1, reg, ref);
  936. OS_F64:
  937. handle_load_store_fpu(list, True, A_SDC1, reg, ref);
  938. else
  939. InternalError(2007042702);
  940. end;
  941. end;
  942. procedure TCGMIPS.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
  943. const
  944. overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
  945. begin
  946. if (op in overflowops) and
  947. (size in [OS_8,OS_S8,OS_16,OS_S16]) then
  948. a_load_reg_reg(list,OS_32,size,dst,dst);
  949. end;
  950. procedure TCGMIPS.a_op_const_reg(list: tasmlist; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister);
  951. var
  952. power: longint;
  953. tmpreg1: tregister;
  954. begin
  955. if ((op = OP_MUL) or (op = OP_IMUL)) then
  956. begin
  957. if ispowerof2(a, power) then
  958. begin
  959. { can be done with a shift }
  960. if power < 32 then
  961. begin
  962. list.concat(taicpu.op_reg_reg_const(A_SLL, reg, reg, power));
  963. exit;
  964. end;
  965. end;
  966. end;
  967. if ((op = OP_SUB) or (op = OP_ADD)) then
  968. begin
  969. if (a = 0) then
  970. exit;
  971. end;
  972. if Op in [OP_NEG, OP_NOT] then
  973. internalerror(200306011);
  974. if (a = 0) then
  975. begin
  976. if (Op = OP_IMUL) or (Op = OP_MUL) then
  977. list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_R0))
  978. else
  979. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), reg, reg, NR_R0))
  980. end
  981. else
  982. begin
  983. if op = OP_IMUL then
  984. begin
  985. tmpreg1 := GetIntRegister(list, OS_INT);
  986. a_load_const_reg(list, OS_INT, a, tmpreg1);
  987. list.concat(taicpu.op_reg_reg(A_MULT, reg, tmpreg1));
  988. list.concat(taicpu.op_reg(A_MFLO, reg));
  989. end
  990. else if op = OP_MUL then
  991. begin
  992. tmpreg1 := GetIntRegister(list, OS_INT);
  993. a_load_const_reg(list, OS_INT, a, tmpreg1);
  994. list.concat(taicpu.op_reg_reg(A_MULTU, reg, tmpreg1));
  995. list.concat(taicpu.op_reg(A_MFLO, reg));
  996. end
  997. else
  998. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), reg, a, reg);
  999. end;
  1000. maybeadjustresult(list,op,size,reg);
  1001. end;
  1002. procedure TCGMIPS.a_op_reg_reg(list: tasmlist; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  1003. var
  1004. a: aint;
  1005. begin
  1006. case Op of
  1007. OP_NEG:
  1008. { discard overflow checking }
  1009. list.concat(taicpu.op_reg_reg(A_NEGU{A_NEG}, dst, src));
  1010. OP_NOT:
  1011. begin
  1012. list.concat(taicpu.op_reg_reg(A_NOT, dst, src));
  1013. end;
  1014. else
  1015. begin
  1016. if op = OP_IMUL then
  1017. begin
  1018. list.concat(taicpu.op_reg_reg(A_MULT, dst, src));
  1019. list.concat(taicpu.op_reg(A_MFLO, dst));
  1020. end
  1021. else if op = OP_MUL then
  1022. begin
  1023. list.concat(taicpu.op_reg_reg(A_MULTU, dst, src));
  1024. list.concat(taicpu.op_reg(A_MFLO, dst));
  1025. end
  1026. else
  1027. begin
  1028. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, dst, src));
  1029. end;
  1030. end;
  1031. end;
  1032. maybeadjustresult(list,op,size,dst);
  1033. end;
  1034. procedure TCGMIPS.a_op_const_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
  1035. var
  1036. power: longint;
  1037. tmpreg1: tregister;
  1038. begin
  1039. case op of
  1040. OP_MUL,
  1041. OP_IMUL:
  1042. begin
  1043. if ispowerof2(a, power) then
  1044. begin
  1045. { can be done with a shift }
  1046. if power < 32 then
  1047. list.concat(taicpu.op_reg_reg_const(A_SLL, dst, src, power))
  1048. else
  1049. inherited a_op_const_reg_reg(list, op, size, a, src, dst);
  1050. exit;
  1051. end;
  1052. end;
  1053. OP_SUB,
  1054. OP_ADD:
  1055. begin
  1056. if (a = 0) then
  1057. begin
  1058. a_load_reg_reg(list, size, size, src, dst);
  1059. exit;
  1060. end;
  1061. end;
  1062. end;
  1063. if op = OP_IMUL then
  1064. begin
  1065. tmpreg1 := GetIntRegister(list, OS_INT);
  1066. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1067. list.concat(taicpu.op_reg_reg(A_MULT, src, tmpreg1));
  1068. list.concat(taicpu.op_reg(A_MFLO, dst));
  1069. end
  1070. else if op = OP_MUL then
  1071. begin
  1072. tmpreg1 := GetIntRegister(list, OS_INT);
  1073. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1074. list.concat(taicpu.op_reg_reg(A_MULTU, src, tmpreg1));
  1075. list.concat(taicpu.op_reg(A_MFLO, dst));
  1076. end
  1077. else
  1078. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
  1079. maybeadjustresult(list,op,size,dst);
  1080. end;
  1081. procedure TCGMIPS.a_op_reg_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
  1082. begin
  1083. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
  1084. maybeadjustresult(list,op,size,dst);
  1085. end;
  1086. procedure TCGMIPS.a_op_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation);
  1087. var
  1088. tmpreg1: tregister;
  1089. begin
  1090. ovloc.loc := LOC_VOID;
  1091. case op of
  1092. OP_SUB,
  1093. OP_ADD:
  1094. begin
  1095. if (a = 0) then
  1096. begin
  1097. a_load_reg_reg(list, size, size, src, dst);
  1098. exit;
  1099. end;
  1100. end;
  1101. end;{case}
  1102. case op of
  1103. OP_ADD:
  1104. begin
  1105. if setflags then
  1106. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1107. else
  1108. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
  1109. end;
  1110. OP_SUB:
  1111. begin
  1112. if setflags then
  1113. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1114. else
  1115. handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
  1116. end;
  1117. OP_MUL:
  1118. begin
  1119. if setflags then
  1120. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1121. else
  1122. begin
  1123. tmpreg1 := GetIntRegister(list, OS_INT);
  1124. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1125. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size),src, tmpreg1));
  1126. list.concat(taicpu.op_reg(A_MFLO, dst));
  1127. end;
  1128. end;
  1129. OP_IMUL:
  1130. begin
  1131. if setflags then
  1132. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
  1133. else
  1134. begin
  1135. tmpreg1 := GetIntRegister(list, OS_INT);
  1136. a_load_const_reg(list, OS_INT, a, tmpreg1);
  1137. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size),src, tmpreg1));
  1138. list.concat(taicpu.op_reg(A_MFLO, dst));
  1139. end;
  1140. end;
  1141. OP_XOR, OP_OR, OP_AND:
  1142. begin
  1143. handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst);
  1144. end;
  1145. else
  1146. internalerror(2007012601);
  1147. end;
  1148. maybeadjustresult(list,op,size,dst);
  1149. end;
  1150. procedure TCGMIPS.a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
  1151. begin
  1152. ovloc.loc := LOC_VOID;
  1153. case op of
  1154. OP_ADD:
  1155. begin
  1156. if setflags then
  1157. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1158. else
  1159. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
  1160. end;
  1161. OP_SUB:
  1162. begin
  1163. if setflags then
  1164. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1165. else
  1166. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
  1167. end;
  1168. OP_MUL:
  1169. begin
  1170. if setflags then
  1171. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1172. else
  1173. begin
  1174. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size), src2, src1));
  1175. list.concat(taicpu.op_reg(A_MFLO, dst));
  1176. end;
  1177. end;
  1178. OP_IMUL:
  1179. begin
  1180. if setflags then
  1181. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
  1182. else
  1183. begin
  1184. list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size), src2, src1));
  1185. list.concat(taicpu.op_reg(A_MFLO, dst));
  1186. end;
  1187. end;
  1188. OP_XOR, OP_OR, OP_AND:
  1189. begin
  1190. list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1));
  1191. end;
  1192. else
  1193. internalerror(2007012602);
  1194. end;
  1195. maybeadjustresult(list,op,size,dst);
  1196. end;
  1197. {*************** compare instructructions ****************}
  1198. procedure TCGMIPS.a_cmp_const_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
  1199. var
  1200. tmpreg: tregister;
  1201. ai : Taicpu;
  1202. begin
  1203. if a = 0 then
  1204. tmpreg := NR_R0
  1205. else
  1206. begin
  1207. tmpreg := GetIntRegister(list, OS_INT);
  1208. list.concat(taicpu.op_reg_const(A_LI, tmpreg, a));
  1209. end;
  1210. ai := taicpu.op_reg_reg_sym(A_BC, reg, tmpreg, l);
  1211. ai.SetCondition(TOpCmp2AsmCond[cmp_op]);
  1212. list.concat(ai);
  1213. { Delay slot }
  1214. list.Concat(TAiCpu.Op_none(A_NOP));
  1215. end;
  1216. procedure TCGMIPS.a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  1217. var
  1218. ai : Taicpu;
  1219. begin
  1220. ai := taicpu.op_reg_reg_sym(A_BC, reg2, reg1, l);
  1221. ai.SetCondition(TOpCmp2AsmCond[cmp_op]);
  1222. list.concat(ai);
  1223. { Delay slot }
  1224. list.Concat(TAiCpu.Op_none(A_NOP));
  1225. end;
  1226. procedure TCGMIPS.a_jmp_always(List: tasmlist; l: TAsmLabel);
  1227. var
  1228. ai : Taicpu;
  1229. begin
  1230. ai := taicpu.op_sym(A_BA, l);
  1231. list.concat(ai);
  1232. { Delay slot }
  1233. list.Concat(TAiCpu.Op_none(A_NOP));
  1234. end;
  1235. procedure TCGMIPS.a_jmp_name(list: tasmlist; const s: string);
  1236. begin
  1237. List.Concat(TAiCpu.op_sym(A_BA, current_asmdata.RefAsmSymbol(s)));
  1238. { Delay slot }
  1239. list.Concat(TAiCpu.Op_none(A_NOP));
  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. function reference_is_reusable(const ref: treference): boolean;
  1572. begin
  1573. result:=(ref.base<>NR_NO) and (ref.index=NR_NO) and
  1574. (ref.symbol=nil) and
  1575. (ref.alignment>=sizeof(aint)) and
  1576. (ref.offset>=simm16lo) and (ref.offset+len<=simm16hi);
  1577. end;
  1578. begin
  1579. if len > high(longint) then
  1580. internalerror(2002072704);
  1581. { anybody wants to determine a good value here :)? }
  1582. if len > 100 then
  1583. g_concatcopy_move(list, Source, dest, len)
  1584. else
  1585. begin
  1586. Count := len div 4;
  1587. if (count<=4) and reference_is_reusable(source) then
  1588. src:=source
  1589. else
  1590. begin
  1591. reference_reset(src,sizeof(aint));
  1592. { load the address of source into src.base }
  1593. src.base := GetAddressRegister(list);
  1594. a_loadaddr_ref_reg(list, Source, src.base);
  1595. end;
  1596. if (count<=4) and reference_is_reusable(dest) then
  1597. dst:=dest
  1598. else
  1599. begin
  1600. reference_reset(dst,sizeof(aint));
  1601. { load the address of dest into dst.base }
  1602. dst.base := GetAddressRegister(list);
  1603. a_loadaddr_ref_reg(list, dest, dst.base);
  1604. end;
  1605. { generate a loop }
  1606. if Count > 4 then
  1607. begin
  1608. { the offsets are zero after the a_loadaddress_ref_reg and just }
  1609. { have to be set to 8. I put an Inc there so debugging may be }
  1610. { easier (should offset be different from zero here, it will be }
  1611. { easy to notice in the generated assembler }
  1612. countreg := GetIntRegister(list, OS_INT);
  1613. tmpreg1 := GetIntRegister(list, OS_INT);
  1614. a_load_const_reg(list, OS_INT, Count, countreg);
  1615. { explicitely allocate R_O0 since it can be used safely here }
  1616. { (for holding date that's being copied) }
  1617. current_asmdata.getjumplabel(lab);
  1618. a_label(list, lab);
  1619. list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
  1620. list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
  1621. list.concat(taicpu.op_reg_reg_const(A_ADDIU, src.base, src.base, 4));
  1622. list.concat(taicpu.op_reg_reg_const(A_ADDIU, dst.base, dst.base, 4));
  1623. list.concat(taicpu.op_reg_reg_const(A_ADDIU, countreg, countreg, -1));
  1624. //list.concat(taicpu.op_reg_sym(A_BGTZ, countreg, lab));
  1625. ai := taicpu.op_reg_reg_sym(A_BC,countreg, NR_R0, lab);
  1626. ai.setcondition(C_GT);
  1627. list.concat(ai);
  1628. list.concat(taicpu.op_none(A_NOP));
  1629. len := len mod 4;
  1630. end;
  1631. { unrolled loop }
  1632. Count := len div 4;
  1633. if Count > 0 then
  1634. begin
  1635. tmpreg1 := GetIntRegister(list, OS_INT);
  1636. for count2 := 1 to Count do
  1637. begin
  1638. list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
  1639. list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
  1640. Inc(src.offset, 4);
  1641. Inc(dst.offset, 4);
  1642. end;
  1643. len := len mod 4;
  1644. end;
  1645. if (len and 4) <> 0 then
  1646. begin
  1647. hreg := GetIntRegister(list, OS_INT);
  1648. a_load_ref_reg(list, OS_32, OS_32, src, hreg);
  1649. a_load_reg_ref(list, OS_32, OS_32, hreg, dst);
  1650. Inc(src.offset, 4);
  1651. Inc(dst.offset, 4);
  1652. end;
  1653. { copy the leftovers }
  1654. if (len and 2) <> 0 then
  1655. begin
  1656. hreg := GetIntRegister(list, OS_INT);
  1657. a_load_ref_reg(list, OS_16, OS_16, src, hreg);
  1658. a_load_reg_ref(list, OS_16, OS_16, hreg, dst);
  1659. Inc(src.offset, 2);
  1660. Inc(dst.offset, 2);
  1661. end;
  1662. if (len and 1) <> 0 then
  1663. begin
  1664. hreg := GetIntRegister(list, OS_INT);
  1665. a_load_ref_reg(list, OS_8, OS_8, src, hreg);
  1666. a_load_reg_ref(list, OS_8, OS_8, hreg, dst);
  1667. end;
  1668. end;
  1669. end;
  1670. procedure TCGMIPS.g_concatcopy_unaligned(list: tasmlist; const Source, dest: treference; len: tcgint);
  1671. var
  1672. src, dst: TReference;
  1673. tmpreg1, countreg: TRegister;
  1674. i: aint;
  1675. lab: tasmlabel;
  1676. ai : TaiCpu;
  1677. begin
  1678. if len > 31 then
  1679. g_concatcopy_move(list, Source, dest, len)
  1680. else
  1681. begin
  1682. reference_reset(src,sizeof(aint));
  1683. reference_reset(dst,sizeof(aint));
  1684. { load the address of source into src.base }
  1685. src.base := GetAddressRegister(list);
  1686. a_loadaddr_ref_reg(list, Source, src.base);
  1687. { load the address of dest into dst.base }
  1688. dst.base := GetAddressRegister(list);
  1689. a_loadaddr_ref_reg(list, dest, dst.base);
  1690. { generate a loop }
  1691. if len > 4 then
  1692. begin
  1693. { the offsets are zero after the a_loadaddress_ref_reg and just }
  1694. { have to be set to 8. I put an Inc there so debugging may be }
  1695. { easier (should offset be different from zero here, it will be }
  1696. { easy to notice in the generated assembler }
  1697. countreg := cg.GetIntRegister(list, OS_INT);
  1698. tmpreg1 := cg.GetIntRegister(list, OS_INT);
  1699. a_load_const_reg(list, OS_INT, len, countreg);
  1700. { explicitely allocate R_O0 since it can be used safely here }
  1701. { (for holding date that's being copied) }
  1702. current_asmdata.getjumplabel(lab);
  1703. a_label(list, lab);
  1704. list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
  1705. list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst));
  1706. list.concat(taicpu.op_reg_reg_const(A_ADDIU, src.base, src.base, 1));
  1707. list.concat(taicpu.op_reg_reg_const(A_ADDIU, dst.base, dst.base, 1));
  1708. list.concat(taicpu.op_reg_reg_const(A_ADDIU, countreg, countreg, -1));
  1709. //list.concat(taicpu.op_reg_sym(A_BGTZ, countreg, lab));
  1710. ai := taicpu.op_reg_reg_sym(A_BC,countreg, NR_R0, lab);
  1711. ai.setcondition(C_GT);
  1712. list.concat(ai);
  1713. list.concat(taicpu.op_none(A_NOP));
  1714. end
  1715. else
  1716. begin
  1717. { unrolled loop }
  1718. tmpreg1 := cg.GetIntRegister(list, OS_INT);
  1719. for i := 1 to len do
  1720. begin
  1721. list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
  1722. list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst));
  1723. Inc(src.offset);
  1724. Inc(dst.offset);
  1725. end;
  1726. end;
  1727. end;
  1728. end;
  1729. procedure TCGMIPS.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labelname: string; ioffset: longint);
  1730. procedure loadvmttorvmt;
  1731. var
  1732. href: treference;
  1733. begin
  1734. { TODO: Hardcoded register is ugly!
  1735. Look for the 'self' parameter again? g_adjust_self_value() does it right before,
  1736. but the result is local to g_adjust_self_value. }
  1737. reference_reset_base(href, NR_R4, 0, sizeof(aint));
  1738. cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_VMT);
  1739. end;
  1740. procedure op_onrvmtmethodaddr;
  1741. var
  1742. href : treference;
  1743. reg : tregister;
  1744. begin
  1745. if (procdef.extnumber=$ffff) then
  1746. Internalerror(200006139);
  1747. { call/jmp vmtoffs(%eax) ; method offs }
  1748. reference_reset_base(href, NR_VMT, tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber), sizeof(aint));
  1749. if (cs_create_pic in current_settings.moduleswitches) then
  1750. reg:=NR_PIC_FUNC
  1751. else
  1752. reg:=NR_VMT;
  1753. cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, reg);
  1754. list.concat(taicpu.op_reg(A_JR, reg));
  1755. end;
  1756. var
  1757. make_global: boolean;
  1758. href: treference;
  1759. begin
  1760. if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
  1761. Internalerror(200006137);
  1762. if not assigned(procdef.struct) or
  1763. (procdef.procoptions * [po_classmethod, po_staticmethod,
  1764. po_methodpointer, po_interrupt, po_iocheck] <> []) then
  1765. Internalerror(200006138);
  1766. if procdef.owner.symtabletype <> objectsymtable then
  1767. Internalerror(200109191);
  1768. make_global := False;
  1769. if (not current_module.is_unit) or create_smartlink or
  1770. (procdef.owner.defowner.owner.symtabletype = globalsymtable) then
  1771. make_global := True;
  1772. if make_global then
  1773. List.concat(Tai_symbol.Createname_global(labelname, AT_FUNCTION, 0))
  1774. else
  1775. List.concat(Tai_symbol.Createname(labelname, AT_FUNCTION, 0));
  1776. { set param1 interface to self }
  1777. g_adjust_self_value(list, procdef, ioffset);
  1778. if (po_virtualmethod in procdef.procoptions) and
  1779. not is_objectpascal_helper(procdef.struct) then
  1780. begin
  1781. loadvmttorvmt;
  1782. op_onrvmtmethodaddr;
  1783. end
  1784. else
  1785. list.concat(taicpu.op_sym(A_J,current_asmdata.RefAsmSymbol(procdef.mangledname)));
  1786. { Delay slot }
  1787. list.Concat(TAiCpu.Op_none(A_NOP));
  1788. List.concat(Tai_symbol_end.Createname(labelname));
  1789. end;
  1790. procedure TCGMIPS.g_stackpointer_alloc(list : TAsmList;localsize : longint);
  1791. begin
  1792. Comment(V_Error,'TCgMPSel.g_stackpointer_alloc method not implemented');
  1793. end;
  1794. procedure TCGMIPS.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
  1795. begin
  1796. Comment(V_Error,'TCgMPSel.a_bit_scan_reg_reg method not implemented');
  1797. end;
  1798. {****************************************************************************
  1799. TCG64_MIPSel
  1800. ****************************************************************************}
  1801. procedure TCg64MPSel.a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference);
  1802. var
  1803. tmpref: treference;
  1804. tmpreg: tregister;
  1805. begin
  1806. { Override this function to prevent loading the reference twice }
  1807. if target_info.endian = endian_big then
  1808. begin
  1809. tmpreg := reg.reglo;
  1810. reg.reglo := reg.reghi;
  1811. reg.reghi := tmpreg;
  1812. end;
  1813. tmpref := ref;
  1814. cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reglo, tmpref);
  1815. Inc(tmpref.offset, 4);
  1816. cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reghi, tmpref);
  1817. end;
  1818. procedure TCg64MPSel.a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64);
  1819. var
  1820. tmpref: treference;
  1821. tmpreg: tregister;
  1822. begin
  1823. { Override this function to prevent loading the reference twice }
  1824. if target_info.endian = endian_big then
  1825. begin
  1826. tmpreg := reg.reglo;
  1827. reg.reglo := reg.reghi;
  1828. reg.reghi := tmpreg;
  1829. end;
  1830. tmpref := ref;
  1831. cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reglo);
  1832. Inc(tmpref.offset, 4);
  1833. cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reghi);
  1834. end;
  1835. procedure TCg64MPSel.a_load64_ref_cgpara(list: tasmlist; const r: treference; const paraloc: tcgpara);
  1836. var
  1837. hreg64: tregister64;
  1838. begin
  1839. { Override this function to prevent loading the reference twice.
  1840. Use here some extra registers, but those are optimized away by the RA }
  1841. hreg64.reglo := cg.GetIntRegister(list, OS_S32);
  1842. hreg64.reghi := cg.GetIntRegister(list, OS_S32);
  1843. a_load64_ref_reg(list, r, hreg64);
  1844. a_load64_reg_cgpara(list, hreg64, paraloc);
  1845. end;
  1846. procedure TCg64MPSel.a_op64_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc, regdst: TRegister64);
  1847. var
  1848. op1, op2, op_call64: TAsmOp;
  1849. tmpreg1, tmpreg2: TRegister;
  1850. begin
  1851. tmpreg1 := cg.GetIntRegister(list, OS_INT);
  1852. tmpreg2 := cg.GetIntRegister(list, OS_INT);
  1853. case op of
  1854. OP_ADD:
  1855. begin
  1856. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reglo, regsrc.reglo, regdst.reglo));
  1857. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg1, regdst.reglo, regsrc.reglo));
  1858. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg2, regsrc.reghi, regdst.reghi));
  1859. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, tmpreg1, tmpreg2));
  1860. exit;
  1861. end;
  1862. OP_AND:
  1863. begin
  1864. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reglo, regsrc.reglo, regdst.reglo));
  1865. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reghi, regsrc.reghi, regdst.reghi));
  1866. exit;
  1867. end;
  1868. OP_NEG:
  1869. begin
  1870. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reglo, NR_R0, regsrc.reglo));
  1871. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg1, NR_R0, regdst.reglo));
  1872. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, NR_R0, regsrc.reghi));
  1873. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, tmpreg1));
  1874. exit;
  1875. end;
  1876. OP_NOT:
  1877. begin
  1878. list.concat(taicpu.op_reg_reg_reg(A_NOR, regdst.reglo, NR_R0, regsrc.reglo));
  1879. list.concat(taicpu.op_reg_reg_reg(A_NOR, regdst.reghi, NR_R0, regsrc.reghi));
  1880. exit;
  1881. end;
  1882. OP_OR:
  1883. begin
  1884. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reglo, regsrc.reglo, regdst.reglo));
  1885. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reghi, regsrc.reghi, regdst.reghi));
  1886. exit;
  1887. end;
  1888. OP_SUB:
  1889. begin
  1890. list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg1, regdst.reglo, regsrc.reglo));
  1891. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg2, regdst.reglo, tmpreg1));
  1892. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, regsrc.reghi));
  1893. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, tmpreg2));
  1894. list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
  1895. exit;
  1896. end;
  1897. OP_XOR:
  1898. begin
  1899. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reglo, regdst.reglo, regsrc.reglo));
  1900. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reghi, regsrc.reghi, regdst.reghi));
  1901. exit;
  1902. end;
  1903. else
  1904. internalerror(200306017);
  1905. end; {case}
  1906. end;
  1907. procedure TCg64MPSel.a_op64_const_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regdst: TRegister64);
  1908. begin
  1909. a_op64_const_reg_reg(list, op, size, value, regdst, regdst);
  1910. end;
  1911. procedure TCg64MPSel.a_op64_const_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64);
  1912. var
  1913. l: tlocation;
  1914. begin
  1915. a_op64_const_reg_reg_checkoverflow(list, op, size, Value, regsrc, regdst, False, l);
  1916. end;
  1917. procedure TCg64MPSel.a_op64_reg_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64);
  1918. var
  1919. l: tlocation;
  1920. begin
  1921. a_op64_reg_reg_reg_checkoverflow(list, op, size, regsrc1, regsrc2, regdst, False, l);
  1922. end;
  1923. procedure TCg64MPSel.a_op64_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64; setflags: boolean; var ovloc: tlocation);
  1924. var
  1925. tmpreg64: TRegister64;
  1926. begin
  1927. tmpreg64.reglo := cg.GetIntRegister(list, OS_S32);
  1928. tmpreg64.reghi := cg.GetIntRegister(list, OS_S32);
  1929. list.concat(taicpu.op_reg_const(A_LI, tmpreg64.reglo, aint(lo(Value))));
  1930. list.concat(taicpu.op_reg_const(A_LI, tmpreg64.reghi, aint(hi(Value))));
  1931. a_op64_reg_reg_reg_checkoverflow(list, op, size, tmpreg64, regsrc, regdst, False, ovloc);
  1932. end;
  1933. procedure TCg64MPSel.a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation);
  1934. var
  1935. op1, op2: TAsmOp;
  1936. tmpreg1, tmpreg2: TRegister;
  1937. begin
  1938. case op of
  1939. OP_ADD:
  1940. begin
  1941. tmpreg1 := cg.GetIntRegister(list,OS_S32);
  1942. tmpreg2 := cg.GetIntRegister(list,OS_S32);
  1943. // destreg.reglo could be regsrc1.reglo or regsrc2.reglo
  1944. list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, regsrc2.reglo, regsrc1.reglo));
  1945. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg2, tmpreg1, regsrc2.reglo));
  1946. list.concat(taicpu.op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
  1947. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1948. list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, regdst.reghi, tmpreg2));
  1949. exit;
  1950. end;
  1951. OP_AND:
  1952. begin
  1953. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
  1954. list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1955. exit;
  1956. end;
  1957. OP_OR:
  1958. begin
  1959. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
  1960. list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1961. exit;
  1962. end;
  1963. OP_SUB:
  1964. begin
  1965. tmpreg1 := cg.GetIntRegister(list,OS_S32);
  1966. tmpreg2 := cg.GetIntRegister(list,OS_S32);
  1967. // destreg.reglo could be regsrc1.reglo or regsrc2.reglo
  1968. list.concat(taicpu.op_reg_reg_reg(A_SUBU,tmpreg1, regsrc2.reglo, regsrc1.reglo));
  1969. list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg2, regsrc2.reglo,tmpreg1));
  1970. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1971. list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regdst.reghi, tmpreg2));
  1972. list.concat(taicpu.op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
  1973. exit;
  1974. end;
  1975. OP_XOR:
  1976. begin
  1977. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
  1978. list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
  1979. exit;
  1980. end;
  1981. else
  1982. internalerror(200306017);
  1983. end; {case}
  1984. end;
  1985. procedure create_codegen;
  1986. begin
  1987. cg:=TCGMIPS.Create;
  1988. cg64:=TCg64MPSel.Create;
  1989. end;
  1990. end.