cg64f32.pas 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  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. tmpref := ref;
  294. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  295. { Preload base and index to a separate temp register for 8 & 16 bit CPUs
  296. to reduce spilling and produce a better code. }
  297. if (tmpref.base<>NR_NO) and (getsupreg(tmpref.base)>=first_int_imreg) then
  298. begin
  299. tmpreg:=cg.getaddressregister(list);
  300. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  301. tmpref.base:=tmpreg;
  302. if tmpref.index<>NR_NO then
  303. begin
  304. cg.a_op_reg_reg(list,OP_ADD,OS_ADDR,tmpref.index,tmpref.base);
  305. tmpref.index:=NR_NO;
  306. end;
  307. end;
  308. {$endif}
  309. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,tmpref);
  310. inc(tmpref.offset,4);
  311. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  312. end;
  313. procedure tcg64f32.a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);
  314. var
  315. tmpref: treference;
  316. begin
  317. if target_info.endian = endian_big then
  318. swap64(value);
  319. cg.a_load_const_ref(list,OS_32,longint(lo(value)),ref);
  320. tmpref := ref;
  321. inc(tmpref.offset,4);
  322. cg.a_load_const_ref(list,OS_32,longint(hi(value)),tmpref);
  323. end;
  324. procedure tcg64f32.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
  325. var
  326. tmpreg: tregister;
  327. tmpref: treference;
  328. begin
  329. if target_info.endian = endian_big then
  330. begin
  331. tmpreg := reg.reglo;
  332. reg.reglo := reg.reghi;
  333. reg.reghi := tmpreg;
  334. end;
  335. tmpref := ref;
  336. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  337. { Preload base and index to a separate temp register for 8 & 16 bit CPUs
  338. to reduce spilling and produce a better code. }
  339. if (tmpref.base<>NR_NO) and (getsupreg(tmpref.base)>=first_int_imreg) then
  340. begin
  341. tmpreg:=cg.getaddressregister(list);
  342. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  343. tmpref.base:=tmpreg;
  344. if tmpref.index<>NR_NO then
  345. begin
  346. cg.a_op_reg_reg(list,OP_ADD,OS_ADDR,tmpref.index,tmpref.base);
  347. tmpref.index:=NR_NO;
  348. end;
  349. end;
  350. {$endif}
  351. if (tmpref.base=reg.reglo) then
  352. begin
  353. tmpreg:=cg.getaddressregister(list);
  354. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  355. tmpref.base:=tmpreg;
  356. end
  357. else
  358. { this works only for the i386, thus the i386 needs to override }
  359. { this method and this method must be replaced by a more generic }
  360. { implementation FK }
  361. if (tmpref.index=reg.reglo) then
  362. begin
  363. tmpreg:=cg.getaddressregister(list);
  364. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
  365. tmpref.index:=tmpreg;
  366. end;
  367. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  368. inc(tmpref.offset,4);
  369. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  370. end;
  371. procedure tcg64f32.a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);
  372. begin
  373. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
  374. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
  375. end;
  376. procedure tcg64f32.a_load64_const_reg(list : TAsmList;value : int64;reg : tregister64);
  377. begin
  378. cg.a_load_const_reg(list,OS_32,longint(lo(value)),reg.reglo);
  379. cg.a_load_const_reg(list,OS_32,longint(hi(value)),reg.reghi);
  380. end;
  381. procedure tcg64f32.a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);
  382. var
  383. tmpreg: tregister;
  384. tmpsref: tsubsetreference;
  385. begin
  386. if (sref.bitindexreg <> NR_NO) or
  387. (sref.bitlen <> 64) then
  388. internalerror(2006082310);
  389. if (sref.startbit = 0) then
  390. begin
  391. a_load64_ref_reg(list,sref.ref,destreg);
  392. exit;
  393. end;
  394. if target_info.endian = endian_big then
  395. begin
  396. tmpreg := destreg.reglo;
  397. destreg.reglo := destreg.reghi;
  398. destreg.reghi := tmpreg;
  399. end;
  400. tmpsref:=sref;
  401. if (tmpsref.ref.base=destreg.reglo) then
  402. begin
  403. tmpreg:=cg.getaddressregister(list);
  404. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.base,tmpreg);
  405. tmpsref.ref.base:=tmpreg;
  406. end
  407. else
  408. if (tmpsref.ref.index=destreg.reglo) then
  409. begin
  410. tmpreg:=cg.getaddressregister(list);
  411. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.index,tmpreg);
  412. tmpsref.ref.index:=tmpreg;
  413. end;
  414. tmpsref.bitlen:=32;
  415. hlcg.a_load_subsetref_reg(list,u32inttype,u32inttype,tmpsref,destreg.reglo);
  416. inc(tmpsref.ref.offset,4);
  417. hlcg.a_load_subsetref_reg(list,u32inttype,u32inttype,tmpsref,destreg.reghi);
  418. end;
  419. procedure tcg64f32.a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);
  420. var
  421. tmpreg: tregister;
  422. tmpsref: tsubsetreference;
  423. begin
  424. if (sref.bitindexreg <> NR_NO) or
  425. (sref.bitlen <> 64) then
  426. internalerror(2006082311);
  427. if (sref.startbit = 0) then
  428. begin
  429. a_load64_reg_ref(list,fromreg,sref.ref);
  430. exit;
  431. end;
  432. if target_info.endian = endian_big then
  433. begin
  434. tmpreg:=fromreg.reglo;
  435. fromreg.reglo:=fromreg.reghi;
  436. fromreg.reghi:=tmpreg;
  437. end;
  438. tmpsref:=sref;
  439. tmpsref.bitlen:=32;
  440. hlcg.a_load_reg_subsetref(list,u32inttype,u32inttype,fromreg.reglo,tmpsref);
  441. inc(tmpsref.ref.offset,4);
  442. hlcg.a_load_reg_subsetref(list,u32inttype,u32inttype,fromreg.reghi,tmpsref);
  443. end;
  444. procedure tcg64f32.a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);
  445. var
  446. tmpsref: tsubsetreference;
  447. begin
  448. if (sref.bitindexreg <> NR_NO) or
  449. (sref.bitlen <> 64) then
  450. internalerror(2006082312);
  451. if target_info.endian = endian_big then
  452. swap64(a);
  453. tmpsref := sref;
  454. tmpsref.bitlen := 32;
  455. hlcg.a_load_const_subsetref(list,u32inttype,longint(lo(a)),tmpsref);
  456. inc(tmpsref.ref.offset,4);
  457. hlcg.a_load_const_subsetref(list,u32inttype,longint(hi(a)),tmpsref);
  458. end;
  459. procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
  460. var
  461. tmpreg64 : tregister64;
  462. begin
  463. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  464. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  465. a_load64_subsetref_reg(list,fromsref,tmpreg64);
  466. a_load64_reg_subsetref(list,tmpreg64,tosref);
  467. end;
  468. procedure tcg64f32.a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);
  469. var
  470. tmpreg64 : tregister64;
  471. begin
  472. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  473. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  474. a_load64_subsetref_reg(list,sref,tmpreg64);
  475. a_load64_reg_ref(list,tmpreg64,destref);
  476. end;
  477. procedure tcg64f32.a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);
  478. var
  479. tmpreg64 : tregister64;
  480. begin
  481. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  482. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  483. a_load64_ref_reg(list,fromref,tmpreg64);
  484. a_load64_reg_subsetref(list,tmpreg64,sref);
  485. end;
  486. procedure tcg64f32.a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);
  487. begin
  488. case l.loc of
  489. LOC_REFERENCE, LOC_CREFERENCE:
  490. a_load64_ref_reg(list,l.reference,reg);
  491. LOC_REGISTER,LOC_CREGISTER:
  492. a_load64_reg_reg(list,l.register64,reg);
  493. LOC_CONSTANT :
  494. a_load64_const_reg(list,l.value64,reg);
  495. LOC_SUBSETREF, LOC_CSUBSETREF:
  496. a_load64_subsetref_reg(list,l.sref,reg);
  497. else
  498. internalerror(200112292);
  499. end;
  500. end;
  501. procedure tcg64f32.a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);
  502. begin
  503. case l.loc of
  504. LOC_REGISTER,LOC_CREGISTER:
  505. a_load64_reg_ref(list,l.register64,ref);
  506. LOC_CONSTANT :
  507. a_load64_const_ref(list,l.value64,ref);
  508. LOC_SUBSETREF, LOC_CSUBSETREF:
  509. a_load64_subsetref_ref(list,l.sref,ref);
  510. else
  511. internalerror(200203288);
  512. end;
  513. end;
  514. procedure tcg64f32.a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);
  515. begin
  516. case l.loc of
  517. LOC_REFERENCE, LOC_CREFERENCE:
  518. a_load64_const_ref(list,value,l.reference);
  519. LOC_REGISTER,LOC_CREGISTER:
  520. a_load64_const_reg(list,value,l.register64);
  521. LOC_SUBSETREF, LOC_CSUBSETREF:
  522. a_load64_const_subsetref(list,value,l.sref);
  523. else
  524. internalerror(200112293);
  525. end;
  526. end;
  527. procedure tcg64f32.a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);
  528. begin
  529. case l.loc of
  530. LOC_REFERENCE, LOC_CREFERENCE:
  531. a_load64_reg_ref(list,reg,l.reference);
  532. LOC_REGISTER,LOC_CREGISTER:
  533. a_load64_reg_reg(list,reg,l.register64);
  534. LOC_SUBSETREF, LOC_CSUBSETREF:
  535. a_load64_reg_subsetref(list,reg,l.sref);
  536. LOC_MMREGISTER, LOC_CMMREGISTER:
  537. a_loadmm_intreg64_reg(list,l.size,reg,l.register);
  538. else
  539. internalerror(200112294);
  540. end;
  541. end;
  542. procedure tcg64f32.a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  543. var
  544. tmpref: treference;
  545. begin
  546. if target_info.endian = endian_big then
  547. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  548. else
  549. begin
  550. tmpref := ref;
  551. inc(tmpref.offset,4);
  552. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  553. end;
  554. end;
  555. procedure tcg64f32.a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  556. var
  557. tmpref: treference;
  558. begin
  559. if target_info.endian = endian_little then
  560. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  561. else
  562. begin
  563. tmpref := ref;
  564. inc(tmpref.offset,4);
  565. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  566. end;
  567. end;
  568. procedure tcg64f32.a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  569. var
  570. tmpref: treference;
  571. begin
  572. if target_info.endian = endian_big then
  573. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  574. else
  575. begin
  576. tmpref := ref;
  577. inc(tmpref.offset,4);
  578. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  579. end;
  580. end;
  581. procedure tcg64f32.a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  582. var
  583. tmpref: treference;
  584. begin
  585. if target_info.endian = endian_little then
  586. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  587. else
  588. begin
  589. tmpref := ref;
  590. inc(tmpref.offset,4);
  591. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  592. end;
  593. end;
  594. procedure tcg64f32.a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  595. begin
  596. case l.loc of
  597. LOC_REFERENCE,
  598. LOC_CREFERENCE :
  599. a_load64low_ref_reg(list,l.reference,reg);
  600. LOC_REGISTER,
  601. LOC_CREGISTER :
  602. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reglo,reg);
  603. LOC_CONSTANT :
  604. cg.a_load_const_reg(list,OS_32,longint(lo(l.value64)),reg);
  605. else
  606. internalerror(200203244);
  607. end;
  608. end;
  609. procedure tcg64f32.a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  610. begin
  611. case l.loc of
  612. LOC_REFERENCE,
  613. LOC_CREFERENCE :
  614. a_load64high_ref_reg(list,l.reference,reg);
  615. LOC_REGISTER,
  616. LOC_CREGISTER :
  617. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reghi,reg);
  618. LOC_CONSTANT :
  619. cg.a_load_const_reg(list,OS_32,longint(hi(l.value64)),reg);
  620. else
  621. internalerror(2002032411);
  622. end;
  623. end;
  624. procedure tcg64f32.a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);
  625. begin
  626. case l.loc of
  627. LOC_REFERENCE, LOC_CREFERENCE:
  628. a_op64_const_ref(list,op,size,value,l.reference);
  629. LOC_REGISTER,LOC_CREGISTER:
  630. a_op64_const_reg(list,op,size,value,l.register64);
  631. else
  632. internalerror(200203292);
  633. end;
  634. end;
  635. procedure tcg64f32.a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);
  636. begin
  637. case l.loc of
  638. LOC_REFERENCE, LOC_CREFERENCE:
  639. a_op64_reg_ref(list,op,size,reg,l.reference);
  640. LOC_REGISTER,LOC_CREGISTER:
  641. a_op64_reg_reg(list,op,size,reg,l.register64);
  642. else
  643. internalerror(2002032422);
  644. end;
  645. end;
  646. procedure tcg64f32.a_op64_ref_loc(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;const l : tlocation);
  647. var
  648. tempreg: tregister64;
  649. begin
  650. case l.loc of
  651. LOC_REFERENCE, LOC_CREFERENCE:
  652. begin
  653. tempreg.reghi:=cg.getintregister(list,OS_32);
  654. tempreg.reglo:=cg.getintregister(list,OS_32);
  655. a_load64_ref_reg(list,ref,tempreg);
  656. a_op64_reg_ref(list,op,size,tempreg,l.reference);
  657. end;
  658. LOC_REGISTER,LOC_CREGISTER:
  659. a_op64_ref_reg(list,op,size,ref,l.register64);
  660. else
  661. internalerror(2020042803);
  662. end;
  663. end;
  664. procedure tcg64f32.a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);
  665. begin
  666. case l.loc of
  667. LOC_REFERENCE, LOC_CREFERENCE:
  668. a_op64_ref_reg(list,op,size,l.reference,reg);
  669. LOC_REGISTER,LOC_CREGISTER:
  670. a_op64_reg_reg(list,op,size,l.register64,reg);
  671. LOC_CONSTANT :
  672. a_op64_const_reg(list,op,size,l.value64,reg);
  673. else
  674. internalerror(200203242);
  675. end;
  676. end;
  677. procedure tcg64f32.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
  678. var
  679. tempreg: tregister64;
  680. begin
  681. tempreg.reghi:=cg.getintregister(list,OS_32);
  682. tempreg.reglo:=cg.getintregister(list,OS_32);
  683. a_load64_ref_reg(list,ref,tempreg);
  684. a_op64_reg_reg(list,op,size,tempreg,reg);
  685. end;
  686. procedure tcg64f32.a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
  687. var
  688. tempreg: tregister64;
  689. begin
  690. tempreg.reghi:=cg.getintregister(list,OS_32);
  691. tempreg.reglo:=cg.getintregister(list,OS_32);
  692. if op in [OP_NEG,OP_NOT] then
  693. begin
  694. a_op64_reg_reg(list,op,size,reg,tempreg);
  695. a_load64_reg_ref(list,tempreg,ref);
  696. end
  697. else
  698. begin
  699. a_load64_ref_reg(list,ref,tempreg);
  700. a_op64_reg_reg(list,op,size,reg,tempreg);
  701. a_load64_reg_ref(list,tempreg,ref);
  702. end;
  703. end;
  704. procedure tcg64f32.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
  705. var
  706. tempreg: tregister64;
  707. begin
  708. tempreg.reghi:=cg.getintregister(list,OS_32);
  709. tempreg.reglo:=cg.getintregister(list,OS_32);
  710. a_load64_ref_reg(list,ref,tempreg);
  711. a_op64_const_reg(list,op,size,value,tempreg);
  712. a_load64_reg_ref(list,tempreg,ref);
  713. end;
  714. procedure tcg64f32.a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);
  715. var
  716. tmplochi,tmploclo: tcgpara;
  717. begin
  718. tmploclo.init;
  719. tmplochi.init;
  720. splitparaloc64(paraloc,tmploclo,tmplochi);
  721. if target_info.endian=endian_big then
  722. begin
  723. { Keep this order of first lo before hi to have
  724. the correct push order for m68k }
  725. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  726. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  727. end
  728. else
  729. begin
  730. { Keep this order of first hi before lo to have
  731. the correct push order for i386 }
  732. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  733. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  734. end;
  735. tmploclo.done;
  736. tmplochi.done;
  737. end;
  738. procedure tcg64f32.a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);
  739. var
  740. tmplochi,tmploclo: tcgpara;
  741. begin
  742. tmploclo.init;
  743. tmplochi.init;
  744. splitparaloc64(paraloc,tmploclo,tmplochi);
  745. if target_info.endian=endian_big then
  746. begin
  747. { Keep this order of first lo before hi to have
  748. the correct push order for m68k }
  749. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  750. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  751. end
  752. else
  753. begin
  754. { Keep this order of first hi before lo to have
  755. the correct push order for i386 }
  756. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  757. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  758. end;
  759. tmploclo.done;
  760. tmplochi.done;
  761. end;
  762. procedure tcg64f32.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
  763. var
  764. tmprefhi,tmpreflo : treference;
  765. tmploclo,tmplochi : tcgpara;
  766. begin
  767. tmploclo.init;
  768. tmplochi.init;
  769. splitparaloc64(paraloc,tmploclo,tmplochi);
  770. tmprefhi:=r;
  771. tmpreflo:=r;
  772. if target_info.endian=endian_big then
  773. begin
  774. { Keep this order of first lo before hi to have
  775. the correct push order for m68k }
  776. inc(tmpreflo.offset,4);
  777. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  778. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  779. end
  780. else
  781. begin
  782. { Keep this order of first hi before lo to have
  783. the correct push order for i386 }
  784. inc(tmprefhi.offset,4);
  785. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  786. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  787. end;
  788. tmploclo.done;
  789. tmplochi.done;
  790. end;
  791. procedure tcg64f32.a_load64_loc_cgpara(list : TAsmList;const l:tlocation;const paraloc : tcgpara);
  792. begin
  793. case l.loc of
  794. LOC_REGISTER,
  795. LOC_CREGISTER :
  796. a_load64_reg_cgpara(list,l.register64,paraloc);
  797. LOC_CONSTANT :
  798. a_load64_const_cgpara(list,l.value64,paraloc);
  799. LOC_CREFERENCE,
  800. LOC_REFERENCE :
  801. a_load64_ref_cgpara(list,l.reference,paraloc);
  802. else
  803. internalerror(200203287);
  804. end;
  805. end;
  806. procedure tcg64f32.a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);
  807. var
  808. tmpref: treference;
  809. begin
  810. if (tcgsize2size[mmsize]<>8) then
  811. internalerror(2009112501);
  812. tg.gettemp(list,8,8,tt_normal,tmpref);
  813. a_load64_reg_ref(list,intreg,tmpref);
  814. cg.a_loadmm_ref_reg(list,mmsize,mmsize,tmpref,mmreg,mms_movescalar);
  815. tg.ungettemp(list,tmpref);
  816. end;
  817. procedure tcg64f32.a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);
  818. var
  819. tmpref: treference;
  820. begin
  821. if (tcgsize2size[mmsize]<>8) then
  822. internalerror(2009112502);
  823. tg.gettemp(list,8,8,tt_normal,tmpref);
  824. cg.a_loadmm_reg_ref(list,mmsize,mmsize,mmreg,tmpref,mms_movescalar);
  825. a_load64_ref_reg(list,tmpref,intreg);
  826. tg.ungettemp(list,tmpref);
  827. end;
  828. procedure tcg64f32.g_rangecheck64(list : TAsmList;const l:tlocation;fromdef,todef:tdef);
  829. var
  830. neglabel,
  831. poslabel,
  832. endlabel: tasmlabel;
  833. hreg : tregister;
  834. hdef : torddef;
  835. opsize : tcgsize;
  836. from_signed,to_signed: boolean;
  837. temploc : tlocation;
  838. begin
  839. from_signed := is_signed(fromdef);
  840. to_signed := is_signed(todef);
  841. if not is_64bit(todef) then
  842. begin
  843. { get the high dword in a register }
  844. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  845. begin
  846. hreg := l.register64.reghi;
  847. end
  848. else
  849. begin
  850. hreg:=cg.getintregister(list,OS_32);
  851. a_load64high_ref_reg(list,l.reference,hreg);
  852. end;
  853. current_asmdata.getjumplabel(poslabel);
  854. { check high dword, must be 0 (for positive numbers) }
  855. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  856. { It can also be $ffffffff, but only for negative numbers }
  857. if from_signed and to_signed then
  858. begin
  859. current_asmdata.getjumplabel(neglabel);
  860. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  861. end
  862. else
  863. { we do not have dynamic dfa, so avoid a warning below about the unused
  864. neglabel }
  865. neglabel:=nil;
  866. { For all other values we have a range check error }
  867. cg.a_call_name(list,'fpc_rangeerror',false);
  868. { if the high dword = 0, the low dword can be considered a }
  869. { simple cardinal }
  870. cg.a_label(list,poslabel);
  871. hdef:=corddef.create(u32bit,0,$ffffffff,false);
  872. location_copy(temploc,l);
  873. temploc.size:=OS_32;
  874. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  875. (target_info.endian = endian_big) then
  876. begin
  877. inc(temploc.reference.offset,4);
  878. temploc.reference.alignment:=newalignment(temploc.reference.alignment,4);
  879. end;
  880. hlcg.g_rangecheck(list,temploc,hdef,todef);
  881. hdef.free;
  882. if from_signed and to_signed then
  883. begin
  884. current_asmdata.getjumplabel(endlabel);
  885. cg.a_jmp_always(list,endlabel);
  886. { if the high dword = $ffffffff, then the low dword (when }
  887. { considered as a longint) must be < 0 }
  888. cg.a_label(list,neglabel);
  889. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  890. begin
  891. hreg := l.register64.reglo;
  892. end
  893. else
  894. begin
  895. hreg:=cg.getintregister(list,OS_32);
  896. a_load64low_ref_reg(list,l.reference,hreg);
  897. end;
  898. { get a new neglabel (JM) }
  899. current_asmdata.getjumplabel(neglabel);
  900. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  901. cg.a_call_name(list,'fpc_rangeerror',false);
  902. { if we get here, the 64bit value lies between }
  903. { longint($80000000) and -1 (JM) }
  904. cg.a_label(list,neglabel);
  905. hdef:=corddef.create(s32bit,int64(longint($80000000)),int64(-1),false);
  906. location_copy(temploc,l);
  907. temploc.size:=OS_32;
  908. hlcg.g_rangecheck(list,temploc,hdef,todef);
  909. hdef.free;
  910. cg.a_label(list,endlabel);
  911. end;
  912. end
  913. else
  914. { todef = 64bit int }
  915. { no 64bit subranges supported, so only a small check is necessary }
  916. { if both are signed or both are unsigned, no problem! }
  917. if (from_signed xor to_signed) and
  918. { also not if the fromdef is unsigned and < 64bit, since that will }
  919. { always fit in a 64bit int (todef is 64bit) }
  920. (from_signed or
  921. (torddef(fromdef).ordtype = u64bit)) then
  922. begin
  923. { in all cases, there is only a problem if the higest bit is set }
  924. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  925. begin
  926. if is_64bit(fromdef) then
  927. begin
  928. hreg := l.register64.reghi;
  929. opsize := OS_32;
  930. end
  931. else
  932. begin
  933. hreg := l.register;
  934. opsize := def_cgsize(fromdef);
  935. end;
  936. end
  937. else
  938. begin
  939. hreg:=cg.getintregister(list,OS_32);
  940. opsize:=OS_32;
  941. if l.size in [OS_64,OS_S64] then
  942. a_load64high_ref_reg(list,l.reference,hreg)
  943. else
  944. cg.a_load_ref_reg(list,l.size,OS_32,l.reference,hreg);
  945. end;
  946. current_asmdata.getjumplabel(poslabel);
  947. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  948. cg.a_call_name(list,'fpc_rangeerror',false);
  949. cg.a_label(list,poslabel);
  950. end;
  951. end;
  952. function tcg64f32.optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;
  953. var
  954. lowvalue, highvalue : longint;
  955. hreg: tregister;
  956. begin
  957. lowvalue := longint(a);
  958. highvalue:= longint(a shr 32);
  959. { assume it will be optimized out }
  960. optimize64_op_const_reg := true;
  961. case op of
  962. OP_ADD:
  963. begin
  964. if a = 0 then
  965. exit;
  966. end;
  967. OP_AND:
  968. begin
  969. if lowvalue <> -1 then
  970. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  971. if highvalue <> -1 then
  972. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  973. { already emitted correctly }
  974. exit;
  975. end;
  976. OP_OR:
  977. begin
  978. if lowvalue <> 0 then
  979. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  980. if highvalue <> 0 then
  981. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  982. { already emitted correctly }
  983. exit;
  984. end;
  985. OP_SUB:
  986. begin
  987. if a = 0 then
  988. exit;
  989. end;
  990. OP_XOR:
  991. begin
  992. end;
  993. OP_SHL:
  994. begin
  995. if a = 0 then
  996. exit;
  997. { simply clear low-register
  998. and shift the rest and swap
  999. registers.
  1000. }
  1001. if (a > 31) then
  1002. begin
  1003. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  1004. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  1005. { swap the registers }
  1006. hreg := reg.reghi;
  1007. reg.reghi := reg.reglo;
  1008. reg.reglo := hreg;
  1009. exit;
  1010. end;
  1011. end;
  1012. OP_SHR:
  1013. begin
  1014. if a = 0 then exit;
  1015. { simply clear high-register
  1016. and shift the rest and swap
  1017. registers.
  1018. }
  1019. if (a > 31) then
  1020. begin
  1021. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  1022. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  1023. { swap the registers }
  1024. hreg := reg.reghi;
  1025. reg.reghi := reg.reglo;
  1026. reg.reglo := hreg;
  1027. exit;
  1028. end;
  1029. end;
  1030. OP_IMUL,OP_MUL:
  1031. begin
  1032. if a = 1 then exit;
  1033. end;
  1034. OP_IDIV,OP_DIV:
  1035. begin
  1036. if a = 1 then exit;
  1037. end;
  1038. else
  1039. internalerror(20020817);
  1040. end;
  1041. optimize64_op_const_reg := false;
  1042. end;
  1043. end.