n8086add.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Code generation for add nodes on the i8086
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit n8086add;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,nadd,cpubase,nx86add;
  22. type
  23. { ti8086addnode }
  24. ti8086addnode = class(tx86addnode)
  25. function use_generic_mul32to64: boolean; override;
  26. procedure second_addordinal; override;
  27. procedure second_add64bit;override;
  28. procedure second_cmp64bit;override;
  29. procedure second_cmp32bit;
  30. procedure second_cmpordinal;override;
  31. procedure second_mul(unsigned: boolean);
  32. end;
  33. implementation
  34. uses
  35. globtype,systems,
  36. cutils,verbose,globals,
  37. symconst,symdef,paramgr,defutil,
  38. aasmbase,aasmtai,aasmdata,aasmcpu,
  39. cgbase,procinfo,
  40. ncon,nset,cgutils,tgobj,
  41. cga,ncgutil,cgobj,cg64f32,cgx86,
  42. hlcgobj;
  43. {*****************************************************************************
  44. use_generic_mul32to64
  45. *****************************************************************************}
  46. function ti8086addnode.use_generic_mul32to64: boolean;
  47. begin
  48. result := True;
  49. end;
  50. { handles all multiplications }
  51. procedure ti8086addnode.second_addordinal;
  52. var
  53. unsigned: boolean;
  54. begin
  55. unsigned:=not(is_signed(left.resultdef)) or
  56. not(is_signed(right.resultdef));
  57. if nodetype=muln then
  58. second_mul(unsigned)
  59. else
  60. inherited second_addordinal;
  61. end;
  62. {*****************************************************************************
  63. Add64bit
  64. *****************************************************************************}
  65. procedure ti8086addnode.second_add64bit;
  66. var
  67. op : TOpCG;
  68. op1,op2 : TAsmOp;
  69. hregister,
  70. hregister2 : tregister;
  71. hl4 : tasmlabel;
  72. mboverflow,
  73. unsigned:boolean;
  74. r:Tregister;
  75. begin
  76. pass_left_right;
  77. op1:=A_NONE;
  78. op2:=A_NONE;
  79. mboverflow:=false;
  80. unsigned:=((left.resultdef.typ=orddef) and
  81. (torddef(left.resultdef).ordtype=u64bit)) or
  82. ((right.resultdef.typ=orddef) and
  83. (torddef(right.resultdef).ordtype=u64bit));
  84. case nodetype of
  85. addn :
  86. begin
  87. op:=OP_ADD;
  88. mboverflow:=true;
  89. end;
  90. subn :
  91. begin
  92. op:=OP_SUB;
  93. op1:=A_SUB;
  94. op2:=A_SBB;
  95. mboverflow:=true;
  96. end;
  97. xorn:
  98. op:=OP_XOR;
  99. orn:
  100. op:=OP_OR;
  101. andn:
  102. op:=OP_AND;
  103. else
  104. begin
  105. { everything should be handled in pass_1 (JM) }
  106. internalerror(200109051);
  107. end;
  108. end;
  109. { left and right no register? }
  110. { then one must be demanded }
  111. if (left.location.loc<>LOC_REGISTER) then
  112. begin
  113. if (right.location.loc<>LOC_REGISTER) then
  114. begin
  115. hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  116. hregister2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  117. cg64.a_load64_loc_reg(current_asmdata.CurrAsmList,left.location,joinreg64(hregister,hregister2));
  118. location_reset(left.location,LOC_REGISTER,left.location.size);
  119. left.location.register64.reglo:=hregister;
  120. left.location.register64.reghi:=hregister2;
  121. end
  122. else
  123. begin
  124. location_swap(left.location,right.location);
  125. toggleflag(nf_swapped);
  126. end;
  127. end;
  128. { at this point, left.location.loc should be LOC_REGISTER }
  129. if right.location.loc=LOC_REGISTER then
  130. begin
  131. { when swapped another result register }
  132. if (nodetype=subn) and (nf_swapped in flags) then
  133. begin
  134. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,op,location.size,
  135. left.location.register64,
  136. right.location.register64);
  137. location_swap(left.location,right.location);
  138. toggleflag(nf_swapped);
  139. end
  140. else
  141. begin
  142. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,op,location.size,
  143. right.location.register64,
  144. left.location.register64);
  145. end;
  146. end
  147. else
  148. begin
  149. { right.location<>LOC_REGISTER }
  150. if (nodetype=subn) and (nf_swapped in flags) then
  151. begin
  152. r:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  153. cg64.a_load64low_loc_reg(current_asmdata.CurrAsmList,right.location,r);
  154. emit_reg_reg(op1,S_W,left.location.register64.reglo,r);
  155. emit_reg_reg(op2,S_W,GetNextReg(left.location.register64.reglo),GetNextReg(r));
  156. emit_reg_reg(A_MOV,S_W,r,left.location.register64.reglo);
  157. emit_reg_reg(A_MOV,S_W,GetNextReg(r),GetNextReg(left.location.register64.reglo));
  158. cg64.a_load64high_loc_reg(current_asmdata.CurrAsmList,right.location,r);
  159. { the carry flag is still ok }
  160. emit_reg_reg(op2,S_W,left.location.register64.reghi,r);
  161. emit_reg_reg(op2,S_W,GetNextReg(left.location.register64.reghi),GetNextReg(r));
  162. emit_reg_reg(A_MOV,S_W,r,left.location.register64.reghi);
  163. emit_reg_reg(A_MOV,S_W,GetNextReg(r),GetNextReg(left.location.register64.reghi));
  164. end
  165. else
  166. begin
  167. cg64.a_op64_loc_reg(current_asmdata.CurrAsmList,op,location.size,right.location,
  168. left.location.register64);
  169. end;
  170. location_freetemp(current_asmdata.CurrAsmList,right.location);
  171. end;
  172. { only in case of overflow operations }
  173. { produce overflow code }
  174. { we must put it here directly, because sign of operation }
  175. { is in unsigned VAR!! }
  176. if mboverflow then
  177. begin
  178. if cs_check_overflow in current_settings.localswitches then
  179. begin
  180. current_asmdata.getjumplabel(hl4);
  181. if unsigned then
  182. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4)
  183. else
  184. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NO,hl4);
  185. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
  186. cg.a_label(current_asmdata.CurrAsmList,hl4);
  187. end;
  188. end;
  189. location_copy(location,left.location);
  190. end;
  191. procedure ti8086addnode.second_cmp64bit;
  192. var
  193. hregister,
  194. hregister2 : tregister;
  195. href : treference;
  196. unsigned : boolean;
  197. procedure firstjmp64bitcmp;
  198. var
  199. oldnodetype : tnodetype;
  200. begin
  201. {$ifdef OLDREGVARS}
  202. load_all_regvars(current_asmdata.CurrAsmList);
  203. {$endif OLDREGVARS}
  204. { the jump the sequence is a little bit hairy }
  205. case nodetype of
  206. ltn,gtn:
  207. begin
  208. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
  209. { cheat a little bit for the negative test }
  210. toggleflag(nf_swapped);
  211. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
  212. toggleflag(nf_swapped);
  213. end;
  214. lten,gten:
  215. begin
  216. oldnodetype:=nodetype;
  217. if nodetype=lten then
  218. nodetype:=ltn
  219. else
  220. nodetype:=gtn;
  221. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
  222. { cheat for the negative test }
  223. if nodetype=ltn then
  224. nodetype:=gtn
  225. else
  226. nodetype:=ltn;
  227. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
  228. nodetype:=oldnodetype;
  229. end;
  230. equaln:
  231. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
  232. unequaln:
  233. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
  234. end;
  235. end;
  236. procedure middlejmp64bitcmp;
  237. var
  238. oldnodetype : tnodetype;
  239. begin
  240. {$ifdef OLDREGVARS}
  241. load_all_regvars(current_asmdata.CurrAsmList);
  242. {$endif OLDREGVARS}
  243. { the jump the sequence is a little bit hairy }
  244. case nodetype of
  245. ltn,gtn:
  246. begin
  247. { the comparisaion of the low word have to be }
  248. { always unsigned! }
  249. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
  250. { cheat a little bit for the negative test }
  251. toggleflag(nf_swapped);
  252. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrFalseLabel);
  253. toggleflag(nf_swapped);
  254. end;
  255. lten,gten:
  256. begin
  257. oldnodetype:=nodetype;
  258. if nodetype=lten then
  259. nodetype:=ltn
  260. else
  261. nodetype:=gtn;
  262. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
  263. { cheat for the negative test }
  264. if nodetype=ltn then
  265. nodetype:=gtn
  266. else
  267. nodetype:=ltn;
  268. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrFalseLabel);
  269. nodetype:=oldnodetype;
  270. end;
  271. equaln:
  272. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
  273. unequaln:
  274. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
  275. end;
  276. end;
  277. procedure lastjmp64bitcmp;
  278. begin
  279. { the jump the sequence is a little bit hairy }
  280. case nodetype of
  281. ltn,gtn,lten,gten:
  282. begin
  283. { the comparisaion of the low word have to be }
  284. { always unsigned! }
  285. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
  286. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  287. end;
  288. equaln:
  289. begin
  290. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
  291. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  292. end;
  293. unequaln:
  294. begin
  295. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
  296. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  297. end;
  298. end;
  299. end;
  300. begin
  301. pass_left_right;
  302. unsigned:=((left.resultdef.typ=orddef) and
  303. (torddef(left.resultdef).ordtype=u64bit)) or
  304. ((right.resultdef.typ=orddef) and
  305. (torddef(right.resultdef).ordtype=u64bit));
  306. { left and right no register? }
  307. { then one must be demanded }
  308. if (left.location.loc<>LOC_REGISTER) then
  309. begin
  310. if (right.location.loc<>LOC_REGISTER) then
  311. begin
  312. { we can reuse a CREGISTER for comparison }
  313. if (left.location.loc<>LOC_CREGISTER) then
  314. begin
  315. hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  316. hregister2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  317. cg64.a_load64_loc_reg(current_asmdata.CurrAsmList,left.location,joinreg64(hregister,hregister2));
  318. location_freetemp(current_asmdata.CurrAsmList,left.location);
  319. location_reset(left.location,LOC_REGISTER,left.location.size);
  320. left.location.register64.reglo:=hregister;
  321. left.location.register64.reghi:=hregister2;
  322. end;
  323. end
  324. else
  325. begin
  326. location_swap(left.location,right.location);
  327. toggleflag(nf_swapped);
  328. end;
  329. end;
  330. { at this point, left.location.loc should be LOC_REGISTER }
  331. if right.location.loc=LOC_REGISTER then
  332. begin
  333. emit_reg_reg(A_CMP,S_W,GetNextReg(right.location.register64.reghi),GetNextReg(left.location.register64.reghi));
  334. firstjmp64bitcmp;
  335. emit_reg_reg(A_CMP,S_W,right.location.register64.reghi,left.location.register64.reghi);
  336. middlejmp64bitcmp;
  337. emit_reg_reg(A_CMP,S_W,GetNextReg(right.location.register64.reglo),GetNextReg(left.location.register64.reglo));
  338. middlejmp64bitcmp;
  339. emit_reg_reg(A_CMP,S_W,right.location.register64.reglo,left.location.register64.reglo);
  340. lastjmp64bitcmp;
  341. end
  342. else
  343. begin
  344. case right.location.loc of
  345. LOC_CREGISTER :
  346. begin
  347. emit_reg_reg(A_CMP,S_W,GetNextReg(right.location.register64.reghi),GetNextReg(left.location.register64.reghi));
  348. firstjmp64bitcmp;
  349. emit_reg_reg(A_CMP,S_W,right.location.register64.reghi,left.location.register64.reghi);
  350. middlejmp64bitcmp;
  351. emit_reg_reg(A_CMP,S_W,GetNextReg(right.location.register64.reglo),GetNextReg(left.location.register64.reglo));
  352. middlejmp64bitcmp;
  353. emit_reg_reg(A_CMP,S_W,right.location.register64.reglo,left.location.register64.reglo);
  354. lastjmp64bitcmp;
  355. end;
  356. LOC_CREFERENCE,
  357. LOC_REFERENCE :
  358. begin
  359. tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,right.location.reference);
  360. href:=right.location.reference;
  361. inc(href.offset,6);
  362. emit_ref_reg(A_CMP,S_W,href,GetNextReg(left.location.register64.reghi));
  363. firstjmp64bitcmp;
  364. dec(href.offset,2);
  365. emit_ref_reg(A_CMP,S_W,href,left.location.register64.reghi);
  366. middlejmp64bitcmp;
  367. dec(href.offset,2);
  368. emit_ref_reg(A_CMP,S_W,href,GetNextReg(left.location.register64.reglo));
  369. middlejmp64bitcmp;
  370. emit_ref_reg(A_CMP,S_W,right.location.reference,left.location.register64.reglo);
  371. lastjmp64bitcmp;
  372. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  373. location_freetemp(current_asmdata.CurrAsmList,right.location);
  374. end;
  375. LOC_CONSTANT :
  376. begin
  377. current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_W,aint((right.location.value64 shr 48) and $FFFF),GetNextReg(left.location.register64.reghi)));
  378. firstjmp64bitcmp;
  379. current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_W,aint((right.location.value64 shr 32) and $FFFF),left.location.register64.reghi));
  380. middlejmp64bitcmp;
  381. current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_W,aint((right.location.value64 shr 16) and $FFFF),GetNextReg(left.location.register64.reglo)));
  382. middlejmp64bitcmp;
  383. current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_W,aint(right.location.value64 and $FFFF),left.location.register64.reglo));
  384. lastjmp64bitcmp;
  385. end;
  386. else
  387. internalerror(200203282);
  388. end;
  389. end;
  390. { we have LOC_JUMP as result }
  391. location_reset(location,LOC_JUMP,OS_NO)
  392. end;
  393. procedure ti8086addnode.second_cmp32bit;
  394. var
  395. hregister : tregister;
  396. href : treference;
  397. unsigned : boolean;
  398. procedure firstjmp32bitcmp;
  399. var
  400. oldnodetype : tnodetype;
  401. begin
  402. {$ifdef OLDREGVARS}
  403. load_all_regvars(current_asmdata.CurrAsmList);
  404. {$endif OLDREGVARS}
  405. { the jump the sequence is a little bit hairy }
  406. case nodetype of
  407. ltn,gtn:
  408. begin
  409. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
  410. { cheat a little bit for the negative test }
  411. toggleflag(nf_swapped);
  412. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
  413. toggleflag(nf_swapped);
  414. end;
  415. lten,gten:
  416. begin
  417. oldnodetype:=nodetype;
  418. if nodetype=lten then
  419. nodetype:=ltn
  420. else
  421. nodetype:=gtn;
  422. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
  423. { cheat for the negative test }
  424. if nodetype=ltn then
  425. nodetype:=gtn
  426. else
  427. nodetype:=ltn;
  428. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
  429. nodetype:=oldnodetype;
  430. end;
  431. equaln:
  432. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
  433. unequaln:
  434. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
  435. end;
  436. end;
  437. procedure secondjmp32bitcmp;
  438. begin
  439. { the jump the sequence is a little bit hairy }
  440. case nodetype of
  441. ltn,gtn,lten,gten:
  442. begin
  443. { the comparisaion of the low dword have to be }
  444. { always unsigned! }
  445. cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
  446. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  447. end;
  448. equaln:
  449. begin
  450. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
  451. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  452. end;
  453. unequaln:
  454. begin
  455. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
  456. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  457. end;
  458. end;
  459. end;
  460. begin
  461. pass_left_right;
  462. unsigned:=((left.resultdef.typ=orddef) and
  463. (torddef(left.resultdef).ordtype=u32bit)) or
  464. ((right.resultdef.typ=orddef) and
  465. (torddef(right.resultdef).ordtype=u32bit));
  466. { left and right no register? }
  467. { then one must be demanded }
  468. if (left.location.loc<>LOC_REGISTER) then
  469. begin
  470. if (right.location.loc<>LOC_REGISTER) then
  471. begin
  472. { we can reuse a CREGISTER for comparison }
  473. if (left.location.loc<>LOC_CREGISTER) then
  474. begin
  475. hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  476. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_32,left.location,hregister);
  477. location_freetemp(current_asmdata.CurrAsmList,left.location);
  478. location_reset(left.location,LOC_REGISTER,left.location.size);
  479. left.location.register:=hregister;
  480. end;
  481. end
  482. else
  483. begin
  484. location_swap(left.location,right.location);
  485. toggleflag(nf_swapped);
  486. end;
  487. end;
  488. { at this point, left.location.loc should be LOC_REGISTER }
  489. if right.location.loc=LOC_REGISTER then
  490. begin
  491. emit_reg_reg(A_CMP,S_W,GetNextReg(right.location.register),GetNextReg(left.location.register));
  492. firstjmp32bitcmp;
  493. emit_reg_reg(A_CMP,S_W,right.location.register,left.location.register);
  494. secondjmp32bitcmp;
  495. end
  496. else
  497. begin
  498. case right.location.loc of
  499. LOC_CREGISTER :
  500. begin
  501. emit_reg_reg(A_CMP,S_W,GetNextReg(right.location.register),GetNextReg(left.location.register));
  502. firstjmp32bitcmp;
  503. emit_reg_reg(A_CMP,S_W,right.location.register,left.location.register);
  504. secondjmp32bitcmp;
  505. end;
  506. LOC_CREFERENCE,
  507. LOC_REFERENCE :
  508. begin
  509. tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,right.location.reference);
  510. href:=right.location.reference;
  511. inc(href.offset,2);
  512. emit_ref_reg(A_CMP,S_W,href,GetNextReg(left.location.register));
  513. firstjmp32bitcmp;
  514. dec(href.offset,2);
  515. emit_ref_reg(A_CMP,S_W,href,left.location.register);
  516. secondjmp32bitcmp;
  517. cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  518. location_freetemp(current_asmdata.CurrAsmList,right.location);
  519. end;
  520. LOC_CONSTANT :
  521. begin
  522. current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_W,aint((right.location.value shr 16) and $FFFF),GetNextReg(left.location.register)));
  523. firstjmp32bitcmp;
  524. current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_W,aint(right.location.value and $FFFF),left.location.register));
  525. secondjmp32bitcmp;
  526. end;
  527. else
  528. internalerror(200203282);
  529. end;
  530. end;
  531. { we have LOC_JUMP as result }
  532. location_reset(location,LOC_JUMP,OS_NO)
  533. end;
  534. procedure ti8086addnode.second_cmpordinal;
  535. begin
  536. if is_32bit(left.resultdef) then
  537. second_cmp32bit
  538. else
  539. inherited second_cmpordinal;
  540. end;
  541. {*****************************************************************************
  542. x86 MUL
  543. *****************************************************************************}
  544. procedure ti8086addnode.second_mul(unsigned: boolean);
  545. procedure add_mov(instr: Taicpu);
  546. begin
  547. { Notify the register allocator that we have written a move instruction so
  548. it can try to eliminate it. }
  549. if (instr.oper[0]^.reg<>current_procinfo.framepointer) and (instr.oper[0]^.reg<>NR_STACK_POINTER_REG) then
  550. tcgx86(cg).add_move_instruction(instr);
  551. current_asmdata.CurrAsmList.concat(instr);
  552. end;
  553. var reg:Tregister;
  554. ref:Treference;
  555. use_ref:boolean;
  556. hl4 : tasmlabel;
  557. const
  558. asmops: array[boolean] of tasmop = (A_IMUL, A_MUL);
  559. begin
  560. pass_left_right;
  561. {The location.register will be filled in later (JM)}
  562. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  563. { Mul supports registers and references, so if not register/reference,
  564. load the location into a register. }
  565. use_ref:=false;
  566. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  567. reg:=left.location.register
  568. else if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  569. begin
  570. tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,left.location.reference);
  571. ref:=left.location.reference;
  572. use_ref:=true;
  573. end
  574. else
  575. begin
  576. {LOC_CONSTANT for example.}
  577. reg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  578. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,left.resultdef,osuinttype,left.location,reg);
  579. end;
  580. {Allocate AX.}
  581. cg.getcpuregister(current_asmdata.CurrAsmList,NR_AX);
  582. {Load the right value.}
  583. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,osuinttype,right.location,NR_AX);
  584. {Also allocate DX, since it is also modified by a mul (JM).}
  585. cg.getcpuregister(current_asmdata.CurrAsmList,NR_DX);
  586. if use_ref then
  587. emit_ref(asmops[unsigned],S_W,ref)
  588. else
  589. emit_reg(asmops[unsigned],S_W,reg);
  590. if (cs_check_overflow in current_settings.localswitches) and
  591. { 16->32 bit cannot overflow }
  592. (not is_32bitint(resultdef)) then
  593. begin
  594. current_asmdata.getjumplabel(hl4);
  595. cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4);
  596. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
  597. cg.a_label(current_asmdata.CurrAsmList,hl4);
  598. end;
  599. {Free AX,DX}
  600. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_DX);
  601. if is_32bitint(resultdef) then
  602. begin
  603. {Allocate an imaginary 32-bit register, which consists of a pair of
  604. 16-bit registers and store DX:AX into it}
  605. location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  606. add_mov(Taicpu.Op_reg_reg(A_MOV,S_W,NR_AX,location.register));
  607. add_mov(Taicpu.Op_reg_reg(A_MOV,S_W,NR_DX,GetNextReg(location.register)));
  608. end
  609. else
  610. begin
  611. {Allocate a new register and store the result in AX in it.}
  612. location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  613. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_AX);
  614. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_AX,location.register);
  615. end;
  616. location_freetemp(current_asmdata.CurrAsmList,left.location);
  617. location_freetemp(current_asmdata.CurrAsmList,right.location);
  618. end;
  619. begin
  620. caddnode:=ti8086addnode;
  621. end.