ncgmat.pas 24 KB

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