cgcpu.pas 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168
  1. {
  2. Copyright (c) 2008 by Florian Klaempfl
  3. Member of the Free Pascal development team
  4. This unit implements the code generator for the Z80
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,symtype,symdef,
  23. cgbase,cgutils,cgobj,
  24. aasmbase,aasmcpu,aasmtai,aasmdata,
  25. parabase,
  26. cpubase,cpuinfo,node,cg64f32,rgcpu;
  27. type
  28. { tcgz80 }
  29. tcgz80 = class(tcg)
  30. { true, if the next arithmetic operation should modify the flags }
  31. cgsetflags : boolean;
  32. procedure init_register_allocators;override;
  33. procedure done_register_allocators;override;
  34. function getaddressregister(list:TAsmList):TRegister;override;
  35. procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
  36. procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : TCGPara);override;
  37. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
  38. procedure a_load_reg_cgpara(list : TAsmList; size : tcgsize;r : tregister; const cgpara : tcgpara);override;
  39. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  40. procedure a_call_reg(list : TAsmList;reg: tregister);override;
  41. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
  42. procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override;
  43. { move instructions }
  44. procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
  45. procedure a_load_const_ref(list : TAsmList;size : tcgsize;a : tcgint;const ref : treference);override;
  46. procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  47. procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  48. procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  49. { fpu move instructions }
  50. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
  51. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
  52. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
  53. { comparison operations }
  54. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
  55. l : tasmlabel);override;
  56. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  57. procedure a_jmp_name(list : TAsmList;const s : string); override;
  58. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  59. procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
  60. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  61. procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
  62. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  63. procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
  64. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  65. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
  66. procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  67. procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
  68. procedure g_save_registers(list : TAsmList);override;
  69. procedure g_restore_registers(list : TAsmList);override;
  70. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  71. procedure fixref(list : TAsmList;var ref : treference);
  72. function normalize_ref(list : TAsmList;ref : treference;
  73. tmpreg : tregister) : treference;
  74. procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  75. procedure a_adjust_sp(list: TAsmList; value: longint);
  76. procedure make_simple_ref(list:TAsmList;var ref: treference);
  77. protected
  78. procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  79. procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
  80. procedure maybegetcpuregister(list : tasmlist; reg : tregister);
  81. end;
  82. tcg64fz80 = class(tcg64f32)
  83. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  84. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  85. end;
  86. function GetByteLoc(const loc : tlocation;nr : byte) : tlocation;
  87. procedure create_codegen;
  88. const
  89. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_LD,A_ADD,A_AND,A_NONE,
  90. A_NONE,A_NONE,A_NONE,A_NEG,A_CPL,A_OR,
  91. A_SRA,A_SLA,A_SRL,A_SUB,A_XOR,A_RLCA,A_RRCA);
  92. implementation
  93. uses
  94. globals,verbose,systems,cutils,
  95. fmodule,
  96. symconst,symsym,symtable,
  97. tgobj,rgobj,
  98. procinfo,cpupi,
  99. paramgr;
  100. function use_push(const cgpara:tcgpara):boolean;
  101. begin
  102. result:=(not paramanager.use_fixed_stack) and
  103. assigned(cgpara.location) and
  104. (cgpara.location^.loc=LOC_REFERENCE) and
  105. (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
  106. end;
  107. procedure tcgz80.init_register_allocators;
  108. begin
  109. inherited init_register_allocators;
  110. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  111. [RS_A,RS_B,RS_C,RS_D,RS_E,RS_H,RS_L],first_int_imreg,[]);
  112. end;
  113. procedure tcgz80.done_register_allocators;
  114. begin
  115. rg[R_INTREGISTER].free;
  116. // rg[R_ADDRESSREGISTER].free;
  117. inherited done_register_allocators;
  118. end;
  119. function tcgz80.getaddressregister(list: TAsmList): TRegister;
  120. begin
  121. Result:=getintregister(list,OS_ADDR);
  122. end;
  123. procedure tcgz80.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
  124. procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
  125. var
  126. ref : treference;
  127. begin
  128. paramanager.allocparaloc(list,paraloc);
  129. case paraloc^.loc of
  130. LOC_REGISTER,LOC_CREGISTER:
  131. a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
  132. LOC_REFERENCE,LOC_CREFERENCE:
  133. begin
  134. reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
  135. a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
  136. end;
  137. else
  138. internalerror(2002071004);
  139. end;
  140. end;
  141. var
  142. i, i2 : longint;
  143. hp : PCGParaLocation;
  144. begin
  145. if use_push(cgpara) then
  146. begin
  147. case tcgsize2size[cgpara.Size] of
  148. 1:
  149. begin
  150. cgpara.check_simple_location;
  151. getcpuregister(list,NR_A);
  152. a_load_reg_reg(list,OS_8,OS_8,r,NR_A);
  153. list.concat(taicpu.op_reg(A_PUSH,NR_AF));
  154. list.concat(taicpu.op_reg(A_INC,NR_SP));
  155. ungetcpuregister(list,NR_A);
  156. end;
  157. else
  158. internalerror(2020040801);
  159. end;
  160. { if tcgsize2size[cgpara.Size] > 2 then
  161. begin
  162. if tcgsize2size[cgpara.Size] <> 4 then
  163. internalerror(2013031101);
  164. if cgpara.location^.Next = nil then
  165. begin
  166. if tcgsize2size[cgpara.location^.size] <> 4 then
  167. internalerror(2013031101);
  168. end
  169. else
  170. begin
  171. if tcgsize2size[cgpara.location^.size] <> 2 then
  172. internalerror(2013031101);
  173. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  174. internalerror(2013031101);
  175. if cgpara.location^.Next^.Next <> nil then
  176. internalerror(2013031101);
  177. end;
  178. if tcgsize2size[cgpara.size]>cgpara.alignment then
  179. pushsize:=cgpara.size
  180. else
  181. pushsize:=int_cgsize(cgpara.alignment);
  182. pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2);
  183. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2)));
  184. list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16)));
  185. end
  186. else
  187. begin
  188. cgpara.check_simple_location;
  189. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  190. pushsize:=cgpara.location^.size
  191. else
  192. pushsize:=int_cgsize(cgpara.alignment);
  193. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
  194. end;}
  195. end
  196. else
  197. begin
  198. if not(tcgsize2size[cgpara.Size] in [1..4]) then
  199. internalerror(2014011101);
  200. hp:=cgpara.location;
  201. i:=0;
  202. while i<tcgsize2size[cgpara.Size] do
  203. begin
  204. if not(assigned(hp)) then
  205. internalerror(2014011102);
  206. inc(i, tcgsize2size[hp^.Size]);
  207. if hp^.Loc=LOC_REGISTER then
  208. begin
  209. load_para_loc(r,hp);
  210. hp:=hp^.Next;
  211. r:=GetNextReg(r);
  212. end
  213. else
  214. begin
  215. load_para_loc(r,hp);
  216. for i2:=1 to tcgsize2size[hp^.Size] do
  217. r:=GetNextReg(r);
  218. hp:=hp^.Next;
  219. end;
  220. end;
  221. if assigned(hp) then
  222. internalerror(2014011103);
  223. end;
  224. end;
  225. procedure tcgz80.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
  226. var
  227. i : longint;
  228. hp : PCGParaLocation;
  229. ref: treference;
  230. begin
  231. if not(tcgsize2size[paraloc.Size] in [1..4]) then
  232. internalerror(2014011101);
  233. if use_push(paraloc) then
  234. begin
  235. case tcgsize2size[paraloc.Size] of
  236. 1:
  237. begin
  238. getcpuregister(list,NR_A);
  239. a_load_const_reg(list,OS_8,a,NR_A);
  240. list.Concat(taicpu.op_reg(A_PUSH,NR_AF));
  241. list.Concat(taicpu.op_reg(A_INC,NR_SP));
  242. ungetcpuregister(list,NR_A);
  243. end;
  244. 2:
  245. begin
  246. getcpuregister(list,NR_IY);
  247. list.Concat(taicpu.op_reg_const(A_LD,NR_IY,a));
  248. list.Concat(taicpu.op_reg(A_PUSH,NR_IY));
  249. ungetcpuregister(list,NR_IY);
  250. end;
  251. 4:
  252. begin
  253. getcpuregister(list,NR_IY);
  254. list.Concat(taicpu.op_reg_const(A_LD,NR_IY,Word(a shr 16)));
  255. list.Concat(taicpu.op_reg(A_PUSH,NR_IY));
  256. list.Concat(taicpu.op_reg_const(A_LD,NR_IY,Word(a)));
  257. list.Concat(taicpu.op_reg(A_PUSH,NR_IY));
  258. ungetcpuregister(list,NR_IY);
  259. end;
  260. else
  261. internalerror(2020040701);
  262. end;
  263. end
  264. else
  265. begin
  266. hp:=paraloc.location;
  267. i:=1;
  268. while i<=tcgsize2size[paraloc.Size] do
  269. begin
  270. if not(assigned(hp)) then
  271. internalerror(2014011105);
  272. //paramanager.allocparaloc(list,hp);
  273. case hp^.loc of
  274. LOC_REGISTER,LOC_CREGISTER:
  275. begin
  276. if (tcgsize2size[hp^.size]<>1) or
  277. (hp^.shiftval<>0) then
  278. internalerror(2015041101);
  279. a_load_const_reg(list,hp^.size,(a shr (8*(i-1))) and $ff,hp^.register);
  280. inc(i,tcgsize2size[hp^.size]);
  281. hp:=hp^.Next;
  282. end;
  283. LOC_REFERENCE,LOC_CREFERENCE:
  284. begin
  285. reference_reset(ref,paraloc.alignment,[]);
  286. ref.base:=hp^.reference.index;
  287. ref.offset:=hp^.reference.offset;
  288. a_load_const_ref(list,hp^.size,a shr (8*(i-1)),ref);
  289. inc(i,tcgsize2size[hp^.size]);
  290. hp:=hp^.Next;
  291. end;
  292. else
  293. internalerror(2002071004);
  294. end;
  295. end;
  296. end;
  297. end;
  298. procedure tcgz80.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : TCGPara);
  299. procedure pushdata(paraloc:pcgparalocation;ofs:tcgint);
  300. var
  301. pushsize : tcgsize;
  302. opsize : topsize;
  303. tmpreg : tregister;
  304. href,tmpref: treference;
  305. begin
  306. if not assigned(paraloc) then
  307. exit;
  308. if (paraloc^.loc<>LOC_REFERENCE) or
  309. (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
  310. (tcgsize2size[paraloc^.size]>4) then
  311. internalerror(200501162);
  312. { Pushes are needed in reverse order, add the size of the
  313. current location to the offset where to load from. This
  314. prevents wrong calculations for the last location when
  315. the size is not a power of 2 }
  316. if assigned(paraloc^.next) then
  317. pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
  318. { Push the data starting at ofs }
  319. href:=r;
  320. inc(href.offset,ofs);
  321. {if tcgsize2size[paraloc^.size]>cgpara.alignment then}
  322. pushsize:=paraloc^.size
  323. {else
  324. pushsize:=int_cgsize(cgpara.alignment)};
  325. {Writeln(pushsize);}
  326. case tcgsize2size[pushsize] of
  327. 1:
  328. begin
  329. tmpreg:=getintregister(list,OS_8);
  330. a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  331. getcpuregister(list,NR_A);
  332. a_load_reg_reg(list,OS_8,OS_8,tmpreg,NR_A);
  333. list.concat(taicpu.op_reg(A_PUSH,NR_AF));
  334. list.concat(taicpu.op_reg(A_INC,NR_SP));
  335. ungetcpuregister(list,NR_A);
  336. end;
  337. else
  338. internalerror(2020040803);
  339. end;
  340. //if tcgsize2size[paraloc^.size]<cgpara.alignment then
  341. // begin
  342. // tmpreg:=getintregister(list,pushsize);
  343. // a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  344. // list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
  345. // end
  346. //else
  347. // begin
  348. // make_simple_ref(list,href);
  349. // if tcgsize2size[pushsize] > 2 then
  350. // begin
  351. // tmpref := href;
  352. // Inc(tmpref.offset, 2);
  353. // list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[int_cgsize(tcgsize2size[pushsize]-2)],tmpref));
  354. // end;
  355. // list.concat(taicpu.op_ref(A_PUSH,opsize,href));
  356. // end;
  357. end;
  358. var
  359. tmpref, ref: treference;
  360. location: pcgparalocation;
  361. sizeleft: tcgint;
  362. begin
  363. { cgpara.size=OS_NO requires a copy on the stack }
  364. if use_push(cgpara) then
  365. begin
  366. { Record copy? }
  367. if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
  368. begin
  369. internalerror(2020040802);
  370. //cgpara.check_simple_location;
  371. //len:=align(cgpara.intsize,cgpara.alignment);
  372. //g_stackpointer_alloc(list,len);
  373. //reference_reset_base(href,NR_STACK_POINTER_REG,0,ctempposinvalid,4,[]);
  374. //g_concatcopy(list,r,href,len);
  375. end
  376. else
  377. begin
  378. if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
  379. internalerror(200501161);
  380. { We need to push the data in reverse order,
  381. therefor we use a recursive algorithm }
  382. pushdata(cgpara.location,0);
  383. end
  384. end
  385. else
  386. begin
  387. location := cgpara.location;
  388. tmpref := r;
  389. sizeleft := cgpara.intsize;
  390. while assigned(location) do
  391. begin
  392. paramanager.allocparaloc(list,location);
  393. case location^.loc of
  394. LOC_REGISTER,LOC_CREGISTER:
  395. a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
  396. LOC_REFERENCE:
  397. begin
  398. reference_reset_base(ref,location^.reference.index,location^.reference.offset,ctempposinvalid,cgpara.alignment,[]);
  399. { doubles in softemu mode have a strange order of registers and references }
  400. if location^.size=OS_32 then
  401. g_concatcopy(list,tmpref,ref,4)
  402. else
  403. begin
  404. g_concatcopy(list,tmpref,ref,sizeleft);
  405. if assigned(location^.next) then
  406. internalerror(2005010710);
  407. end;
  408. end;
  409. LOC_VOID:
  410. begin
  411. // nothing to do
  412. end;
  413. else
  414. internalerror(2002081103);
  415. end;
  416. inc(tmpref.offset,tcgsize2size[location^.size]);
  417. dec(sizeleft,tcgsize2size[location^.size]);
  418. location := location^.next;
  419. end;
  420. end;
  421. end;
  422. procedure tcgz80.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
  423. var
  424. tmpreg: tregister;
  425. begin
  426. tmpreg:=getaddressregister(list);
  427. a_loadaddr_ref_reg(list,r,tmpreg);
  428. a_load_reg_cgpara(list,OS_ADDR,tmpreg,paraloc);
  429. end;
  430. procedure tcgz80.a_call_name(list : TAsmList;const s : string; weak: boolean);
  431. var
  432. sym: TAsmSymbol;
  433. begin
  434. if weak then
  435. sym:=current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION)
  436. else
  437. sym:=current_asmdata.RefAsmSymbol(s,AT_FUNCTION);
  438. list.concat(taicpu.op_sym(A_CALL,sym));
  439. include(current_procinfo.flags,pi_do_call);
  440. end;
  441. procedure tcgz80.a_call_reg(list : TAsmList;reg: tregister);
  442. var
  443. l : TAsmLabel;
  444. ref : treference;
  445. begin
  446. current_asmdata.getjumplabel(l);
  447. reference_reset(ref,0,[]);
  448. ref.symbol:=l;
  449. list.concat(taicpu.op_ref_reg(A_LD,ref,reg));
  450. list.concat(tai_const.Create_8bit($CD));
  451. list.concat(tai_label.Create(l));
  452. include(current_procinfo.flags,pi_do_call);
  453. end;
  454. procedure tcgz80.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
  455. begin
  456. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  457. internalerror(2012102403);
  458. a_op_const_reg_internal(list,Op,size,a,reg,NR_NO);
  459. end;
  460. procedure tcgz80.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister);
  461. begin
  462. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  463. internalerror(2012102401);
  464. a_op_reg_reg_internal(list,Op,size,src,NR_NO,dst,NR_NO);
  465. end;
  466. procedure tcgz80.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  467. var
  468. countreg,
  469. tmpreg,tmpreg2: tregister;
  470. i : integer;
  471. instr : taicpu;
  472. paraloc1,paraloc2,paraloc3 : TCGPara;
  473. l1,l2 : tasmlabel;
  474. pd : tprocdef;
  475. procedure NextSrcDst;
  476. begin
  477. if i=5 then
  478. begin
  479. dst:=dsthi;
  480. src:=srchi;
  481. end
  482. else
  483. begin
  484. dst:=GetNextReg(dst);
  485. src:=GetNextReg(src);
  486. end;
  487. end;
  488. { iterates TmpReg through all registers of dst }
  489. procedure NextTmp;
  490. begin
  491. if i=5 then
  492. tmpreg:=dsthi
  493. else
  494. tmpreg:=GetNextReg(tmpreg);
  495. end;
  496. begin
  497. case op of
  498. OP_ADD:
  499. begin
  500. getcpuregister(list,NR_A);
  501. a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  502. list.concat(taicpu.op_reg_reg(A_ADD,NR_A,src));
  503. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  504. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  505. begin
  506. for i:=2 to tcgsize2size[size] do
  507. begin
  508. NextSrcDst;
  509. a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  510. list.concat(taicpu.op_reg_reg(A_ADC,NR_A,src));
  511. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  512. end;
  513. end;
  514. ungetcpuregister(list,NR_A);
  515. end;
  516. OP_SUB:
  517. begin
  518. getcpuregister(list,NR_A);
  519. a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  520. list.concat(taicpu.op_reg_reg(A_SUB,NR_A,src));
  521. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  522. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  523. begin
  524. for i:=2 to tcgsize2size[size] do
  525. begin
  526. NextSrcDst;
  527. a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  528. list.concat(taicpu.op_reg_reg(A_SBC,NR_A,src));
  529. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  530. end;
  531. end;
  532. ungetcpuregister(list,NR_A);
  533. end;
  534. OP_NEG:
  535. begin
  536. getcpuregister(list,NR_A);
  537. if tcgsize2size[size]>=2 then
  538. begin
  539. tmpreg:=GetNextReg(src);
  540. tmpreg2:=GetNextReg(dst);
  541. for i:=2 to tcgsize2size[size] do
  542. begin
  543. a_load_reg_reg(list,OS_8,OS_8,tmpreg,NR_A);
  544. list.concat(taicpu.op_none(A_CPL));
  545. a_load_reg_reg(list,OS_8,OS_8,NR_A,tmpreg2);
  546. if i<>tcgsize2size[size] then
  547. begin
  548. if i=5 then
  549. begin
  550. tmpreg:=srchi;
  551. tmpreg2:=dsthi;
  552. end
  553. else
  554. begin
  555. tmpreg:=GetNextReg(tmpreg);
  556. tmpreg2:=GetNextReg(tmpreg2);
  557. end;
  558. end;
  559. end;
  560. end;
  561. a_load_reg_reg(list,OS_8,OS_8,src,NR_A);
  562. list.concat(taicpu.op_none(A_NEG));
  563. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  564. if tcgsize2size[size]>=2 then
  565. begin
  566. tmpreg2:=GetNextReg(dst);
  567. for i:=2 to tcgsize2size[size] do
  568. begin
  569. a_load_reg_reg(list,OS_8,OS_8,tmpreg2,NR_A);
  570. list.concat(taicpu.op_reg_const(A_SBC,NR_A,-1));
  571. a_load_reg_reg(list,OS_8,OS_8,NR_A,tmpreg2);
  572. if i<>tcgsize2size[size] then
  573. begin
  574. if i=5 then
  575. begin
  576. tmpreg2:=dsthi;
  577. end
  578. else
  579. begin
  580. tmpreg2:=GetNextReg(tmpreg2);
  581. end;
  582. end;
  583. end;
  584. end;
  585. ungetcpuregister(list,NR_A);
  586. end;
  587. OP_NOT:
  588. begin
  589. getcpuregister(list,NR_A);
  590. for i:=1 to tcgsize2size[size] do
  591. begin
  592. a_load_reg_reg(list,OS_8,OS_8,src,NR_A);
  593. list.concat(taicpu.op_none(A_CPL));
  594. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  595. if i<>tcgsize2size[size] then
  596. NextSrcDst;
  597. end;
  598. ungetcpuregister(list,NR_A);
  599. end;
  600. OP_MUL,OP_IMUL:
  601. { special stuff, needs separate handling inside code
  602. generator }
  603. internalerror(2017032604);
  604. OP_DIV,OP_IDIV:
  605. { special stuff, needs separate handling inside code
  606. generator }
  607. internalerror(2017032604);
  608. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  609. begin
  610. //current_asmdata.getjumplabel(l1);
  611. //current_asmdata.getjumplabel(l2);
  612. //countreg:=getintregister(list,OS_8);
  613. //a_load_reg_reg(list,size,OS_8,src,countreg);
  614. //list.concat(taicpu.op_reg(A_TST,countreg));
  615. //a_jmp_flags(list,F_EQ,l2);
  616. //cg.a_label(list,l1);
  617. //case op of
  618. // OP_SHR:
  619. // list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  620. // OP_SHL:
  621. // list.concat(taicpu.op_reg(A_LSL,dst));
  622. // OP_SAR:
  623. // list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  624. // OP_ROR:
  625. // begin
  626. // { load carry? }
  627. // if not(size in [OS_8,OS_S8]) then
  628. // begin
  629. // list.concat(taicpu.op_none(A_CLC));
  630. // list.concat(taicpu.op_reg_const(A_SBRC,src,0));
  631. // list.concat(taicpu.op_none(A_SEC));
  632. // end;
  633. // list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  634. // end;
  635. // OP_ROL:
  636. // begin
  637. // { load carry? }
  638. // if not(size in [OS_8,OS_S8]) then
  639. // begin
  640. // list.concat(taicpu.op_none(A_CLC));
  641. // list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7));
  642. // list.concat(taicpu.op_none(A_SEC));
  643. // end;
  644. // list.concat(taicpu.op_reg(A_ROL,dst))
  645. // end;
  646. // else
  647. // internalerror(2011030901);
  648. //end;
  649. //if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  650. // begin
  651. // for i:=2 to tcgsize2size[size] do
  652. // begin
  653. // case op of
  654. // OP_ROR,
  655. // OP_SHR:
  656. // list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  657. // OP_ROL,
  658. // OP_SHL:
  659. // list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)));
  660. // OP_SAR:
  661. // list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  662. // else
  663. // internalerror(2011030902);
  664. // end;
  665. // end;
  666. // end;
  667. //
  668. //list.concat(taicpu.op_reg(A_DEC,countreg));
  669. //a_jmp_flags(list,F_NE,l1);
  670. //// keep registers alive
  671. //list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  672. //cg.a_label(list,l2);
  673. end;
  674. OP_AND,OP_OR,OP_XOR:
  675. begin
  676. getcpuregister(list,NR_A);
  677. for i:=1 to tcgsize2size[size] do
  678. begin
  679. a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  680. list.concat(taicpu.op_reg_reg(topcg2asmop[op],NR_A,src));
  681. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  682. if i<>tcgsize2size[size] then
  683. NextSrcDst;
  684. end;
  685. ungetcpuregister(list,NR_A);
  686. end;
  687. else
  688. internalerror(2011022004);
  689. end;
  690. end;
  691. procedure tcgz80.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
  692. size: TCGSize; a: tcgint; reg, reghi: TRegister);
  693. var
  694. mask : qword;
  695. shift : byte;
  696. i,j : byte;
  697. tmpreg : tregister;
  698. tmpreg64 : tregister64;
  699. procedure NextReg;
  700. begin
  701. if i=4 then
  702. reg:=reghi
  703. else
  704. reg:=GetNextReg(reg);
  705. end;
  706. var
  707. curvalue : byte;
  708. tmpop: TAsmOp;
  709. begin
  710. optimize_op_const(size,op,a);
  711. mask:=$ff;
  712. shift:=0;
  713. case op of
  714. OP_NONE:
  715. begin
  716. { Opcode is optimized away }
  717. end;
  718. OP_MOVE:
  719. begin
  720. { Optimized, replaced with a simple load }
  721. a_load_const_reg(list,size,a,reg);
  722. end;
  723. OP_AND:
  724. begin
  725. curvalue:=a and mask;
  726. for i:=1 to tcgsize2size[size] do
  727. begin
  728. case curvalue of
  729. 0:
  730. list.concat(taicpu.op_reg_const(A_LD,reg,0));
  731. $ff:
  732. {nothing};
  733. else
  734. begin
  735. getcpuregister(list,NR_A);
  736. emit_mov(list,NR_A,reg);
  737. list.concat(taicpu.op_reg_const(A_AND,NR_A,curvalue));
  738. emit_mov(list,reg,NR_A);
  739. ungetcpuregister(list,NR_A);
  740. end;
  741. end;
  742. if i<>tcgsize2size[size] then
  743. begin
  744. NextReg;
  745. mask:=mask shl 8;
  746. inc(shift,8);
  747. curvalue:=(qword(a) and mask) shr shift;
  748. end;
  749. end;
  750. end;
  751. OP_OR:
  752. begin
  753. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_op_const_reg_internal, OP_OR')));
  754. //for i:=1 to tcgsize2size[size] do
  755. // begin
  756. // if ((qword(a) and mask) shr shift)<>0 then
  757. // list.concat(taicpu.op_reg_const(A_ORI,reg,(qword(a) and mask) shr shift));
  758. // NextReg;
  759. // mask:=mask shl 8;
  760. // inc(shift,8);
  761. // end;
  762. end;
  763. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  764. begin
  765. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_op_const_reg_internal, OP_shift/ror')));
  766. //if a*tcgsize2size[size]<=8 then
  767. // begin
  768. // for j:=1 to a do
  769. // begin
  770. // case op of
  771. // OP_SHR:
  772. // list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  773. // OP_SHL:
  774. // list.concat(taicpu.op_reg(A_LSL,reg));
  775. // OP_SAR:
  776. // list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  777. // OP_ROR:
  778. // begin
  779. // { load carry? }
  780. // if not(size in [OS_8,OS_S8]) then
  781. // begin
  782. // list.concat(taicpu.op_none(A_CLC));
  783. // list.concat(taicpu.op_reg_const(A_SBRC,reg,0));
  784. // list.concat(taicpu.op_none(A_SEC));
  785. // end;
  786. // list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  787. // end;
  788. // OP_ROL:
  789. // begin
  790. // { load carry? }
  791. // if not(size in [OS_8,OS_S8]) then
  792. // begin
  793. // list.concat(taicpu.op_none(A_CLC));
  794. // list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1),7));
  795. // list.concat(taicpu.op_none(A_SEC));
  796. // end;
  797. // list.concat(taicpu.op_reg(A_ROL,reg))
  798. // end;
  799. // else
  800. // internalerror(2011030901);
  801. // end;
  802. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  803. // begin
  804. // for i:=2 to tcgsize2size[size] do
  805. // begin
  806. // case op of
  807. // OP_ROR,
  808. // OP_SHR:
  809. // list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  810. // OP_ROL,
  811. // OP_SHL:
  812. // list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(reg,reghi,i-1)));
  813. // OP_SAR:
  814. // list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  815. // else
  816. // internalerror(2011030902);
  817. // end;
  818. // end;
  819. // end;
  820. // end;
  821. // end
  822. //else
  823. // begin
  824. // tmpreg:=getintregister(list,size);
  825. // a_load_const_reg(list,size,a,tmpreg);
  826. // a_op_reg_reg(list,op,size,tmpreg,reg);
  827. // end;
  828. end;
  829. OP_ADD:
  830. begin
  831. curvalue:=a and mask;
  832. tmpop:=A_NONE;
  833. for i:=1 to tcgsize2size[size] do
  834. begin
  835. if (tmpop=A_NONE) and (curvalue=1) and (i=tcgsize2size[size]) then
  836. tmpop:=A_INC
  837. else if (tmpop=A_NONE) and (curvalue<>0) then
  838. tmpop:=A_ADD
  839. else if tmpop=A_ADD then
  840. tmpop:=A_ADC;
  841. case tmpop of
  842. A_NONE:
  843. {nothing};
  844. A_INC:
  845. list.concat(taicpu.op_reg(tmpop,reg));
  846. A_ADD,A_ADC:
  847. begin
  848. getcpuregister(list,NR_A);
  849. emit_mov(list,NR_A,reg);
  850. list.concat(taicpu.op_reg_const(tmpop,NR_A,curvalue));
  851. emit_mov(list,reg,NR_A);
  852. ungetcpuregister(list,NR_A);
  853. end;
  854. else
  855. internalerror(2020040901);
  856. end;
  857. if i<>tcgsize2size[size] then
  858. begin
  859. NextReg;
  860. mask:=mask shl 8;
  861. inc(shift,8);
  862. curvalue:=(qword(a) and mask) shr shift;
  863. end;
  864. end;
  865. end;
  866. OP_SUB:
  867. begin
  868. curvalue:=a and mask;
  869. tmpop:=A_NONE;
  870. for i:=1 to tcgsize2size[size] do
  871. begin
  872. if (tmpop=A_NONE) and (curvalue=1) and (i=tcgsize2size[size]) then
  873. tmpop:=A_DEC
  874. else if (tmpop=A_NONE) and (curvalue<>0) then
  875. tmpop:=A_SUB
  876. else if tmpop=A_ADD then
  877. tmpop:=A_SBC;
  878. case tmpop of
  879. A_NONE:
  880. {nothing};
  881. A_DEC:
  882. list.concat(taicpu.op_reg(tmpop,reg));
  883. A_SUB,A_SBC:
  884. begin
  885. getcpuregister(list,NR_A);
  886. emit_mov(list,NR_A,reg);
  887. list.concat(taicpu.op_reg_const(tmpop,NR_A,curvalue));
  888. emit_mov(list,reg,NR_A);
  889. ungetcpuregister(list,NR_A);
  890. end;
  891. else
  892. internalerror(2020040902);
  893. end;
  894. if i<>tcgsize2size[size] then
  895. begin
  896. NextReg;
  897. mask:=mask shl 8;
  898. inc(shift,8);
  899. curvalue:=(qword(a) and mask) shr shift;
  900. end;
  901. end;
  902. end;
  903. else
  904. begin
  905. if size in [OS_64,OS_S64] then
  906. begin
  907. tmpreg64.reglo:=getintregister(list,OS_32);
  908. tmpreg64.reghi:=getintregister(list,OS_32);
  909. cg64.a_load64_const_reg(list,a,tmpreg64);
  910. cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
  911. end
  912. else
  913. begin
  914. {$if 0}
  915. { code not working yet }
  916. if (op=OP_SAR) and (a=31) and (size in [OS_32,OS_S32]) then
  917. begin
  918. tmpreg:=reg;
  919. for i:=1 to 4 do
  920. begin
  921. list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_R1));
  922. tmpreg:=GetNextReg(tmpreg);
  923. end;
  924. end
  925. else
  926. {$endif}
  927. begin
  928. tmpreg:=getintregister(list,size);
  929. a_load_const_reg(list,size,a,tmpreg);
  930. a_op_reg_reg(list,op,size,tmpreg,reg);
  931. end;
  932. end;
  933. end;
  934. end;
  935. end;
  936. procedure tcgz80.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
  937. var
  938. mask : qword;
  939. shift : byte;
  940. i : byte;
  941. begin
  942. mask:=$ff;
  943. shift:=0;
  944. for i:=tcgsize2size[size] downto 1 do
  945. begin
  946. list.Concat(taicpu.op_reg_const(A_LD,reg,(qword(a) and mask) shr shift));
  947. if i<>1 then
  948. begin
  949. mask:=mask shl 8;
  950. inc(shift,8);
  951. reg:=GetNextReg(reg);
  952. end;
  953. end;
  954. end;
  955. procedure tcgz80.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
  956. var
  957. mask : qword;
  958. shift : byte;
  959. href: treference;
  960. i: Integer;
  961. begin
  962. mask:=$ff;
  963. shift:=0;
  964. href:=ref;
  965. if (href.base=NR_NO) and (href.index<>NR_NO) then
  966. begin
  967. href.base:=href.index;
  968. href.index:=NR_NO;
  969. end;
  970. if not assigned(href.symbol) and
  971. ((href.base=NR_IX) or (href.base=NR_IY) or
  972. ((href.base=NR_HL) and (size in [OS_8,OS_S8]) and (href.offset=0))) then
  973. begin
  974. for i:=tcgsize2size[size] downto 1 do
  975. begin
  976. list.Concat(taicpu.op_ref_const(A_LD,href,(qword(a) and mask) shr shift));
  977. if i<>1 then
  978. begin
  979. mask:=mask shl 8;
  980. inc(shift,8);
  981. inc(href.offset);
  982. end;
  983. end;
  984. end
  985. else
  986. inherited;
  987. end;
  988. procedure tcgz80.maybegetcpuregister(list:tasmlist;reg : tregister);
  989. begin
  990. { allocate the register only, if a cpu register is passed }
  991. if getsupreg(reg)<first_int_imreg then
  992. getcpuregister(list,reg);
  993. end;
  994. function tcgz80.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
  995. var
  996. tmpref : treference;
  997. l : tasmlabel;
  998. begin
  999. Result:=ref;
  1000. //
  1001. // if ref.addressmode<>AM_UNCHANGED then
  1002. // internalerror(2011021701);
  1003. //
  1004. // { Be sure to have a base register }
  1005. // if (ref.base=NR_NO) then
  1006. // begin
  1007. // { only symbol+offset? }
  1008. // if ref.index=NR_NO then
  1009. // exit;
  1010. // ref.base:=ref.index;
  1011. // ref.index:=NR_NO;
  1012. // end;
  1013. //
  1014. // { can we take advantage of adiw/sbiw? }
  1015. // if (current_settings.cputype>=cpu_avr2) and not(assigned(ref.symbol)) and (ref.offset<>0) and (ref.offset>=-63) and (ref.offset<=63) and
  1016. // ((tmpreg=NR_R24) or (tmpreg=NR_R26) or (tmpreg=NR_R28) or (tmpreg=NR_R30)) and (ref.base<>NR_NO) then
  1017. // begin
  1018. // maybegetcpuregister(list,tmpreg);
  1019. // emit_mov(list,tmpreg,ref.base);
  1020. // maybegetcpuregister(list,GetNextReg(tmpreg));
  1021. // emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  1022. // if ref.index<>NR_NO then
  1023. // begin
  1024. // list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  1025. // list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  1026. // end;
  1027. // if ref.offset>0 then
  1028. // list.concat(taicpu.op_reg_const(A_ADIW,tmpreg,ref.offset))
  1029. // else
  1030. // list.concat(taicpu.op_reg_const(A_SBIW,tmpreg,-ref.offset));
  1031. // ref.offset:=0;
  1032. // ref.base:=tmpreg;
  1033. // ref.index:=NR_NO;
  1034. // end
  1035. // else if assigned(ref.symbol) or (ref.offset<>0) then
  1036. // begin
  1037. // reference_reset(tmpref,0,[]);
  1038. // tmpref.symbol:=ref.symbol;
  1039. // tmpref.offset:=ref.offset;
  1040. // if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1041. // tmpref.refaddr:=addr_lo8_gs
  1042. // else
  1043. // tmpref.refaddr:=addr_lo8;
  1044. // maybegetcpuregister(list,tmpreg);
  1045. // list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
  1046. //
  1047. // if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1048. // tmpref.refaddr:=addr_hi8_gs
  1049. // else
  1050. // tmpref.refaddr:=addr_hi8;
  1051. // maybegetcpuregister(list,GetNextReg(tmpreg));
  1052. // list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
  1053. //
  1054. // if (ref.base<>NR_NO) then
  1055. // begin
  1056. // list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  1057. // list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  1058. // end;
  1059. // if (ref.index<>NR_NO) then
  1060. // begin
  1061. // list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  1062. // list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  1063. // end;
  1064. // ref.symbol:=nil;
  1065. // ref.offset:=0;
  1066. // ref.base:=tmpreg;
  1067. // ref.index:=NR_NO;
  1068. // end
  1069. // else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
  1070. // begin
  1071. // maybegetcpuregister(list,tmpreg);
  1072. // emit_mov(list,tmpreg,ref.base);
  1073. // maybegetcpuregister(list,GetNextReg(tmpreg));
  1074. // emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  1075. // list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  1076. // list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  1077. // ref.base:=tmpreg;
  1078. // ref.index:=NR_NO;
  1079. // end
  1080. // else if (ref.base<>NR_NO) then
  1081. // begin
  1082. // maybegetcpuregister(list,tmpreg);
  1083. // emit_mov(list,tmpreg,ref.base);
  1084. // maybegetcpuregister(list,GetNextReg(tmpreg));
  1085. // emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  1086. // ref.base:=tmpreg;
  1087. // ref.index:=NR_NO;
  1088. // end
  1089. // else if (ref.index<>NR_NO) then
  1090. // begin
  1091. // maybegetcpuregister(list,tmpreg);
  1092. // emit_mov(list,tmpreg,ref.index);
  1093. // maybegetcpuregister(list,GetNextReg(tmpreg));
  1094. // emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
  1095. // ref.base:=tmpreg;
  1096. // ref.index:=NR_NO;
  1097. // end;
  1098. Result:=ref;
  1099. end;
  1100. procedure tcgz80.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  1101. var
  1102. href : treference;
  1103. i : integer;
  1104. begin
  1105. href:=Ref;
  1106. { ensure, href.base contains a valid register if there is any register used }
  1107. if href.base=NR_NO then
  1108. begin
  1109. href.base:=href.index;
  1110. href.index:=NR_NO;
  1111. end;
  1112. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1113. internalerror(2011021307);
  1114. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1115. internalerror(2020040802);
  1116. if (fromsize=tosize) or (fromsize in [OS_8,OS_16,OS_32]) then
  1117. begin
  1118. getcpuregister(list,NR_A);
  1119. for i:=1 to tcgsize2size[fromsize] do
  1120. begin
  1121. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1122. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1123. if i<>tcgsize2size[fromsize] then
  1124. reg:=GetNextReg(reg);
  1125. if i<>tcgsize2size[tosize] then
  1126. inc(href.offset);
  1127. end;
  1128. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1129. begin
  1130. if i=(tcgsize2size[fromsize]+1) then
  1131. list.concat(taicpu.op_reg_const(A_LD,NR_A,0));
  1132. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1133. if i<>tcgsize2size[tosize] then
  1134. begin
  1135. inc(href.offset);
  1136. reg:=GetNextReg(reg);
  1137. end;
  1138. end;
  1139. ungetcpuregister(list,NR_A);
  1140. end
  1141. else
  1142. begin
  1143. getcpuregister(list,NR_A);
  1144. for i:=1 to tcgsize2size[fromsize] do
  1145. begin
  1146. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1147. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1148. if i<>tcgsize2size[fromsize] then
  1149. reg:=GetNextReg(reg);
  1150. if i<>tcgsize2size[tosize] then
  1151. inc(href.offset);
  1152. end;
  1153. list.concat(taicpu.op_none(A_RLA));
  1154. list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1155. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1156. begin
  1157. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1158. if i<>tcgsize2size[tosize] then
  1159. begin
  1160. inc(href.offset);
  1161. reg:=GetNextReg(reg);
  1162. end;
  1163. end;
  1164. ungetcpuregister(list,NR_A);
  1165. end;
  1166. end;
  1167. procedure tcgz80.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1168. const Ref : treference;reg : tregister);
  1169. var
  1170. href : treference;
  1171. i : integer;
  1172. begin
  1173. href:=Ref;
  1174. { ensure, href.base contains a valid register if there is any register used }
  1175. if href.base=NR_NO then
  1176. begin
  1177. href.base:=href.index;
  1178. href.index:=NR_NO;
  1179. end;
  1180. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1181. internalerror(2011021307);
  1182. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1183. internalerror(2020040804);
  1184. if (tosize=fromsize) or (fromsize in [OS_8,OS_16,OS_32]) then
  1185. begin
  1186. getcpuregister(list,NR_A);
  1187. for i:=1 to tcgsize2size[fromsize] do
  1188. begin
  1189. list.concat(taicpu.op_reg_ref(A_LD,NR_A,href));
  1190. a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1191. if i<>tcgsize2size[fromsize] then
  1192. inc(href.offset);
  1193. if i<>tcgsize2size[tosize] then
  1194. reg:=GetNextReg(reg);
  1195. end;
  1196. ungetcpuregister(list,NR_A);
  1197. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1198. begin
  1199. list.concat(taicpu.op_reg_const(A_LD,reg,0));
  1200. if i<>tcgsize2size[tosize] then
  1201. reg:=GetNextReg(reg);
  1202. end;
  1203. end
  1204. else
  1205. begin
  1206. getcpuregister(list,NR_A);
  1207. for i:=1 to tcgsize2size[fromsize] do
  1208. begin
  1209. list.concat(taicpu.op_reg_ref(A_LD,NR_A,href));
  1210. a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1211. if i<>tcgsize2size[fromsize] then
  1212. inc(href.offset);
  1213. if i<>tcgsize2size[tosize] then
  1214. reg:=GetNextReg(reg);
  1215. end;
  1216. list.concat(taicpu.op_none(A_RLA));
  1217. list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1218. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1219. begin
  1220. emit_mov(list,reg,NR_A);
  1221. if i<>tcgsize2size[tosize] then
  1222. reg:=GetNextReg(reg);
  1223. end;
  1224. ungetcpuregister(list,NR_A);
  1225. end;
  1226. end;
  1227. procedure tcgz80.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1228. var
  1229. conv_done: boolean;
  1230. tmpreg : tregister;
  1231. i : integer;
  1232. begin
  1233. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1234. internalerror(2011021310);
  1235. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1236. fromsize:=tosize;
  1237. if (tosize=fromsize) or (fromsize in [OS_8,OS_16,OS_32]) then
  1238. begin
  1239. if reg1<>reg2 then
  1240. for i:=1 to tcgsize2size[fromsize] do
  1241. begin
  1242. emit_mov(list,reg2,reg1);
  1243. if i<>tcgsize2size[fromsize] then
  1244. reg1:=GetNextReg(reg1);
  1245. if i<>tcgsize2size[tosize] then
  1246. reg2:=GetNextReg(reg2);
  1247. end
  1248. else
  1249. for i:=1 to tcgsize2size[fromsize] do
  1250. if i<>tcgsize2size[tosize] then
  1251. reg2:=GetNextReg(reg2);
  1252. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1253. begin
  1254. list.Concat(taicpu.op_reg_const(A_LD,reg2,0));
  1255. if i<>tcgsize2size[tosize] then
  1256. reg2:=GetNextReg(reg2);
  1257. end
  1258. end
  1259. else
  1260. begin
  1261. if reg1<>reg2 then
  1262. for i:=1 to tcgsize2size[fromsize]-1 do
  1263. begin
  1264. emit_mov(list,reg2,reg1);
  1265. reg1:=GetNextReg(reg1);
  1266. reg2:=GetNextReg(reg2);
  1267. end
  1268. else
  1269. for i:=1 to tcgsize2size[fromsize]-1 do
  1270. reg2:=GetNextReg(reg2);
  1271. emit_mov(list,reg2,reg1);
  1272. getcpuregister(list,NR_A);
  1273. emit_mov(list,NR_A,reg2);
  1274. reg2:=GetNextReg(reg2);
  1275. list.concat(taicpu.op_none(A_RLA));
  1276. list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1277. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1278. begin
  1279. emit_mov(list,reg2,NR_A);
  1280. if i<>tcgsize2size[tosize] then
  1281. reg2:=GetNextReg(reg2);
  1282. end;
  1283. ungetcpuregister(list,NR_A);
  1284. end;
  1285. end;
  1286. procedure tcgz80.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1287. begin
  1288. internalerror(2012010702);
  1289. end;
  1290. procedure tcgz80.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1291. begin
  1292. internalerror(2012010703);
  1293. end;
  1294. procedure tcgz80.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1295. begin
  1296. internalerror(2012010704);
  1297. end;
  1298. { comparison operations }
  1299. procedure tcgz80.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1300. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1301. var
  1302. swapped : boolean;
  1303. tmpreg : tregister;
  1304. i : byte;
  1305. begin
  1306. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_cmp_const_reg_label')));
  1307. //if a=0 then
  1308. // begin
  1309. // swapped:=false;
  1310. // { swap parameters? }
  1311. // case cmp_op of
  1312. // OC_GT:
  1313. // begin
  1314. // swapped:=true;
  1315. // cmp_op:=OC_LT;
  1316. // end;
  1317. // OC_LTE:
  1318. // begin
  1319. // swapped:=true;
  1320. // cmp_op:=OC_GTE;
  1321. // end;
  1322. // OC_BE:
  1323. // begin
  1324. // swapped:=true;
  1325. // cmp_op:=OC_AE;
  1326. // end;
  1327. // OC_A:
  1328. // begin
  1329. // swapped:=true;
  1330. // cmp_op:=OC_B;
  1331. // end;
  1332. // end;
  1333. //
  1334. // if swapped then
  1335. // list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg))
  1336. // else
  1337. // list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
  1338. //
  1339. // for i:=2 to tcgsize2size[size] do
  1340. // begin
  1341. // reg:=GetNextReg(reg);
  1342. // if swapped then
  1343. // list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg))
  1344. // else
  1345. // list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1));
  1346. // end;
  1347. //
  1348. // a_jmp_cond(list,cmp_op,l);
  1349. // end
  1350. //else
  1351. // inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
  1352. end;
  1353. procedure tcgz80.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1354. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1355. var
  1356. swapped : boolean;
  1357. tmpreg : tregister;
  1358. i : byte;
  1359. begin
  1360. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_cmp_reg_reg_label')));
  1361. //swapped:=false;
  1362. //{ swap parameters? }
  1363. //case cmp_op of
  1364. // OC_GT:
  1365. // begin
  1366. // swapped:=true;
  1367. // cmp_op:=OC_LT;
  1368. // end;
  1369. // OC_LTE:
  1370. // begin
  1371. // swapped:=true;
  1372. // cmp_op:=OC_GTE;
  1373. // end;
  1374. // OC_BE:
  1375. // begin
  1376. // swapped:=true;
  1377. // cmp_op:=OC_AE;
  1378. // end;
  1379. // OC_A:
  1380. // begin
  1381. // swapped:=true;
  1382. // cmp_op:=OC_B;
  1383. // end;
  1384. //end;
  1385. //if swapped then
  1386. // begin
  1387. // tmpreg:=reg1;
  1388. // reg1:=reg2;
  1389. // reg2:=tmpreg;
  1390. // end;
  1391. //list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1392. //
  1393. //for i:=2 to tcgsize2size[size] do
  1394. // begin
  1395. // reg1:=GetNextReg(reg1);
  1396. // reg2:=GetNextReg(reg2);
  1397. // list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1398. // end;
  1399. //
  1400. //a_jmp_cond(list,cmp_op,l);
  1401. end;
  1402. procedure tcgz80.a_jmp_name(list : TAsmList;const s : string);
  1403. var
  1404. ai : taicpu;
  1405. begin
  1406. ai:=taicpu.op_sym(A_JP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1407. ai.is_jmp:=true;
  1408. list.concat(ai);
  1409. end;
  1410. procedure tcgz80.a_jmp_always(list : TAsmList;l: tasmlabel);
  1411. var
  1412. ai : taicpu;
  1413. begin
  1414. ai:=taicpu.op_sym(A_JP,l);
  1415. ai.is_jmp:=true;
  1416. list.concat(ai);
  1417. end;
  1418. procedure tcgz80.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1419. var
  1420. ai : taicpu;
  1421. begin
  1422. ai:=taicpu.op_cond_sym(A_JP,flags_to_cond(f),l);
  1423. ai.is_jmp:=true;
  1424. list.concat(ai);
  1425. end;
  1426. procedure tcgz80.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1427. var
  1428. l : TAsmLabel;
  1429. tmpflags : TResFlags;
  1430. begin
  1431. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: g_flags2reg')));
  1432. current_asmdata.getjumplabel(l);
  1433. {
  1434. if flags_to_cond(f) then
  1435. begin
  1436. tmpflags:=f;
  1437. inverse_flags(tmpflags);
  1438. emit_mov(reg,NR_R1);
  1439. a_jmp_flags(list,tmpflags,l);
  1440. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1441. end
  1442. else
  1443. }
  1444. begin
  1445. //list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1446. //a_jmp_flags(list,f,l);
  1447. //emit_mov(list,reg,NR_R1);
  1448. end;
  1449. cg.a_label(list,l);
  1450. end;
  1451. procedure tcgz80.g_stackpointer_alloc(list: TAsmList; localsize: longint);
  1452. begin
  1453. if localsize>0 then
  1454. begin
  1455. list.Concat(taicpu.op_reg_const(A_LD,NR_HL,-localsize));
  1456. list.Concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_SP));
  1457. list.Concat(taicpu.op_reg_reg(A_LD,NR_SP,NR_HL));
  1458. end;
  1459. end;
  1460. procedure tcgz80.a_adjust_sp(list : TAsmList; value : longint);
  1461. var
  1462. i : integer;
  1463. begin
  1464. //case value of
  1465. // 0:
  1466. // ;
  1467. // {-14..-1:
  1468. // begin
  1469. // if ((-value) mod 2)<>0 then
  1470. // list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  1471. // for i:=1 to (-value) div 2 do
  1472. // list.concat(taicpu.op_const(A_RCALL,0));
  1473. // end;
  1474. // 1..7:
  1475. // begin
  1476. // for i:=1 to value do
  1477. // list.concat(taicpu.op_reg(A_POP,NR_R0));
  1478. // end;}
  1479. // else
  1480. // begin
  1481. // list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1482. // list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1483. // // get SREG
  1484. // list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  1485. //
  1486. // // block interrupts
  1487. // list.concat(taicpu.op_none(A_CLI));
  1488. //
  1489. // // write high SP
  1490. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1491. //
  1492. // // release interrupts
  1493. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  1494. //
  1495. // // write low SP
  1496. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1497. // end;
  1498. //end;
  1499. end;
  1500. procedure tcgz80.make_simple_ref(list: TAsmList; var ref: treference);
  1501. begin
  1502. end;
  1503. procedure tcgz80.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1504. var
  1505. regsize,stackmisalignment: longint;
  1506. begin
  1507. regsize:=0;
  1508. stackmisalignment:=0;
  1509. { save old framepointer }
  1510. if not nostackframe then
  1511. begin
  1512. { return address }
  1513. inc(stackmisalignment,2);
  1514. list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
  1515. if current_procinfo.framepointer=NR_FRAME_POINTER_REG then
  1516. begin
  1517. { push <frame_pointer> }
  1518. inc(stackmisalignment,2);
  1519. include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
  1520. list.concat(Taicpu.op_reg(A_PUSH,NR_FRAME_POINTER_REG));
  1521. { Return address and FP are both on stack }
  1522. current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*2);
  1523. current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*2));
  1524. if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then
  1525. begin
  1526. list.concat(Taicpu.op_reg_const(A_LD,NR_FRAME_POINTER_REG,0));
  1527. list.concat(Taicpu.op_reg_reg(A_ADD,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG))
  1528. end
  1529. else
  1530. begin
  1531. internalerror(2020040301);
  1532. (*push_regs;
  1533. gen_load_frame_for_exceptfilter(list);
  1534. { Need only as much stack space as necessary to do the calls.
  1535. Exception filters don't have own local vars, and temps are 'mapped'
  1536. to the parent procedure.
  1537. maxpushedparasize is already aligned at least on x86_64. }
  1538. localsize:=current_procinfo.maxpushedparasize;*)
  1539. end;
  1540. current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG);
  1541. end
  1542. else
  1543. begin
  1544. CGmessage(cg_d_stackframe_omited);
  1545. end;
  1546. { allocate stackframe space }
  1547. if (localsize<>0) or
  1548. ((target_info.stackalign>sizeof(pint)) and
  1549. (stackmisalignment <> 0) and
  1550. ((pi_do_call in current_procinfo.flags) or
  1551. (po_assembler in current_procinfo.procdef.procoptions))) then
  1552. begin
  1553. if target_info.stackalign>sizeof(pint) then
  1554. localsize := align(localsize+stackmisalignment,target_info.stackalign)-stackmisalignment;
  1555. g_stackpointer_alloc(list,localsize);
  1556. if current_procinfo.framepointer=NR_STACK_POINTER_REG then
  1557. current_asmdata.asmcfi.cfa_def_cfa_offset(list,regsize+localsize+sizeof(pint));
  1558. current_procinfo.final_localsize:=localsize;
  1559. end
  1560. end;
  1561. end;
  1562. procedure tcgz80.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  1563. var
  1564. regs : tcpuregisterset;
  1565. reg : TSuperRegister;
  1566. LocalSize : longint;
  1567. begin
  1568. { every byte counts for Z80, so if a subroutine is marked as non-returning, we do
  1569. not generate any exit code, so we really trust the noreturn directive
  1570. }
  1571. if po_noreturn in current_procinfo.procdef.procoptions then
  1572. exit;
  1573. { remove stackframe }
  1574. if not nostackframe then
  1575. begin
  1576. stacksize:=current_procinfo.calc_stackframe_size;
  1577. if (target_info.stackalign>4) and
  1578. ((stacksize <> 0) or
  1579. (pi_do_call in current_procinfo.flags) or
  1580. { can't detect if a call in this case -> use nostackframe }
  1581. { if you (think you) know what you are doing }
  1582. (po_assembler in current_procinfo.procdef.procoptions)) then
  1583. stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint);
  1584. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  1585. begin
  1586. internalerror(2020040302);
  1587. {if (stacksize<>0) then
  1588. cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);}
  1589. end
  1590. else
  1591. begin
  1592. list.Concat(taicpu.op_reg_reg(A_LD,NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG));
  1593. list.Concat(taicpu.op_reg(A_POP,NR_FRAME_POINTER_REG));
  1594. end;
  1595. list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
  1596. end;
  1597. list.concat(taicpu.op_none(A_RET));
  1598. end;
  1599. procedure tcgz80.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  1600. var
  1601. tmpref : treference;
  1602. begin
  1603. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_loadaddr_ref_reg')));
  1604. // if ref.addressmode<>AM_UNCHANGED then
  1605. // internalerror(2011021701);
  1606. //
  1607. //if assigned(ref.symbol) or (ref.offset<>0) then
  1608. // begin
  1609. // reference_reset(tmpref,0,[]);
  1610. // tmpref.symbol:=ref.symbol;
  1611. // tmpref.offset:=ref.offset;
  1612. //
  1613. // if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1614. // tmpref.refaddr:=addr_lo8_gs
  1615. // else
  1616. // tmpref.refaddr:=addr_lo8;
  1617. // list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref));
  1618. //
  1619. // if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1620. // tmpref.refaddr:=addr_hi8_gs
  1621. // else
  1622. // tmpref.refaddr:=addr_hi8;
  1623. // list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref));
  1624. //
  1625. // if (ref.base<>NR_NO) then
  1626. // begin
  1627. // list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
  1628. // list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
  1629. // end;
  1630. // if (ref.index<>NR_NO) then
  1631. // begin
  1632. // list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1633. // list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1634. // end;
  1635. // end
  1636. //else if (ref.base<>NR_NO)then
  1637. // begin
  1638. // emit_mov(list,r,ref.base);
  1639. // emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
  1640. // if (ref.index<>NR_NO) then
  1641. // begin
  1642. // list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1643. // list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1644. // end;
  1645. // end
  1646. //else if (ref.index<>NR_NO) then
  1647. // begin
  1648. // emit_mov(list,r,ref.index);
  1649. // emit_mov(list,GetNextReg(r),GetNextReg(ref.index));
  1650. // end;
  1651. end;
  1652. procedure tcgz80.fixref(list : TAsmList;var ref : treference);
  1653. begin
  1654. internalerror(2011021320);
  1655. end;
  1656. procedure tcgz80.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  1657. var
  1658. paraloc1,paraloc2,paraloc3 : TCGPara;
  1659. pd : tprocdef;
  1660. begin
  1661. pd:=search_system_proc('MOVE');
  1662. paraloc1.init;
  1663. paraloc2.init;
  1664. paraloc3.init;
  1665. {$warning TODO: implement!!!}
  1666. //paramanager.getintparaloc(list,pd,1,paraloc1);
  1667. //paramanager.getintparaloc(list,pd,2,paraloc2);
  1668. //paramanager.getintparaloc(list,pd,3,paraloc3);
  1669. a_load_const_cgpara(list,OS_SINT,len,paraloc3);
  1670. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  1671. a_loadaddr_ref_cgpara(list,source,paraloc1);
  1672. paramanager.freecgpara(list,paraloc3);
  1673. paramanager.freecgpara(list,paraloc2);
  1674. paramanager.freecgpara(list,paraloc1);
  1675. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1676. a_call_name_static(list,'FPC_MOVE');
  1677. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1678. paraloc3.done;
  1679. paraloc2.done;
  1680. paraloc1.done;
  1681. end;
  1682. procedure tcgz80.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  1683. var
  1684. countreg,tmpreg : tregister;
  1685. srcref,dstref : treference;
  1686. copysize,countregsize : tcgsize;
  1687. l : TAsmLabel;
  1688. i : longint;
  1689. SrcQuickRef, DestQuickRef : Boolean;
  1690. begin
  1691. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: g_concatcopy')));
  1692. //if len>16 then
  1693. // begin
  1694. // current_asmdata.getjumplabel(l);
  1695. //
  1696. // reference_reset(srcref,source.alignment,source.volatility);
  1697. // reference_reset(dstref,dest.alignment,source.volatility);
  1698. // srcref.base:=NR_R30;
  1699. // srcref.addressmode:=AM_POSTINCREMENT;
  1700. // dstref.base:=NR_R26;
  1701. // dstref.addressmode:=AM_POSTINCREMENT;
  1702. //
  1703. // copysize:=OS_8;
  1704. // if len<256 then
  1705. // countregsize:=OS_8
  1706. // else if len<65536 then
  1707. // countregsize:=OS_16
  1708. // else
  1709. // internalerror(2011022007);
  1710. // countreg:=getintregister(list,countregsize);
  1711. // a_load_const_reg(list,countregsize,len,countreg);
  1712. // a_loadaddr_ref_reg(list,source,NR_R30);
  1713. //
  1714. // { only base or index register in dest? }
  1715. // if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1716. // ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1717. // begin
  1718. // if dest.base<>NR_NO then
  1719. // tmpreg:=dest.base
  1720. // else if dest.index<>NR_NO then
  1721. // tmpreg:=dest.index
  1722. // else
  1723. // internalerror(2016112001);
  1724. // end
  1725. // else
  1726. // begin
  1727. // tmpreg:=getaddressregister(list);
  1728. // a_loadaddr_ref_reg(list,dest,tmpreg);
  1729. // end;
  1730. //
  1731. // { X is used for spilling code so we can load it
  1732. // only by a push/pop sequence, this can be
  1733. // optimized later on by the peephole optimizer
  1734. // }
  1735. // list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1736. // list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1737. // list.concat(taicpu.op_reg(A_POP,NR_R27));
  1738. // list.concat(taicpu.op_reg(A_POP,NR_R26));
  1739. // cg.a_label(list,l);
  1740. // list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  1741. // list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  1742. // list.concat(taicpu.op_reg(A_DEC,countreg));
  1743. // a_jmp_flags(list,F_NE,l);
  1744. // // keep registers alive
  1745. // list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  1746. // end
  1747. //else
  1748. // begin
  1749. // SrcQuickRef:=false;
  1750. // DestQuickRef:=false;
  1751. // if not((source.addressmode=AM_UNCHANGED) and
  1752. // (source.symbol=nil) and
  1753. // ((source.base=NR_R28) or
  1754. // (source.base=NR_R30)) and
  1755. // (source.Index=NR_NO) and
  1756. // (source.Offset in [0..64-len])) and
  1757. // not((source.Base=NR_NO) and (source.Index=NR_NO)) then
  1758. // srcref:=normalize_ref(list,source,NR_R30)
  1759. // else
  1760. // begin
  1761. // SrcQuickRef:=true;
  1762. // srcref:=source;
  1763. // end;
  1764. //
  1765. // if not((dest.addressmode=AM_UNCHANGED) and
  1766. // (dest.symbol=nil) and
  1767. // ((dest.base=NR_R28) or
  1768. // (dest.base=NR_R30)) and
  1769. // (dest.Index=NR_No) and
  1770. // (dest.Offset in [0..64-len])) and
  1771. // not((dest.Base=NR_NO) and (dest.Index=NR_NO)) then
  1772. // begin
  1773. // if not(SrcQuickRef) then
  1774. // begin
  1775. // { only base or index register in dest? }
  1776. // if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1777. // ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1778. // begin
  1779. // if dest.base<>NR_NO then
  1780. // tmpreg:=dest.base
  1781. // else if dest.index<>NR_NO then
  1782. // tmpreg:=dest.index
  1783. // else
  1784. // internalerror(2016112002);
  1785. // end
  1786. // else
  1787. // tmpreg:=getaddressregister(list);
  1788. //
  1789. // dstref:=normalize_ref(list,dest,tmpreg);
  1790. //
  1791. // { X is used for spilling code so we can load it
  1792. // only by a push/pop sequence, this can be
  1793. // optimized later on by the peephole optimizer
  1794. // }
  1795. // list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1796. // list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1797. // list.concat(taicpu.op_reg(A_POP,NR_R27));
  1798. // list.concat(taicpu.op_reg(A_POP,NR_R26));
  1799. // dstref.base:=NR_R26;
  1800. // end
  1801. // else
  1802. // dstref:=normalize_ref(list,dest,NR_R30);
  1803. // end
  1804. // else
  1805. // begin
  1806. // DestQuickRef:=true;
  1807. // dstref:=dest;
  1808. // end;
  1809. //
  1810. // for i:=1 to len do
  1811. // begin
  1812. // if not(SrcQuickRef) and (i<len) then
  1813. // srcref.addressmode:=AM_POSTINCREMENT
  1814. // else
  1815. // srcref.addressmode:=AM_UNCHANGED;
  1816. //
  1817. // if not(DestQuickRef) and (i<len) then
  1818. // dstref.addressmode:=AM_POSTINCREMENT
  1819. // else
  1820. // dstref.addressmode:=AM_UNCHANGED;
  1821. //
  1822. // list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  1823. // list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  1824. //
  1825. // if SrcQuickRef then
  1826. // inc(srcref.offset);
  1827. // if DestQuickRef then
  1828. // inc(dstref.offset);
  1829. // end;
  1830. // if not(SrcQuickRef) then
  1831. // begin
  1832. // ungetcpuregister(list,srcref.base);
  1833. // ungetcpuregister(list,GetNextReg(srcref.base));
  1834. // end;
  1835. // end;
  1836. end;
  1837. procedure tcgz80.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
  1838. var
  1839. hl : tasmlabel;
  1840. ai : taicpu;
  1841. cond : TAsmCond;
  1842. begin
  1843. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: g_overflowCheck')));
  1844. //if not(cs_check_overflow in current_settings.localswitches) then
  1845. // exit;
  1846. //current_asmdata.getjumplabel(hl);
  1847. //if not ((def.typ=pointerdef) or
  1848. // ((def.typ=orddef) and
  1849. // (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  1850. // pasbool8,pasbool16,pasbool32,pasbool64]))) then
  1851. // cond:=C_VC
  1852. //else
  1853. // cond:=C_CC;
  1854. //ai:=Taicpu.Op_Sym(A_BRxx,hl);
  1855. //ai.SetCondition(cond);
  1856. //ai.is_jmp:=true;
  1857. //list.concat(ai);
  1858. //
  1859. //a_call_name(list,'FPC_OVERFLOW',false);
  1860. //a_label(list,hl);
  1861. end;
  1862. procedure tcgz80.g_save_registers(list: TAsmList);
  1863. begin
  1864. { this is done by the entry code }
  1865. end;
  1866. procedure tcgz80.g_restore_registers(list: TAsmList);
  1867. begin
  1868. { this is done by the exit code }
  1869. end;
  1870. procedure tcgz80.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  1871. var
  1872. ai1,ai2 : taicpu;
  1873. hl : TAsmLabel;
  1874. begin
  1875. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_jmp_cond')));
  1876. //ai1:=Taicpu.Op_sym(A_BRxx,l);
  1877. //ai1.is_jmp:=true;
  1878. //hl:=nil;
  1879. //case cond of
  1880. // OC_EQ:
  1881. // ai1.SetCondition(C_EQ);
  1882. // OC_GT:
  1883. // begin
  1884. // { emulate GT }
  1885. // current_asmdata.getjumplabel(hl);
  1886. // ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  1887. // ai2.SetCondition(C_EQ);
  1888. // ai2.is_jmp:=true;
  1889. // list.concat(ai2);
  1890. //
  1891. // ai1.SetCondition(C_GE);
  1892. // end;
  1893. // OC_LT:
  1894. // ai1.SetCondition(C_LT);
  1895. // OC_GTE:
  1896. // ai1.SetCondition(C_GE);
  1897. // OC_LTE:
  1898. // begin
  1899. // { emulate LTE }
  1900. // ai2:=Taicpu.Op_Sym(A_BRxx,l);
  1901. // ai2.SetCondition(C_EQ);
  1902. // ai2.is_jmp:=true;
  1903. // list.concat(ai2);
  1904. //
  1905. // ai1.SetCondition(C_LT);
  1906. // end;
  1907. // OC_NE:
  1908. // ai1.SetCondition(C_NE);
  1909. // OC_BE:
  1910. // begin
  1911. // { emulate BE }
  1912. // ai2:=Taicpu.Op_Sym(A_BRxx,l);
  1913. // ai2.SetCondition(C_EQ);
  1914. // ai2.is_jmp:=true;
  1915. // list.concat(ai2);
  1916. //
  1917. // ai1.SetCondition(C_LO);
  1918. // end;
  1919. // OC_B:
  1920. // ai1.SetCondition(C_LO);
  1921. // OC_AE:
  1922. // ai1.SetCondition(C_SH);
  1923. // OC_A:
  1924. // begin
  1925. // { emulate A (unsigned GT) }
  1926. // current_asmdata.getjumplabel(hl);
  1927. // ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  1928. // ai2.SetCondition(C_EQ);
  1929. // ai2.is_jmp:=true;
  1930. // list.concat(ai2);
  1931. //
  1932. // ai1.SetCondition(C_SH);
  1933. // end;
  1934. // else
  1935. // internalerror(2011082501);
  1936. //end;
  1937. //list.concat(ai1);
  1938. //if assigned(hl) then
  1939. // a_label(list,hl);
  1940. end;
  1941. procedure tcgz80.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  1942. var
  1943. instr: taicpu;
  1944. begin
  1945. instr:=taicpu.op_reg_reg(A_LD,reg2,reg1);
  1946. list.Concat(instr);
  1947. { Notify the register allocator that we have written a move instruction so
  1948. it can try to eliminate it. }
  1949. add_move_instruction(instr);
  1950. end;
  1951. procedure tcg64fz80.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  1952. begin
  1953. if not(size in [OS_S64,OS_64]) then
  1954. internalerror(2012102402);
  1955. tcgz80(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  1956. end;
  1957. procedure tcg64fz80.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  1958. begin
  1959. tcgz80(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  1960. end;
  1961. function GetByteLoc(const loc : tlocation; nr : byte) : tlocation;
  1962. var
  1963. i : Integer;
  1964. begin
  1965. Result:=loc;
  1966. Result.size:=OS_8;
  1967. case loc.loc of
  1968. LOC_REFERENCE,LOC_CREFERENCE:
  1969. inc(Result.reference.offset,nr);
  1970. LOC_REGISTER,LOC_CREGISTER:
  1971. begin
  1972. if nr>=4 then
  1973. Result.register:=Result.register64.reghi;
  1974. nr:=nr mod 4;
  1975. for i:=1 to nr do
  1976. Result.register:=GetNextReg(Result.register);
  1977. end;
  1978. LOC_CONSTANT:
  1979. if loc.size in [OS_64,OS_S64] then
  1980. Result.value:=(Result.value64 shr (nr*8)) and $ff
  1981. else
  1982. Result.value:=(Result.value shr (nr*8)) and $ff;
  1983. else
  1984. Internalerror(2019020902);
  1985. end;
  1986. end;
  1987. procedure create_codegen;
  1988. begin
  1989. cg:=tcgz80.create;
  1990. cg64:=tcg64fz80.create;
  1991. end;
  1992. end.