cgcpu.pas 84 KB

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