aasmcpu.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. {
  2. $Id$
  3. Copyright (c) 2003 by Florian Klaempfl
  4. Contains the assembler object for the ARM
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit aasmcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cclasses,aasmtai,
  23. aasmbase,globals,verbose,
  24. cpubase,cpuinfo;
  25. const
  26. { "mov reg,reg" source operand number }
  27. O_MOV_SOURCE = 1;
  28. { "mov reg,reg" source operand number }
  29. O_MOV_DEST = 0;
  30. type
  31. taicpu = class(taicpu_abstract)
  32. oppostfix : TOpPostfix;
  33. roundingmode : troundingmode;
  34. procedure loadshifterop(opidx:longint;const so:tshifterop);
  35. procedure loadregset(opidx:longint;const s:tsupregset);
  36. constructor op_none(op : tasmop);
  37. constructor op_reg(op : tasmop;_op1 : tregister);
  38. constructor op_const(op : tasmop;_op1 : longint);
  39. constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  40. constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  41. constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
  42. constructor op_reg_regset(op:tasmop; _op1: tregister; _op2: tsupregset);
  43. constructor op_const_const(op : tasmop;_op1,_op2 : longint);
  44. constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  45. constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: Longint);
  46. constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  47. constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  48. constructor op_const_reg_reg(op : tasmop;_op1 : longint;_op2, _op3 : tregister);
  49. constructor op_const_reg_const(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : longint);
  50. constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  51. constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  52. constructor op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : Longint);
  53. constructor op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : Longint);
  54. { this is for Jmp instructions }
  55. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  56. constructor op_const_const_sym(op : tasmop;_op1,_op2 : longint;_op3: tasmsymbol);
  57. constructor op_sym(op : tasmop;_op1 : tasmsymbol);
  58. constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  59. constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  60. constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  61. function is_nop: boolean; override;
  62. function is_move:boolean; override;
  63. function spill_registers(list:Taasmoutput;
  64. rgget:Trggetproc;
  65. rgunget:Trgungetproc;
  66. r:Tsupregset;
  67. var unusedregsint:Tsupregset;
  68. const spilltemplist:Tspill_temp_list):boolean; override;
  69. end;
  70. tai_align = class(tai_align_abstract)
  71. { nothing to add }
  72. end;
  73. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  74. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  75. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  76. procedure InitAsm;
  77. procedure DoneAsm;
  78. implementation
  79. uses
  80. cutils,rgobj;
  81. procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
  82. begin
  83. if opidx>=ops then
  84. ops:=opidx+1;
  85. with oper[opidx] do
  86. begin
  87. if typ<>top_shifterop then
  88. begin
  89. clearop(opidx);
  90. new(shifterop);
  91. end;
  92. shifterop^:=so;
  93. typ:=top_shifterop;
  94. end;
  95. end;
  96. procedure taicpu.loadregset(opidx:longint;const s:tsupregset);
  97. begin
  98. if opidx>=ops then
  99. ops:=opidx+1;
  100. with oper[opidx] do
  101. begin
  102. if typ<>top_regset then
  103. clearop(opidx);
  104. regset:=s;
  105. typ:=top_regset;
  106. end;
  107. end;
  108. {*****************************************************************************
  109. taicpu Constructors
  110. *****************************************************************************}
  111. constructor taicpu.op_none(op : tasmop);
  112. begin
  113. inherited create(op);
  114. end;
  115. constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
  116. begin
  117. inherited create(op);
  118. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  119. internalerror(2003031207);
  120. ops:=1;
  121. loadreg(0,_op1);
  122. end;
  123. constructor taicpu.op_const(op : tasmop;_op1 : longint);
  124. begin
  125. inherited create(op);
  126. ops:=1;
  127. loadconst(0,aword(_op1));
  128. end;
  129. constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  130. begin
  131. inherited create(op);
  132. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  133. internalerror(2003031205);
  134. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  135. internalerror(2003031206);
  136. ops:=2;
  137. loadreg(0,_op1);
  138. loadreg(1,_op2);
  139. end;
  140. constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
  141. begin
  142. inherited create(op);
  143. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  144. internalerror(2003031208);
  145. ops:=2;
  146. loadreg(0,_op1);
  147. loadconst(1,aword(_op2));
  148. end;
  149. constructor taicpu.op_reg_regset(op:tasmop; _op1: tregister; _op2: tsupregset);
  150. begin
  151. inherited create(op);
  152. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  153. internalerror(2003031208);
  154. ops:=2;
  155. loadreg(0,_op1);
  156. loadregset(1,_op2);
  157. end;
  158. constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  159. begin
  160. inherited create(op);
  161. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  162. internalerror(2003031210);
  163. ops:=2;
  164. loadreg(0,_op1);
  165. loadref(1,_op2);
  166. end;
  167. constructor taicpu.op_const_const(op : tasmop;_op1,_op2 : longint);
  168. begin
  169. inherited create(op);
  170. ops:=2;
  171. loadconst(0,aword(_op1));
  172. loadconst(1,aword(_op2));
  173. end;
  174. constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  175. begin
  176. inherited create(op);
  177. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  178. internalerror(2003031211);
  179. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  180. internalerror(2003031212);
  181. if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
  182. internalerror(2003031213);
  183. ops:=3;
  184. loadreg(0,_op1);
  185. loadreg(1,_op2);
  186. loadreg(2,_op3);
  187. end;
  188. constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: Longint);
  189. begin
  190. inherited create(op);
  191. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  192. internalerror(2003031214);
  193. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  194. internalerror(2003031215);
  195. ops:=3;
  196. loadreg(0,_op1);
  197. loadreg(1,_op2);
  198. loadconst(2,aword(_op3));
  199. end;
  200. constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  201. begin
  202. inherited create(op);
  203. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  204. internalerror(2003031216);
  205. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  206. internalerror(2003031217);
  207. ops:=3;
  208. loadreg(0,_op1);
  209. loadreg(1,_op2);
  210. loadsymbol(0,_op3,_op3ofs);
  211. end;
  212. constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  213. begin
  214. inherited create(op);
  215. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  216. internalerror(2003031218);
  217. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  218. internalerror(2003031219);
  219. ops:=3;
  220. loadreg(0,_op1);
  221. loadreg(1,_op2);
  222. loadref(2,_op3);
  223. end;
  224. constructor taicpu.op_const_reg_reg(op : tasmop;_op1 : longint;_op2, _op3 : tregister);
  225. begin
  226. inherited create(op);
  227. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  228. internalerror(2003031221);
  229. if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
  230. internalerror(2003031220);
  231. ops:=3;
  232. loadconst(0,aword(_op1));
  233. loadreg(1,_op2);
  234. loadreg(2,_op3);
  235. end;
  236. constructor taicpu.op_const_reg_const(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : longint);
  237. begin
  238. inherited create(op);
  239. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  240. internalerror(2003031222);
  241. ops:=3;
  242. loadconst(0,aword(_op1));
  243. loadreg(1,_op2);
  244. loadconst(2,aword(_op3));
  245. end;
  246. constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  247. begin
  248. inherited create(op);
  249. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  250. internalerror(200308233);
  251. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  252. internalerror(200308233);
  253. ops:=3;
  254. loadreg(0,_op1);
  255. loadreg(1,_op2);
  256. loadshifterop(2,_op3);
  257. end;
  258. constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  259. begin
  260. inherited create(op);
  261. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  262. internalerror(2003031223);
  263. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  264. internalerror(2003031224);
  265. if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
  266. internalerror(2003031225);
  267. if (_op4.enum = R_INTREGISTER) and (_op4.number = NR_NO) then
  268. internalerror(2003031226);
  269. ops:=4;
  270. loadreg(0,_op1);
  271. loadreg(1,_op2);
  272. loadreg(2,_op3);
  273. loadreg(3,_op4);
  274. end;
  275. constructor taicpu.op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : Longint);
  276. begin
  277. inherited create(op);
  278. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  279. internalerror(2003031232);
  280. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  281. internalerror(2003031233);
  282. if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
  283. internalerror(2003031233);
  284. ops:=5;
  285. loadreg(0,_op1);
  286. loadreg(1,_op2);
  287. loadreg(2,_op3);
  288. loadconst(3,cardinal(_op4));
  289. loadconst(4,cardinal(_op5));
  290. end;
  291. constructor taicpu.op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : Longint);
  292. begin
  293. inherited create(op);
  294. if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
  295. internalerror(2003031232);
  296. if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
  297. internalerror(2003031233);
  298. ops:=5;
  299. loadreg(0,_op1);
  300. loadreg(1,_op2);
  301. loadconst(2,aword(_op3));
  302. loadconst(3,cardinal(_op4));
  303. loadconst(4,cardinal(_op5));
  304. end;
  305. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  306. begin
  307. inherited create(op);
  308. condition:=cond;
  309. ops:=1;
  310. loadsymbol(0,_op1,0);
  311. end;
  312. constructor taicpu.op_const_const_sym(op : tasmop;_op1,_op2 : longint; _op3: tasmsymbol);
  313. begin
  314. inherited create(op);
  315. ops:=3;
  316. loadconst(0,aword(_op1));
  317. loadconst(1,aword(_op2));
  318. loadsymbol(2,_op3,0);
  319. end;
  320. constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
  321. begin
  322. inherited create(op);
  323. ops:=1;
  324. loadsymbol(0,_op1,0);
  325. end;
  326. constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  327. begin
  328. inherited create(op);
  329. ops:=1;
  330. loadsymbol(0,_op1,_op1ofs);
  331. end;
  332. constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  333. begin
  334. inherited create(op);
  335. ops:=2;
  336. loadreg(0,_op1);
  337. loadsymbol(1,_op2,_op2ofs);
  338. end;
  339. constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  340. begin
  341. inherited create(op);
  342. ops:=2;
  343. loadsymbol(0,_op1,_op1ofs);
  344. loadref(1,_op2);
  345. end;
  346. { ****************************** newra stuff *************************** }
  347. function taicpu.is_nop: boolean;
  348. begin
  349. { we don't insert any more nops than necessary }
  350. is_nop := false;
  351. end;
  352. function taicpu.is_move:boolean;
  353. begin
  354. is_move := opcode = A_MOV;
  355. end;
  356. function taicpu.spill_registers(list:Taasmoutput;
  357. rgget:Trggetproc;
  358. rgunget:Trgungetproc;
  359. r:Tsupregset;
  360. var unusedregsint:Tsupregset;
  361. const spilltemplist:Tspill_temp_list): boolean;
  362. function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
  363. var back:Tsupregset;
  364. begin
  365. back:=unusedregsint;
  366. get_insert_pos:=p;
  367. while (p<>nil) and (p.typ=ait_regalloc) do
  368. begin
  369. {Rewind the register allocation.}
  370. if Tai_regalloc(p).allocation then
  371. include(unusedregsint,Tai_regalloc(p).reg.number shr 8)
  372. else
  373. begin
  374. exclude(unusedregsint,Tai_regalloc(p).reg.number shr 8);
  375. if Tai_regalloc(p).reg.number shr 8=huntfor1 then
  376. begin
  377. get_insert_pos:=Tai(p.previous);
  378. back:=unusedregsint;
  379. end;
  380. if Tai_regalloc(p).reg.number shr 8=huntfor2 then
  381. begin
  382. get_insert_pos:=Tai(p.previous);
  383. back:=unusedregsint;
  384. end;
  385. if Tai_regalloc(p).reg.number shr 8=huntfor3 then
  386. begin
  387. get_insert_pos:=Tai(p.previous);
  388. back:=unusedregsint;
  389. end;
  390. end;
  391. p:=Tai(p.previous);
  392. end;
  393. unusedregsint:=back;
  394. end;
  395. procedure forward_allocation(p:Tai);
  396. begin
  397. {Forward the register allocation again.}
  398. while (p<>self) do
  399. begin
  400. if p.typ<>ait_regalloc then
  401. internalerror(200305311);
  402. if Tai_regalloc(p).allocation then
  403. exclude(unusedregsint,Tai_regalloc(p).reg.number shr 8)
  404. else
  405. include(unusedregsint,Tai_regalloc(p).reg.number shr 8);
  406. p:=Tai(p.next);
  407. end;
  408. end;
  409. function decode_loadstore(op: tasmop; var counterpart: tasmop; wasload: boolean): boolean;
  410. begin
  411. result := true;
  412. wasload := true;
  413. case op of
  414. A_LDR:
  415. begin
  416. counterpart := A_STR;
  417. end;
  418. A_LDM:
  419. internalerror(2003070602);
  420. else
  421. result := false;
  422. end;
  423. end;
  424. var i:byte;
  425. supreg, reg1, reg2, reg3: Tsuperregister;
  426. helpreg:Tregister;
  427. helpins:Taicpu;
  428. op:Tasmop;
  429. pos:Tai;
  430. wasload: boolean;
  431. begin
  432. spill_registers:=false;
  433. if (ops = 2) and
  434. (oper[1].typ=top_ref) and
  435. { oper[1] can also be ref in case of "lis r3,symbol@ha" or so }
  436. decode_loadstore(opcode,op,wasload) then
  437. begin
  438. { the register that's being stored/loaded }
  439. supreg:=oper[0].reg.number shr 8;
  440. if supreg in r then
  441. begin
  442. // Example:
  443. // l?? r20d, 8(r1) ; r20d must be spilled into -60(r1)
  444. //
  445. // Change into:
  446. //
  447. // l?? r21d, 8(r1)
  448. // st? r21d, -60(r1)
  449. //
  450. // And:
  451. //
  452. // st? r20d, 8(r1) ; r20d must be spilled into -60(r1)
  453. //
  454. // Change into:
  455. //
  456. // l?? r21d, -60(r1)
  457. // st? r21d, 8(r1)
  458. pos := get_insert_pos(Tai(previous),oper[0].reg.number shr 8,
  459. oper[1].ref^.base.number shr 8,oper[1].ref^.index.number shr 8);
  460. rgget(list,pos,0,helpreg);
  461. spill_registers := true;
  462. if wasload then
  463. begin
  464. helpins := taicpu.op_reg_ref(opcode,helpreg,oper[1].ref^);
  465. loadref(1,spilltemplist[supreg]);
  466. opcode := op;
  467. end
  468. else
  469. helpins := taicpu.op_reg_ref(op,helpreg,spilltemplist[supreg]);
  470. if pos=nil then
  471. list.insertafter(helpins,list.first)
  472. else
  473. list.insertafter(helpins,pos.next);
  474. loadreg(0,helpreg);
  475. rgunget(list,helpins,helpreg);
  476. forward_allocation(tai(helpins.next));
  477. {$ifdef debugra}
  478. writeln('spilling!');
  479. list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
  480. {$endif debugra}
  481. end;
  482. { now the registers used in the reference }
  483. { a) base }
  484. supreg := oper[1].ref^.base.number shr 8;
  485. if supreg in r then
  486. begin
  487. if wasload then
  488. pos:=get_insert_pos(Tai(previous),oper[1].ref^.index.number shr 8,oper[0].reg.number shr 8,0)
  489. else
  490. pos:=get_insert_pos(Tai(previous),oper[1].ref^.index.number shr 8,0,0);
  491. rgget(list,pos,0,helpreg);
  492. spill_registers:=true;
  493. helpins:=Taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
  494. if pos=nil then
  495. list.insertafter(helpins,list.first)
  496. else
  497. list.insertafter(helpins,pos.next);
  498. oper[1].ref^.base:=helpreg;
  499. rgunget(list,helpins,helpreg);
  500. forward_allocation(Tai(helpins.next));
  501. {$ifdef debugra}
  502. writeln('spilling!');
  503. list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
  504. {$endif debugra}
  505. end;
  506. { b) index }
  507. supreg := oper[1].ref^.index.number shr 8;
  508. if supreg in r then
  509. begin
  510. if wasload then
  511. pos:=get_insert_pos(Tai(previous),oper[1].ref^.base.number shr 8,oper[0].reg.number shr 8,0)
  512. else
  513. pos:=get_insert_pos(Tai(previous),oper[1].ref^.base.number shr 8,0,0);
  514. rgget(list,pos,0,helpreg);
  515. spill_registers:=true;
  516. helpins:=Taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
  517. if pos=nil then
  518. list.insertafter(helpins,list.first)
  519. else
  520. list.insertafter(helpins,pos.next);
  521. oper[1].ref^.index:=helpreg;
  522. rgunget(list,helpins,helpreg);
  523. forward_allocation(Tai(helpins.next));
  524. {$ifdef debugra}
  525. writeln('spilling!');
  526. list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
  527. {$endif debugra}
  528. end;
  529. { load/store is done }
  530. exit;
  531. end;
  532. { all other instructions the compiler generates are the same (I hope): }
  533. { operand 0 is a register and is the destination, the others are sources }
  534. { and can be either registers or constants }
  535. { exception: branches (is_jmp isn't always set for them) }
  536. if oper[0].typ <> top_reg then
  537. exit;
  538. reg1 := oper[0].reg.number shr 8;
  539. if oper[1].typ = top_reg then
  540. reg2 := oper[1].reg.number shr 8
  541. else
  542. reg2 := 0;
  543. if (ops >= 3) and
  544. (oper[2].typ = top_reg) then
  545. reg3 := oper[2].reg.number shr 8
  546. else
  547. reg3 := 0;
  548. supreg:=reg1;
  549. if supreg in r then
  550. begin
  551. // Example:
  552. // add r20d, r21d, r22d ; r20d must be spilled into -60(r1)
  553. //
  554. // Change into:
  555. //
  556. // lwz r23d, -60(r1)
  557. // add r23d, r21d, r22d
  558. // stw r23d, -60(r1)
  559. pos := get_insert_pos(Tai(previous),reg1,reg2,reg3);
  560. rgget(list,pos,0,helpreg);
  561. spill_registers := true;
  562. helpins := taicpu.op_reg_ref(A_STR,helpreg,spilltemplist[supreg]);
  563. list.insertafter(helpins,self);
  564. helpins := taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
  565. if pos=nil then
  566. list.insertafter(helpins,list.first)
  567. else
  568. list.insertafter(helpins,pos.next);
  569. loadreg(0,helpreg);
  570. rgunget(list,helpins,helpreg);
  571. forward_allocation(tai(helpins.next));
  572. {$ifdef debugra}
  573. writeln('spilling!');
  574. list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
  575. {$endif debugra}
  576. end;
  577. for i := 1 to 2 do
  578. if (oper[i].typ = top_reg) then
  579. begin
  580. supreg:=oper[i].reg.number;
  581. if supreg in r then
  582. begin
  583. // Example:
  584. // add r20d, r21d, r22d ; r20d must be spilled into -60(r1)
  585. //
  586. // Change into:
  587. //
  588. // lwz r23d, -60(r1)
  589. // add r23d, r21d, r22d
  590. // stw r23d, -60(r1)
  591. pos := get_insert_pos(Tai(previous),reg1,reg2,reg3);
  592. rgget(list,pos,0,helpreg);
  593. spill_registers := true;
  594. helpins := taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
  595. if pos=nil then
  596. list.insertafter(helpins,list.first)
  597. else
  598. list.insertafter(helpins,pos.next);
  599. loadreg(i,helpreg);
  600. rgunget(list,helpins,helpreg);
  601. forward_allocation(tai(helpins.next));
  602. {$ifdef debugra}
  603. writeln('spilling!');
  604. list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
  605. {$endif debugra}
  606. end;
  607. end;
  608. end;
  609. procedure InitAsm;
  610. begin
  611. end;
  612. procedure DoneAsm;
  613. begin
  614. end;
  615. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  616. begin
  617. i.oppostfix:=pf;
  618. result:=i;
  619. end;
  620. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  621. begin
  622. i.roundingmode:=rm;
  623. result:=i;
  624. end;
  625. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  626. begin
  627. i.condition:=c;
  628. result:=i;
  629. end;
  630. end.
  631. {
  632. $Log$
  633. Revision 1.8 2003-09-03 11:18:37 florian
  634. * fixed arm concatcopy
  635. + arm support in the common compiler sources added
  636. * moved some generic cg code around
  637. + tfputype added
  638. * ...
  639. Revision 1.7 2003/08/29 21:36:28 florian
  640. * fixed procedure entry/exit code
  641. * started to fix reference handling
  642. Revision 1.6 2003/08/28 00:05:29 florian
  643. * today's arm patches
  644. Revision 1.5 2003/08/27 00:27:56 florian
  645. + same procedure as very day: today's work on arm
  646. Revision 1.4 2003/08/25 23:20:38 florian
  647. + started to implement FPU support for the ARM
  648. * fixed a lot of other things
  649. Revision 1.3 2003/08/24 12:27:26 florian
  650. * continued to work on the arm port
  651. Revision 1.2 2003/08/20 15:50:12 florian
  652. * more arm stuff
  653. Revision 1.1 2003/08/16 13:23:01 florian
  654. * several arm related stuff fixed
  655. }