ncgmat.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate generic mathematical nodes
  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 ncgmat;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. symtype,
  22. node,nmat,cpubase,cgbase;
  23. type
  24. tcgunaryminusnode = class(tunaryminusnode)
  25. protected
  26. { This routine is called to change the sign of the
  27. floating point value in the floating point
  28. register r.
  29. This routine should be overridden, since
  30. the generic version is not optimal at all. The
  31. generic version assumes that floating
  32. point values are stored in the register
  33. in IEEE-754 format.
  34. }
  35. procedure emit_float_sign_change(r: tregister; _size : tdef);virtual;
  36. {$ifdef SUPPORT_MMX}
  37. procedure second_mmx;virtual;abstract;
  38. {$endif SUPPORT_MMX}
  39. {$ifndef cpu64bitalu}
  40. procedure second_64bit;virtual;
  41. {$endif not cpu64bitalu}
  42. procedure second_integer;virtual;
  43. procedure second_float;virtual;
  44. procedure second_float_emulated;virtual;
  45. public
  46. procedure pass_generate_code;override;
  47. end;
  48. tcgmoddivnode = class(tmoddivnode)
  49. procedure pass_generate_code;override;
  50. protected
  51. { This routine must do an actual 32-bit division, be it
  52. signed or unsigned. The result must set into the the
  53. @var(num) register.
  54. @param(signed Indicates if the division must be signed)
  55. @param(denum Register containing the denominator
  56. @param(num Register containing the numerator, will also receive result)
  57. The actual optimizations regarding shifts have already
  58. been done and emitted, so this should really a do a divide.
  59. }
  60. procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
  61. { This routine must do an actual 32-bit modulo, be it
  62. signed or unsigned. The result must set into the the
  63. @var(num) register.
  64. @param(signed Indicates if the modulo must be signed)
  65. @param(denum Register containing the denominator
  66. @param(num Register containing the numerator, will also receive result)
  67. The actual optimizations regarding shifts have already
  68. been done and emitted, so this should really a do a modulo.
  69. }
  70. procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
  71. {$ifndef cpu64bitalu}
  72. { This routine must do an actual 64-bit division, be it
  73. signed or unsigned. The result must set into the the
  74. @var(num) register.
  75. @param(signed Indicates if the division must be signed)
  76. @param(denum Register containing the denominator
  77. @param(num Register containing the numerator, will also receive result)
  78. The actual optimizations regarding shifts have already
  79. been done and emitted, so this should really a do a divide.
  80. Currently, this routine should only be implemented on
  81. 64-bit systems, otherwise a helper is called in 1st pass.
  82. }
  83. procedure emit64_div_reg_reg(signed: boolean;denum,num : tregister64);virtual;
  84. {$endif not cpu64bitalu}
  85. end;
  86. tcgshlshrnode = class(tshlshrnode)
  87. {$ifdef SUPPORT_MMX}
  88. procedure second_mmx;virtual;abstract;
  89. {$endif SUPPORT_MMX}
  90. {$ifndef cpu64bitalu}
  91. procedure second_64bit;virtual;
  92. {$endif not cpu64bitalu}
  93. procedure second_integer;virtual;
  94. procedure pass_generate_code;override;
  95. end;
  96. tcgnotnode = class(tnotnode)
  97. protected
  98. function handle_locjump: boolean;
  99. procedure second_boolean;virtual;abstract;
  100. {$ifdef SUPPORT_MMX}
  101. procedure second_mmx;virtual;abstract;
  102. {$endif SUPPORT_MMX}
  103. {$ifndef cpu64bitalu}
  104. procedure second_64bit;virtual;
  105. {$endif not cpu64bitalu}
  106. procedure second_integer;virtual;
  107. public
  108. procedure pass_generate_code;override;
  109. end;
  110. implementation
  111. uses
  112. globtype,systems,
  113. cutils,verbose,globals,
  114. symtable,symconst,symdef,aasmbase,aasmdata,aasmcpu,defutil,
  115. parabase,
  116. pass_2,
  117. ncon,
  118. tgobj,cgobj,cgutils,paramgr,hlcgobj;
  119. {*****************************************************************************
  120. TCGUNARYMINUSNODE
  121. *****************************************************************************}
  122. procedure tcgunaryminusnode.emit_float_sign_change(r: tregister; _size : tdef);
  123. var
  124. href,
  125. href2 : treference;
  126. begin
  127. { get a temporary memory reference to store the floating
  128. point value
  129. }
  130. tg.gethltemp(current_asmdata.CurrAsmList,_size,_size.size,tt_normal,href);
  131. { store the floating point value in the temporary memory area }
  132. case getregtype(r) of
  133. R_FPUREGISTER:
  134. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,_size,_size,r,href);
  135. R_MMREGISTER:
  136. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,_size,_size,r,href,mms_movescalar);
  137. else
  138. internalerror(2015091005);
  139. end;
  140. { only single and double ieee are supported, for little endian
  141. the signed bit is in the second dword }
  142. href2:=href;
  143. if _size.typ<>floatdef then
  144. internalerror(2014012211);
  145. case tfloatdef(_size).floattype of
  146. s64real,
  147. s64comp,
  148. s64currency:
  149. if target_info.endian = endian_little then
  150. inc(href2.offset,4);
  151. s32real :
  152. ;
  153. else
  154. internalerror(200406021);
  155. end;
  156. { flip sign-bit (bit 31/63) of single/double }
  157. hlcg.a_op_const_ref(current_asmdata.CurrAsmList,OP_XOR,u32inttype,
  158. {$ifdef cpu64bitalu}
  159. aint($80000000),
  160. {$else cpu64bitalu}
  161. longint($80000000),
  162. {$endif cpu64bitalu}
  163. href2);
  164. case getregtype(r) of
  165. R_FPUREGISTER:
  166. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,_size,_size,href,r);
  167. R_MMREGISTER:
  168. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,_size,_size,href,r,mms_movescalar);
  169. else
  170. internalerror(2015091006);
  171. end;
  172. tg.ungetiftemp(current_asmdata.CurrAsmList,href);
  173. end;
  174. {$ifndef cpu64bitalu}
  175. procedure tcgunaryminusnode.second_64bit;
  176. var
  177. tr: tregister;
  178. hl: tasmlabel;
  179. begin
  180. secondpass(left);
  181. location_reset(location,LOC_REGISTER,left.location.size);
  182. location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  183. location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  184. cg64.a_op64_loc_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  185. left.location,joinreg64(location.register64.reglo,location.register64.reghi));
  186. { there's only overflow in case left was low(int64) -> -left = left }
  187. if (cs_check_overflow in current_settings.localswitches) then
  188. begin
  189. tr:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  190. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,
  191. longint($80000000),location.register64.reghi,tr);
  192. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,
  193. location.register64.reglo,tr);
  194. current_asmdata.getjumplabel(hl);
  195. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_32,OC_NE,0,tr,hl);
  196. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
  197. cg.a_label(current_asmdata.CurrAsmList,hl);
  198. end;
  199. end;
  200. {$endif not cpu64bitalu}
  201. procedure tcgunaryminusnode.second_float_emulated;
  202. begin
  203. secondpass(left);
  204. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  205. location:=left.location;
  206. case location.size of
  207. OS_32:
  208. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.register);
  209. OS_64:
  210. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.registerhi);
  211. else
  212. internalerror(2014033101);
  213. end;
  214. end;
  215. procedure tcgunaryminusnode.second_float;
  216. begin
  217. secondpass(left);
  218. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  219. case left.location.loc of
  220. LOC_REFERENCE,
  221. LOC_CREFERENCE :
  222. begin
  223. location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);
  224. case getregtype(location.register) of
  225. R_FPUREGISTER:
  226. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  227. left.resultdef,resultdef,
  228. left.location.reference,location.register);
  229. R_MMREGISTER:
  230. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  231. left.resultdef,resultdef,
  232. left.location.reference,location.register,mms_movescalar);
  233. else
  234. internalerror(2015091004);
  235. end;
  236. emit_float_sign_change(location.register,left.resultdef);
  237. end;
  238. LOC_FPUREGISTER,
  239. LOC_CFPUREGISTER:
  240. begin
  241. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  242. hlcg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register);
  243. emit_float_sign_change(location.register,left.resultdef);
  244. end;
  245. LOC_MMREGISTER,
  246. LOC_CMMREGISTER:
  247. begin
  248. location.register:=hlcg.getmmregister(current_asmdata.CurrAsmList,resultdef);
  249. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register,mms_movescalar);
  250. emit_float_sign_change(location.register,left.resultdef);
  251. end
  252. else
  253. internalerror(200306021);
  254. end;
  255. end;
  256. procedure tcgunaryminusnode.second_integer;
  257. var
  258. hl: tasmlabel;
  259. opsize: tdef;
  260. begin
  261. secondpass(left);
  262. {$ifdef cpunodefaultint}
  263. opsize:=left.resultdef;
  264. {$else cpunodefaultint}
  265. { in case of a 32 bit system that can natively execute 64 bit operations }
  266. if (left.resultdef.size<=sinttype.size) then
  267. opsize:=sinttype
  268. else
  269. opsize:={$ifdef cpu16bitalu}s32inttype{$else}s64inttype{$endif};
  270. {$endif cpunodefaultint}
  271. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  272. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opsize,false);
  273. location_reset(location,LOC_REGISTER,def_cgsize(opsize));
  274. location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  275. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,opsize,left.location.register,location.register);
  276. if (cs_check_overflow in current_settings.localswitches) then
  277. begin
  278. current_asmdata.getjumplabel(hl);
  279. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_NE,torddef(opsize).low.svalue,location.register,hl);
  280. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_overflow',[],nil);
  281. hlcg.a_label(current_asmdata.CurrAsmList,hl);
  282. end;
  283. end;
  284. procedure tcgunaryminusnode.pass_generate_code;
  285. begin
  286. {$ifndef cpu64bitalu}
  287. if is_64bit(left.resultdef) then
  288. second_64bit
  289. else
  290. {$endif not cpu64bitalu}
  291. {$ifdef SUPPORT_MMX}
  292. if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
  293. second_mmx
  294. else
  295. {$endif SUPPORT_MMX}
  296. if (left.resultdef.typ=floatdef) then
  297. begin
  298. if (cs_fp_emulation in current_settings.moduleswitches) then
  299. second_float_emulated
  300. else
  301. second_float;
  302. end
  303. else
  304. second_integer;
  305. end;
  306. {*****************************************************************************
  307. TCGMODDIVNODE
  308. *****************************************************************************}
  309. {$ifndef cpu64bitalu}
  310. procedure tcgmoddivnode.emit64_div_reg_reg(signed: boolean; denum,num:tregister64);
  311. begin
  312. { handled in pass_1 already, unless pass_1 is
  313. overridden
  314. }
  315. { should be handled in pass_1 (JM) }
  316. internalerror(200109052);
  317. end;
  318. {$endif not cpu64bitalu}
  319. procedure tcgmoddivnode.pass_generate_code;
  320. var
  321. hreg1 : tregister;
  322. hdenom : tregister;
  323. power : longint;
  324. hl : tasmlabel;
  325. paraloc1 : tcgpara;
  326. opsize : tcgsize;
  327. opdef : tdef;
  328. pd: tprocdef;
  329. begin
  330. secondpass(left);
  331. if codegenerror then
  332. exit;
  333. secondpass(right);
  334. if codegenerror then
  335. exit;
  336. location_copy(location,left.location);
  337. {$ifndef cpu64bitalu}
  338. if is_64bit(resultdef) then
  339. begin
  340. if is_signed(left.resultdef) then
  341. opdef:=s64inttype
  342. else
  343. opdef:=u64inttype;
  344. { this code valid for 64-bit cpu's only ,
  345. otherwise helpers are called in pass_1
  346. }
  347. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,opdef,false);
  348. location_copy(location,left.location);
  349. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,opdef,false);
  350. emit64_div_reg_reg(is_signed(left.resultdef),
  351. joinreg64(right.location.register64.reglo,right.location.register64.reghi),
  352. joinreg64(location.register64.reglo,location.register64.reghi));
  353. end
  354. else
  355. {$endif not cpu64bitalu}
  356. begin
  357. if is_signed(left.resultdef) then
  358. begin
  359. opsize:=OS_SINT;
  360. opdef:=ossinttype;
  361. end
  362. else
  363. begin
  364. opsize:=OS_INT;
  365. opdef:=osuinttype;
  366. end;
  367. { put numerator in register }
  368. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,false);
  369. hreg1:=left.location.register;
  370. if (nodetype=divn) and
  371. (right.nodetype=ordconstn) and
  372. ispowerof2(tordconstnode(right).value.svalue,power) then
  373. Begin
  374. { for signed numbers, the numerator must be adjusted before the
  375. shift instruction, but not wih unsigned numbers! Otherwise,
  376. "Cardinal($ffffffff) div 16" overflows! (JM) }
  377. If is_signed(left.resultdef) Then
  378. Begin
  379. current_asmdata.getjumplabel(hl);
  380. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_GT,0,hreg1,hl);
  381. if power=1 then
  382. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,1,hreg1)
  383. else
  384. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,Tordconstnode(right).value.svalue-1,hreg1);
  385. cg.a_label(current_asmdata.CurrAsmList,hl);
  386. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,power,hreg1);
  387. End
  388. Else { not signed }
  389. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,hreg1);
  390. End
  391. else
  392. begin
  393. { bring denominator to hdenom }
  394. { hdenom is always free, it's }
  395. { only used for temporary }
  396. { purposes }
  397. hdenom := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  398. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,osuinttype,right.location,hdenom);
  399. { verify if the divisor is zero, if so return an error immediately,
  400. except if we have a const node, where we don't need this, because
  401. then zero check was done earlier.
  402. }
  403. if (right.nodetype <> ordconstn) then
  404. begin
  405. current_asmdata.getjumplabel(hl);
  406. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_NE,0,hdenom,hl);
  407. paraloc1.init;
  408. pd:=search_system_proc('fpc_handleerror');
  409. paramanager.getintparaloc(current_asmdata.CurrAsmList,pd,1,paraloc1);
  410. cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,aint(200),paraloc1);
  411. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  412. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false);
  413. paraloc1.done;
  414. cg.a_label(current_asmdata.CurrAsmList,hl);
  415. end;
  416. if nodetype = modn then
  417. emit_mod_reg_reg(is_signed(left.resultdef),hdenom,hreg1)
  418. else
  419. emit_div_reg_reg(is_signed(left.resultdef),hdenom,hreg1);
  420. end;
  421. location_reset(location,LOC_REGISTER,opsize);
  422. location.register:=hreg1;
  423. end;
  424. cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
  425. end;
  426. {*****************************************************************************
  427. TCGSHLRSHRNODE
  428. *****************************************************************************}
  429. {$ifndef cpu64bitalu}
  430. procedure tcgshlshrnode.second_64bit;
  431. begin
  432. { already hanled in 1st pass }
  433. internalerror(2002081501);
  434. end;
  435. {$endif not cpu64bitalu}
  436. procedure tcgshlshrnode.second_integer;
  437. var
  438. op : topcg;
  439. opdef,shiftcountdef: tdef;
  440. hcountreg : tregister;
  441. opsize : tcgsize;
  442. shiftval : longint;
  443. begin
  444. { determine operator }
  445. case nodetype of
  446. shln: op:=OP_SHL;
  447. shrn: op:=OP_SHR;
  448. else
  449. internalerror(2013120102);
  450. end;
  451. {$ifdef cpunodefaultint}
  452. opsize:=left.location.size;
  453. opdef:=left.resultdef;
  454. shiftcountdef:=opdef;
  455. {$else cpunodefaultint}
  456. if left.resultdef.size<=4 then
  457. begin
  458. if is_signed(left.resultdef) then
  459. begin
  460. if (sizeof(aint)<4) and
  461. (left.resultdef.size<=sizeof(aint)) then
  462. begin
  463. opsize:=OS_SINT;
  464. opdef:=sinttype;
  465. end
  466. else
  467. begin
  468. opdef:=s32inttype;
  469. opsize:=OS_S32;
  470. end;
  471. {$ifdef cpu16bitalu}
  472. shiftcountdef:=s16inttype;
  473. {$else cpu16bitalu}
  474. shiftcountdef:=opdef;
  475. {$endif cpu16bitalu}
  476. end
  477. else
  478. begin
  479. if (sizeof(aint)<4) and
  480. (left.resultdef.size<=sizeof(aint)) then
  481. begin
  482. opsize:=OS_INT;
  483. opdef:=uinttype;
  484. end
  485. else
  486. begin
  487. opdef:=u32inttype;
  488. opsize:=OS_32;
  489. end;
  490. {$ifdef cpu16bitalu}
  491. shiftcountdef:=u16inttype;
  492. {$else cpu16bitalu}
  493. shiftcountdef:=opdef;
  494. {$endif cpu16bitalu}
  495. end
  496. end
  497. else
  498. begin
  499. if is_signed(left.resultdef) then
  500. begin
  501. opdef:=s64inttype;
  502. opsize:=OS_S64;
  503. end
  504. else
  505. begin
  506. opdef:=u64inttype;
  507. opsize:=OS_64;
  508. end;
  509. shiftcountdef:=opdef;
  510. end;
  511. {$endif cpunodefaultint}
  512. if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
  513. { location_force_reg can be also used to change the size of a register }
  514. (left.location.size<>opsize) then
  515. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
  516. location_reset(location,LOC_REGISTER,opsize);
  517. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  518. { shifting by a constant directly coded: }
  519. if (right.nodetype=ordconstn) then
  520. begin
  521. { shl/shr must "wrap around", so use ... and 31 }
  522. { In TP, "byte/word shl 16 = 0", so no "and 15" in case of
  523. a 16 bit ALU }
  524. if tcgsize2size[opsize]<=4 then
  525. shiftval:=tordconstnode(right).value.uvalue and 31
  526. else
  527. shiftval:=tordconstnode(right).value.uvalue and 63;
  528. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef,
  529. shiftval,left.location.register,location.register);
  530. end
  531. else
  532. begin
  533. { load right operators in a register - this
  534. is done since most target cpu which will use this
  535. node do not support a shift count in a mem. location (cec)
  536. }
  537. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,shiftcountdef,true);
  538. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,right.location.register,left.location.register,location.register);
  539. end;
  540. { shl/shr nodes return the same type as left, which can be different
  541. from opdef }
  542. if opdef<>resultdef then
  543. begin
  544. hcountreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  545. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,opdef,resultdef,location.register,hcountreg);
  546. location.register:=hcountreg;
  547. end;
  548. end;
  549. procedure tcgshlshrnode.pass_generate_code;
  550. begin
  551. secondpass(left);
  552. secondpass(right);
  553. {$ifdef SUPPORT_MMX}
  554. if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
  555. second_mmx
  556. else
  557. {$endif SUPPORT_MMX}
  558. {$ifndef cpu64bitalu}
  559. if is_64bit(left.resultdef) then
  560. second_64bit
  561. else
  562. {$endif not cpu64bitalu}
  563. second_integer;
  564. end;
  565. {*****************************************************************************
  566. TCGNOTNODE
  567. *****************************************************************************}
  568. {$ifndef cpu64bitalu}
  569. procedure tcgnotnode.second_64bit;
  570. begin
  571. secondpass(left);
  572. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  573. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  574. location_reset(location,LOC_REGISTER,left.location.size);
  575. location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  576. location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  577. { perform the NOT operation }
  578. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,left.location.register64,location.register64);
  579. end;
  580. {$endif not cpu64bitalu}
  581. procedure tcgnotnode.second_integer;
  582. begin
  583. secondpass(left);
  584. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  585. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  586. location_reset(location,LOC_REGISTER,left.location.size);
  587. location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  588. { perform the NOT operation }
  589. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,location.register);
  590. end;
  591. function tcgnotnode.handle_locjump: boolean;
  592. begin
  593. result:=(left.expectloc=LOC_JUMP);
  594. if result then
  595. begin
  596. secondpass(left);
  597. if is_constboolnode(left) then
  598. internalerror(2014010101);
  599. if left.location.loc<>LOC_JUMP then
  600. internalerror(2012081306);
  601. { switch true and false labels to invert result }
  602. location_reset_jump(location,left.location.falselabel,left.location.truelabel);
  603. end;
  604. end;
  605. procedure tcgnotnode.pass_generate_code;
  606. begin
  607. if is_boolean(resultdef) then
  608. second_boolean
  609. {$ifdef SUPPORT_MMX}
  610. else if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
  611. second_mmx
  612. {$endif SUPPORT_MMX}
  613. {$ifndef cpu64bitalu}
  614. else if is_64bit(left.resultdef) then
  615. second_64bit
  616. {$endif not cpu64bitalu}
  617. else
  618. second_integer;
  619. end;
  620. begin
  621. cmoddivnode:=tcgmoddivnode;
  622. cunaryminusnode:=tcgunaryminusnode;
  623. cshlshrnode:=tcgshlshrnode;
  624. cnotnode:=tcgnotnode;
  625. end.