ncgmat.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  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. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  40. procedure second_64bit;virtual;
  41. {$endif not cpu64bitalu and not cpuhighleveltarget}
  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. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  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 and not cpuhighleveltarget}
  85. end;
  86. tcgshlshrnode = class(tshlshrnode)
  87. {$ifdef SUPPORT_MMX}
  88. procedure second_mmx;virtual;abstract;
  89. {$endif SUPPORT_MMX}
  90. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  91. procedure second_64bit;virtual;
  92. {$endif not cpu64bitalu and not cpuhighleveltarget}
  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. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  104. procedure second_64bit;virtual;
  105. {$endif not cpu64bitalu and not cpuhighleveltarget}
  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. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  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 and not cpuhighleveltarget}
  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. {$ifdef cpu64bitalu}
  211. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_64,tcgint($80000000),location.register);
  212. {$else cpu64bitalu}
  213. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.registerhi);
  214. {$endif cpu64bitalu}
  215. else
  216. internalerror(2014033101);
  217. end;
  218. end;
  219. procedure tcgunaryminusnode.second_float;
  220. begin
  221. secondpass(left);
  222. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  223. case left.location.loc of
  224. LOC_REFERENCE,
  225. LOC_CREFERENCE :
  226. begin
  227. location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);
  228. case getregtype(location.register) of
  229. R_FPUREGISTER:
  230. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  231. left.resultdef,resultdef,
  232. left.location.reference,location.register);
  233. R_MMREGISTER:
  234. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  235. left.resultdef,resultdef,
  236. left.location.reference,location.register,mms_movescalar);
  237. else
  238. internalerror(2015091004);
  239. end;
  240. emit_float_sign_change(location.register,left.resultdef);
  241. end;
  242. LOC_FPUREGISTER,
  243. LOC_CFPUREGISTER:
  244. begin
  245. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  246. hlcg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register);
  247. emit_float_sign_change(location.register,left.resultdef);
  248. end;
  249. LOC_MMREGISTER,
  250. LOC_CMMREGISTER:
  251. begin
  252. location.register:=hlcg.getmmregister(current_asmdata.CurrAsmList,resultdef);
  253. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register,mms_movescalar);
  254. emit_float_sign_change(location.register,left.resultdef);
  255. end
  256. else
  257. internalerror(200306021);
  258. end;
  259. end;
  260. procedure tcgunaryminusnode.second_integer;
  261. var
  262. hl: tasmlabel;
  263. opsize: tdef;
  264. begin
  265. secondpass(left);
  266. {$ifdef cpunodefaultint}
  267. opsize:=left.resultdef;
  268. {$else cpunodefaultint}
  269. { in case of a 32 bit system that can natively execute 64 bit operations }
  270. if (left.resultdef.size<=sinttype.size) then
  271. opsize:=sinttype
  272. else
  273. opsize:={$ifdef cpu16bitalu}s32inttype{$else}s64inttype{$endif};
  274. {$endif cpunodefaultint}
  275. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  276. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opsize,false);
  277. location_reset(location,LOC_REGISTER,def_cgsize(opsize));
  278. location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  279. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,opsize,left.location.register,location.register);
  280. if (cs_check_overflow in current_settings.localswitches) then
  281. begin
  282. current_asmdata.getjumplabel(hl);
  283. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_NE,torddef(opsize).low.svalue,location.register,hl);
  284. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_overflow',[],nil).resetiftemp;
  285. hlcg.a_label(current_asmdata.CurrAsmList,hl);
  286. end;
  287. end;
  288. procedure tcgunaryminusnode.pass_generate_code;
  289. begin
  290. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  291. if is_64bit(left.resultdef) then
  292. second_64bit
  293. else
  294. {$endif not cpu64bitalu and not cpuhighleveltarget}
  295. {$ifdef SUPPORT_MMX}
  296. if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
  297. second_mmx
  298. else
  299. {$endif SUPPORT_MMX}
  300. if (left.resultdef.typ=floatdef) then
  301. begin
  302. if (cs_fp_emulation in current_settings.moduleswitches) then
  303. second_float_emulated
  304. else
  305. second_float;
  306. end
  307. else
  308. second_integer;
  309. end;
  310. {*****************************************************************************
  311. TCGMODDIVNODE
  312. *****************************************************************************}
  313. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  314. procedure tcgmoddivnode.emit64_div_reg_reg(signed: boolean; denum,num:tregister64);
  315. begin
  316. { handled in pass_1 already, unless pass_1 is
  317. overridden
  318. }
  319. { should be handled in pass_1 (JM) }
  320. internalerror(200109052);
  321. end;
  322. {$endif not cpu64bitalu and not cpuhighleveltarget}
  323. procedure tcgmoddivnode.pass_generate_code;
  324. var
  325. hreg1 : tregister;
  326. hdenom : tregister;
  327. power : longint;
  328. hl : tasmlabel;
  329. paraloc1 : tcgpara;
  330. opsize : tcgsize;
  331. opdef : tdef;
  332. pd: tprocdef;
  333. begin
  334. secondpass(left);
  335. if codegenerror then
  336. exit;
  337. secondpass(right);
  338. if codegenerror then
  339. exit;
  340. location_copy(location,left.location);
  341. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  342. if is_64bit(resultdef) then
  343. begin
  344. if is_signed(left.resultdef) then
  345. opdef:=s64inttype
  346. else
  347. opdef:=u64inttype;
  348. { this code valid for 64-bit cpu's only ,
  349. otherwise helpers are called in pass_1
  350. }
  351. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,opdef,false);
  352. location_copy(location,left.location);
  353. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,opdef,false);
  354. emit64_div_reg_reg(is_signed(left.resultdef),
  355. joinreg64(right.location.register64.reglo,right.location.register64.reghi),
  356. joinreg64(location.register64.reglo,location.register64.reghi));
  357. end
  358. else
  359. {$endif not cpu64bitalu and not cpuhighleveltarget}
  360. begin
  361. if is_signed(left.resultdef) then
  362. begin
  363. opsize:=OS_SINT;
  364. opdef:=ossinttype;
  365. end
  366. else
  367. begin
  368. opsize:=OS_INT;
  369. opdef:=osuinttype;
  370. end;
  371. { put numerator in register }
  372. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,false);
  373. hreg1:=left.location.register;
  374. if (nodetype=divn) and
  375. (right.nodetype=ordconstn) and
  376. ispowerof2(tordconstnode(right).value.svalue,power) then
  377. Begin
  378. { for signed numbers, the numerator must be adjusted before the
  379. shift instruction, but not wih unsigned numbers! Otherwise,
  380. "Cardinal($ffffffff) div 16" overflows! (JM) }
  381. If is_signed(left.resultdef) Then
  382. Begin
  383. current_asmdata.getjumplabel(hl);
  384. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_GT,0,hreg1,hl);
  385. if power=1 then
  386. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,1,hreg1)
  387. else
  388. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,Tordconstnode(right).value.svalue-1,hreg1);
  389. cg.a_label(current_asmdata.CurrAsmList,hl);
  390. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,power,hreg1);
  391. End
  392. Else { not signed }
  393. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,hreg1);
  394. End
  395. else
  396. begin
  397. { bring denominator to hdenom }
  398. { hdenom is always free, it's }
  399. { only used for temporary }
  400. { purposes }
  401. hdenom := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  402. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,osuinttype,right.location,hdenom);
  403. { verify if the divisor is zero, if so return an error immediately,
  404. except if we have a const node, where we don't need this, because
  405. then zero check was done earlier.
  406. }
  407. if (right.nodetype <> ordconstn) then
  408. begin
  409. current_asmdata.getjumplabel(hl);
  410. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_NE,0,hdenom,hl);
  411. paraloc1.init;
  412. pd:=search_system_proc('fpc_handleerror');
  413. paramanager.getintparaloc(current_asmdata.CurrAsmList,pd,1,paraloc1);
  414. cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,aint(200),paraloc1);
  415. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  416. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false);
  417. paraloc1.done;
  418. cg.a_label(current_asmdata.CurrAsmList,hl);
  419. end;
  420. if nodetype = modn then
  421. emit_mod_reg_reg(is_signed(left.resultdef),hdenom,hreg1)
  422. else
  423. emit_div_reg_reg(is_signed(left.resultdef),hdenom,hreg1);
  424. end;
  425. location_reset(location,LOC_REGISTER,opsize);
  426. location.register:=hreg1;
  427. end;
  428. cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
  429. end;
  430. {*****************************************************************************
  431. TCGSHLRSHRNODE
  432. *****************************************************************************}
  433. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  434. procedure tcgshlshrnode.second_64bit;
  435. begin
  436. { already hanled in 1st pass }
  437. internalerror(2002081501);
  438. end;
  439. {$endif not cpu64bitalu and not cpuhighleveltarget}
  440. procedure tcgshlshrnode.second_integer;
  441. var
  442. op : topcg;
  443. opdef,shiftcountdef: tdef;
  444. hcountreg : tregister;
  445. opsize : tcgsize;
  446. shiftval : longint;
  447. begin
  448. { determine operator }
  449. case nodetype of
  450. shln: op:=OP_SHL;
  451. shrn: op:=OP_SHR;
  452. else
  453. internalerror(2013120102);
  454. end;
  455. {$ifdef cpunodefaultint}
  456. opsize:=left.location.size;
  457. opdef:=left.resultdef;
  458. shiftcountdef:=opdef;
  459. {$else cpunodefaultint}
  460. if left.resultdef.size<=4 then
  461. begin
  462. if is_signed(left.resultdef) then
  463. begin
  464. if (sizeof(aint)<4) and
  465. (left.resultdef.size<=sizeof(aint)) then
  466. begin
  467. opsize:=OS_SINT;
  468. opdef:=sinttype;
  469. end
  470. else
  471. begin
  472. opdef:=s32inttype;
  473. opsize:=OS_S32;
  474. end;
  475. {$ifdef cpu16bitalu}
  476. shiftcountdef:=s16inttype;
  477. {$else cpu16bitalu}
  478. shiftcountdef:=opdef;
  479. {$endif cpu16bitalu}
  480. end
  481. else
  482. begin
  483. if (sizeof(aint)<4) and
  484. (left.resultdef.size<=sizeof(aint)) then
  485. begin
  486. opsize:=OS_INT;
  487. opdef:=uinttype;
  488. end
  489. else
  490. begin
  491. opdef:=u32inttype;
  492. opsize:=OS_32;
  493. end;
  494. {$ifdef cpu16bitalu}
  495. shiftcountdef:=u16inttype;
  496. {$else cpu16bitalu}
  497. shiftcountdef:=opdef;
  498. {$endif cpu16bitalu}
  499. end
  500. end
  501. else
  502. begin
  503. if is_signed(left.resultdef) then
  504. begin
  505. opdef:=s64inttype;
  506. opsize:=OS_S64;
  507. end
  508. else
  509. begin
  510. opdef:=u64inttype;
  511. opsize:=OS_64;
  512. end;
  513. shiftcountdef:=opdef;
  514. end;
  515. {$endif cpunodefaultint}
  516. if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
  517. { location_force_reg can be also used to change the size of a register }
  518. (left.location.size<>opsize) then
  519. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
  520. location_reset(location,LOC_REGISTER,opsize);
  521. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  522. { shifting by a constant directly coded: }
  523. if (right.nodetype=ordconstn) then
  524. begin
  525. { shl/shr must "wrap around", so use ... and 31 }
  526. { In TP, "byte/word shl 16 = 0", so no "and 15" in case of
  527. a 16 bit ALU }
  528. if tcgsize2size[opsize]<=4 then
  529. shiftval:=tordconstnode(right).value.uvalue and 31
  530. else
  531. shiftval:=tordconstnode(right).value.uvalue and 63;
  532. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef,
  533. shiftval,left.location.register,location.register);
  534. end
  535. else
  536. begin
  537. { load right operators in a register - this
  538. is done since most target cpu which will use this
  539. node do not support a shift count in a mem. location (cec)
  540. }
  541. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,shiftcountdef,true);
  542. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,right.location.register,left.location.register,location.register);
  543. end;
  544. { shl/shr nodes return the same type as left, which can be different
  545. from opdef }
  546. if opdef<>resultdef then
  547. begin
  548. hcountreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  549. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,opdef,resultdef,location.register,hcountreg);
  550. location.register:=hcountreg;
  551. end;
  552. end;
  553. procedure tcgshlshrnode.pass_generate_code;
  554. begin
  555. secondpass(left);
  556. secondpass(right);
  557. {$ifdef SUPPORT_MMX}
  558. if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
  559. second_mmx
  560. else
  561. {$endif SUPPORT_MMX}
  562. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  563. if is_64bit(left.resultdef) then
  564. second_64bit
  565. else
  566. {$endif not cpu64bitalu and not cpuhighleveltarget}
  567. second_integer;
  568. end;
  569. {*****************************************************************************
  570. TCGNOTNODE
  571. *****************************************************************************}
  572. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  573. procedure tcgnotnode.second_64bit;
  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.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  580. location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  581. { perform the NOT operation }
  582. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,left.location.register64,location.register64);
  583. end;
  584. {$endif not cpu64bitalu and not cpuhighleveltarget}
  585. procedure tcgnotnode.second_integer;
  586. begin
  587. secondpass(left);
  588. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  589. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  590. location_reset(location,LOC_REGISTER,left.location.size);
  591. location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  592. { perform the NOT operation }
  593. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,location.register);
  594. end;
  595. function tcgnotnode.handle_locjump: boolean;
  596. begin
  597. result:=(left.expectloc=LOC_JUMP);
  598. if result then
  599. begin
  600. secondpass(left);
  601. if is_constboolnode(left) then
  602. internalerror(2014010101);
  603. if left.location.loc<>LOC_JUMP then
  604. internalerror(2012081306);
  605. { switch true and false labels to invert result }
  606. location_reset_jump(location,left.location.falselabel,left.location.truelabel);
  607. end;
  608. end;
  609. procedure tcgnotnode.pass_generate_code;
  610. begin
  611. if is_boolean(resultdef) then
  612. second_boolean
  613. {$ifdef SUPPORT_MMX}
  614. else if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
  615. second_mmx
  616. {$endif SUPPORT_MMX}
  617. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  618. else if is_64bit(left.resultdef) then
  619. second_64bit
  620. {$endif not cpu64bitalu and not cpuhighleveltarget}
  621. else
  622. second_integer;
  623. end;
  624. begin
  625. cmoddivnode:=tcgmoddivnode;
  626. cunaryminusnode:=tcgunaryminusnode;
  627. cshlshrnode:=tcgshlshrnode;
  628. cnotnode:=tcgnotnode;
  629. end.