cgcpu.pas 88 KB

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