ncgmat.pas 26 KB

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