ncgmat.pas 24 KB

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