ncgmat.pas 27 KB

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