nz80add.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. {
  2. Copyright (c) 2008 by Florian Klaempfl
  3. Code generation for add nodes on the AVR
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nz80add;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,ncgadd, symtype,cpubase;
  22. type
  23. { TZ80AddNode }
  24. TZ80AddNode = class(tcgaddnode)
  25. private
  26. function GetResFlags(unsigned:Boolean;anodetype:tnodetype):TResFlags;
  27. protected
  28. function use_mul_helper: boolean;override;
  29. function first_cmppointer: tnode;override;
  30. function pass_1 : tnode;override;
  31. procedure second_cmpordinal;override;
  32. procedure second_cmpsmallset;override;
  33. procedure second_cmp64bit;override;
  34. procedure second_cmp16_32_64bit;
  35. procedure second_cmp;
  36. end;
  37. implementation
  38. uses
  39. globtype,systems,
  40. cutils,verbose,globals,
  41. symconst,symdef,paramgr,
  42. aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
  43. cgbase,cgutils,cgcpu,
  44. cpuinfo,pass_1,pass_2,procinfo,
  45. cpupara,
  46. ncon,nset,nadd,
  47. ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32,
  48. hlcgobj;
  49. {*****************************************************************************
  50. TZ80AddNode
  51. *****************************************************************************}
  52. function TZ80AddNode.GetResFlags(unsigned: Boolean; anodetype: tnodetype): TResFlags;
  53. begin
  54. case anodetype of
  55. equaln:
  56. GetResFlags:=F_E;
  57. unequaln:
  58. GetResFlags:=F_NE;
  59. else
  60. if not(unsigned) then
  61. begin
  62. { signed }
  63. if nf_swapped in flags then
  64. case anodetype of
  65. ltn:
  66. GetResFlags:=F_NotPossible;
  67. lten:
  68. GetResFlags:=F_P;
  69. gtn:
  70. GetResFlags:=F_M;
  71. gten:
  72. GetResFlags:=F_NotPossible;
  73. else
  74. internalerror(2014082020);
  75. end
  76. else
  77. case anodetype of
  78. ltn:
  79. GetResFlags:=F_M;
  80. lten:
  81. GetResFlags:=F_NotPossible;
  82. gtn:
  83. GetResFlags:=F_NotPossible;
  84. gten:
  85. GetResFlags:=F_P;
  86. else
  87. internalerror(2014082021);
  88. end;
  89. end
  90. else
  91. begin
  92. { unsigned }
  93. if nf_swapped in Flags then
  94. case anodetype of
  95. ltn:
  96. GetResFlags:=F_NotPossible;
  97. lten:
  98. GetResFlags:=F_NC;
  99. gtn:
  100. GetResFlags:=F_C;
  101. gten:
  102. GetResFlags:=F_NotPossible;
  103. else
  104. internalerror(2014082022);
  105. end
  106. else
  107. case anodetype of
  108. ltn:
  109. GetResFlags:=F_C;
  110. lten:
  111. GetResFlags:=F_NotPossible;
  112. gtn:
  113. GetResFlags:=F_NotPossible;
  114. gten:
  115. GetResFlags:=F_NC;
  116. else
  117. internalerror(2014082023);
  118. end;
  119. end;
  120. end;
  121. end;
  122. function TZ80AddNode.use_mul_helper: boolean;
  123. begin
  124. result:=(nodetype=muln);
  125. end;
  126. function TZ80AddNode.first_cmppointer: tnode;
  127. begin
  128. result:=nil;
  129. expectloc:=LOC_JUMP;
  130. end;
  131. procedure TZ80AddNode.second_cmpsmallset;
  132. begin
  133. case nodetype of
  134. equaln,unequaln:
  135. begin
  136. if left.resultdef.size>=2 then
  137. internalerror(2021100302);
  138. second_cmp;
  139. end;
  140. lten,gten:
  141. begin
  142. if left.resultdef.size>=2 then
  143. internalerror(2021100302);
  144. pass_left_right;
  145. if (not(nf_swapped in flags) and (nodetype = lten)) or
  146. ((nf_swapped in flags) and (nodetype = gten)) then
  147. swapleftright;
  148. if left.location.loc<>LOC_REGISTER then
  149. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  150. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  151. begin
  152. if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  153. begin
  154. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  155. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  156. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_AND,NR_A,right.location.reference));
  157. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_CP,NR_A,right.location.reference));
  158. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  159. end
  160. else
  161. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
  162. end;
  163. case right.location.loc of
  164. LOC_CONSTANT:
  165. begin
  166. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  167. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  168. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_AND,NR_A,right.location.value));
  169. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_CP,NR_A,right.location.value));
  170. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  171. end;
  172. LOC_REGISTER,LOC_CREGISTER:
  173. begin
  174. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  175. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  176. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_AND,NR_A,right.location.register));
  177. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_CP,NR_A,right.location.register));
  178. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  179. end;
  180. LOC_REFERENCE,LOC_CREFERENCE:
  181. begin
  182. { Already handled before the case statement. Nothing to do here. }
  183. end;
  184. else
  185. internalerror(2021100303);
  186. end;
  187. location_reset(location,LOC_FLAGS,OS_NO);
  188. location.resflags:=F_E;
  189. end
  190. else
  191. internalerror(2021100301);
  192. end;
  193. end;
  194. procedure TZ80AddNode.second_cmp;
  195. var
  196. unsigned : boolean;
  197. tmpreg1,tmpreg2 : tregister;
  198. i : longint;
  199. opdef: tdef;
  200. opsize: TCgSize;
  201. l: TAsmLabel;
  202. begin
  203. unsigned:=not(is_signed(left.resultdef)) or
  204. not(is_signed(right.resultdef));
  205. opdef:=left.resultdef;
  206. opsize:=def_cgsize(opdef);
  207. pass_left_right;
  208. if (opsize=OS_8) or ((opsize=OS_S8) and (NodeType in [equaln,unequaln])) then
  209. begin
  210. if getresflags(unsigned,NodeType)=F_NotPossible then
  211. swapleftright;
  212. if left.location.loc<>LOC_REGISTER then
  213. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  214. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  215. begin
  216. if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  217. begin
  218. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  219. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  220. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_CP,NR_A,right.location.reference));
  221. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  222. end
  223. else
  224. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
  225. end;
  226. case right.location.loc of
  227. LOC_CONSTANT:
  228. begin
  229. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  230. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  231. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_CP,NR_A,right.location.value));
  232. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  233. end;
  234. LOC_REGISTER,LOC_CREGISTER:
  235. begin
  236. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  237. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  238. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_CP,NR_A,right.location.register));
  239. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  240. end;
  241. LOC_REFERENCE,LOC_CREFERENCE:
  242. begin
  243. { Already handled before the case statement. Nothing to do here. }
  244. end;
  245. else
  246. internalerror(2020040402);
  247. end;
  248. location_reset(location,LOC_FLAGS,OS_NO);
  249. location.resflags:=getresflags(unsigned,NodeType);
  250. end
  251. else if opsize=OS_S8 then
  252. begin
  253. if getresflags(unsigned,NodeType)=F_NotPossible then
  254. swapleftright;
  255. if left.location.loc<>LOC_REGISTER then
  256. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  257. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  258. begin
  259. if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  260. begin
  261. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  262. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  263. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_SUB,NR_A,right.location.reference));
  264. end
  265. else
  266. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
  267. end;
  268. case right.location.loc of
  269. LOC_CONSTANT:
  270. begin
  271. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  272. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  273. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SUB,NR_A,right.location.value));
  274. end;
  275. LOC_REGISTER,LOC_CREGISTER:
  276. begin
  277. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  278. cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
  279. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_SUB,NR_A,right.location.register));
  280. end;
  281. LOC_REFERENCE,LOC_CREFERENCE:
  282. begin
  283. { Already handled before the case statement. Nothing to do here. }
  284. end;
  285. else
  286. internalerror(2020040403);
  287. end;
  288. current_asmdata.getjumplabel(l);
  289. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_PO,l);
  290. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  291. cg.a_label(current_asmdata.CurrAsmList,l);
  292. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  293. location_reset(location,LOC_FLAGS,OS_NO);
  294. location.resflags:=getresflags(unsigned,NodeType);
  295. end
  296. else
  297. internalerror(2020040401);
  298. end;
  299. procedure TZ80AddNode.second_cmp64bit;
  300. begin
  301. second_cmp16_32_64bit;
  302. end;
  303. procedure TZ80AddNode.second_cmp16_32_64bit;
  304. var
  305. truelabel,
  306. falselabel: tasmlabel;
  307. unsigned : boolean;
  308. i, size: Integer;
  309. tmpref: treference;
  310. op: TAsmOp;
  311. actualnodetype: tnodetype;
  312. begin
  313. truelabel:=nil;
  314. falselabel:=nil;
  315. pass_left_right;
  316. unsigned:=not(is_signed(left.resultdef)) or
  317. not(is_signed(right.resultdef));
  318. { we have LOC_JUMP as result }
  319. current_asmdata.getjumplabel(truelabel);
  320. current_asmdata.getjumplabel(falselabel);
  321. location_reset_jump(location,truelabel,falselabel);
  322. size:=tcgsize2size[def_cgsize(left.resultdef)];
  323. if NodeType in [equaln,unequaln] then
  324. begin
  325. if left.location.loc<>LOC_REGISTER then
  326. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  327. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  328. begin
  329. if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  330. begin
  331. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  332. tmpref:=right.location.reference;
  333. for i:=0 to size-1 do
  334. begin
  335. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
  336. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_CP,NR_A,tmpref));
  337. case NodeType of
  338. equaln:
  339. if i<>(size-1) then
  340. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,falselabel)
  341. else
  342. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,truelabel);
  343. unequaln:
  344. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,truelabel);
  345. else
  346. internalerror(2020042102);
  347. end;
  348. if i<>(size-1) then
  349. tcgz80(cg).adjust_normalized_ref(current_asmdata.CurrAsmList,tmpref,1);
  350. end;
  351. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  352. cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
  353. end
  354. else
  355. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
  356. end;
  357. case right.location.loc of
  358. LOC_CONSTANT:
  359. begin
  360. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  361. for i:=0 to size-1 do
  362. begin
  363. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
  364. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_CP,NR_A,byte(right.location.value shr (i*8))));
  365. case NodeType of
  366. equaln:
  367. if i<>(size-1) then
  368. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,falselabel)
  369. else
  370. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,truelabel);
  371. unequaln:
  372. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,truelabel);
  373. else
  374. internalerror(2020042104);
  375. end;
  376. end;
  377. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  378. cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
  379. end;
  380. LOC_REGISTER,LOC_CREGISTER:
  381. begin
  382. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  383. for i:=0 to size-1 do
  384. begin
  385. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
  386. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_CP,NR_A,tcgz80(cg).GetOffsetReg64(right.location.register,right.location.registerhi,i)));
  387. case NodeType of
  388. equaln:
  389. if i<>(size-1) then
  390. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,falselabel)
  391. else
  392. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,truelabel);
  393. unequaln:
  394. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,truelabel);
  395. else
  396. internalerror(2020042105);
  397. end;
  398. end;
  399. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  400. cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
  401. end;
  402. LOC_REFERENCE,LOC_CREFERENCE:
  403. begin
  404. { Already handled before the case statement. Nothing to do here. }
  405. end;
  406. else
  407. internalerror(2020042103);
  408. end;
  409. end
  410. else
  411. begin
  412. if nf_swapped in Flags then
  413. begin
  414. case NodeType of
  415. ltn:
  416. actualnodetype:=gtn;
  417. lten:
  418. actualnodetype:=gten;
  419. gtn:
  420. actualnodetype:=ltn;
  421. gten:
  422. actualnodetype:=lten;
  423. else
  424. internalerror(2020042701);
  425. end;
  426. end
  427. else
  428. actualnodetype:=NodeType;
  429. if left.location.loc<>LOC_REGISTER then
  430. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  431. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  432. begin
  433. if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  434. begin
  435. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  436. tmpref:=right.location.reference;
  437. tcgz80(cg).adjust_normalized_ref(current_asmdata.CurrAsmList,tmpref,size-1);
  438. for i:=size-1 downto 0 do
  439. begin
  440. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
  441. if (i=(size-1)) and (not unsigned) then
  442. op:=A_SUB
  443. else
  444. op:=A_CP;
  445. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(op,NR_A,tmpref));
  446. if (i=(size-1)) and (not unsigned) then
  447. case actualnodetype of
  448. ltn,
  449. lten:
  450. tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
  451. gtn,
  452. gten:
  453. tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
  454. else
  455. internalerror(2020042202);
  456. end
  457. else if i<>0 then
  458. case actualnodetype of
  459. ltn,
  460. lten:
  461. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
  462. gtn,
  463. gten:
  464. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
  465. else
  466. internalerror(2020042207);
  467. end
  468. else
  469. case actualnodetype of
  470. ltn:
  471. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,falselabel,falselabel);
  472. lten:
  473. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,truelabel,falselabel);
  474. gtn:
  475. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,falselabel,truelabel);
  476. gten:
  477. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,truelabel,truelabel);
  478. else
  479. internalerror(2020042203);
  480. end;
  481. if i<>0 then
  482. tcgz80(cg).adjust_normalized_ref(current_asmdata.CurrAsmList,tmpref,-1);
  483. end;
  484. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  485. end
  486. else
  487. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
  488. end;
  489. case right.location.loc of
  490. LOC_CONSTANT:
  491. begin
  492. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  493. for i:=size-1 downto 0 do
  494. begin
  495. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
  496. if (i=(size-1)) and (not unsigned) then
  497. op:=A_SUB
  498. else
  499. op:=A_CP;
  500. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(op,NR_A,byte(right.location.value shr (i*8))));
  501. if (i=(size-1)) and (not unsigned) then
  502. case actualnodetype of
  503. ltn,
  504. lten:
  505. tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
  506. gtn,
  507. gten:
  508. tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
  509. else
  510. internalerror(2020042210);
  511. end
  512. else if i<>0 then
  513. case actualnodetype of
  514. ltn,
  515. lten:
  516. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
  517. gtn,
  518. gten:
  519. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
  520. else
  521. internalerror(2020042211);
  522. end
  523. else
  524. case actualnodetype of
  525. ltn:
  526. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,falselabel,falselabel);
  527. lten:
  528. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,truelabel,falselabel);
  529. gtn:
  530. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,falselabel,truelabel);
  531. gten:
  532. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,truelabel,truelabel);
  533. else
  534. internalerror(2020042215);
  535. end;
  536. end;
  537. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  538. end;
  539. LOC_REGISTER,LOC_CREGISTER:
  540. begin
  541. cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
  542. for i:=size-1 downto 0 do
  543. begin
  544. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
  545. if (i=(size-1)) and (not unsigned) then
  546. op:=A_SUB
  547. else
  548. op:=A_CP;
  549. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(op,NR_A,tcgz80(cg).GetOffsetReg64(right.location.register,right.location.registerhi,i)));
  550. if (i=(size-1)) and (not unsigned) then
  551. case actualnodetype of
  552. ltn,
  553. lten:
  554. tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
  555. gtn,
  556. gten:
  557. tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
  558. else
  559. internalerror(2020042212);
  560. end
  561. else if i<>0 then
  562. case actualnodetype of
  563. ltn,
  564. lten:
  565. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
  566. gtn,
  567. gten:
  568. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
  569. else
  570. internalerror(2020042213);
  571. end
  572. else
  573. case actualnodetype of
  574. ltn:
  575. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,falselabel,falselabel);
  576. lten:
  577. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,truelabel,falselabel);
  578. gtn:
  579. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,falselabel,truelabel);
  580. gten:
  581. tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,truelabel,truelabel);
  582. else
  583. internalerror(2020042216);
  584. end;
  585. end;
  586. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
  587. end;
  588. LOC_REFERENCE,LOC_CREFERENCE:
  589. begin
  590. { Already handled before the case statement. Nothing to do here. }
  591. end;
  592. else
  593. internalerror(2020042106);
  594. end;
  595. end;
  596. end;
  597. function TZ80AddNode.pass_1 : tnode;
  598. begin
  599. result:=inherited pass_1;
  600. {$ifdef dummy}
  601. if not(assigned(result)) then
  602. begin
  603. unsigned:=not(is_signed(left.resultdef)) or
  604. not(is_signed(right.resultdef));
  605. if is_64bit(left.resultdef) and
  606. ((nodetype in [equaln,unequaln]) or
  607. (unsigned and (nodetype in [ltn,lten,gtn,gten]))
  608. ) then
  609. expectloc:=LOC_FLAGS;
  610. end;
  611. { handling boolean expressions }
  612. if not(assigned(result)) and
  613. (
  614. not(is_boolean(left.resultdef)) or
  615. not(is_boolean(right.resultdef)) or
  616. is_dynamic_array(left.resultdef)
  617. ) then
  618. expectloc:=LOC_FLAGS;
  619. {$endif dummy}
  620. end;
  621. procedure TZ80AddNode.second_cmpordinal;
  622. begin
  623. if left.resultdef.size>=2 then
  624. second_cmp16_32_64bit
  625. else
  626. second_cmp;
  627. end;
  628. begin
  629. caddnode:=TZ80AddNode;
  630. end.