ncgmat.pas 24 KB

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