cg64f32.pas 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  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. if op in [OP_NEG,OP_NOT] then
  663. begin
  664. a_op64_reg_reg(list,op,size,reg,tempreg);
  665. a_load64_reg_ref(list,tempreg,ref);
  666. end
  667. else
  668. begin
  669. a_load64_ref_reg(list,ref,tempreg);
  670. a_op64_reg_reg(list,op,size,reg,tempreg);
  671. a_load64_reg_ref(list,tempreg,ref);
  672. end;
  673. end;
  674. procedure tcg64f32.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
  675. var
  676. tempreg: tregister64;
  677. begin
  678. tempreg.reghi:=cg.getintregister(list,OS_32);
  679. tempreg.reglo:=cg.getintregister(list,OS_32);
  680. a_load64_ref_reg(list,ref,tempreg);
  681. a_op64_const_reg(list,op,size,value,tempreg);
  682. a_load64_reg_ref(list,tempreg,ref);
  683. end;
  684. procedure tcg64f32.a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);
  685. var
  686. tmplochi,tmploclo: tcgpara;
  687. begin
  688. tmploclo.init;
  689. tmplochi.init;
  690. splitparaloc64(paraloc,tmploclo,tmplochi);
  691. if target_info.endian=endian_big then
  692. begin
  693. { Keep this order of first lo before hi to have
  694. the correct push order for m68k }
  695. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  696. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  697. end
  698. else
  699. begin
  700. { Keep this order of first hi before lo to have
  701. the correct push order for i386 }
  702. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  703. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  704. end;
  705. tmploclo.done;
  706. tmplochi.done;
  707. end;
  708. procedure tcg64f32.a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);
  709. var
  710. tmplochi,tmploclo: tcgpara;
  711. begin
  712. tmploclo.init;
  713. tmplochi.init;
  714. splitparaloc64(paraloc,tmploclo,tmplochi);
  715. if target_info.endian=endian_big then
  716. begin
  717. { Keep this order of first lo before hi to have
  718. the correct push order for m68k }
  719. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  720. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  721. end
  722. else
  723. begin
  724. { Keep this order of first hi before lo to have
  725. the correct push order for i386 }
  726. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  727. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  728. end;
  729. tmploclo.done;
  730. tmplochi.done;
  731. end;
  732. procedure tcg64f32.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
  733. var
  734. tmprefhi,tmpreflo : treference;
  735. tmploclo,tmplochi : tcgpara;
  736. begin
  737. tmploclo.init;
  738. tmplochi.init;
  739. splitparaloc64(paraloc,tmploclo,tmplochi);
  740. tmprefhi:=r;
  741. tmpreflo:=r;
  742. if target_info.endian=endian_big then
  743. begin
  744. { Keep this order of first lo before hi to have
  745. the correct push order for m68k }
  746. inc(tmpreflo.offset,4);
  747. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  748. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  749. end
  750. else
  751. begin
  752. { Keep this order of first hi before lo to have
  753. the correct push order for i386 }
  754. inc(tmprefhi.offset,4);
  755. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  756. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  757. end;
  758. tmploclo.done;
  759. tmplochi.done;
  760. end;
  761. procedure tcg64f32.a_load64_loc_cgpara(list : TAsmList;const l:tlocation;const paraloc : tcgpara);
  762. begin
  763. case l.loc of
  764. LOC_REGISTER,
  765. LOC_CREGISTER :
  766. a_load64_reg_cgpara(list,l.register64,paraloc);
  767. LOC_CONSTANT :
  768. a_load64_const_cgpara(list,l.value64,paraloc);
  769. LOC_CREFERENCE,
  770. LOC_REFERENCE :
  771. a_load64_ref_cgpara(list,l.reference,paraloc);
  772. else
  773. internalerror(200203287);
  774. end;
  775. end;
  776. procedure tcg64f32.a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);
  777. var
  778. tmpref: treference;
  779. begin
  780. if (tcgsize2size[mmsize]<>8) then
  781. internalerror(2009112501);
  782. tg.gettemp(list,8,8,tt_normal,tmpref);
  783. a_load64_reg_ref(list,intreg,tmpref);
  784. cg.a_loadmm_ref_reg(list,mmsize,mmsize,tmpref,mmreg,mms_movescalar);
  785. tg.ungettemp(list,tmpref);
  786. end;
  787. procedure tcg64f32.a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);
  788. var
  789. tmpref: treference;
  790. begin
  791. if (tcgsize2size[mmsize]<>8) then
  792. internalerror(2009112502);
  793. tg.gettemp(list,8,8,tt_normal,tmpref);
  794. cg.a_loadmm_reg_ref(list,mmsize,mmsize,mmreg,tmpref,mms_movescalar);
  795. a_load64_ref_reg(list,tmpref,intreg);
  796. tg.ungettemp(list,tmpref);
  797. end;
  798. procedure tcg64f32.g_rangecheck64(list : TAsmList;const l:tlocation;fromdef,todef:tdef);
  799. var
  800. neglabel,
  801. poslabel,
  802. endlabel: tasmlabel;
  803. hreg : tregister;
  804. hdef : torddef;
  805. opsize : tcgsize;
  806. from_signed,to_signed: boolean;
  807. temploc : tlocation;
  808. begin
  809. from_signed := is_signed(fromdef);
  810. to_signed := is_signed(todef);
  811. if not is_64bit(todef) then
  812. begin
  813. { get the high dword in a register }
  814. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  815. begin
  816. hreg := l.register64.reghi;
  817. end
  818. else
  819. begin
  820. hreg:=cg.getintregister(list,OS_32);
  821. a_load64high_ref_reg(list,l.reference,hreg);
  822. end;
  823. current_asmdata.getjumplabel(poslabel);
  824. { check high dword, must be 0 (for positive numbers) }
  825. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  826. { It can also be $ffffffff, but only for negative numbers }
  827. if from_signed and to_signed then
  828. begin
  829. current_asmdata.getjumplabel(neglabel);
  830. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  831. end
  832. else
  833. { we do not have dynamic dfa, so avoid a warning below about the unused
  834. neglabel }
  835. neglabel:=nil;
  836. { For all other values we have a range check error }
  837. cg.a_call_name(list,'fpc_rangeerror',false);
  838. { if the high dword = 0, the low dword can be considered a }
  839. { simple cardinal }
  840. cg.a_label(list,poslabel);
  841. hdef:=corddef.create(u32bit,0,$ffffffff,false);
  842. location_copy(temploc,l);
  843. temploc.size:=OS_32;
  844. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  845. (target_info.endian = endian_big) then
  846. begin
  847. inc(temploc.reference.offset,4);
  848. temploc.reference.alignment:=newalignment(temploc.reference.alignment,4);
  849. end;
  850. hlcg.g_rangecheck(list,temploc,hdef,todef);
  851. hdef.free;
  852. if from_signed and to_signed then
  853. begin
  854. current_asmdata.getjumplabel(endlabel);
  855. cg.a_jmp_always(list,endlabel);
  856. { if the high dword = $ffffffff, then the low dword (when }
  857. { considered as a longint) must be < 0 }
  858. cg.a_label(list,neglabel);
  859. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  860. begin
  861. hreg := l.register64.reglo;
  862. end
  863. else
  864. begin
  865. hreg:=cg.getintregister(list,OS_32);
  866. a_load64low_ref_reg(list,l.reference,hreg);
  867. end;
  868. { get a new neglabel (JM) }
  869. current_asmdata.getjumplabel(neglabel);
  870. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  871. cg.a_call_name(list,'fpc_rangeerror',false);
  872. { if we get here, the 64bit value lies between }
  873. { longint($80000000) and -1 (JM) }
  874. cg.a_label(list,neglabel);
  875. hdef:=corddef.create(s32bit,int64(longint($80000000)),int64(-1),false);
  876. location_copy(temploc,l);
  877. temploc.size:=OS_32;
  878. hlcg.g_rangecheck(list,temploc,hdef,todef);
  879. hdef.free;
  880. cg.a_label(list,endlabel);
  881. end;
  882. end
  883. else
  884. { todef = 64bit int }
  885. { no 64bit subranges supported, so only a small check is necessary }
  886. { if both are signed or both are unsigned, no problem! }
  887. if (from_signed xor to_signed) and
  888. { also not if the fromdef is unsigned and < 64bit, since that will }
  889. { always fit in a 64bit int (todef is 64bit) }
  890. (from_signed or
  891. (torddef(fromdef).ordtype = u64bit)) then
  892. begin
  893. { in all cases, there is only a problem if the higest bit is set }
  894. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  895. begin
  896. if is_64bit(fromdef) then
  897. begin
  898. hreg := l.register64.reghi;
  899. opsize := OS_32;
  900. end
  901. else
  902. begin
  903. hreg := l.register;
  904. opsize := def_cgsize(fromdef);
  905. end;
  906. end
  907. else
  908. begin
  909. hreg:=cg.getintregister(list,OS_32);
  910. opsize:=OS_32;
  911. if l.size in [OS_64,OS_S64] then
  912. a_load64high_ref_reg(list,l.reference,hreg)
  913. else
  914. cg.a_load_ref_reg(list,l.size,OS_32,l.reference,hreg);
  915. end;
  916. current_asmdata.getjumplabel(poslabel);
  917. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  918. cg.a_call_name(list,'fpc_rangeerror',false);
  919. cg.a_label(list,poslabel);
  920. end;
  921. end;
  922. function tcg64f32.optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;
  923. var
  924. lowvalue, highvalue : longint;
  925. hreg: tregister;
  926. begin
  927. lowvalue := longint(a);
  928. highvalue:= longint(a shr 32);
  929. { assume it will be optimized out }
  930. optimize64_op_const_reg := true;
  931. case op of
  932. OP_ADD:
  933. begin
  934. if a = 0 then
  935. exit;
  936. end;
  937. OP_AND:
  938. begin
  939. if lowvalue <> -1 then
  940. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  941. if highvalue <> -1 then
  942. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  943. { already emitted correctly }
  944. exit;
  945. end;
  946. OP_OR:
  947. begin
  948. if lowvalue <> 0 then
  949. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  950. if highvalue <> 0 then
  951. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  952. { already emitted correctly }
  953. exit;
  954. end;
  955. OP_SUB:
  956. begin
  957. if a = 0 then
  958. exit;
  959. end;
  960. OP_XOR:
  961. begin
  962. end;
  963. OP_SHL:
  964. begin
  965. if a = 0 then
  966. exit;
  967. { simply clear low-register
  968. and shift the rest and swap
  969. registers.
  970. }
  971. if (a > 31) then
  972. begin
  973. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  974. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  975. { swap the registers }
  976. hreg := reg.reghi;
  977. reg.reghi := reg.reglo;
  978. reg.reglo := hreg;
  979. exit;
  980. end;
  981. end;
  982. OP_SHR:
  983. begin
  984. if a = 0 then exit;
  985. { simply clear high-register
  986. and shift the rest and swap
  987. registers.
  988. }
  989. if (a > 31) then
  990. begin
  991. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  992. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  993. { swap the registers }
  994. hreg := reg.reghi;
  995. reg.reghi := reg.reglo;
  996. reg.reglo := hreg;
  997. exit;
  998. end;
  999. end;
  1000. OP_IMUL,OP_MUL:
  1001. begin
  1002. if a = 1 then exit;
  1003. end;
  1004. OP_IDIV,OP_DIV:
  1005. begin
  1006. if a = 1 then exit;
  1007. end;
  1008. else
  1009. internalerror(20020817);
  1010. end;
  1011. optimize64_op_const_reg := false;
  1012. end;
  1013. end.