cgcpu.pas 75 KB

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