cgcpu.pas 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347
  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_IX) or (ref.base=NR_IY) then
  1149. begin
  1150. getcpuregister(list,NR_D);
  1151. getcpuregister(list,NR_E);
  1152. list.concat(taicpu.op_reg(A_PUSH,ref.base));
  1153. list.concat(taicpu.op_reg(A_POP,NR_DE));
  1154. list.concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_DE));
  1155. ungetcpuregister(list,NR_E);
  1156. ungetcpuregister(list,NR_D);
  1157. end
  1158. else if ref.base<>NR_NO then
  1159. begin
  1160. getcpuregister(list,NR_A);
  1161. emit_mov(list,NR_A,NR_L);
  1162. list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.base));
  1163. emit_mov(list,NR_L,NR_A);
  1164. emit_mov(list,NR_A,NR_H);
  1165. list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.base)));
  1166. emit_mov(list,NR_H,NR_A);
  1167. ungetcpuregister(list,NR_A);
  1168. end;
  1169. if ref.index<>NR_NO then
  1170. begin
  1171. if ref.scalefactor>1 then
  1172. internalerror(2020042002);
  1173. getcpuregister(list,NR_A);
  1174. emit_mov(list,NR_A,NR_L);
  1175. list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.index));
  1176. emit_mov(list,NR_L,NR_A);
  1177. emit_mov(list,NR_A,NR_H);
  1178. list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.index)));
  1179. emit_mov(list,NR_H,NR_A);
  1180. ungetcpuregister(list,NR_A);
  1181. end;
  1182. reference_reset_base(result,NR_HL,0,ctempposinvalid,0,[]);
  1183. end
  1184. else
  1185. internalerror(2020042001);
  1186. end;
  1187. procedure tcgz80.adjust_normalized_ref(list: TAsmList; var ref: treference; value: longint);
  1188. var
  1189. i: Integer;
  1190. begin
  1191. if is_ref_addr16(ref) then
  1192. Inc(ref.offset,value)
  1193. else if is_ref_hl(ref) then
  1194. begin
  1195. if value>0 then
  1196. for i:=1 to value do
  1197. list.concat(taicpu.op_reg(A_INC,NR_HL))
  1198. else
  1199. for i:=-1 downto value do
  1200. list.concat(taicpu.op_reg(A_DEC,NR_HL));
  1201. end
  1202. else if is_ref_ix_d(ref) then
  1203. begin
  1204. if ((ref.offset+value)<=127) and ((ref.offset+value)>=-128) then
  1205. inc(ref.offset,value)
  1206. else
  1207. begin
  1208. { todo: IX is the frame pointer, we cannot change it, so we }
  1209. { think of another mechanism to deal with this situation }
  1210. internalerror(2020042101);
  1211. //if value>0 then
  1212. // for i:=1 to value do
  1213. // list.concat(taicpu.op_reg(A_INC,NR_IX))
  1214. //else
  1215. // for i:=-1 downto value do
  1216. // list.concat(taicpu.op_reg(A_DEC,NR_IX));
  1217. end;
  1218. end
  1219. else if is_ref_iy_d(ref) then
  1220. begin
  1221. if ((ref.offset+value)<=127) and ((ref.offset+value)>=-128) then
  1222. inc(ref.offset,value)
  1223. else
  1224. if value>0 then
  1225. for i:=1 to value do
  1226. list.concat(taicpu.op_reg(A_INC,NR_IY))
  1227. else
  1228. for i:=-1 downto value do
  1229. list.concat(taicpu.op_reg(A_DEC,NR_IY));
  1230. end;
  1231. end;
  1232. procedure tcgz80.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  1233. var
  1234. href : treference;
  1235. i : integer;
  1236. regsused: tregisterlist;
  1237. begin
  1238. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1239. internalerror(2011021307);
  1240. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1241. internalerror(2020040802);
  1242. href:=normalize_ref(list,Ref,[OT_REF_ADDR16,OT_REF_HL,OT_REF_IX_d,OT_REF_IY_d],regsused);
  1243. if (fromsize=tosize) or (fromsize in [OS_8,OS_16,OS_32]) then
  1244. begin
  1245. getcpuregister(list,NR_A);
  1246. for i:=1 to tcgsize2size[fromsize] do
  1247. begin
  1248. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1249. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1250. if i<>tcgsize2size[fromsize] then
  1251. reg:=GetNextReg(reg);
  1252. if i<>tcgsize2size[tosize] then
  1253. adjust_normalized_ref(list,href,1);
  1254. end;
  1255. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1256. begin
  1257. if i=(tcgsize2size[fromsize]+1) then
  1258. list.concat(taicpu.op_reg_const(A_LD,NR_A,0));
  1259. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1260. if i<>tcgsize2size[tosize] then
  1261. begin
  1262. adjust_normalized_ref(list,href,1);
  1263. reg:=GetNextReg(reg);
  1264. end;
  1265. end;
  1266. ungetcpuregister(list,NR_A);
  1267. end
  1268. else
  1269. begin
  1270. getcpuregister(list,NR_A);
  1271. for i:=1 to tcgsize2size[fromsize] do
  1272. begin
  1273. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1274. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1275. if i<>tcgsize2size[fromsize] then
  1276. reg:=GetNextReg(reg);
  1277. if i<>tcgsize2size[tosize] then
  1278. adjust_normalized_ref(list,href,1);
  1279. end;
  1280. list.concat(taicpu.op_none(A_RLA));
  1281. list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1282. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1283. begin
  1284. list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1285. if i<>tcgsize2size[tosize] then
  1286. begin
  1287. adjust_normalized_ref(list,href,1);
  1288. reg:=GetNextReg(reg);
  1289. end;
  1290. end;
  1291. ungetcpuregister(list,NR_A);
  1292. end;
  1293. ungetcpuregisters(list,regsused);
  1294. end;
  1295. procedure tcgz80.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1296. const Ref : treference;reg : tregister);
  1297. var
  1298. href : treference;
  1299. i : integer;
  1300. regsused: tregisterlist;
  1301. begin
  1302. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1303. internalerror(2011021307);
  1304. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1305. internalerror(2020040804);
  1306. href:=normalize_ref(list,Ref,[OT_REF_ADDR16,OT_REF_HL,OT_REF_IX_d,OT_REF_IY_d],regsused);
  1307. if (tosize=fromsize) or (fromsize in [OS_8,OS_16,OS_32]) then
  1308. begin
  1309. getcpuregister(list,NR_A);
  1310. for i:=1 to tcgsize2size[fromsize] do
  1311. begin
  1312. list.concat(taicpu.op_reg_ref(A_LD,NR_A,href));
  1313. a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1314. if i<>tcgsize2size[fromsize] then
  1315. adjust_normalized_ref(list,href,1);
  1316. if i<>tcgsize2size[tosize] then
  1317. reg:=GetNextReg(reg);
  1318. end;
  1319. ungetcpuregisters(list,regsused);
  1320. ungetcpuregister(list,NR_A);
  1321. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1322. begin
  1323. list.concat(taicpu.op_reg_const(A_LD,reg,0));
  1324. if i<>tcgsize2size[tosize] then
  1325. reg:=GetNextReg(reg);
  1326. end;
  1327. end
  1328. else
  1329. begin
  1330. getcpuregister(list,NR_A);
  1331. for i:=1 to tcgsize2size[fromsize] do
  1332. begin
  1333. list.concat(taicpu.op_reg_ref(A_LD,NR_A,href));
  1334. a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1335. if i<>tcgsize2size[fromsize] then
  1336. adjust_normalized_ref(list,href,1);
  1337. if i<>tcgsize2size[tosize] then
  1338. reg:=GetNextReg(reg);
  1339. end;
  1340. ungetcpuregisters(list,regsused);
  1341. list.concat(taicpu.op_none(A_RLA));
  1342. list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1343. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1344. begin
  1345. emit_mov(list,reg,NR_A);
  1346. if i<>tcgsize2size[tosize] then
  1347. reg:=GetNextReg(reg);
  1348. end;
  1349. ungetcpuregister(list,NR_A);
  1350. end;
  1351. end;
  1352. procedure tcgz80.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1353. var
  1354. conv_done: boolean;
  1355. tmpreg : tregister;
  1356. i : integer;
  1357. begin
  1358. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1359. internalerror(2011021310);
  1360. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1361. fromsize:=tosize;
  1362. if (tosize=fromsize) or (fromsize in [OS_8,OS_16,OS_32]) then
  1363. begin
  1364. if reg1<>reg2 then
  1365. for i:=1 to tcgsize2size[fromsize] do
  1366. begin
  1367. emit_mov(list,reg2,reg1);
  1368. if i<>tcgsize2size[fromsize] then
  1369. reg1:=GetNextReg(reg1);
  1370. if i<>tcgsize2size[tosize] then
  1371. reg2:=GetNextReg(reg2);
  1372. end
  1373. else
  1374. for i:=1 to tcgsize2size[fromsize] do
  1375. if i<>tcgsize2size[tosize] then
  1376. reg2:=GetNextReg(reg2);
  1377. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1378. begin
  1379. list.Concat(taicpu.op_reg_const(A_LD,reg2,0));
  1380. if i<>tcgsize2size[tosize] then
  1381. reg2:=GetNextReg(reg2);
  1382. end
  1383. end
  1384. else
  1385. begin
  1386. if reg1<>reg2 then
  1387. for i:=1 to tcgsize2size[fromsize]-1 do
  1388. begin
  1389. emit_mov(list,reg2,reg1);
  1390. reg1:=GetNextReg(reg1);
  1391. reg2:=GetNextReg(reg2);
  1392. end
  1393. else
  1394. for i:=1 to tcgsize2size[fromsize]-1 do
  1395. reg2:=GetNextReg(reg2);
  1396. emit_mov(list,reg2,reg1);
  1397. getcpuregister(list,NR_A);
  1398. emit_mov(list,NR_A,reg2);
  1399. reg2:=GetNextReg(reg2);
  1400. list.concat(taicpu.op_none(A_RLA));
  1401. list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1402. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1403. begin
  1404. emit_mov(list,reg2,NR_A);
  1405. if i<>tcgsize2size[tosize] then
  1406. reg2:=GetNextReg(reg2);
  1407. end;
  1408. ungetcpuregister(list,NR_A);
  1409. end;
  1410. end;
  1411. procedure tcgz80.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1412. begin
  1413. internalerror(2012010702);
  1414. end;
  1415. procedure tcgz80.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1416. begin
  1417. internalerror(2012010703);
  1418. end;
  1419. procedure tcgz80.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1420. begin
  1421. internalerror(2012010704);
  1422. end;
  1423. { comparison operations }
  1424. procedure tcgz80.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1425. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1426. var
  1427. swapped : boolean;
  1428. tmpreg : tregister;
  1429. i : byte;
  1430. tmpl: TAsmLabel;
  1431. begin
  1432. if size in [OS_8,OS_S8]then
  1433. begin
  1434. if cmp_op in [OC_EQ,OC_NE,OC_B,OC_AE] then
  1435. begin
  1436. getcpuregister(list,NR_A);
  1437. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1438. list.concat(taicpu.op_reg_const(A_CP,NR_A,a));
  1439. case cmp_op of
  1440. OC_EQ:
  1441. a_jmp_flags(list,F_E,l);
  1442. OC_NE:
  1443. a_jmp_flags(list,F_NE,l);
  1444. OC_B:
  1445. a_jmp_flags(list,F_C,l);
  1446. OC_AE:
  1447. a_jmp_flags(list,F_NC,l);
  1448. else
  1449. internalerror(2020042206);
  1450. end;
  1451. ungetcpuregister(list,NR_A);
  1452. end
  1453. else if cmp_op in [OC_A,OC_BE] then
  1454. begin
  1455. getcpuregister(list,NR_A);
  1456. a_load_const_reg(list,OS_8,a,NR_A);
  1457. list.concat(taicpu.op_reg_reg(A_CP,NR_A,reg));
  1458. case cmp_op of
  1459. OC_A:
  1460. a_jmp_flags(list,F_C,l);
  1461. OC_BE:
  1462. a_jmp_flags(list,F_NC,l);
  1463. else
  1464. internalerror(2020042206);
  1465. end;
  1466. ungetcpuregister(list,NR_A);
  1467. end
  1468. else if cmp_op in [OC_LT,OC_GTE] then
  1469. begin
  1470. getcpuregister(list,NR_A);
  1471. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1472. list.concat(taicpu.op_reg_const(A_SUB,NR_A,a));
  1473. current_asmdata.getjumplabel(tmpl);
  1474. a_jmp_flags(list,F_PO,tmpl);
  1475. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1476. cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1477. case cmp_op of
  1478. OC_LT:
  1479. a_jmp_flags(list,F_M,l);
  1480. OC_GTE:
  1481. a_jmp_flags(list,F_P,l);
  1482. else
  1483. internalerror(2020042206);
  1484. end;
  1485. ungetcpuregister(list,NR_A);
  1486. end
  1487. else if cmp_op in [OC_GT,OC_LTE] then
  1488. begin
  1489. getcpuregister(list,NR_A);
  1490. a_load_const_reg(list,OS_8,a,NR_A);
  1491. list.concat(taicpu.op_reg_reg(A_SUB,NR_A,reg));
  1492. current_asmdata.getjumplabel(tmpl);
  1493. a_jmp_flags(list,F_PO,tmpl);
  1494. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1495. cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1496. case cmp_op of
  1497. OC_GT:
  1498. a_jmp_flags(list,F_M,l);
  1499. OC_LTE:
  1500. a_jmp_flags(list,F_P,l);
  1501. else
  1502. internalerror(2020042206);
  1503. end;
  1504. ungetcpuregister(list,NR_A);
  1505. end;
  1506. end
  1507. else if cmp_op in [OC_EQ,OC_NE] then
  1508. begin
  1509. if cmp_op=OC_EQ then
  1510. current_asmdata.getjumplabel(tmpl);
  1511. for i:=0 to tcgsize2size[size]-1 do
  1512. begin
  1513. a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg(reg,i),NR_A);
  1514. list.concat(taicpu.op_reg_const(A_CP,NR_A,Byte(a shr (8*i))));
  1515. case cmp_op of
  1516. OC_EQ:
  1517. if i<>(tcgsize2size[size]-1) then
  1518. a_jmp_flags(list,F_NE,tmpl)
  1519. else
  1520. a_jmp_flags(list,F_E,l);
  1521. OC_NE:
  1522. a_jmp_flags(list,F_NE,l);
  1523. else
  1524. internalerror(2020042206);
  1525. end;
  1526. end;
  1527. if cmp_op=OC_EQ then
  1528. cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1529. end
  1530. else if cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE,OC_BE,OC_B,OC_AE,OC_A] then
  1531. begin
  1532. { todo: implement these }
  1533. internalerror(2020042207);
  1534. end
  1535. else
  1536. internalerror(2020042205);
  1537. end;
  1538. procedure tcgz80.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1539. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1540. var
  1541. swapped : boolean;
  1542. tmpreg : tregister;
  1543. i : byte;
  1544. begin
  1545. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_cmp_reg_reg_label')));
  1546. //swapped:=false;
  1547. //{ swap parameters? }
  1548. //case cmp_op of
  1549. // OC_GT:
  1550. // begin
  1551. // swapped:=true;
  1552. // cmp_op:=OC_LT;
  1553. // end;
  1554. // OC_LTE:
  1555. // begin
  1556. // swapped:=true;
  1557. // cmp_op:=OC_GTE;
  1558. // end;
  1559. // OC_BE:
  1560. // begin
  1561. // swapped:=true;
  1562. // cmp_op:=OC_AE;
  1563. // end;
  1564. // OC_A:
  1565. // begin
  1566. // swapped:=true;
  1567. // cmp_op:=OC_B;
  1568. // end;
  1569. //end;
  1570. //if swapped then
  1571. // begin
  1572. // tmpreg:=reg1;
  1573. // reg1:=reg2;
  1574. // reg2:=tmpreg;
  1575. // end;
  1576. //list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1577. //
  1578. //for i:=2 to tcgsize2size[size] do
  1579. // begin
  1580. // reg1:=GetNextReg(reg1);
  1581. // reg2:=GetNextReg(reg2);
  1582. // list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1583. // end;
  1584. //
  1585. //a_jmp_cond(list,cmp_op,l);
  1586. end;
  1587. procedure tcgz80.a_jmp_name(list : TAsmList;const s : string);
  1588. var
  1589. ai : taicpu;
  1590. begin
  1591. ai:=taicpu.op_sym(A_JP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1592. ai.is_jmp:=true;
  1593. list.concat(ai);
  1594. end;
  1595. procedure tcgz80.a_jmp_always(list : TAsmList;l: tasmlabel);
  1596. var
  1597. ai : taicpu;
  1598. begin
  1599. ai:=taicpu.op_sym(A_JP,l);
  1600. ai.is_jmp:=true;
  1601. list.concat(ai);
  1602. end;
  1603. procedure tcgz80.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1604. var
  1605. ai : taicpu;
  1606. begin
  1607. ai:=taicpu.op_cond_sym(A_JP,flags_to_cond(f),l);
  1608. ai.is_jmp:=true;
  1609. list.concat(ai);
  1610. end;
  1611. procedure tcgz80.a_jmp_unsigned_cmp_3way(list: TAsmList; onbelow, onequal, onabove: tasmlabel);
  1612. var
  1613. skiplabel: TAsmLabel;
  1614. begin
  1615. if (onbelow= nil) and (onequal= nil) and (onabove= nil) then
  1616. {nothing}
  1617. else if (onbelow= nil) and (onequal= nil) and (onabove<>nil) then
  1618. begin
  1619. current_asmdata.getjumplabel(skiplabel);
  1620. a_jmp_flags(list,F_E,skiplabel);
  1621. a_jmp_flags(list,F_NC,onabove);
  1622. cg.a_label(list,skiplabel);
  1623. end
  1624. else if (onbelow= nil) and (onequal<>nil) and (onabove= nil) then
  1625. a_jmp_flags(list,F_E,onequal)
  1626. else if (onbelow= nil) and (onequal<>nil) and (onabove<>nil) then
  1627. begin
  1628. if onequal<>onabove then
  1629. a_jmp_flags(list,F_E,onequal);
  1630. a_jmp_flags(list,F_NC,onabove);
  1631. end
  1632. else if (onbelow<>nil) and (onequal= nil) and (onabove= nil) then
  1633. a_jmp_flags(list,F_C,onbelow)
  1634. else if (onbelow<>nil) and (onequal= nil) and (onabove<>nil) then
  1635. begin
  1636. if onbelow<>onabove then
  1637. a_jmp_flags(list,F_C,onbelow);
  1638. a_jmp_flags(list,F_NE,onabove);
  1639. end
  1640. else if (onbelow<>nil) and (onequal<>nil) and (onabove= nil) then
  1641. begin
  1642. a_jmp_flags(list,F_C,onbelow);
  1643. a_jmp_flags(list,F_E,onequal);
  1644. end
  1645. else if (onbelow<>nil) and (onequal<>nil) and (onabove<>nil) then
  1646. begin
  1647. if (onbelow=onequal) and (onequal=onabove) then
  1648. a_jmp_always(list,onbelow)
  1649. else if onequal=onabove then
  1650. begin
  1651. a_jmp_flags(list,F_C,onbelow);
  1652. a_jmp_always(list,onabove);
  1653. end
  1654. else if onbelow=onequal then
  1655. begin
  1656. a_jmp_flags(list,F_C,onbelow);
  1657. a_jmp_flags(list,F_E,onequal);
  1658. a_jmp_always(list,onabove);
  1659. end
  1660. else if onbelow=onabove then
  1661. begin
  1662. a_jmp_flags(list,F_E,onequal);
  1663. a_jmp_always(list,onabove);
  1664. end
  1665. else
  1666. begin
  1667. { the generic case - all 3 are different labels }
  1668. a_jmp_flags(list,F_C,onbelow);
  1669. a_jmp_flags(list,F_E,onequal);
  1670. a_jmp_always(list,onabove);
  1671. end;
  1672. end
  1673. else
  1674. begin
  1675. { Shouldn't happen! All possible combinations are handled by the above code. }
  1676. internalerror(2020042201);
  1677. end;
  1678. end;
  1679. procedure tcgz80.a_jmp_signed_cmp_3way(list: TAsmList; onless, onequal, ongreater: tasmlabel);
  1680. var
  1681. l, skiplabel: TAsmLabel;
  1682. begin
  1683. if (onless= nil) and (onequal= nil) and (ongreater= nil) then
  1684. {nothing}
  1685. else if (onless= nil) and (onequal= nil) and (ongreater<>nil) then
  1686. begin
  1687. current_asmdata.getjumplabel(skiplabel);
  1688. a_jmp_flags(list,F_E,skiplabel);
  1689. current_asmdata.getjumplabel(l);
  1690. a_jmp_flags(list,F_PO,l);
  1691. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1692. cg.a_label(current_asmdata.CurrAsmList,l);
  1693. a_jmp_flags(list,F_P,ongreater);
  1694. cg.a_label(list,skiplabel);
  1695. end
  1696. else if (onless= nil) and (onequal<>nil) and (ongreater= nil) then
  1697. a_jmp_flags(list,F_E,onequal)
  1698. else if (onless= nil) and (onequal<>nil) and (ongreater<>nil) then
  1699. begin
  1700. if onequal<>ongreater then
  1701. a_jmp_flags(list,F_E,onequal);
  1702. current_asmdata.getjumplabel(l);
  1703. a_jmp_flags(list,F_PO,l);
  1704. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1705. cg.a_label(current_asmdata.CurrAsmList,l);
  1706. a_jmp_flags(list,F_P,ongreater);
  1707. end
  1708. else if (onless<>nil) and (onequal= nil) and (ongreater= nil) then
  1709. begin
  1710. current_asmdata.getjumplabel(l);
  1711. a_jmp_flags(list,F_PO,l);
  1712. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1713. cg.a_label(current_asmdata.CurrAsmList,l);
  1714. a_jmp_flags(list,F_M,onless);
  1715. end
  1716. else if (onless<>nil) and (onequal= nil) and (ongreater<>nil) then
  1717. begin
  1718. if onless=ongreater then
  1719. a_jmp_flags(list,F_NE,onless)
  1720. else
  1721. begin
  1722. current_asmdata.getjumplabel(skiplabel);
  1723. a_jmp_flags(list,F_E,skiplabel);
  1724. current_asmdata.getjumplabel(l);
  1725. a_jmp_flags(list,F_PO,l);
  1726. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1727. cg.a_label(current_asmdata.CurrAsmList,l);
  1728. a_jmp_flags(list,F_M,onless);
  1729. a_jmp_always(list,ongreater);
  1730. cg.a_label(list,skiplabel);
  1731. end;
  1732. end
  1733. else if (onless<>nil) and (onequal<>nil) and (ongreater= nil) then
  1734. begin
  1735. a_jmp_flags(list,F_E,onequal);
  1736. current_asmdata.getjumplabel(l);
  1737. a_jmp_flags(list,F_PO,l);
  1738. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1739. cg.a_label(current_asmdata.CurrAsmList,l);
  1740. a_jmp_flags(list,F_M,onless);
  1741. end
  1742. else if (onless<>nil) and (onequal<>nil) and (ongreater<>nil) then
  1743. begin
  1744. if (onless=onequal) and (onequal=ongreater) then
  1745. a_jmp_always(list,onless)
  1746. else if onequal=ongreater then
  1747. begin
  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=onequal then
  1756. begin
  1757. a_jmp_flags(list,F_E,onequal);
  1758. current_asmdata.getjumplabel(l);
  1759. a_jmp_flags(list,F_PO,l);
  1760. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1761. cg.a_label(current_asmdata.CurrAsmList,l);
  1762. a_jmp_flags(list,F_M,onless);
  1763. a_jmp_always(list,ongreater);
  1764. end
  1765. else if onless=ongreater then
  1766. begin
  1767. a_jmp_flags(list,F_E,onequal);
  1768. a_jmp_always(list,ongreater);
  1769. end
  1770. else
  1771. begin
  1772. { the generic case - all 3 are different labels }
  1773. a_jmp_flags(list,F_E,onequal);
  1774. current_asmdata.getjumplabel(l);
  1775. a_jmp_flags(list,F_PO,l);
  1776. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1777. cg.a_label(current_asmdata.CurrAsmList,l);
  1778. a_jmp_flags(list,F_M,onless);
  1779. a_jmp_always(list,ongreater);
  1780. end;
  1781. end
  1782. else
  1783. begin
  1784. { Shouldn't happen! All possible combinations are handled by the above code. }
  1785. internalerror(2020042204);
  1786. end;
  1787. end;
  1788. procedure tcgz80.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1789. var
  1790. l : TAsmLabel;
  1791. tmpflags : TResFlags;
  1792. begin
  1793. if f in [F_C,F_NC] then
  1794. begin
  1795. a_load_const_reg(list,size,0,reg);
  1796. if f=F_NC then
  1797. list.concat(taicpu.op_none(A_CCF));
  1798. list.concat(taicpu.op_reg(A_RL,reg));
  1799. end
  1800. else
  1801. begin
  1802. current_asmdata.getjumplabel(l);
  1803. a_load_const_reg(list,size,0,reg);
  1804. tmpflags:=f;
  1805. inverse_flags(tmpflags);
  1806. a_jmp_flags(list,tmpflags,l);
  1807. list.concat(taicpu.op_reg(A_INC,reg));
  1808. cg.a_label(list,l);
  1809. end;
  1810. end;
  1811. procedure tcgz80.g_stackpointer_alloc(list: TAsmList; localsize: longint);
  1812. begin
  1813. if localsize>0 then
  1814. begin
  1815. list.Concat(taicpu.op_reg_const(A_LD,NR_HL,-localsize));
  1816. list.Concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_SP));
  1817. list.Concat(taicpu.op_reg_reg(A_LD,NR_SP,NR_HL));
  1818. end;
  1819. end;
  1820. procedure tcgz80.a_adjust_sp(list : TAsmList; value : longint);
  1821. var
  1822. i : integer;
  1823. begin
  1824. //case value of
  1825. // 0:
  1826. // ;
  1827. // {-14..-1:
  1828. // begin
  1829. // if ((-value) mod 2)<>0 then
  1830. // list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  1831. // for i:=1 to (-value) div 2 do
  1832. // list.concat(taicpu.op_const(A_RCALL,0));
  1833. // end;
  1834. // 1..7:
  1835. // begin
  1836. // for i:=1 to value do
  1837. // list.concat(taicpu.op_reg(A_POP,NR_R0));
  1838. // end;}
  1839. // else
  1840. // begin
  1841. // list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1842. // list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1843. // // get SREG
  1844. // list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  1845. //
  1846. // // block interrupts
  1847. // list.concat(taicpu.op_none(A_CLI));
  1848. //
  1849. // // write high SP
  1850. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1851. //
  1852. // // release interrupts
  1853. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  1854. //
  1855. // // write low SP
  1856. // list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1857. // end;
  1858. //end;
  1859. end;
  1860. procedure tcgz80.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1861. var
  1862. regsize,stackmisalignment: longint;
  1863. begin
  1864. regsize:=0;
  1865. stackmisalignment:=0;
  1866. { save old framepointer }
  1867. if not nostackframe then
  1868. begin
  1869. { return address }
  1870. inc(stackmisalignment,2);
  1871. list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
  1872. if current_procinfo.framepointer=NR_FRAME_POINTER_REG then
  1873. begin
  1874. { push <frame_pointer> }
  1875. inc(stackmisalignment,2);
  1876. include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
  1877. list.concat(Taicpu.op_reg(A_PUSH,NR_FRAME_POINTER_REG));
  1878. { Return address and FP are both on stack }
  1879. current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*2);
  1880. current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*2));
  1881. if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then
  1882. begin
  1883. list.concat(Taicpu.op_reg_const(A_LD,NR_FRAME_POINTER_REG,0));
  1884. list.concat(Taicpu.op_reg_reg(A_ADD,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG))
  1885. end
  1886. else
  1887. begin
  1888. internalerror(2020040301);
  1889. (*push_regs;
  1890. gen_load_frame_for_exceptfilter(list);
  1891. { Need only as much stack space as necessary to do the calls.
  1892. Exception filters don't have own local vars, and temps are 'mapped'
  1893. to the parent procedure.
  1894. maxpushedparasize is already aligned at least on x86_64. }
  1895. localsize:=current_procinfo.maxpushedparasize;*)
  1896. end;
  1897. current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG);
  1898. end
  1899. else
  1900. begin
  1901. CGmessage(cg_d_stackframe_omited);
  1902. end;
  1903. { allocate stackframe space }
  1904. if (localsize<>0) or
  1905. ((target_info.stackalign>sizeof(pint)) and
  1906. (stackmisalignment <> 0) and
  1907. ((pi_do_call in current_procinfo.flags) or
  1908. (po_assembler in current_procinfo.procdef.procoptions))) then
  1909. begin
  1910. if target_info.stackalign>sizeof(pint) then
  1911. localsize := align(localsize+stackmisalignment,target_info.stackalign)-stackmisalignment;
  1912. g_stackpointer_alloc(list,localsize);
  1913. if current_procinfo.framepointer=NR_STACK_POINTER_REG then
  1914. current_asmdata.asmcfi.cfa_def_cfa_offset(list,regsize+localsize+sizeof(pint));
  1915. current_procinfo.final_localsize:=localsize;
  1916. end
  1917. end;
  1918. end;
  1919. procedure tcgz80.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  1920. var
  1921. regs : tcpuregisterset;
  1922. reg : TSuperRegister;
  1923. LocalSize : longint;
  1924. begin
  1925. { every byte counts for Z80, so if a subroutine is marked as non-returning, we do
  1926. not generate any exit code, so we really trust the noreturn directive
  1927. }
  1928. if po_noreturn in current_procinfo.procdef.procoptions then
  1929. exit;
  1930. { remove stackframe }
  1931. if not nostackframe then
  1932. begin
  1933. stacksize:=current_procinfo.calc_stackframe_size;
  1934. if (target_info.stackalign>4) and
  1935. ((stacksize <> 0) or
  1936. (pi_do_call in current_procinfo.flags) or
  1937. { can't detect if a call in this case -> use nostackframe }
  1938. { if you (think you) know what you are doing }
  1939. (po_assembler in current_procinfo.procdef.procoptions)) then
  1940. stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint);
  1941. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  1942. begin
  1943. internalerror(2020040302);
  1944. {if (stacksize<>0) then
  1945. cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);}
  1946. end
  1947. else
  1948. begin
  1949. list.Concat(taicpu.op_reg_reg(A_LD,NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG));
  1950. list.Concat(taicpu.op_reg(A_POP,NR_FRAME_POINTER_REG));
  1951. end;
  1952. list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
  1953. end;
  1954. list.concat(taicpu.op_none(A_RET));
  1955. end;
  1956. procedure tcgz80.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  1957. var
  1958. tmpref : treference;
  1959. begin
  1960. if assigned(ref.symbol) then
  1961. begin
  1962. reference_reset(tmpref,0,[]);
  1963. tmpref.symbol:=ref.symbol;
  1964. tmpref.offset:=ref.offset;
  1965. tmpref.refaddr:=addr_lo8;
  1966. list.concat(taicpu.op_reg_ref(A_LD,r,tmpref));
  1967. tmpref.refaddr:=addr_hi8;
  1968. list.concat(taicpu.op_reg_ref(A_LD,GetNextReg(r),tmpref));
  1969. if (ref.base<>NR_NO) then
  1970. a_op_reg_reg(list,OP_ADD,OS_16,ref.base,r);
  1971. if (ref.index<>NR_NO) then
  1972. a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  1973. end
  1974. else if ref.base=NR_IX then
  1975. begin
  1976. list.concat(taicpu.op_reg(A_PUSH,NR_IX));
  1977. getcpuregister(list,NR_H);
  1978. getcpuregister(list,NR_L);
  1979. list.concat(taicpu.op_reg(A_POP,NR_HL));
  1980. emit_mov(list,r,NR_L);
  1981. ungetcpuregister(list,NR_L);
  1982. emit_mov(list,GetNextReg(r),NR_H);
  1983. ungetcpuregister(list,NR_H);
  1984. if (ref.index<>NR_NO) then
  1985. a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  1986. if ref.offset<>0 then
  1987. a_op_const_reg(list,OP_ADD,OS_16,ref.offset,r);
  1988. end
  1989. else
  1990. begin
  1991. a_load_const_reg(list,OS_16,ref.offset,r);
  1992. if (ref.base<>NR_NO) then
  1993. a_op_reg_reg(list,OP_ADD,OS_16,ref.base,r);
  1994. if (ref.index<>NR_NO) then
  1995. a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  1996. end;
  1997. end;
  1998. procedure tcgz80.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  1999. var
  2000. tmpreg,srcreg,dstreg: tregister;
  2001. srcref,dstref : treference;
  2002. i: Integer;
  2003. begin
  2004. if (len<=2) and
  2005. is_ref_in_opertypes(source,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) and
  2006. is_ref_in_opertypes(dest,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  2007. begin
  2008. srcref:=source;
  2009. dstref:=dest;
  2010. tmpreg:=getintregister(list,OS_8);
  2011. for i:=1 to len do
  2012. begin
  2013. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  2014. list.concat(taicpu.op_ref_reg(A_LD,dstref,tmpreg));
  2015. if i<>len then
  2016. begin
  2017. adjust_normalized_ref(list,srcref,1);
  2018. adjust_normalized_ref(list,dstref,1);
  2019. end;
  2020. end;
  2021. end
  2022. else
  2023. begin
  2024. srcreg:=getintregister(list,OS_16);
  2025. a_loadaddr_ref_reg(list,source,srcreg);
  2026. dstreg:=getintregister(list,OS_16);
  2027. a_loadaddr_ref_reg(list,dest,dstreg);
  2028. getcpuregister(list,NR_L);
  2029. a_load_reg_reg(list,OS_8,OS_8,srcreg,NR_L);
  2030. getcpuregister(list,NR_H);
  2031. a_load_reg_reg(list,OS_8,OS_8,GetNextReg(srcreg),NR_H);
  2032. getcpuregister(list,NR_E);
  2033. a_load_reg_reg(list,OS_8,OS_8,dstreg,NR_E);
  2034. getcpuregister(list,NR_D);
  2035. a_load_reg_reg(list,OS_8,OS_8,GetNextReg(dstreg),NR_D);
  2036. getcpuregister(list,NR_B);
  2037. getcpuregister(list,NR_C);
  2038. list.concat(taicpu.op_reg_const(A_LD,NR_BC,len));
  2039. list.concat(taicpu.op_none(A_LDIR));
  2040. ungetcpuregister(list,NR_B);
  2041. ungetcpuregister(list,NR_C);
  2042. ungetcpuregister(list,NR_D);
  2043. ungetcpuregister(list,NR_E);
  2044. ungetcpuregister(list,NR_H);
  2045. ungetcpuregister(list,NR_L);
  2046. end;
  2047. end;
  2048. procedure tcgz80.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
  2049. var
  2050. hl : tasmlabel;
  2051. ai : taicpu;
  2052. cond : TAsmCond;
  2053. begin
  2054. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: g_overflowCheck')));
  2055. //if not(cs_check_overflow in current_settings.localswitches) then
  2056. // exit;
  2057. //current_asmdata.getjumplabel(hl);
  2058. //if not ((def.typ=pointerdef) or
  2059. // ((def.typ=orddef) and
  2060. // (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2061. // pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2062. // cond:=C_VC
  2063. //else
  2064. // cond:=C_CC;
  2065. //ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2066. //ai.SetCondition(cond);
  2067. //ai.is_jmp:=true;
  2068. //list.concat(ai);
  2069. //
  2070. //a_call_name(list,'FPC_OVERFLOW',false);
  2071. //a_label(list,hl);
  2072. end;
  2073. procedure tcgz80.g_save_registers(list: TAsmList);
  2074. begin
  2075. { this is done by the entry code }
  2076. end;
  2077. procedure tcgz80.g_restore_registers(list: TAsmList);
  2078. begin
  2079. { this is done by the exit code }
  2080. end;
  2081. procedure tcgz80.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  2082. begin
  2083. case cond of
  2084. OC_EQ:
  2085. a_jmp_unsigned_cmp_3way(list,nil,l,nil);
  2086. OC_NE:
  2087. a_jmp_unsigned_cmp_3way(list,l,nil,l);
  2088. OC_A:
  2089. a_jmp_unsigned_cmp_3way(list,nil,nil,l);
  2090. OC_B:
  2091. a_jmp_unsigned_cmp_3way(list,l,nil,nil);
  2092. OC_AE:
  2093. a_jmp_unsigned_cmp_3way(list,nil,l,l);
  2094. OC_BE:
  2095. a_jmp_unsigned_cmp_3way(list,l,l,nil);
  2096. OC_GT:
  2097. a_jmp_signed_cmp_3way(list,nil,nil,l);
  2098. OC_LT:
  2099. a_jmp_signed_cmp_3way(list,l,nil,nil);
  2100. OC_GTE:
  2101. a_jmp_signed_cmp_3way(list,nil,l,l);
  2102. OC_LTE:
  2103. a_jmp_signed_cmp_3way(list,l,l,nil);
  2104. else
  2105. internalerror(2011082501);
  2106. end;
  2107. end;
  2108. procedure tcgz80.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2109. var
  2110. instr: taicpu;
  2111. begin
  2112. instr:=taicpu.op_reg_reg(A_LD,reg2,reg1);
  2113. list.Concat(instr);
  2114. { Notify the register allocator that we have written a move instruction so
  2115. it can try to eliminate it. }
  2116. add_move_instruction(instr);
  2117. end;
  2118. procedure tcg64fz80.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2119. begin
  2120. if not(size in [OS_S64,OS_64]) then
  2121. internalerror(2012102402);
  2122. tcgz80(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2123. end;
  2124. procedure tcg64fz80.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2125. begin
  2126. tcgz80(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2127. end;
  2128. function GetByteLoc(const loc : tlocation; nr : byte) : tlocation;
  2129. var
  2130. i : Integer;
  2131. begin
  2132. Result:=loc;
  2133. Result.size:=OS_8;
  2134. case loc.loc of
  2135. LOC_REFERENCE,LOC_CREFERENCE:
  2136. inc(Result.reference.offset,nr);
  2137. LOC_REGISTER,LOC_CREGISTER:
  2138. begin
  2139. if nr>=4 then
  2140. Result.register:=Result.register64.reghi;
  2141. nr:=nr mod 4;
  2142. for i:=1 to nr do
  2143. Result.register:=GetNextReg(Result.register);
  2144. end;
  2145. LOC_CONSTANT:
  2146. if loc.size in [OS_64,OS_S64] then
  2147. Result.value:=(Result.value64 shr (nr*8)) and $ff
  2148. else
  2149. Result.value:=(Result.value shr (nr*8)) and $ff;
  2150. else
  2151. Internalerror(2019020902);
  2152. end;
  2153. end;
  2154. procedure create_codegen;
  2155. begin
  2156. cg:=tcgz80.create;
  2157. cg64:=tcg64fz80.create;
  2158. end;
  2159. end.