cgcpu.pas 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381
  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. tmpl: TAsmLabel;
  1421. begin
  1422. if size in [OS_8,OS_S8]then
  1423. begin
  1424. if cmp_op in [OC_EQ,OC_NE,OC_B,OC_AE] then
  1425. begin
  1426. getcpuregister(list,NR_A);
  1427. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1428. list.concat(taicpu.op_reg_const(A_CP,NR_A,a));
  1429. case cmp_op of
  1430. OC_EQ:
  1431. a_jmp_flags(list,F_E,l);
  1432. OC_NE:
  1433. a_jmp_flags(list,F_NE,l);
  1434. OC_B:
  1435. a_jmp_flags(list,F_C,l);
  1436. OC_AE:
  1437. a_jmp_flags(list,F_NC,l);
  1438. else
  1439. internalerror(2020042206);
  1440. end;
  1441. ungetcpuregister(list,NR_A);
  1442. end
  1443. else if cmp_op in [OC_A,OC_BE] then
  1444. begin
  1445. getcpuregister(list,NR_A);
  1446. a_load_const_reg(list,OS_8,a,NR_A);
  1447. list.concat(taicpu.op_reg_reg(A_CP,NR_A,reg));
  1448. case cmp_op of
  1449. OC_A:
  1450. a_jmp_flags(list,F_C,l);
  1451. OC_BE:
  1452. a_jmp_flags(list,F_NC,l);
  1453. else
  1454. internalerror(2020042206);
  1455. end;
  1456. ungetcpuregister(list,NR_A);
  1457. end
  1458. else if cmp_op in [OC_LT,OC_GTE] then
  1459. begin
  1460. getcpuregister(list,NR_A);
  1461. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1462. list.concat(taicpu.op_reg_const(A_SUB,NR_A,a));
  1463. current_asmdata.getjumplabel(tmpl);
  1464. a_jmp_flags(list,F_PO,tmpl);
  1465. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1466. cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1467. case cmp_op of
  1468. OC_LT:
  1469. a_jmp_flags(list,F_M,l);
  1470. OC_GTE:
  1471. a_jmp_flags(list,F_P,l);
  1472. else
  1473. internalerror(2020042206);
  1474. end;
  1475. ungetcpuregister(list,NR_A);
  1476. end
  1477. else if cmp_op in [OC_GT,OC_LTE] then
  1478. begin
  1479. getcpuregister(list,NR_A);
  1480. a_load_const_reg(list,OS_8,a,NR_A);
  1481. list.concat(taicpu.op_reg_reg(A_SUB,NR_A,reg));
  1482. current_asmdata.getjumplabel(tmpl);
  1483. a_jmp_flags(list,F_PO,tmpl);
  1484. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1485. cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1486. case cmp_op of
  1487. OC_GT:
  1488. a_jmp_flags(list,F_M,l);
  1489. OC_LTE:
  1490. a_jmp_flags(list,F_P,l);
  1491. else
  1492. internalerror(2020042206);
  1493. end;
  1494. ungetcpuregister(list,NR_A);
  1495. end;
  1496. end
  1497. else if cmp_op in [OC_EQ,OC_NE] then
  1498. begin
  1499. if cmp_op=OC_EQ then
  1500. current_asmdata.getjumplabel(tmpl);
  1501. for i:=0 to tcgsize2size[size]-1 do
  1502. begin
  1503. a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg(reg,i),NR_A);
  1504. list.concat(taicpu.op_reg_const(A_CP,NR_A,Byte(a shr (8*i))));
  1505. case cmp_op of
  1506. OC_EQ:
  1507. if i<>(tcgsize2size[size]-1) then
  1508. a_jmp_flags(list,F_NE,tmpl)
  1509. else
  1510. a_jmp_flags(list,F_E,l);
  1511. OC_NE:
  1512. a_jmp_flags(list,F_NE,l);
  1513. else
  1514. internalerror(2020042206);
  1515. end;
  1516. end;
  1517. if cmp_op=OC_EQ then
  1518. cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1519. end
  1520. else if cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE,OC_BE,OC_B,OC_AE,OC_A] then
  1521. begin
  1522. { todo: implement these }
  1523. internalerror(2020042207);
  1524. end
  1525. else
  1526. internalerror(2020042205);
  1527. end;
  1528. procedure tcgz80.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1529. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1530. var
  1531. swapped : boolean;
  1532. tmpreg : tregister;
  1533. i : byte;
  1534. begin
  1535. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_cmp_reg_reg_label')));
  1536. //swapped:=false;
  1537. //{ swap parameters? }
  1538. //case cmp_op of
  1539. // OC_GT:
  1540. // begin
  1541. // swapped:=true;
  1542. // cmp_op:=OC_LT;
  1543. // end;
  1544. // OC_LTE:
  1545. // begin
  1546. // swapped:=true;
  1547. // cmp_op:=OC_GTE;
  1548. // end;
  1549. // OC_BE:
  1550. // begin
  1551. // swapped:=true;
  1552. // cmp_op:=OC_AE;
  1553. // end;
  1554. // OC_A:
  1555. // begin
  1556. // swapped:=true;
  1557. // cmp_op:=OC_B;
  1558. // end;
  1559. //end;
  1560. //if swapped then
  1561. // begin
  1562. // tmpreg:=reg1;
  1563. // reg1:=reg2;
  1564. // reg2:=tmpreg;
  1565. // end;
  1566. //list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1567. //
  1568. //for i:=2 to tcgsize2size[size] do
  1569. // begin
  1570. // reg1:=GetNextReg(reg1);
  1571. // reg2:=GetNextReg(reg2);
  1572. // list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1573. // end;
  1574. //
  1575. //a_jmp_cond(list,cmp_op,l);
  1576. end;
  1577. procedure tcgz80.a_jmp_name(list : TAsmList;const s : string);
  1578. var
  1579. ai : taicpu;
  1580. begin
  1581. ai:=taicpu.op_sym(A_JP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1582. ai.is_jmp:=true;
  1583. list.concat(ai);
  1584. end;
  1585. procedure tcgz80.a_jmp_always(list : TAsmList;l: tasmlabel);
  1586. var
  1587. ai : taicpu;
  1588. begin
  1589. ai:=taicpu.op_sym(A_JP,l);
  1590. ai.is_jmp:=true;
  1591. list.concat(ai);
  1592. end;
  1593. procedure tcgz80.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1594. var
  1595. ai : taicpu;
  1596. begin
  1597. ai:=taicpu.op_cond_sym(A_JP,flags_to_cond(f),l);
  1598. ai.is_jmp:=true;
  1599. list.concat(ai);
  1600. end;
  1601. procedure tcgz80.a_jmp_unsigned_cmp_3way(list: TAsmList; onbelow, onequal, onabove: tasmlabel);
  1602. var
  1603. skiplabel: TAsmLabel;
  1604. begin
  1605. if (onbelow= nil) and (onequal= nil) and (onabove= nil) then
  1606. {nothing}
  1607. else if (onbelow= nil) and (onequal= nil) and (onabove<>nil) then
  1608. begin
  1609. current_asmdata.getjumplabel(skiplabel);
  1610. a_jmp_flags(list,F_E,skiplabel);
  1611. a_jmp_flags(list,F_NC,onabove);
  1612. cg.a_label(list,skiplabel);
  1613. end
  1614. else if (onbelow= nil) and (onequal<>nil) and (onabove= nil) then
  1615. a_jmp_flags(list,F_E,onequal)
  1616. else if (onbelow= nil) and (onequal<>nil) and (onabove<>nil) then
  1617. begin
  1618. if onequal<>onabove then
  1619. a_jmp_flags(list,F_E,onequal);
  1620. a_jmp_flags(list,F_NC,onabove);
  1621. end
  1622. else if (onbelow<>nil) and (onequal= nil) and (onabove= nil) then
  1623. a_jmp_flags(list,F_C,onbelow)
  1624. else if (onbelow<>nil) and (onequal= nil) and (onabove<>nil) then
  1625. begin
  1626. if onbelow<>onabove then
  1627. a_jmp_flags(list,F_C,onbelow);
  1628. a_jmp_flags(list,F_NE,onabove);
  1629. end
  1630. else if (onbelow<>nil) and (onequal<>nil) and (onabove= nil) then
  1631. begin
  1632. a_jmp_flags(list,F_C,onbelow);
  1633. a_jmp_flags(list,F_E,onequal);
  1634. end
  1635. else if (onbelow<>nil) and (onequal<>nil) and (onabove<>nil) then
  1636. begin
  1637. if (onbelow=onequal) and (onequal=onabove) then
  1638. a_jmp_always(list,onbelow)
  1639. else if onequal=onabove then
  1640. begin
  1641. a_jmp_flags(list,F_C,onbelow);
  1642. a_jmp_always(list,onabove);
  1643. end
  1644. else if onbelow=onequal then
  1645. begin
  1646. a_jmp_flags(list,F_C,onbelow);
  1647. a_jmp_flags(list,F_E,onequal);
  1648. a_jmp_always(list,onabove);
  1649. end
  1650. else if onbelow=onabove then
  1651. begin
  1652. a_jmp_flags(list,F_E,onequal);
  1653. a_jmp_always(list,onabove);
  1654. end
  1655. else
  1656. begin
  1657. { the generic case - all 3 are different labels }
  1658. a_jmp_flags(list,F_C,onbelow);
  1659. a_jmp_flags(list,F_E,onequal);
  1660. a_jmp_always(list,onabove);
  1661. end;
  1662. end
  1663. else
  1664. begin
  1665. { Shouldn't happen! All possible combinations are handled by the above code. }
  1666. internalerror(2020042201);
  1667. end;
  1668. end;
  1669. procedure tcgz80.a_jmp_signed_cmp_3way(list: TAsmList; onless, onequal, ongreater: tasmlabel);
  1670. var
  1671. l, skiplabel: TAsmLabel;
  1672. begin
  1673. if (onless= nil) and (onequal= nil) and (ongreater= nil) then
  1674. {nothing}
  1675. else if (onless= nil) and (onequal= nil) and (ongreater<>nil) then
  1676. begin
  1677. current_asmdata.getjumplabel(skiplabel);
  1678. a_jmp_flags(list,F_E,skiplabel);
  1679. current_asmdata.getjumplabel(l);
  1680. a_jmp_flags(list,F_PO,l);
  1681. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1682. cg.a_label(current_asmdata.CurrAsmList,l);
  1683. a_jmp_flags(list,F_P,ongreater);
  1684. cg.a_label(list,skiplabel);
  1685. end
  1686. else if (onless= nil) and (onequal<>nil) and (ongreater= nil) then
  1687. a_jmp_flags(list,F_E,onequal)
  1688. else if (onless= nil) and (onequal<>nil) and (ongreater<>nil) then
  1689. begin
  1690. if onequal<>ongreater then
  1691. a_jmp_flags(list,F_E,onequal);
  1692. current_asmdata.getjumplabel(l);
  1693. a_jmp_flags(list,F_PO,l);
  1694. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1695. cg.a_label(current_asmdata.CurrAsmList,l);
  1696. a_jmp_flags(list,F_P,ongreater);
  1697. end
  1698. else if (onless<>nil) and (onequal= nil) and (ongreater= nil) then
  1699. begin
  1700. current_asmdata.getjumplabel(l);
  1701. a_jmp_flags(list,F_PO,l);
  1702. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1703. cg.a_label(current_asmdata.CurrAsmList,l);
  1704. a_jmp_flags(list,F_M,onless);
  1705. end
  1706. else if (onless<>nil) and (onequal= nil) and (ongreater<>nil) then
  1707. begin
  1708. if onless=ongreater then
  1709. a_jmp_flags(list,F_NE,onless)
  1710. else
  1711. begin
  1712. current_asmdata.getjumplabel(skiplabel);
  1713. a_jmp_flags(list,F_E,skiplabel);
  1714. current_asmdata.getjumplabel(l);
  1715. a_jmp_flags(list,F_PO,l);
  1716. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1717. cg.a_label(current_asmdata.CurrAsmList,l);
  1718. a_jmp_flags(list,F_M,onless);
  1719. a_jmp_always(list,ongreater);
  1720. cg.a_label(list,skiplabel);
  1721. end;
  1722. end
  1723. else if (onless<>nil) and (onequal<>nil) and (ongreater= nil) then
  1724. begin
  1725. a_jmp_flags(list,F_E,onequal);
  1726. current_asmdata.getjumplabel(l);
  1727. a_jmp_flags(list,F_PO,l);
  1728. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1729. cg.a_label(current_asmdata.CurrAsmList,l);
  1730. a_jmp_flags(list,F_M,onless);
  1731. end
  1732. else if (onless<>nil) and (onequal<>nil) and (ongreater<>nil) then
  1733. begin
  1734. if (onless=onequal) and (onequal=ongreater) then
  1735. a_jmp_always(list,onless)
  1736. else if onequal=ongreater then
  1737. begin
  1738. current_asmdata.getjumplabel(l);
  1739. a_jmp_flags(list,F_PO,l);
  1740. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1741. cg.a_label(current_asmdata.CurrAsmList,l);
  1742. a_jmp_flags(list,F_M,onless);
  1743. a_jmp_always(list,ongreater);
  1744. end
  1745. else if onless=onequal then
  1746. begin
  1747. a_jmp_flags(list,F_E,onequal);
  1748. current_asmdata.getjumplabel(l);
  1749. a_jmp_flags(list,F_PO,l);
  1750. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1751. cg.a_label(current_asmdata.CurrAsmList,l);
  1752. a_jmp_flags(list,F_M,onless);
  1753. a_jmp_always(list,ongreater);
  1754. end
  1755. else if onless=ongreater then
  1756. begin
  1757. a_jmp_flags(list,F_E,onequal);
  1758. a_jmp_always(list,ongreater);
  1759. end
  1760. else
  1761. begin
  1762. { the generic case - all 3 are different labels }
  1763. a_jmp_flags(list,F_E,onequal);
  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. end;
  1771. end
  1772. else
  1773. begin
  1774. { Shouldn't happen! All possible combinations are handled by the above code. }
  1775. internalerror(2020042204);
  1776. end;
  1777. end;
  1778. procedure tcgz80.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1779. var
  1780. l : TAsmLabel;
  1781. tmpflags : TResFlags;
  1782. begin
  1783. if f in [F_C,F_NC] then
  1784. begin
  1785. a_load_const_reg(list,size,0,reg);
  1786. if f=F_NC then
  1787. list.concat(taicpu.op_none(A_CCF));
  1788. list.concat(taicpu.op_reg(A_RL,reg));
  1789. end
  1790. else
  1791. begin
  1792. current_asmdata.getjumplabel(l);
  1793. a_load_const_reg(list,size,0,reg);
  1794. tmpflags:=f;
  1795. inverse_flags(tmpflags);
  1796. a_jmp_flags(list,tmpflags,l);
  1797. list.concat(taicpu.op_reg(A_INC,reg));
  1798. cg.a_label(list,l);
  1799. end;
  1800. end;
  1801. procedure tcgz80.g_stackpointer_alloc(list: TAsmList; localsize: longint);
  1802. begin
  1803. if localsize>0 then
  1804. begin
  1805. list.Concat(taicpu.op_reg_const(A_LD,NR_HL,-localsize));
  1806. list.Concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_SP));
  1807. list.Concat(taicpu.op_reg_reg(A_LD,NR_SP,NR_HL));
  1808. end;
  1809. end;
  1810. procedure tcgz80.a_adjust_sp(list : TAsmList; value : longint);
  1811. var
  1812. i : integer;
  1813. begin
  1814. //case value of
  1815. // 0:
  1816. // ;
  1817. // {-14..-1:
  1818. // begin
  1819. // if ((-value) mod 2)<>0 then
  1820. // list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  1821. // for i:=1 to (-value) div 2 do
  1822. // list.concat(taicpu.op_const(A_RCALL,0));
  1823. // end;
  1824. // 1..7:
  1825. // begin
  1826. // for i:=1 to value do
  1827. // list.concat(taicpu.op_reg(A_POP,NR_R0));
  1828. // end;}
  1829. // else
  1830. // begin
  1831. // list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1832. // list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1833. // // get SREG
  1834. // list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  1835. //
  1836. // // block interrupts
  1837. // list.concat(taicpu.op_none(A_CLI));
  1838. //
  1839. // // write high SP
  1840. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1841. //
  1842. // // release interrupts
  1843. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  1844. //
  1845. // // write low SP
  1846. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1847. // end;
  1848. //end;
  1849. end;
  1850. procedure tcgz80.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1851. var
  1852. regsize,stackmisalignment: longint;
  1853. begin
  1854. regsize:=0;
  1855. stackmisalignment:=0;
  1856. { save old framepointer }
  1857. if not nostackframe then
  1858. begin
  1859. { return address }
  1860. inc(stackmisalignment,2);
  1861. list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
  1862. if current_procinfo.framepointer=NR_FRAME_POINTER_REG then
  1863. begin
  1864. { push <frame_pointer> }
  1865. inc(stackmisalignment,2);
  1866. include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
  1867. list.concat(Taicpu.op_reg(A_PUSH,NR_FRAME_POINTER_REG));
  1868. { Return address and FP are both on stack }
  1869. current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*2);
  1870. current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*2));
  1871. if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then
  1872. begin
  1873. list.concat(Taicpu.op_reg_const(A_LD,NR_FRAME_POINTER_REG,0));
  1874. list.concat(Taicpu.op_reg_reg(A_ADD,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG))
  1875. end
  1876. else
  1877. begin
  1878. internalerror(2020040301);
  1879. (*push_regs;
  1880. gen_load_frame_for_exceptfilter(list);
  1881. { Need only as much stack space as necessary to do the calls.
  1882. Exception filters don't have own local vars, and temps are 'mapped'
  1883. to the parent procedure.
  1884. maxpushedparasize is already aligned at least on x86_64. }
  1885. localsize:=current_procinfo.maxpushedparasize;*)
  1886. end;
  1887. current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG);
  1888. end
  1889. else
  1890. begin
  1891. CGmessage(cg_d_stackframe_omited);
  1892. end;
  1893. { allocate stackframe space }
  1894. if (localsize<>0) or
  1895. ((target_info.stackalign>sizeof(pint)) and
  1896. (stackmisalignment <> 0) and
  1897. ((pi_do_call in current_procinfo.flags) or
  1898. (po_assembler in current_procinfo.procdef.procoptions))) then
  1899. begin
  1900. if target_info.stackalign>sizeof(pint) then
  1901. localsize := align(localsize+stackmisalignment,target_info.stackalign)-stackmisalignment;
  1902. g_stackpointer_alloc(list,localsize);
  1903. if current_procinfo.framepointer=NR_STACK_POINTER_REG then
  1904. current_asmdata.asmcfi.cfa_def_cfa_offset(list,regsize+localsize+sizeof(pint));
  1905. current_procinfo.final_localsize:=localsize;
  1906. end
  1907. end;
  1908. end;
  1909. procedure tcgz80.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  1910. var
  1911. regs : tcpuregisterset;
  1912. reg : TSuperRegister;
  1913. LocalSize : longint;
  1914. begin
  1915. { every byte counts for Z80, so if a subroutine is marked as non-returning, we do
  1916. not generate any exit code, so we really trust the noreturn directive
  1917. }
  1918. if po_noreturn in current_procinfo.procdef.procoptions then
  1919. exit;
  1920. { remove stackframe }
  1921. if not nostackframe then
  1922. begin
  1923. stacksize:=current_procinfo.calc_stackframe_size;
  1924. if (target_info.stackalign>4) and
  1925. ((stacksize <> 0) or
  1926. (pi_do_call in current_procinfo.flags) or
  1927. { can't detect if a call in this case -> use nostackframe }
  1928. { if you (think you) know what you are doing }
  1929. (po_assembler in current_procinfo.procdef.procoptions)) then
  1930. stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint);
  1931. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  1932. begin
  1933. internalerror(2020040302);
  1934. {if (stacksize<>0) then
  1935. cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);}
  1936. end
  1937. else
  1938. begin
  1939. list.Concat(taicpu.op_reg_reg(A_LD,NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG));
  1940. list.Concat(taicpu.op_reg(A_POP,NR_FRAME_POINTER_REG));
  1941. end;
  1942. list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
  1943. end;
  1944. list.concat(taicpu.op_none(A_RET));
  1945. end;
  1946. procedure tcgz80.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  1947. var
  1948. tmpref : treference;
  1949. begin
  1950. if assigned(ref.symbol) then
  1951. begin
  1952. reference_reset(tmpref,0,[]);
  1953. tmpref.symbol:=ref.symbol;
  1954. tmpref.offset:=ref.offset;
  1955. tmpref.refaddr:=addr_lo8;
  1956. list.concat(taicpu.op_reg_ref(A_LD,r,tmpref));
  1957. tmpref.refaddr:=addr_hi8;
  1958. list.concat(taicpu.op_reg_ref(A_LD,GetNextReg(r),tmpref));
  1959. if (ref.base<>NR_NO) then
  1960. a_op_reg_reg(list,OP_ADD,OS_16,ref.base,r);
  1961. if (ref.index<>NR_NO) then
  1962. a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  1963. end
  1964. else if ref.base=NR_IX then
  1965. begin
  1966. list.concat(taicpu.op_reg(A_PUSH,NR_IX));
  1967. getcpuregister(list,NR_H);
  1968. getcpuregister(list,NR_L);
  1969. list.concat(taicpu.op_reg(A_POP,NR_HL));
  1970. emit_mov(list,r,NR_L);
  1971. ungetcpuregister(list,NR_L);
  1972. emit_mov(list,GetNextReg(r),NR_H);
  1973. ungetcpuregister(list,NR_H);
  1974. if (ref.index<>NR_NO) then
  1975. a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  1976. if ref.offset<>0 then
  1977. a_op_const_reg(list,OP_ADD,OS_16,ref.offset,r);
  1978. end
  1979. else
  1980. begin
  1981. a_load_const_reg(list,OS_16,ref.offset,r);
  1982. if (ref.base<>NR_NO) then
  1983. a_op_reg_reg(list,OP_ADD,OS_16,ref.base,r);
  1984. if (ref.index<>NR_NO) then
  1985. a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  1986. end;
  1987. end;
  1988. procedure tcgz80.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  1989. var
  1990. tmpreg,srcreg,dstreg: tregister;
  1991. srcref,dstref : treference;
  1992. i: Integer;
  1993. begin
  1994. if (len<=2) and
  1995. is_ref_in_opertypes(source,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) and
  1996. is_ref_in_opertypes(dest,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  1997. begin
  1998. srcref:=source;
  1999. dstref:=dest;
  2000. tmpreg:=getintregister(list,OS_8);
  2001. for i:=1 to len do
  2002. begin
  2003. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  2004. list.concat(taicpu.op_ref_reg(A_LD,dstref,tmpreg));
  2005. if i<>len then
  2006. begin
  2007. adjust_normalized_ref(list,srcref,1);
  2008. adjust_normalized_ref(list,dstref,1);
  2009. end;
  2010. end;
  2011. end
  2012. else
  2013. begin
  2014. srcreg:=getintregister(list,OS_16);
  2015. a_loadaddr_ref_reg(list,source,srcreg);
  2016. dstreg:=getintregister(list,OS_16);
  2017. a_loadaddr_ref_reg(list,dest,dstreg);
  2018. getcpuregister(list,NR_L);
  2019. a_load_reg_reg(list,OS_8,OS_8,srcreg,NR_L);
  2020. getcpuregister(list,NR_H);
  2021. a_load_reg_reg(list,OS_8,OS_8,GetNextReg(srcreg),NR_H);
  2022. getcpuregister(list,NR_E);
  2023. a_load_reg_reg(list,OS_8,OS_8,dstreg,NR_E);
  2024. getcpuregister(list,NR_D);
  2025. a_load_reg_reg(list,OS_8,OS_8,GetNextReg(dstreg),NR_D);
  2026. getcpuregister(list,NR_B);
  2027. getcpuregister(list,NR_C);
  2028. list.concat(taicpu.op_reg_const(A_LD,NR_BC,len));
  2029. list.concat(taicpu.op_none(A_LDIR));
  2030. ungetcpuregister(list,NR_B);
  2031. ungetcpuregister(list,NR_C);
  2032. ungetcpuregister(list,NR_D);
  2033. ungetcpuregister(list,NR_E);
  2034. ungetcpuregister(list,NR_H);
  2035. ungetcpuregister(list,NR_L);
  2036. end;
  2037. end;
  2038. procedure tcgz80.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
  2039. var
  2040. hl : tasmlabel;
  2041. ai : taicpu;
  2042. cond : TAsmCond;
  2043. begin
  2044. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: g_overflowCheck')));
  2045. //if not(cs_check_overflow in current_settings.localswitches) then
  2046. // exit;
  2047. //current_asmdata.getjumplabel(hl);
  2048. //if not ((def.typ=pointerdef) or
  2049. // ((def.typ=orddef) and
  2050. // (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2051. // pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2052. // cond:=C_VC
  2053. //else
  2054. // cond:=C_CC;
  2055. //ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2056. //ai.SetCondition(cond);
  2057. //ai.is_jmp:=true;
  2058. //list.concat(ai);
  2059. //
  2060. //a_call_name(list,'FPC_OVERFLOW',false);
  2061. //a_label(list,hl);
  2062. end;
  2063. procedure tcgz80.g_save_registers(list: TAsmList);
  2064. begin
  2065. { this is done by the entry code }
  2066. end;
  2067. procedure tcgz80.g_restore_registers(list: TAsmList);
  2068. begin
  2069. { this is done by the exit code }
  2070. end;
  2071. procedure tcgz80.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  2072. var
  2073. ai1,ai2 : taicpu;
  2074. hl : TAsmLabel;
  2075. begin
  2076. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_jmp_cond')));
  2077. //ai1:=Taicpu.Op_sym(A_BRxx,l);
  2078. //ai1.is_jmp:=true;
  2079. //hl:=nil;
  2080. //case cond of
  2081. // OC_EQ:
  2082. // ai1.SetCondition(C_EQ);
  2083. // OC_GT:
  2084. // begin
  2085. // { emulate GT }
  2086. // current_asmdata.getjumplabel(hl);
  2087. // ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2088. // ai2.SetCondition(C_EQ);
  2089. // ai2.is_jmp:=true;
  2090. // list.concat(ai2);
  2091. //
  2092. // ai1.SetCondition(C_GE);
  2093. // end;
  2094. // OC_LT:
  2095. // ai1.SetCondition(C_LT);
  2096. // OC_GTE:
  2097. // ai1.SetCondition(C_GE);
  2098. // OC_LTE:
  2099. // begin
  2100. // { emulate LTE }
  2101. // ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2102. // ai2.SetCondition(C_EQ);
  2103. // ai2.is_jmp:=true;
  2104. // list.concat(ai2);
  2105. //
  2106. // ai1.SetCondition(C_LT);
  2107. // end;
  2108. // OC_NE:
  2109. // ai1.SetCondition(C_NE);
  2110. // OC_BE:
  2111. // begin
  2112. // { emulate BE }
  2113. // ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2114. // ai2.SetCondition(C_EQ);
  2115. // ai2.is_jmp:=true;
  2116. // list.concat(ai2);
  2117. //
  2118. // ai1.SetCondition(C_LO);
  2119. // end;
  2120. // OC_B:
  2121. // ai1.SetCondition(C_LO);
  2122. // OC_AE:
  2123. // ai1.SetCondition(C_SH);
  2124. // OC_A:
  2125. // begin
  2126. // { emulate A (unsigned GT) }
  2127. // current_asmdata.getjumplabel(hl);
  2128. // ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2129. // ai2.SetCondition(C_EQ);
  2130. // ai2.is_jmp:=true;
  2131. // list.concat(ai2);
  2132. //
  2133. // ai1.SetCondition(C_SH);
  2134. // end;
  2135. // else
  2136. // internalerror(2011082501);
  2137. //end;
  2138. //list.concat(ai1);
  2139. //if assigned(hl) then
  2140. // a_label(list,hl);
  2141. end;
  2142. procedure tcgz80.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2143. var
  2144. instr: taicpu;
  2145. begin
  2146. instr:=taicpu.op_reg_reg(A_LD,reg2,reg1);
  2147. list.Concat(instr);
  2148. { Notify the register allocator that we have written a move instruction so
  2149. it can try to eliminate it. }
  2150. add_move_instruction(instr);
  2151. end;
  2152. procedure tcg64fz80.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2153. begin
  2154. if not(size in [OS_S64,OS_64]) then
  2155. internalerror(2012102402);
  2156. tcgz80(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2157. end;
  2158. procedure tcg64fz80.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2159. begin
  2160. tcgz80(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2161. end;
  2162. function GetByteLoc(const loc : tlocation; nr : byte) : tlocation;
  2163. var
  2164. i : Integer;
  2165. begin
  2166. Result:=loc;
  2167. Result.size:=OS_8;
  2168. case loc.loc of
  2169. LOC_REFERENCE,LOC_CREFERENCE:
  2170. inc(Result.reference.offset,nr);
  2171. LOC_REGISTER,LOC_CREGISTER:
  2172. begin
  2173. if nr>=4 then
  2174. Result.register:=Result.register64.reghi;
  2175. nr:=nr mod 4;
  2176. for i:=1 to nr do
  2177. Result.register:=GetNextReg(Result.register);
  2178. end;
  2179. LOC_CONSTANT:
  2180. if loc.size in [OS_64,OS_S64] then
  2181. Result.value:=(Result.value64 shr (nr*8)) and $ff
  2182. else
  2183. Result.value:=(Result.value shr (nr*8)) and $ff;
  2184. else
  2185. Internalerror(2019020902);
  2186. end;
  2187. end;
  2188. procedure create_codegen;
  2189. begin
  2190. cg:=tcgz80.create;
  2191. cg64:=tcg64fz80.create;
  2192. end;
  2193. end.