cgcpu.pas 87 KB

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