ncgflw.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate assembler for nodes that influence the flow which are
  5. the same for all (most?) processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ncgflw;
  20. {$i defines.inc}
  21. interface
  22. uses
  23. node,nflw;
  24. type
  25. tcgwhilerepeatnode = class(twhilerepeatnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgifnode = class(tifnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgfornode = class(tfornode)
  32. procedure pass_2;override;
  33. end;
  34. tcgexitnode = class(texitnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgbreaknode = class(tbreaknode)
  38. procedure pass_2;override;
  39. end;
  40. tcgcontinuenode = class(tcontinuenode)
  41. procedure pass_2;override;
  42. end;
  43. tcggotonode = class(tgotonode)
  44. procedure pass_2;override;
  45. end;
  46. tcglabelnode = class(tlabelnode)
  47. procedure pass_2;override;
  48. end;
  49. implementation
  50. uses
  51. verbose,globals,systems,globtype,
  52. symconst,symdef,symsym,aasm,types,
  53. cgbase,temp_gen,pass_2,
  54. cpubase,cpuasm,cpuinfo,
  55. nld,ncon,
  56. cga,tgcpu,
  57. ncgutil,
  58. tainst,regvars,cgobj,cgcpu;
  59. {*****************************************************************************
  60. Second_While_RepeatN
  61. *****************************************************************************}
  62. procedure tcgwhilerepeatnode.pass_2;
  63. var
  64. lcont,lbreak,lloop,
  65. oldclabel,oldblabel : tasmlabel;
  66. otlabel,oflabel : tasmlabel;
  67. begin
  68. getlabel(lloop);
  69. getlabel(lcont);
  70. getlabel(lbreak);
  71. { arrange continue and breaklabels: }
  72. oldclabel:=aktcontinuelabel;
  73. oldblabel:=aktbreaklabel;
  74. load_all_regvars(exprasmlist);
  75. { handling code at the end as it is much more efficient, and makes
  76. while equal to repeat loop, only the end true/false is swapped (PFV) }
  77. if nodetype=whilen then
  78. cg.a_jmp_cond(exprasmlist,OC_None,lcont);
  79. { align loop target }
  80. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  81. cg.a_label(exprasmlist,lloop);
  82. aktcontinuelabel:=lcont;
  83. aktbreaklabel:=lbreak;
  84. cleartempgen;
  85. if assigned(right) then
  86. secondpass(right);
  87. load_all_regvars(exprasmlist);
  88. cg.a_label(exprasmlist,lcont);
  89. otlabel:=truelabel;
  90. oflabel:=falselabel;
  91. if nodetype=whilen then
  92. begin
  93. truelabel:=lloop;
  94. falselabel:=lbreak;
  95. end
  96. { repeatn }
  97. else
  98. begin
  99. truelabel:=lbreak;
  100. falselabel:=lloop;
  101. end;
  102. cleartempgen;
  103. secondpass(left);
  104. maketojumpbool(left,lr_load_regvars);
  105. cg.a_label(exprasmlist,lbreak);
  106. truelabel:=otlabel;
  107. falselabel:=oflabel;
  108. aktcontinuelabel:=oldclabel;
  109. aktbreaklabel:=oldblabel;
  110. { a break/continue in a while/repeat block can't be seen outside }
  111. flowcontrol:=flowcontrol-[fc_break,fc_continue];
  112. end;
  113. {*****************************************************************************
  114. tcgIFNODE
  115. *****************************************************************************}
  116. procedure tcgifnode.pass_2;
  117. var
  118. hl,otlabel,oflabel : tasmlabel;
  119. org_regvar_loaded,
  120. then_regvar_loaded,
  121. else_regvar_loaded : regvar_booleanarray;
  122. org_list,
  123. then_list,
  124. else_list : taasmoutput;
  125. regcounter: tregister;
  126. begin
  127. otlabel:=truelabel;
  128. oflabel:=falselabel;
  129. getlabel(truelabel);
  130. getlabel(falselabel);
  131. cleartempgen;
  132. secondpass(left);
  133. { save regvars loaded in the beginning so that we can restore them }
  134. { when processing the else-block }
  135. if cs_regalloc in aktglobalswitches then
  136. begin
  137. org_list := exprasmlist;
  138. exprasmlist := taasmoutput.create;
  139. end;
  140. maketojumpbool(left,lr_dont_load_regvars);
  141. if cs_regalloc in aktglobalswitches then
  142. org_regvar_loaded := regvar_loaded;
  143. if assigned(right) then
  144. begin
  145. cg.a_label(exprasmlist,truelabel);
  146. cleartempgen;
  147. secondpass(right);
  148. end;
  149. { save current asmlist (previous instructions + then-block) and }
  150. { loaded regvar state and create new clean ones }
  151. if cs_regalloc in aktglobalswitches then
  152. begin
  153. then_regvar_loaded := regvar_loaded;
  154. regvar_loaded := org_regvar_loaded;
  155. then_list := exprasmlist;
  156. exprasmlist := taasmoutput.create;
  157. end;
  158. if assigned(t1) then
  159. begin
  160. if assigned(right) then
  161. begin
  162. getlabel(hl);
  163. { do go back to if line !! }
  164. if not(cs_regalloc in aktglobalswitches) then
  165. aktfilepos:=exprasmList.getlasttaifilepos^
  166. else
  167. aktfilepos:=then_list.getlasttaifilepos^;
  168. cg.a_jmp_cond(exprasmlist,OC_None,hl);
  169. end;
  170. cg.a_label(exprasmlist,falselabel);
  171. cleartempgen;
  172. secondpass(t1);
  173. { save current asmlist (previous instructions + else-block) }
  174. { and loaded regvar state and create a new clean list }
  175. if cs_regalloc in aktglobalswitches then
  176. begin
  177. else_regvar_loaded := regvar_loaded;
  178. else_list := exprasmlist;
  179. exprasmlist := taasmoutput.create;
  180. end;
  181. if assigned(right) then
  182. cg.a_label(exprasmlist,hl);
  183. end
  184. else
  185. begin
  186. if cs_regalloc in aktglobalswitches then
  187. begin
  188. else_regvar_loaded := regvar_loaded;
  189. else_list := exprasmlist;
  190. exprasmlist := taasmoutput.create;
  191. end;
  192. cg.a_label(exprasmlist,falselabel);
  193. end;
  194. if not(assigned(right)) then
  195. begin
  196. cg.a_label(exprasmlist,truelabel);
  197. end;
  198. if cs_regalloc in aktglobalswitches then
  199. begin
  200. { add loads of regvars at the end of the then- and else-blocks }
  201. { so that at the end of both blocks the same regvars are loaded }
  202. { no else block? }
  203. if not assigned(t1) then
  204. sync_regvars(org_list,then_list,org_regvar_loaded,
  205. then_regvar_loaded)
  206. { no then block? }
  207. else if not assigned(right) then
  208. sync_regvars(org_list,else_list,org_regvar_loaded,
  209. else_regvar_loaded)
  210. { both else and then blocks }
  211. else
  212. sync_regvars(then_list,else_list,then_regvar_loaded,
  213. else_regvar_loaded);
  214. { add all lists together }
  215. org_list.concatlist(then_list);
  216. then_list.free;
  217. org_list.concatlist(else_list);
  218. else_list.free;
  219. org_list.concatlist(exprasmlist);
  220. exprasmlist.free;
  221. exprasmlist := org_list;
  222. end;
  223. truelabel:=otlabel;
  224. falselabel:=oflabel;
  225. end;
  226. {*****************************************************************************
  227. SecondFor
  228. *****************************************************************************}
  229. procedure tcgfornode.pass_2;
  230. var
  231. l3,oldclabel,oldblabel : tasmlabel;
  232. omitfirstcomp,temptovalue : boolean;
  233. hs : byte;
  234. temp1 : treference;
  235. hop : topcg;
  236. hcond : topcmp;
  237. opsize : tcgsize;
  238. count_var_is_signed : boolean;
  239. begin
  240. oldclabel:=aktcontinuelabel;
  241. oldblabel:=aktbreaklabel;
  242. getlabel(aktcontinuelabel);
  243. getlabel(aktbreaklabel);
  244. getlabel(l3);
  245. { could we spare the first comparison ? }
  246. omitfirstcomp:=false;
  247. if right.nodetype=ordconstn then
  248. if tassignmentnode(left).right.nodetype=ordconstn then
  249. omitfirstcomp:=((nf_backward in flags) and
  250. (tordconstnode(tassignmentnode(left).right).value>=tordconstnode(right).value))
  251. or (not(nf_backward in flags) and
  252. (tordconstnode(tassignmentnode(left).right).value<=tordconstnode(right).value));
  253. { only calculate reference }
  254. cleartempgen;
  255. secondpass(t2);
  256. hs := t2.resulttype.def.size;
  257. opsize := def_cgsize(t2.resulttype.def);
  258. { first set the to value
  259. because the count var can be in the expression !! }
  260. cleartempgen;
  261. secondpass(right);
  262. { calculate pointer value and check if changeable and if so }
  263. { load into temporary variable }
  264. if right.nodetype<>ordconstn then
  265. begin
  266. temp1.symbol:=nil;
  267. gettempofsizereference(hs,temp1);
  268. temptovalue:=true;
  269. if (right.location.loc=LOC_REGISTER) or
  270. (right.location.loc=LOC_CREGISTER) then
  271. begin
  272. cg.a_load_reg_ref(exprasmlist,opsize,
  273. right.location.register,temp1);
  274. ungetregister(right.location.register);
  275. end
  276. else
  277. cg.g_concatcopy(exprasmlist,right.location.reference,temp1,
  278. hs,true,false);
  279. end
  280. else
  281. temptovalue:=false;
  282. { produce start assignment }
  283. cleartempgen;
  284. secondpass(left);
  285. count_var_is_signed:=is_signed(torddef(t2.resulttype.def));
  286. if nf_backward in flags then
  287. if count_var_is_signed then
  288. hcond:=OC_LT
  289. else
  290. hcond:=OC_B
  291. else
  292. if count_var_is_signed then
  293. hcond:=OC_GT
  294. else
  295. hcond:=OC_A;
  296. load_all_regvars(exprasmlist);
  297. if temptovalue then
  298. begin
  299. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,
  300. temp1,t2.location,aktbreaklabel);
  301. end
  302. else
  303. begin
  304. if not(omitfirstcomp) then
  305. begin
  306. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  307. aword(tordconstnode(right).value),
  308. t2.location,aktbreaklabel);
  309. end;
  310. end;
  311. { align loop target }
  312. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  313. cg.a_label(exprasmlist,l3);
  314. { help register must not be in instruction block }
  315. cleartempgen;
  316. if assigned(t1) then
  317. begin
  318. secondpass(t1);
  319. load_all_regvars(exprasmlist);
  320. end;
  321. cg.a_label(exprasmlist,aktcontinuelabel);
  322. { makes no problems there }
  323. cleartempgen;
  324. if nf_backward in flags then
  325. if count_var_is_signed then
  326. hcond:=OC_LTE
  327. else
  328. hcond:=OC_BE
  329. else
  330. if count_var_is_signed then
  331. hcond:=OC_GTE
  332. else
  333. hcond:=OC_AE;
  334. load_all_regvars(exprasmlist);
  335. { produce comparison and the corresponding }
  336. { jump }
  337. if temptovalue then
  338. begin
  339. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,temp1,
  340. t2.location,aktbreaklabel);
  341. end
  342. else
  343. begin
  344. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  345. aword(tordconstnode(right).value),t2.location,aktbreaklabel);
  346. end;
  347. { according to count direction DEC or INC... }
  348. { must be after the test because of 0 to 255 for bytes !! }
  349. if nf_backward in flags then
  350. hop:=OP_SUB
  351. else
  352. hop:=OP_ADD;
  353. cg.a_op_const_loc(exprasmlist,hop,opsize,1,t2.location);
  354. cg.a_jmp_cond(exprasmlist,OC_None,l3);
  355. if temptovalue then
  356. ungetiftemp(temp1);
  357. { this is the break label: }
  358. cg.a_label(exprasmlist,aktbreaklabel);
  359. aktcontinuelabel:=oldclabel;
  360. aktbreaklabel:=oldblabel;
  361. { a break/continue in a for block can't be seen outside }
  362. flowcontrol:=flowcontrol-[fc_break,fc_continue];
  363. end;
  364. {*****************************************************************************
  365. SecondExitN
  366. *****************************************************************************}
  367. procedure tcgexitnode.pass_2;
  368. var
  369. {op : tasmop;
  370. s : topsize;}
  371. otlabel,oflabel : tasmlabel;
  372. r : treference;
  373. is_mem,
  374. allocated_acc,
  375. allocated_acchigh: boolean;
  376. procedure cleanleft;
  377. begin
  378. if is_mem then
  379. begin
  380. del_reference(left.location.reference);
  381. ungetiftemp(left.location.reference);
  382. end
  383. else
  384. begin
  385. ungetregister(left.location.register);
  386. if left.location.registerhigh <> R_NO then
  387. ungetregister(left.location.registerhigh);
  388. end;
  389. end;
  390. label
  391. do_jmp;
  392. begin
  393. { load_all_regvars(exprasmlist); }
  394. include(flowcontrol,fc_exit);
  395. if assigned(left) then
  396. if left.nodetype=assignn then
  397. begin
  398. { just do a normal assignment followed by exit }
  399. secondpass(left);
  400. cg.a_jmp_cond(exprasmlist,OC_NONE,aktexitlabel);
  401. end
  402. else
  403. begin
  404. allocated_acc := false;
  405. allocated_acchigh := false;
  406. otlabel:=truelabel;
  407. oflabel:=falselabel;
  408. getlabel(truelabel);
  409. getlabel(falselabel);
  410. secondpass(left);
  411. case left.location.loc of
  412. LOC_FPU : goto do_jmp;
  413. LOC_MEM,
  414. LOC_REFERENCE : is_mem:=true;
  415. LOC_CREGISTER,
  416. LOC_REGISTER : is_mem:=false;
  417. LOC_FLAGS : begin
  418. cg.a_reg_alloc(exprasmlist,accumulator);
  419. allocated_acc := true;
  420. cg.g_flags2reg(exprasmlist,left.location.resflags,accumulator);
  421. goto do_jmp;
  422. end;
  423. LOC_JUMP : begin
  424. exprasmlist.concat(tairegalloc.alloc(accumulator));
  425. allocated_acc := true;
  426. cg.a_label(exprasmlist,truelabel);
  427. cg.a_load_const_reg(exprasmlist,OS_8,1,
  428. makereg8(accumulator));
  429. cg.a_jmp_cond(exprasmlist,OC_NONE,aktexit2label);
  430. cg.a_label(exprasmlist,falselabel);
  431. cg.a_load_const_reg(exprasmlist,OS_8,0,
  432. makereg8(accumulator));
  433. goto do_jmp;
  434. end;
  435. else
  436. internalerror(2001);
  437. end;
  438. case aktprocdef.rettype.def.deftype of
  439. pointerdef,
  440. procvardef : begin
  441. cleanleft;
  442. cg.a_reg_alloc(exprasmlist,accumulator);
  443. allocated_acc := true;
  444. if is_mem then
  445. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  446. left.location.reference,accumulator)
  447. else
  448. cg.a_load_reg_reg(exprasmlist,OS_ADDR,
  449. left.location.register,accumulator);
  450. end;
  451. floatdef : begin
  452. cleanleft;
  453. if is_mem then
  454. floatload(tfloatdef(aktprocdef.rettype.def).typ,left.location.reference);
  455. end;
  456. { orddef,
  457. enumdef : }
  458. else
  459. { it can be anything shorter than 4 bytes PM
  460. this caused form bug 711 }
  461. begin
  462. cleanleft;
  463. cg.a_reg_alloc(exprasmlist,accumulator);
  464. allocated_acc := true;
  465. case aktprocdef.rettype.def.size of
  466. { it can be a qword/int64 too ... }
  467. 8 :
  468. if is_mem then
  469. begin
  470. cg.a_load_ref_reg(exprasmlist,OS_32,
  471. left.location.reference,accumulator);
  472. r:=left.location.reference;
  473. inc(r.offset,4);
  474. cg.a_reg_alloc(exprasmlist,accumulatorhigh);
  475. allocated_acchigh := true;
  476. cg.a_load_ref_reg(exprasmlist,OS_32,r,accumulatorhigh);
  477. end
  478. else
  479. begin
  480. cg.a_load_reg_reg(exprasmlist,OS_32,left.location.registerlow,accumulator);
  481. cg.a_reg_alloc(exprasmlist,accumulatorhigh);
  482. allocated_acchigh := true;
  483. cg.a_load_reg_reg(exprasmlist,OS_32,left.location.registerhigh,accumulatorhigh);
  484. end;
  485. { if its 3 bytes only we can still
  486. copy one of garbage ! PM }
  487. 4,3 :
  488. cg.a_load_loc_reg(exprasmlist,OS_32,left.location,
  489. accumulator);
  490. 2 :
  491. cg.a_load_loc_reg(exprasmlist,OS_16,left.location,
  492. makereg16(accumulator));
  493. 1 :
  494. cg.a_load_loc_reg(exprasmlist,OS_8,left.location,
  495. makereg8(accumulator));
  496. else internalerror(605001);
  497. end;
  498. end;
  499. end;
  500. do_jmp:
  501. truelabel:=otlabel;
  502. falselabel:=oflabel;
  503. cg.a_jmp_cond(exprasmlist,OC_None,aktexit2label);
  504. if allocated_acc then
  505. cg.a_reg_dealloc(exprasmlist,accumulator);
  506. if allocated_acchigh then
  507. cg.a_reg_dealloc(exprasmlist,accumulator);
  508. end
  509. else
  510. cg.a_jmp_cond(exprasmlist,OC_None,aktexitlabel);
  511. end;
  512. {*****************************************************************************
  513. SecondBreakN
  514. *****************************************************************************}
  515. procedure tcgbreaknode.pass_2;
  516. begin
  517. include(flowcontrol,fc_break);
  518. if aktbreaklabel<>nil then
  519. begin
  520. load_all_regvars(exprasmlist);
  521. cg.a_jmp_cond(exprasmlist,OC_None,aktbreaklabel)
  522. end
  523. else
  524. CGMessage(cg_e_break_not_allowed);
  525. end;
  526. {*****************************************************************************
  527. SecondContinueN
  528. *****************************************************************************}
  529. procedure tcgcontinuenode.pass_2;
  530. begin
  531. include(flowcontrol,fc_continue);
  532. if aktcontinuelabel<>nil then
  533. begin
  534. load_all_regvars(exprasmlist);
  535. cg.a_jmp_cond(exprasmlist,OC_None,aktcontinuelabel)
  536. end
  537. else
  538. CGMessage(cg_e_continue_not_allowed);
  539. end;
  540. {*****************************************************************************
  541. SecondGoto
  542. *****************************************************************************}
  543. procedure tcggotonode.pass_2;
  544. begin
  545. load_all_regvars(exprasmlist);
  546. cg.a_jmp_cond(exprasmlist,OC_None,labelnr)
  547. end;
  548. {*****************************************************************************
  549. SecondLabel
  550. *****************************************************************************}
  551. procedure tcglabelnode.pass_2;
  552. begin
  553. load_all_regvars(exprasmlist);
  554. cg.a_label(exprasmlist,labelnr);
  555. cleartempgen;
  556. secondpass(left);
  557. end;
  558. begin
  559. cwhilerepeatnode:=tcgwhilerepeatnode;
  560. cifnode:=tcgifnode;
  561. cfornode:=tcgfornode;
  562. cexitnode:=tcgexitnode;
  563. cbreaknode:=tcgbreaknode;
  564. ccontinuenode:=tcgcontinuenode;
  565. cgotonode:=tcggotonode;
  566. clabelnode:=tcglabelnode;
  567. end.
  568. {
  569. $Log$
  570. Revision 1.7 2001-12-30 17:24:48 jonas
  571. * range checking is now processor independent (part in cgobj, part in cg64f32) and should work correctly again (it needed some changes after the changes of the low and high of tordef's to int64) * maketojumpbool() is now processor independent (in ncgutil) * getregister32 is now called getregisterint
  572. Revision 1.6 2001/12/29 15:28:57 jonas
  573. * powerpc/cgcpu.pas compiles :)
  574. * several powerpc-related fixes
  575. * cpuasm unit is now based on common tainst unit
  576. + nppcmat unit for powerpc (almost complete)
  577. Revision 1.4 2001/11/02 22:58:01 peter
  578. * procsym definition rewrite
  579. Revision 1.3 2001/10/04 14:33:28 jonas
  580. * fixed range check errors
  581. Revision 1.2 2001/09/30 16:19:58 jonas
  582. - removed unused units
  583. Revision 1.1 2001/09/28 20:39:33 jonas
  584. * changed all flow control structures (except for exception handling
  585. related things) to processor independent code (in new ncgflw unit)
  586. + generic cgobj unit which contains lots of code generator helpers with
  587. global "cg" class instance variable
  588. + cgcpu unit for i386 (implements processor specific routines of the above
  589. unit)
  590. * updated cgbase and cpubase for the new code generator units
  591. * include ncgflw unit in cpunode unit
  592. Revision 1.4 2001/09/09 17:10:25 jonas
  593. * some more things implemented
  594. Revision 1.3 2001/09/06 15:25:55 jonas
  595. * changed type of tcg from object to class -> abstract methods are now
  596. a lot cleaner :)
  597. + more updates: load_*_loc methods, op_*_* methods, g_flags2reg method
  598. (if possible with geenric implementation and necessary ppc
  599. implementations)
  600. * worked a bit further on cgflw, now working on exitnode
  601. Revision 1.2 2001/09/05 20:21:03 jonas
  602. * new cgflow based on n386flw with all nodes until forn "translated"
  603. + a_cmp_*_loc_label methods for tcg
  604. + base implementatino for a_cmp_ref_*_label methods
  605. * small bugfixes to powerpc cg
  606. }