cgcpu.pas 75 KB

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