cg64f32.pas 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Member of the Free Pascal development team
  4. This unit implements the code generation for 64 bit int
  5. arithmethics on 32 bit 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. {# This unit implements the code generation for 64 bit int arithmethics on
  20. 32 bit processors.
  21. }
  22. unit cg64f32;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. aasmbase,aasmtai,aasmdata,aasmcpu,
  27. cpubase,cpupara,
  28. cgbase,cgobj,parabase,cgutils,
  29. symtype
  30. ;
  31. type
  32. {# Defines all the methods required on 32-bit processors
  33. to handle 64-bit integers.
  34. }
  35. tcg64f32 = class(tcg64)
  36. procedure a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);override;
  37. procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
  38. procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
  39. procedure a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);override;
  40. procedure a_load64_const_reg(list : TAsmList;value: int64;reg : tregister64);override;
  41. procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);override;
  42. procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);override;
  43. procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);override;
  44. procedure a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);override;
  45. procedure a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);override;
  46. procedure a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);override;
  47. procedure a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);override;
  48. procedure a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);override;
  49. procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);override;
  50. procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override;
  51. procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
  52. procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
  53. procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
  54. procedure a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
  55. procedure a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
  56. procedure a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
  57. procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
  58. procedure a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);override;
  59. procedure a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);override;
  60. procedure a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);override;
  61. procedure a_op64_ref_loc(list: TAsmList; op: TOpCG; size: tcgsize;const ref: treference; const l: tlocation);override;
  62. procedure a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);override;
  63. procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
  64. procedure a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);override;
  65. procedure a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);override;
  66. procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
  67. procedure a_load64_loc_cgpara(list : TAsmList;const l : tlocation;const paraloc : tcgpara);override;
  68. procedure a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);override;
  69. procedure a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);override;
  70. {# This routine tries to optimize the a_op64_const_reg operation, by
  71. removing superfluous opcodes. Returns TRUE if normal processing
  72. must continue in op64_const_reg, otherwise, everything is processed
  73. entirely in this routine, by emitting the appropriate 32-bit opcodes.
  74. }
  75. function optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;override;
  76. procedure g_rangecheck64(list: TAsmList; const l:tlocation;fromdef,todef: tdef); override;
  77. end;
  78. implementation
  79. uses
  80. globtype,systems,constexp,
  81. verbose,cutils,
  82. symbase,symconst,symdef,symtable,defutil,paramgr,
  83. tgobj,hlcgobj;
  84. {****************************************************************************
  85. Helpers
  86. ****************************************************************************}
  87. procedure swap64(var q : int64);
  88. begin
  89. q:=(int64(lo(q)) shl 32) or hi(q);
  90. end;
  91. procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
  92. var
  93. paraloclo,paraloclo2,paraloclo3,paraloclo4,
  94. paralochi,paralochi2,paralochi3,paralochi4 : pcgparalocation;
  95. curparaloc : PCGParaLocation;
  96. begin
  97. if not(cgpara.size in [OS_64,OS_S64]) then
  98. internalerror(200408231);
  99. if not assigned(cgpara.location) then
  100. internalerror(200408201);
  101. { init lo/hi para }
  102. cgparahi.reset;
  103. if cgpara.size=OS_S64 then
  104. cgparahi.size:=OS_S32
  105. else
  106. cgparahi.size:=OS_32;
  107. cgparahi.intsize:=4;
  108. cgparahi.alignment:=cgpara.alignment;
  109. paralochi:=cgparahi.add_location;
  110. cgparalo.reset;
  111. cgparalo.size:=OS_32;
  112. cgparalo.intsize:=4;
  113. cgparalo.alignment:=cgpara.alignment;
  114. paraloclo:=cgparalo.add_location;
  115. case cgpara.locations_count of
  116. 8:
  117. begin
  118. { 8 parameter fields? }
  119. { Order for multiple locations is always
  120. paraloc^ -> high
  121. paraloc^.next -> low }
  122. if (target_info.endian=ENDIAN_BIG) then
  123. begin
  124. { is there any big endian 8 bit ALU/16 bit Addr CPU? }
  125. internalerror(2015041001);
  126. { paraloc^ -> high }
  127. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  128. paralochi^.next:=nil;
  129. paralochi2:=cgparahi.add_location;
  130. move(cgpara.location^.next,paralochi2^,sizeof(paralochi2^));
  131. { paraloc^.next^.next^ -> low }
  132. move(cgpara.location^.next^.next^,paraloclo^,sizeof(paraloclo^));
  133. paraloclo^.next:=nil;
  134. paraloclo2:=cgparalo.add_location;
  135. move(cgpara.location^.next^.next^.next^,paraloclo2^,sizeof(paraloclo2^));
  136. end
  137. else
  138. begin
  139. { paraloc^ -> low }
  140. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  141. paraloclo^.next:=nil;
  142. paraloclo2:=cgparalo.add_location;
  143. move(cgpara.location^.next^,paraloclo2^,sizeof(paraloclo2^));
  144. paraloclo2^.next:=nil;
  145. paraloclo3:=cgparalo.add_location;
  146. move(cgpara.location^.next^.next^,paraloclo3^,sizeof(paraloclo3^));
  147. paraloclo3^.next:=nil;
  148. paraloclo4:=cgparalo.add_location;
  149. move(cgpara.location^.next^.next^.next^,paraloclo4^,sizeof(paraloclo4^));
  150. { paraloc^.next^.next^.next^.next^ -> high }
  151. curparaloc:=cgpara.location^.next^.next^.next^.next;
  152. move(curparaloc^,paralochi^,sizeof(paralochi^));
  153. paralochi^.next:=nil;
  154. paralochi2:=cgparahi.add_location;
  155. move(curparaloc^.next^,paralochi2^,sizeof(paralochi2^));
  156. paralochi2^.next:=nil;
  157. paralochi3:=cgparahi.add_location;
  158. move(curparaloc^.next^.next^,paralochi3^,sizeof(paralochi3^));
  159. paralochi3^.next:=nil;
  160. paralochi4:=cgparahi.add_location;
  161. move(curparaloc^.next^.next^.next^,paralochi4^,sizeof(paralochi4^));
  162. end;
  163. { fix size }
  164. paraloclo^.size:=OS_8;
  165. paraloclo2^.size:=OS_8;
  166. paraloclo3^.size:=OS_8;
  167. paraloclo4^.size:=OS_8;
  168. paraloclo4^.next:=nil;
  169. paralochi^.size:=OS_8;
  170. paralochi2^.size:=OS_8;
  171. paralochi3^.size:=OS_8;
  172. paralochi4^.size:=OS_8;
  173. paralochi4^.next:=nil;
  174. if cgpara.size=OS_S64 then
  175. if target_info.endian=ENDIAN_BIG then
  176. paralochi^.size:=OS_S8
  177. else
  178. paraloclo4^.size:=OS_S8;
  179. end;
  180. 4:
  181. begin
  182. { 4 parameter fields? }
  183. { Order for multiple locations is always
  184. paraloc^ -> high
  185. paraloc^.next -> low }
  186. if (target_info.endian=ENDIAN_BIG) then
  187. begin
  188. { paraloc^ -> high }
  189. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  190. paralochi^.next:=nil;
  191. paralochi2:=cgparahi.add_location;
  192. move(cgpara.location^.next,paralochi2^,sizeof(paralochi2^));
  193. { paraloc^.next^.next^ -> low }
  194. move(cgpara.location^.next^.next^,paraloclo^,sizeof(paraloclo^));
  195. paraloclo^.next:=nil;
  196. paraloclo2:=cgparalo.add_location;
  197. move(cgpara.location^.next^.next^.next^,paraloclo2^,sizeof(paraloclo2^));
  198. end
  199. else
  200. begin
  201. { paraloc^ -> low }
  202. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  203. paraloclo^.next:=nil;
  204. paraloclo2:=cgparalo.add_location;
  205. move(cgpara.location^.next^,paraloclo2^,sizeof(paraloclo2^));
  206. { paraloc^.next^.next -> high }
  207. move(cgpara.location^.next^.next^,paralochi^,sizeof(paralochi^));
  208. paralochi^.next:=nil;
  209. paralochi2:=cgparahi.add_location;
  210. move(cgpara.location^.next^.next^.next^,paralochi2^,sizeof(paralochi2^));
  211. end;
  212. { fix size }
  213. paraloclo^.size:=OS_16;
  214. paraloclo2^.size:=OS_16;
  215. paraloclo2^.next:=nil;
  216. paralochi^.size:=OS_16;
  217. paralochi2^.size:=OS_16;
  218. paralochi2^.next:=nil;
  219. if cgpara.size=OS_S64 then
  220. if target_info.endian=ENDIAN_BIG then
  221. paralochi^.size:=OS_S16
  222. else
  223. paraloclo2^.size:=OS_S16;
  224. end;
  225. 2:
  226. begin
  227. { 2 parameter fields? }
  228. { Order for multiple locations is always
  229. paraloc^ -> high
  230. paraloc^.next -> low }
  231. if (target_info.endian=ENDIAN_BIG) then
  232. begin
  233. { paraloc^ -> high
  234. paraloc^.next -> low }
  235. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  236. move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
  237. end
  238. else
  239. begin
  240. { paraloc^ -> low
  241. paraloc^.next -> high }
  242. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  243. move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
  244. end;
  245. { fix size }
  246. paraloclo^.size:=cgparalo.size;
  247. paraloclo^.next:=nil;
  248. paralochi^.size:=cgparahi.size;
  249. paralochi^.next:=nil;
  250. end;
  251. 1:
  252. begin
  253. { single parameter, this can only be in memory }
  254. if cgpara.location^.loc<>LOC_REFERENCE then
  255. internalerror(200408282);
  256. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  257. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  258. { for big endian low is at +4, for little endian high }
  259. if target_info.endian = endian_big then
  260. begin
  261. inc(cgparalo.location^.reference.offset,4);
  262. cgparalo.alignment:=newalignment(cgparalo.alignment,4);
  263. end
  264. else
  265. begin
  266. inc(cgparahi.location^.reference.offset,4);
  267. cgparahi.alignment:=newalignment(cgparahi.alignment,4);
  268. end;
  269. { fix size }
  270. paraloclo^.size:=cgparalo.size;
  271. paraloclo^.next:=nil;
  272. paralochi^.size:=cgparahi.size;
  273. paralochi^.next:=nil;
  274. end;
  275. else
  276. internalerror(2013051901);
  277. end;
  278. end;
  279. {****************************************************************************
  280. TCG64F32
  281. ****************************************************************************}
  282. procedure tcg64f32.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
  283. var
  284. tmpreg: tregister;
  285. tmpref: treference;
  286. begin
  287. if target_info.endian = endian_big then
  288. begin
  289. tmpreg:=reg.reglo;
  290. reg.reglo:=reg.reghi;
  291. reg.reghi:=tmpreg;
  292. end;
  293. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,ref);
  294. tmpref := ref;
  295. inc(tmpref.offset,4);
  296. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  297. end;
  298. procedure tcg64f32.a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);
  299. var
  300. tmpref: treference;
  301. begin
  302. if target_info.endian = endian_big then
  303. swap64(value);
  304. cg.a_load_const_ref(list,OS_32,longint(lo(value)),ref);
  305. tmpref := ref;
  306. inc(tmpref.offset,4);
  307. cg.a_load_const_ref(list,OS_32,longint(hi(value)),tmpref);
  308. end;
  309. procedure tcg64f32.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
  310. var
  311. tmpreg: tregister;
  312. tmpref: treference;
  313. begin
  314. if target_info.endian = endian_big then
  315. begin
  316. tmpreg := reg.reglo;
  317. reg.reglo := reg.reghi;
  318. reg.reghi := tmpreg;
  319. end;
  320. tmpref := ref;
  321. if (tmpref.base=reg.reglo) then
  322. begin
  323. tmpreg:=cg.getaddressregister(list);
  324. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  325. tmpref.base:=tmpreg;
  326. end
  327. else
  328. { this works only for the i386, thus the i386 needs to override }
  329. { this method and this method must be replaced by a more generic }
  330. { implementation FK }
  331. if (tmpref.index=reg.reglo) then
  332. begin
  333. tmpreg:=cg.getaddressregister(list);
  334. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
  335. tmpref.index:=tmpreg;
  336. end;
  337. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  338. inc(tmpref.offset,4);
  339. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  340. end;
  341. procedure tcg64f32.a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);
  342. begin
  343. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
  344. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
  345. end;
  346. procedure tcg64f32.a_load64_const_reg(list : TAsmList;value : int64;reg : tregister64);
  347. begin
  348. cg.a_load_const_reg(list,OS_32,longint(lo(value)),reg.reglo);
  349. cg.a_load_const_reg(list,OS_32,longint(hi(value)),reg.reghi);
  350. end;
  351. procedure tcg64f32.a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);
  352. var
  353. tmpreg: tregister;
  354. tmpsref: tsubsetreference;
  355. begin
  356. if (sref.bitindexreg <> NR_NO) or
  357. (sref.bitlen <> 64) then
  358. internalerror(2006082310);
  359. if (sref.startbit = 0) then
  360. begin
  361. a_load64_ref_reg(list,sref.ref,destreg);
  362. exit;
  363. end;
  364. if target_info.endian = endian_big then
  365. begin
  366. tmpreg := destreg.reglo;
  367. destreg.reglo := destreg.reghi;
  368. destreg.reghi := tmpreg;
  369. end;
  370. tmpsref:=sref;
  371. if (tmpsref.ref.base=destreg.reglo) then
  372. begin
  373. tmpreg:=cg.getaddressregister(list);
  374. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.base,tmpreg);
  375. tmpsref.ref.base:=tmpreg;
  376. end
  377. else
  378. if (tmpsref.ref.index=destreg.reglo) then
  379. begin
  380. tmpreg:=cg.getaddressregister(list);
  381. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.index,tmpreg);
  382. tmpsref.ref.index:=tmpreg;
  383. end;
  384. tmpsref.bitlen:=32;
  385. hlcg.a_load_subsetref_reg(list,u32inttype,u32inttype,tmpsref,destreg.reglo);
  386. inc(tmpsref.ref.offset,4);
  387. hlcg.a_load_subsetref_reg(list,u32inttype,u32inttype,tmpsref,destreg.reghi);
  388. end;
  389. procedure tcg64f32.a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);
  390. var
  391. tmpreg: tregister;
  392. tmpsref: tsubsetreference;
  393. begin
  394. if (sref.bitindexreg <> NR_NO) or
  395. (sref.bitlen <> 64) then
  396. internalerror(2006082311);
  397. if (sref.startbit = 0) then
  398. begin
  399. a_load64_reg_ref(list,fromreg,sref.ref);
  400. exit;
  401. end;
  402. if target_info.endian = endian_big then
  403. begin
  404. tmpreg:=fromreg.reglo;
  405. fromreg.reglo:=fromreg.reghi;
  406. fromreg.reghi:=tmpreg;
  407. end;
  408. tmpsref:=sref;
  409. tmpsref.bitlen:=32;
  410. hlcg.a_load_reg_subsetref(list,u32inttype,u32inttype,fromreg.reglo,tmpsref);
  411. inc(tmpsref.ref.offset,4);
  412. hlcg.a_load_reg_subsetref(list,u32inttype,u32inttype,fromreg.reghi,tmpsref);
  413. end;
  414. procedure tcg64f32.a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);
  415. var
  416. tmpsref: tsubsetreference;
  417. begin
  418. if (sref.bitindexreg <> NR_NO) or
  419. (sref.bitlen <> 64) then
  420. internalerror(2006082312);
  421. if target_info.endian = endian_big then
  422. swap64(a);
  423. tmpsref := sref;
  424. tmpsref.bitlen := 32;
  425. hlcg.a_load_const_subsetref(list,u32inttype,longint(lo(a)),tmpsref);
  426. inc(tmpsref.ref.offset,4);
  427. hlcg.a_load_const_subsetref(list,u32inttype,longint(hi(a)),tmpsref);
  428. end;
  429. procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
  430. var
  431. tmpreg64 : tregister64;
  432. begin
  433. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  434. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  435. a_load64_subsetref_reg(list,fromsref,tmpreg64);
  436. a_load64_reg_subsetref(list,tmpreg64,tosref);
  437. end;
  438. procedure tcg64f32.a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);
  439. var
  440. tmpreg64 : tregister64;
  441. begin
  442. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  443. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  444. a_load64_subsetref_reg(list,sref,tmpreg64);
  445. a_load64_reg_ref(list,tmpreg64,destref);
  446. end;
  447. procedure tcg64f32.a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);
  448. var
  449. tmpreg64 : tregister64;
  450. begin
  451. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  452. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  453. a_load64_ref_reg(list,fromref,tmpreg64);
  454. a_load64_reg_subsetref(list,tmpreg64,sref);
  455. end;
  456. procedure tcg64f32.a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);
  457. begin
  458. case l.loc of
  459. LOC_REFERENCE, LOC_CREFERENCE:
  460. a_load64_ref_reg(list,l.reference,reg);
  461. LOC_REGISTER,LOC_CREGISTER:
  462. a_load64_reg_reg(list,l.register64,reg);
  463. LOC_CONSTANT :
  464. a_load64_const_reg(list,l.value64,reg);
  465. LOC_SUBSETREF, LOC_CSUBSETREF:
  466. a_load64_subsetref_reg(list,l.sref,reg);
  467. else
  468. internalerror(200112292);
  469. end;
  470. end;
  471. procedure tcg64f32.a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);
  472. begin
  473. case l.loc of
  474. LOC_REGISTER,LOC_CREGISTER:
  475. a_load64_reg_ref(list,l.register64,ref);
  476. LOC_CONSTANT :
  477. a_load64_const_ref(list,l.value64,ref);
  478. LOC_SUBSETREF, LOC_CSUBSETREF:
  479. a_load64_subsetref_ref(list,l.sref,ref);
  480. else
  481. internalerror(200203288);
  482. end;
  483. end;
  484. procedure tcg64f32.a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);
  485. begin
  486. case l.loc of
  487. LOC_REFERENCE, LOC_CREFERENCE:
  488. a_load64_const_ref(list,value,l.reference);
  489. LOC_REGISTER,LOC_CREGISTER:
  490. a_load64_const_reg(list,value,l.register64);
  491. LOC_SUBSETREF, LOC_CSUBSETREF:
  492. a_load64_const_subsetref(list,value,l.sref);
  493. else
  494. internalerror(200112293);
  495. end;
  496. end;
  497. procedure tcg64f32.a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);
  498. begin
  499. case l.loc of
  500. LOC_REFERENCE, LOC_CREFERENCE:
  501. a_load64_reg_ref(list,reg,l.reference);
  502. LOC_REGISTER,LOC_CREGISTER:
  503. a_load64_reg_reg(list,reg,l.register64);
  504. LOC_SUBSETREF, LOC_CSUBSETREF:
  505. a_load64_reg_subsetref(list,reg,l.sref);
  506. LOC_MMREGISTER, LOC_CMMREGISTER:
  507. a_loadmm_intreg64_reg(list,l.size,reg,l.register);
  508. else
  509. internalerror(200112294);
  510. end;
  511. end;
  512. procedure tcg64f32.a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  513. var
  514. tmpref: treference;
  515. begin
  516. if target_info.endian = endian_big then
  517. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  518. else
  519. begin
  520. tmpref := ref;
  521. inc(tmpref.offset,4);
  522. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  523. end;
  524. end;
  525. procedure tcg64f32.a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  526. var
  527. tmpref: treference;
  528. begin
  529. if target_info.endian = endian_little then
  530. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  531. else
  532. begin
  533. tmpref := ref;
  534. inc(tmpref.offset,4);
  535. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  536. end;
  537. end;
  538. procedure tcg64f32.a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  539. var
  540. tmpref: treference;
  541. begin
  542. if target_info.endian = endian_big then
  543. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  544. else
  545. begin
  546. tmpref := ref;
  547. inc(tmpref.offset,4);
  548. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  549. end;
  550. end;
  551. procedure tcg64f32.a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  552. var
  553. tmpref: treference;
  554. begin
  555. if target_info.endian = endian_little then
  556. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  557. else
  558. begin
  559. tmpref := ref;
  560. inc(tmpref.offset,4);
  561. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  562. end;
  563. end;
  564. procedure tcg64f32.a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  565. begin
  566. case l.loc of
  567. LOC_REFERENCE,
  568. LOC_CREFERENCE :
  569. a_load64low_ref_reg(list,l.reference,reg);
  570. LOC_REGISTER,
  571. LOC_CREGISTER :
  572. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reglo,reg);
  573. LOC_CONSTANT :
  574. cg.a_load_const_reg(list,OS_32,longint(lo(l.value64)),reg);
  575. else
  576. internalerror(200203244);
  577. end;
  578. end;
  579. procedure tcg64f32.a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  580. begin
  581. case l.loc of
  582. LOC_REFERENCE,
  583. LOC_CREFERENCE :
  584. a_load64high_ref_reg(list,l.reference,reg);
  585. LOC_REGISTER,
  586. LOC_CREGISTER :
  587. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reghi,reg);
  588. LOC_CONSTANT :
  589. cg.a_load_const_reg(list,OS_32,longint(hi(l.value64)),reg);
  590. else
  591. internalerror(200203244);
  592. end;
  593. end;
  594. procedure tcg64f32.a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);
  595. begin
  596. case l.loc of
  597. LOC_REFERENCE, LOC_CREFERENCE:
  598. a_op64_const_ref(list,op,size,value,l.reference);
  599. LOC_REGISTER,LOC_CREGISTER:
  600. a_op64_const_reg(list,op,size,value,l.register64);
  601. else
  602. internalerror(200203292);
  603. end;
  604. end;
  605. procedure tcg64f32.a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);
  606. begin
  607. case l.loc of
  608. LOC_REFERENCE, LOC_CREFERENCE:
  609. a_op64_reg_ref(list,op,size,reg,l.reference);
  610. LOC_REGISTER,LOC_CREGISTER:
  611. a_op64_reg_reg(list,op,size,reg,l.register64);
  612. else
  613. internalerror(2002032422);
  614. end;
  615. end;
  616. procedure tcg64f32.a_op64_ref_loc(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;const l : tlocation);
  617. var
  618. tempreg: tregister64;
  619. begin
  620. case l.loc of
  621. LOC_REFERENCE, LOC_CREFERENCE:
  622. begin
  623. tempreg.reghi:=cg.getintregister(list,OS_32);
  624. tempreg.reglo:=cg.getintregister(list,OS_32);
  625. a_load64_ref_reg(list,ref,tempreg);
  626. a_op64_reg_ref(list,op,size,tempreg,l.reference);
  627. end;
  628. LOC_REGISTER,LOC_CREGISTER:
  629. a_op64_ref_reg(list,op,size,ref,l.register64);
  630. else
  631. internalerror(2020042803);
  632. end;
  633. end;
  634. procedure tcg64f32.a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);
  635. begin
  636. case l.loc of
  637. LOC_REFERENCE, LOC_CREFERENCE:
  638. a_op64_ref_reg(list,op,size,l.reference,reg);
  639. LOC_REGISTER,LOC_CREGISTER:
  640. a_op64_reg_reg(list,op,size,l.register64,reg);
  641. LOC_CONSTANT :
  642. a_op64_const_reg(list,op,size,l.value64,reg);
  643. else
  644. internalerror(200203242);
  645. end;
  646. end;
  647. procedure tcg64f32.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
  648. var
  649. tempreg: tregister64;
  650. begin
  651. tempreg.reghi:=cg.getintregister(list,OS_32);
  652. tempreg.reglo:=cg.getintregister(list,OS_32);
  653. a_load64_ref_reg(list,ref,tempreg);
  654. a_op64_reg_reg(list,op,size,tempreg,reg);
  655. end;
  656. procedure tcg64f32.a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
  657. var
  658. tempreg: tregister64;
  659. begin
  660. tempreg.reghi:=cg.getintregister(list,OS_32);
  661. tempreg.reglo:=cg.getintregister(list,OS_32);
  662. a_load64_ref_reg(list,ref,tempreg);
  663. if op in [OP_NEG,OP_NOT] then
  664. a_op64_reg_reg(list,op,size,tempreg,tempreg)
  665. else
  666. a_op64_reg_reg(list,op,size,reg,tempreg);
  667. a_load64_reg_ref(list,tempreg,ref);
  668. end;
  669. procedure tcg64f32.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
  670. var
  671. tempreg: tregister64;
  672. begin
  673. tempreg.reghi:=cg.getintregister(list,OS_32);
  674. tempreg.reglo:=cg.getintregister(list,OS_32);
  675. a_load64_ref_reg(list,ref,tempreg);
  676. a_op64_const_reg(list,op,size,value,tempreg);
  677. a_load64_reg_ref(list,tempreg,ref);
  678. end;
  679. procedure tcg64f32.a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);
  680. var
  681. tmplochi,tmploclo: tcgpara;
  682. begin
  683. tmploclo.init;
  684. tmplochi.init;
  685. splitparaloc64(paraloc,tmploclo,tmplochi);
  686. if target_info.endian=endian_big then
  687. begin
  688. { Keep this order of first lo before hi to have
  689. the correct push order for m68k }
  690. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  691. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  692. end
  693. else
  694. begin
  695. { Keep this order of first hi before lo to have
  696. the correct push order for i386 }
  697. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  698. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  699. end;
  700. tmploclo.done;
  701. tmplochi.done;
  702. end;
  703. procedure tcg64f32.a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);
  704. var
  705. tmplochi,tmploclo: tcgpara;
  706. begin
  707. tmploclo.init;
  708. tmplochi.init;
  709. splitparaloc64(paraloc,tmploclo,tmplochi);
  710. if target_info.endian=endian_big then
  711. begin
  712. { Keep this order of first lo before hi to have
  713. the correct push order for m68k }
  714. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  715. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  716. end
  717. else
  718. begin
  719. { Keep this order of first hi before lo to have
  720. the correct push order for i386 }
  721. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  722. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  723. end;
  724. tmploclo.done;
  725. tmplochi.done;
  726. end;
  727. procedure tcg64f32.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
  728. var
  729. tmprefhi,tmpreflo : treference;
  730. tmploclo,tmplochi : tcgpara;
  731. begin
  732. tmploclo.init;
  733. tmplochi.init;
  734. splitparaloc64(paraloc,tmploclo,tmplochi);
  735. tmprefhi:=r;
  736. tmpreflo:=r;
  737. if target_info.endian=endian_big then
  738. begin
  739. { Keep this order of first lo before hi to have
  740. the correct push order for m68k }
  741. inc(tmpreflo.offset,4);
  742. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  743. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  744. end
  745. else
  746. begin
  747. { Keep this order of first hi before lo to have
  748. the correct push order for i386 }
  749. inc(tmprefhi.offset,4);
  750. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  751. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  752. end;
  753. tmploclo.done;
  754. tmplochi.done;
  755. end;
  756. procedure tcg64f32.a_load64_loc_cgpara(list : TAsmList;const l:tlocation;const paraloc : tcgpara);
  757. begin
  758. case l.loc of
  759. LOC_REGISTER,
  760. LOC_CREGISTER :
  761. a_load64_reg_cgpara(list,l.register64,paraloc);
  762. LOC_CONSTANT :
  763. a_load64_const_cgpara(list,l.value64,paraloc);
  764. LOC_CREFERENCE,
  765. LOC_REFERENCE :
  766. a_load64_ref_cgpara(list,l.reference,paraloc);
  767. else
  768. internalerror(200203287);
  769. end;
  770. end;
  771. procedure tcg64f32.a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);
  772. var
  773. tmpref: treference;
  774. begin
  775. if (tcgsize2size[mmsize]<>8) then
  776. internalerror(2009112501);
  777. tg.gettemp(list,8,8,tt_normal,tmpref);
  778. a_load64_reg_ref(list,intreg,tmpref);
  779. cg.a_loadmm_ref_reg(list,mmsize,mmsize,tmpref,mmreg,mms_movescalar);
  780. tg.ungettemp(list,tmpref);
  781. end;
  782. procedure tcg64f32.a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);
  783. var
  784. tmpref: treference;
  785. begin
  786. if (tcgsize2size[mmsize]<>8) then
  787. internalerror(2009112502);
  788. tg.gettemp(list,8,8,tt_normal,tmpref);
  789. cg.a_loadmm_reg_ref(list,mmsize,mmsize,mmreg,tmpref,mms_movescalar);
  790. a_load64_ref_reg(list,tmpref,intreg);
  791. tg.ungettemp(list,tmpref);
  792. end;
  793. procedure tcg64f32.g_rangecheck64(list : TAsmList;const l:tlocation;fromdef,todef:tdef);
  794. var
  795. neglabel,
  796. poslabel,
  797. endlabel: tasmlabel;
  798. hreg : tregister;
  799. hdef : torddef;
  800. opsize : tcgsize;
  801. from_signed,to_signed: boolean;
  802. temploc : tlocation;
  803. begin
  804. from_signed := is_signed(fromdef);
  805. to_signed := is_signed(todef);
  806. if not is_64bit(todef) then
  807. begin
  808. { get the high dword in a register }
  809. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  810. begin
  811. hreg := l.register64.reghi;
  812. end
  813. else
  814. begin
  815. hreg:=cg.getintregister(list,OS_32);
  816. a_load64high_ref_reg(list,l.reference,hreg);
  817. end;
  818. current_asmdata.getjumplabel(poslabel);
  819. { check high dword, must be 0 (for positive numbers) }
  820. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  821. { It can also be $ffffffff, but only for negative numbers }
  822. if from_signed and to_signed then
  823. begin
  824. current_asmdata.getjumplabel(neglabel);
  825. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  826. end
  827. else
  828. { we do not have dynamic dfa, so avoid a warning below about the unused
  829. neglabel }
  830. neglabel:=nil;
  831. { For all other values we have a range check error }
  832. cg.a_call_name(list,'fpc_rangeerror',false);
  833. { if the high dword = 0, the low dword can be considered a }
  834. { simple cardinal }
  835. cg.a_label(list,poslabel);
  836. hdef:=corddef.create(u32bit,0,$ffffffff,false);
  837. location_copy(temploc,l);
  838. temploc.size:=OS_32;
  839. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  840. (target_info.endian = endian_big) then
  841. begin
  842. inc(temploc.reference.offset,4);
  843. temploc.reference.alignment:=newalignment(temploc.reference.alignment,4);
  844. end;
  845. hlcg.g_rangecheck(list,temploc,hdef,todef);
  846. hdef.free;
  847. if from_signed and to_signed then
  848. begin
  849. current_asmdata.getjumplabel(endlabel);
  850. cg.a_jmp_always(list,endlabel);
  851. { if the high dword = $ffffffff, then the low dword (when }
  852. { considered as a longint) must be < 0 }
  853. cg.a_label(list,neglabel);
  854. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  855. begin
  856. hreg := l.register64.reglo;
  857. end
  858. else
  859. begin
  860. hreg:=cg.getintregister(list,OS_32);
  861. a_load64low_ref_reg(list,l.reference,hreg);
  862. end;
  863. { get a new neglabel (JM) }
  864. current_asmdata.getjumplabel(neglabel);
  865. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  866. cg.a_call_name(list,'fpc_rangeerror',false);
  867. { if we get here, the 64bit value lies between }
  868. { longint($80000000) and -1 (JM) }
  869. cg.a_label(list,neglabel);
  870. hdef:=corddef.create(s32bit,int64(longint($80000000)),int64(-1),false);
  871. location_copy(temploc,l);
  872. temploc.size:=OS_32;
  873. hlcg.g_rangecheck(list,temploc,hdef,todef);
  874. hdef.free;
  875. cg.a_label(list,endlabel);
  876. end;
  877. end
  878. else
  879. { todef = 64bit int }
  880. { no 64bit subranges supported, so only a small check is necessary }
  881. { if both are signed or both are unsigned, no problem! }
  882. if (from_signed xor to_signed) and
  883. { also not if the fromdef is unsigned and < 64bit, since that will }
  884. { always fit in a 64bit int (todef is 64bit) }
  885. (from_signed or
  886. (torddef(fromdef).ordtype = u64bit)) then
  887. begin
  888. { in all cases, there is only a problem if the higest bit is set }
  889. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  890. begin
  891. if is_64bit(fromdef) then
  892. begin
  893. hreg := l.register64.reghi;
  894. opsize := OS_32;
  895. end
  896. else
  897. begin
  898. hreg := l.register;
  899. opsize := def_cgsize(fromdef);
  900. end;
  901. end
  902. else
  903. begin
  904. hreg:=cg.getintregister(list,OS_32);
  905. opsize:=OS_32;
  906. if l.size in [OS_64,OS_S64] then
  907. a_load64high_ref_reg(list,l.reference,hreg)
  908. else
  909. cg.a_load_ref_reg(list,l.size,OS_32,l.reference,hreg);
  910. end;
  911. current_asmdata.getjumplabel(poslabel);
  912. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  913. cg.a_call_name(list,'fpc_rangeerror',false);
  914. cg.a_label(list,poslabel);
  915. end;
  916. end;
  917. function tcg64f32.optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;
  918. var
  919. lowvalue, highvalue : longint;
  920. hreg: tregister;
  921. begin
  922. lowvalue := longint(a);
  923. highvalue:= longint(a shr 32);
  924. { assume it will be optimized out }
  925. optimize64_op_const_reg := true;
  926. case op of
  927. OP_ADD:
  928. begin
  929. if a = 0 then
  930. exit;
  931. end;
  932. OP_AND:
  933. begin
  934. if lowvalue <> -1 then
  935. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  936. if highvalue <> -1 then
  937. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  938. { already emitted correctly }
  939. exit;
  940. end;
  941. OP_OR:
  942. begin
  943. if lowvalue <> 0 then
  944. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  945. if highvalue <> 0 then
  946. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  947. { already emitted correctly }
  948. exit;
  949. end;
  950. OP_SUB:
  951. begin
  952. if a = 0 then
  953. exit;
  954. end;
  955. OP_XOR:
  956. begin
  957. end;
  958. OP_SHL:
  959. begin
  960. if a = 0 then
  961. exit;
  962. { simply clear low-register
  963. and shift the rest and swap
  964. registers.
  965. }
  966. if (a > 31) then
  967. begin
  968. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  969. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  970. { swap the registers }
  971. hreg := reg.reghi;
  972. reg.reghi := reg.reglo;
  973. reg.reglo := hreg;
  974. exit;
  975. end;
  976. end;
  977. OP_SHR:
  978. begin
  979. if a = 0 then exit;
  980. { simply clear high-register
  981. and shift the rest and swap
  982. registers.
  983. }
  984. if (a > 31) then
  985. begin
  986. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  987. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  988. { swap the registers }
  989. hreg := reg.reghi;
  990. reg.reghi := reg.reglo;
  991. reg.reglo := hreg;
  992. exit;
  993. end;
  994. end;
  995. OP_IMUL,OP_MUL:
  996. begin
  997. if a = 1 then exit;
  998. end;
  999. OP_IDIV,OP_DIV:
  1000. begin
  1001. if a = 1 then exit;
  1002. end;
  1003. else
  1004. internalerror(20020817);
  1005. end;
  1006. optimize64_op_const_reg := false;
  1007. end;
  1008. end.