ncgmat.pas 25 KB

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