narmadd.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Code generation for add nodes on the ARM
  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 narmadd;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,ncgadd,cpubase;
  22. type
  23. tarmaddnode = class(tcgaddnode)
  24. private
  25. function GetResFlags(unsigned:Boolean):TResFlags;
  26. public
  27. function pass_1 : tnode;override;
  28. function use_generic_mul32to64: boolean; override;
  29. function use_generic_mul64bit: boolean; override;
  30. protected
  31. function first_addfloat: tnode; override;
  32. procedure second_addordinal;override;
  33. procedure second_addfloat;override;
  34. procedure second_cmpfloat;override;
  35. procedure second_cmpordinal;override;
  36. procedure second_cmpsmallset;override;
  37. procedure second_cmp64bit;override;
  38. procedure second_add64bit;override;
  39. end;
  40. implementation
  41. uses
  42. globtype,verbose,globals,systems,
  43. constexp,symdef,symtable,symtype,symconst,
  44. aasmbase,aasmdata,aasmcpu,
  45. defutil,htypechk,cgbase,cgutils,
  46. cpuinfo,pass_1,pass_2,procinfo,
  47. ncon,nadd,ncnv,ncal,nmat,
  48. ncgutil,cgobj,cgcpu,
  49. hlcgobj
  50. ;
  51. {*****************************************************************************
  52. TSparcAddNode
  53. *****************************************************************************}
  54. function tarmaddnode.GetResFlags(unsigned:Boolean):TResFlags;
  55. begin
  56. case NodeType of
  57. equaln:
  58. GetResFlags:=F_EQ;
  59. unequaln:
  60. GetResFlags:=F_NE;
  61. else
  62. if not(unsigned) then
  63. begin
  64. if nf_swapped in flags then
  65. case NodeType of
  66. ltn:
  67. GetResFlags:=F_GT;
  68. lten:
  69. GetResFlags:=F_GE;
  70. gtn:
  71. GetResFlags:=F_LT;
  72. gten:
  73. GetResFlags:=F_LE;
  74. end
  75. else
  76. case NodeType of
  77. ltn:
  78. GetResFlags:=F_LT;
  79. lten:
  80. GetResFlags:=F_LE;
  81. gtn:
  82. GetResFlags:=F_GT;
  83. gten:
  84. GetResFlags:=F_GE;
  85. end;
  86. end
  87. else
  88. begin
  89. if nf_swapped in Flags then
  90. case NodeType of
  91. ltn:
  92. GetResFlags:=F_HI;
  93. lten:
  94. GetResFlags:=F_CS;
  95. gtn:
  96. GetResFlags:=F_CC;
  97. gten:
  98. GetResFlags:=F_LS;
  99. end
  100. else
  101. case NodeType of
  102. ltn:
  103. GetResFlags:=F_CC;
  104. lten:
  105. GetResFlags:=F_LS;
  106. gtn:
  107. GetResFlags:=F_HI;
  108. gten:
  109. GetResFlags:=F_CS;
  110. end;
  111. end;
  112. end;
  113. end;
  114. procedure tarmaddnode.second_addfloat;
  115. var
  116. op : TAsmOp;
  117. singleprec: boolean;
  118. begin
  119. pass_left_right;
  120. if (nf_swapped in flags) then
  121. swapleftright;
  122. case current_settings.fputype of
  123. fpu_fpa,
  124. fpu_fpa10,
  125. fpu_fpa11:
  126. begin
  127. { force fpureg as location, left right doesn't matter
  128. as both will be in a fpureg }
  129. location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
  130. location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
  131. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  132. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  133. case nodetype of
  134. addn :
  135. op:=A_ADF;
  136. muln :
  137. op:=A_MUF;
  138. subn :
  139. op:=A_SUF;
  140. slashn :
  141. op:=A_DVF;
  142. else
  143. internalerror(200308313);
  144. end;
  145. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op,
  146. location.register,left.location.register,right.location.register),
  147. cgsize2fpuoppostfix[def_cgsize(resultdef)]));
  148. end;
  149. fpu_vfpv2,
  150. fpu_vfpv3,
  151. fpu_vfpv3_d16:
  152. begin
  153. { force mmreg as location, left right doesn't matter
  154. as both will be in a fpureg }
  155. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  156. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
  157. location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
  158. location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
  159. singleprec:=tfloatdef(left.resultdef).floattype=s32real;
  160. case nodetype of
  161. addn :
  162. if singleprec then
  163. op:=A_FADDS
  164. else
  165. op:=A_FADDD;
  166. muln :
  167. if singleprec then
  168. op:=A_FMULS
  169. else
  170. op:=A_FMULD;
  171. subn :
  172. if singleprec then
  173. op:=A_FSUBS
  174. else
  175. op:=A_FSUBD;
  176. slashn :
  177. if singleprec then
  178. op:=A_FDIVS
  179. else
  180. op:=A_FDIVD;
  181. else
  182. internalerror(2009111401);
  183. end;
  184. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
  185. location.register,left.location.register,right.location.register));
  186. end;
  187. fpu_fpv4_s16:
  188. begin
  189. { force mmreg as location, left right doesn't matter
  190. as both will be in a fpureg }
  191. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  192. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
  193. location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
  194. location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
  195. case nodetype of
  196. addn :
  197. op:=A_VADD;
  198. muln :
  199. op:=A_VMUL;
  200. subn :
  201. op:=A_VSUB;
  202. slashn :
  203. op:=A_VDIV;
  204. else
  205. internalerror(2009111401);
  206. end;
  207. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op, location.register,left.location.register,right.location.register), PF_F32));
  208. end;
  209. fpu_soft:
  210. { this case should be handled already by pass1 }
  211. internalerror(200308252);
  212. else
  213. internalerror(200308251);
  214. end;
  215. end;
  216. procedure tarmaddnode.second_cmpfloat;
  217. var
  218. op: TAsmOp;
  219. begin
  220. pass_left_right;
  221. if (nf_swapped in flags) then
  222. swapleftright;
  223. location_reset(location,LOC_FLAGS,OS_NO);
  224. location.resflags:=getresflags(true);
  225. case current_settings.fputype of
  226. fpu_fpa,
  227. fpu_fpa10,
  228. fpu_fpa11:
  229. begin
  230. { force fpureg as location, left right doesn't matter
  231. as both will be in a fpureg }
  232. location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
  233. location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
  234. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  235. if nodetype in [equaln,unequaln] then
  236. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMF,
  237. left.location.register,right.location.register),
  238. cgsize2fpuoppostfix[def_cgsize(resultdef)]))
  239. else
  240. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMFE,
  241. left.location.register,right.location.register),
  242. cgsize2fpuoppostfix[def_cgsize(resultdef)]));
  243. end;
  244. fpu_vfpv2,
  245. fpu_vfpv3,
  246. fpu_vfpv3_d16:
  247. begin
  248. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  249. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
  250. if (tfloatdef(left.resultdef).floattype=s32real) then
  251. if nodetype in [equaln,unequaln] then
  252. op:=A_FCMPS
  253. else
  254. op:=A_FCMPES
  255. else if nodetype in [equaln,unequaln] then
  256. op:=A_FCMPD
  257. else
  258. op:=A_FCMPED;
  259. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
  260. left.location.register,right.location.register));
  261. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  262. current_asmdata.CurrAsmList.concat(taicpu.op_none(A_FMSTAT));
  263. end;
  264. fpu_fpv4_s16:
  265. begin
  266. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  267. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
  268. if nodetype in [equaln,unequaln] then
  269. op:=A_VCMP
  270. else
  271. op:=A_VCMPE;
  272. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
  273. left.location.register,right.location.register));
  274. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  275. current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_VMRS, NR_APSR_nzcv, NR_FPSCR));
  276. end;
  277. fpu_soft:
  278. { this case should be handled already by pass1 }
  279. internalerror(2009112404);
  280. end;
  281. location_reset(location,LOC_FLAGS,OS_NO);
  282. location.resflags:=getresflags(false);
  283. end;
  284. procedure tarmaddnode.second_cmpsmallset;
  285. var
  286. tmpreg : tregister;
  287. b: byte;
  288. begin
  289. pass_left_right;
  290. location_reset(location,LOC_FLAGS,OS_NO);
  291. if (not(nf_swapped in flags) and
  292. (nodetype = lten)) or
  293. ((nf_swapped in flags) and
  294. (nodetype = gten)) then
  295. swapleftright;
  296. (* Try to keep right as a constant *)
  297. if (right.location.loc <> LOC_CONSTANT) or
  298. not(is_shifter_const(right.location.value, b)) or
  299. ((GenerateThumbCode) and not(is_thumb_imm(right.location.value))) then
  300. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
  301. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  302. case nodetype of
  303. equaln,
  304. unequaln:
  305. begin
  306. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  307. if right.location.loc = LOC_CONSTANT then
  308. current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,left.location.register,right.location.value))
  309. else
  310. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
  311. if nodetype = equaln then
  312. location.resflags:=F_EQ
  313. else
  314. location.resflags:=F_NE;
  315. end;
  316. lten,
  317. gten:
  318. begin
  319. tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  320. if right.location.loc = LOC_CONSTANT then
  321. begin
  322. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_AND,tmpreg,left.location.register,right.location.value));
  323. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  324. current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,tmpreg,right.location.value));
  325. end
  326. else
  327. begin
  328. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register));
  329. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  330. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register));
  331. end;
  332. location.resflags:=F_EQ;
  333. end;
  334. else
  335. internalerror(2004012401);
  336. end;
  337. end;
  338. procedure tarmaddnode.second_cmp64bit;
  339. var
  340. unsigned : boolean;
  341. oldnodetype : tnodetype;
  342. dummyreg : tregister;
  343. l: tasmlabel;
  344. begin
  345. unsigned:=not(is_signed(left.resultdef)) or
  346. not(is_signed(right.resultdef));
  347. pass_left_right;
  348. { pass_left_right moves possible consts to the right, the only
  349. remaining case with left consts (currency) can take this path too (KB) }
  350. if (nodetype in [equaln,unequaln]) and
  351. (right.nodetype=ordconstn) and (tordconstnode(right).value=0) then
  352. begin
  353. location_reset(location,LOC_FLAGS,OS_NO);
  354. location.resflags:=getresflags(unsigned);
  355. if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  356. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  357. dummyreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  358. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  359. if GenerateThumbCode then
  360. cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reglo,left.location.register64.reghi,dummyreg)
  361. else
  362. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ORR,dummyreg,left.location.register64.reglo,left.location.register64.reghi),PF_S));
  363. end
  364. else
  365. begin
  366. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  367. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
  368. { operation requiring proper N, Z and C flags ? }
  369. if unsigned or (nodetype in [equaln,unequaln]) then
  370. begin
  371. location_reset(location,LOC_FLAGS,OS_NO);
  372. location.resflags:=getresflags(unsigned);
  373. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  374. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
  375. if GenerateThumbCode or GenerateThumb2Code then
  376. begin
  377. current_asmdata.getjumplabel(l);
  378. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,l);
  379. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo));
  380. cg.a_label(current_asmdata.CurrAsmList,l);
  381. end
  382. else
  383. current_asmdata.CurrAsmList.concat(setcondition(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo),C_EQ));
  384. end
  385. else
  386. { operation requiring proper N, Z and V flags ? }
  387. begin
  388. location_reset(location,LOC_JUMP,OS_NO);
  389. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  390. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
  391. { the jump the sequence is a little bit hairy }
  392. case nodetype of
  393. ltn,gtn:
  394. begin
  395. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),current_procinfo.CurrTrueLabel);
  396. { cheat a little bit for the negative test }
  397. toggleflag(nf_swapped);
  398. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),current_procinfo.CurrFalseLabel);
  399. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  400. toggleflag(nf_swapped);
  401. end;
  402. lten,gten:
  403. begin
  404. oldnodetype:=nodetype;
  405. if nodetype=lten then
  406. nodetype:=ltn
  407. else
  408. nodetype:=gtn;
  409. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
  410. { cheat for the negative test }
  411. if nodetype=ltn then
  412. nodetype:=gtn
  413. else
  414. nodetype:=ltn;
  415. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
  416. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  417. nodetype:=oldnodetype;
  418. end;
  419. end;
  420. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  421. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo));
  422. { the comparisaion of the low dword have to be
  423. always unsigned! }
  424. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
  425. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  426. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  427. end;
  428. end;
  429. end;
  430. procedure tarmaddnode.second_add64bit;
  431. var
  432. asmList : TAsmList;
  433. ll,rl,res : TRegister64;
  434. tmpreg: TRegister;
  435. begin
  436. if (nodetype in [muln]) then
  437. begin
  438. asmList := current_asmdata.CurrAsmList;
  439. pass_left_right;
  440. force_reg_left_right(true, false);
  441. set_result_location_reg;
  442. { shortcuts to register64s }
  443. ll:=left.location.register64;
  444. rl:=right.location.register64;
  445. res:=location.register64;
  446. tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  447. asmList.concat(taicpu.op_reg_reg_reg(A_MUL,tmpreg,ll.reglo,rl.reghi));
  448. asmList.concat(taicpu.op_reg_reg_reg_reg(A_UMULL,res.reglo,res.reghi,rl.reglo,ll.reglo));
  449. tbasecgarm(cg).safe_mla(asmList,tmpreg,rl.reglo,ll.reghi,tmpreg);
  450. asmList.concat(taicpu.op_reg_reg_reg(A_ADD,res.reghi,tmpreg,res.reghi));
  451. end
  452. else
  453. inherited second_add64bit;
  454. end;
  455. function tarmaddnode.pass_1 : tnode;
  456. var
  457. unsigned : boolean;
  458. begin
  459. result:=inherited pass_1;
  460. if not(assigned(result)) then
  461. begin
  462. unsigned:=not(is_signed(left.resultdef)) or
  463. not(is_signed(right.resultdef));
  464. if is_64bit(left.resultdef) and
  465. ((nodetype in [equaln,unequaln]) or
  466. (unsigned and (nodetype in [ltn,lten,gtn,gten]))
  467. ) then
  468. expectloc:=LOC_FLAGS;
  469. end;
  470. end;
  471. function tarmaddnode.first_addfloat: tnode;
  472. var
  473. procname: string[31];
  474. { do we need to reverse the result ? }
  475. notnode : boolean;
  476. fdef : tdef;
  477. begin
  478. result := nil;
  479. notnode := false;
  480. if current_settings.fputype = fpu_fpv4_s16 then
  481. begin
  482. case tfloatdef(left.resultdef).floattype of
  483. s32real:
  484. begin
  485. result:=nil;
  486. notnode:=false;
  487. end;
  488. s64real:
  489. begin
  490. fdef:=search_system_type('FLOAT64').typedef;
  491. procname:='float64';
  492. case nodetype of
  493. addn:
  494. procname:=procname+'_add';
  495. muln:
  496. procname:=procname+'_mul';
  497. subn:
  498. procname:=procname+'_sub';
  499. slashn:
  500. procname:=procname+'_div';
  501. ltn:
  502. procname:=procname+'_lt';
  503. lten:
  504. procname:=procname+'_le';
  505. gtn:
  506. begin
  507. procname:=procname+'_le';
  508. notnode:=true;
  509. end;
  510. gten:
  511. begin
  512. procname:=procname+'_lt';
  513. notnode:=true;
  514. end;
  515. equaln:
  516. procname:=procname+'_eq';
  517. unequaln:
  518. begin
  519. procname:=procname+'_eq';
  520. notnode:=true;
  521. end;
  522. else
  523. CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),left.resultdef.typename,right.resultdef.typename);
  524. end;
  525. if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
  526. resultdef:=pasbool8type;
  527. result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create(
  528. ctypeconvnode.create_internal(right,fdef),
  529. ccallparanode.create(
  530. ctypeconvnode.create_internal(left,fdef),nil))),resultdef);
  531. left:=nil;
  532. right:=nil;
  533. { do we need to reverse the result }
  534. if notnode then
  535. result:=cnotnode.create(result);
  536. end;
  537. end;
  538. end
  539. else
  540. result:=inherited first_addfloat;
  541. end;
  542. procedure tarmaddnode.second_cmpordinal;
  543. var
  544. unsigned : boolean;
  545. tmpreg : tregister;
  546. b : byte;
  547. begin
  548. pass_left_right;
  549. force_reg_left_right(true,true);
  550. unsigned:=not(is_signed(left.resultdef)) or
  551. not(is_signed(right.resultdef));
  552. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  553. if right.location.loc = LOC_CONSTANT then
  554. begin
  555. if (not(GenerateThumbCode) and is_shifter_const(right.location.value,b)) or
  556. ((GenerateThumbCode) and is_thumb_imm(right.location.value)) then
  557. current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,left.location.register,right.location.value))
  558. else
  559. begin
  560. tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  561. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
  562. right.location.value,tmpreg);
  563. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,tmpreg));
  564. end;
  565. end
  566. else
  567. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
  568. location_reset(location,LOC_FLAGS,OS_NO);
  569. location.resflags:=getresflags(unsigned);
  570. end;
  571. const
  572. multops: array[boolean] of TAsmOp = (A_SMULL, A_UMULL);
  573. procedure tarmaddnode.second_addordinal;
  574. var
  575. unsigned: boolean;
  576. begin
  577. if (nodetype=muln) and
  578. is_64bit(resultdef) and
  579. not(GenerateThumbCode) and
  580. (CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]) then
  581. begin
  582. pass_left_right;
  583. force_reg_left_right(true, false);
  584. set_result_location_reg;
  585. unsigned:=not(is_signed(left.resultdef)) or
  586. not(is_signed(right.resultdef));
  587. current_asmdata.CurrAsmList.Concat(
  588. taicpu.op_reg_reg_reg_reg(multops[unsigned], location.register64.reglo, location.register64.reghi,
  589. left.location.register,right.location.register));
  590. end
  591. else
  592. inherited second_addordinal;
  593. end;
  594. function tarmaddnode.use_generic_mul32to64: boolean;
  595. begin
  596. result:=GenerateThumbCode or not(CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]);
  597. end;
  598. function tarmaddnode.use_generic_mul64bit: boolean;
  599. begin
  600. result:=GenerateThumbCode or
  601. not(CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]) or
  602. (cs_check_overflow in current_settings.localswitches);
  603. end;
  604. begin
  605. caddnode:=tarmaddnode;
  606. end.