ncgmat.pas 24 KB

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