cgcpu.pas 75 KB

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