aasmcpu.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  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,cgbase;
  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:tcpuregisterset);
  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: aword);
  42. constructor op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
  43. constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  44. constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aword);
  45. constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  46. constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  47. constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  48. { this is for Jmp instructions }
  49. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  50. constructor op_sym(op : tasmop;_op1 : tasmsymbol);
  51. constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  52. constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  53. constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  54. function is_same_reg_move: boolean; override;
  55. function is_reg_move:boolean; override;
  56. { register spilling code }
  57. function spilling_create_load(const ref:treference;r:tregister): tai;override;
  58. function spilling_create_store(r:tregister; const ref:treference): tai;override;
  59. function spilling_get_operation_type(opnr: longint): topertype;override;
  60. end;
  61. tai_align = class(tai_align_abstract)
  62. { nothing to add }
  63. end;
  64. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  65. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  66. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  67. { inserts pc relative symbols at places where they are reachable }
  68. procedure insertpcrelativedata(list,listtoinsert : taasmoutput);
  69. procedure InitAsm;
  70. procedure DoneAsm;
  71. implementation
  72. uses
  73. cutils,rgobj,itcpugas;
  74. procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
  75. begin
  76. allocate_oper(opidx+1);
  77. with oper[opidx]^ do
  78. begin
  79. if typ<>top_shifterop then
  80. begin
  81. clearop(opidx);
  82. new(shifterop);
  83. end;
  84. shifterop^:=so;
  85. typ:=top_shifterop;
  86. if assigned(add_reg_instruction_hook) then
  87. add_reg_instruction_hook(self,shifterop^.rs);
  88. end;
  89. end;
  90. procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset);
  91. var
  92. i : byte;
  93. begin
  94. allocate_oper(opidx+1);
  95. with oper[opidx]^ do
  96. begin
  97. if typ<>top_regset then
  98. clearop(opidx);
  99. new(regset);
  100. regset^:=s;
  101. typ:=top_regset;
  102. for i:=RS_R0 to RS_R15 do
  103. begin
  104. if assigned(add_reg_instruction_hook) and (i in regset^) then
  105. add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,R_SUBWHOLE));
  106. end;
  107. end;
  108. end;
  109. {*****************************************************************************
  110. taicpu Constructors
  111. *****************************************************************************}
  112. constructor taicpu.op_none(op : tasmop);
  113. begin
  114. inherited create(op);
  115. end;
  116. constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
  117. begin
  118. inherited create(op);
  119. ops:=1;
  120. loadreg(0,_op1);
  121. end;
  122. constructor taicpu.op_const(op : tasmop;_op1 : longint);
  123. begin
  124. inherited create(op);
  125. ops:=1;
  126. loadconst(0,aword(_op1));
  127. end;
  128. constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  129. begin
  130. inherited create(op);
  131. ops:=2;
  132. loadreg(0,_op1);
  133. loadreg(1,_op2);
  134. end;
  135. constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aword);
  136. begin
  137. inherited create(op);
  138. ops:=2;
  139. loadreg(0,_op1);
  140. loadconst(1,aword(_op2));
  141. end;
  142. constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
  143. begin
  144. inherited create(op);
  145. ops:=2;
  146. loadref(0,_op1);
  147. loadregset(1,_op2);
  148. end;
  149. constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  150. begin
  151. inherited create(op);
  152. ops:=2;
  153. loadreg(0,_op1);
  154. loadref(1,_op2);
  155. end;
  156. constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  157. begin
  158. inherited create(op);
  159. ops:=3;
  160. loadreg(0,_op1);
  161. loadreg(1,_op2);
  162. loadreg(2,_op3);
  163. end;
  164. constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aword);
  165. begin
  166. inherited create(op);
  167. ops:=3;
  168. loadreg(0,_op1);
  169. loadreg(1,_op2);
  170. loadconst(2,aword(_op3));
  171. end;
  172. constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  173. begin
  174. inherited create(op);
  175. ops:=3;
  176. loadreg(0,_op1);
  177. loadreg(1,_op2);
  178. loadsymbol(0,_op3,_op3ofs);
  179. end;
  180. constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  181. begin
  182. inherited create(op);
  183. ops:=3;
  184. loadreg(0,_op1);
  185. loadreg(1,_op2);
  186. loadref(2,_op3);
  187. end;
  188. constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  189. begin
  190. inherited create(op);
  191. ops:=3;
  192. loadreg(0,_op1);
  193. loadreg(1,_op2);
  194. loadshifterop(2,_op3);
  195. end;
  196. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  197. begin
  198. inherited create(op);
  199. condition:=cond;
  200. ops:=1;
  201. loadsymbol(0,_op1,0);
  202. end;
  203. constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
  204. begin
  205. inherited create(op);
  206. ops:=1;
  207. loadsymbol(0,_op1,0);
  208. end;
  209. constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  210. begin
  211. inherited create(op);
  212. ops:=1;
  213. loadsymbol(0,_op1,_op1ofs);
  214. end;
  215. constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  216. begin
  217. inherited create(op);
  218. ops:=2;
  219. loadreg(0,_op1);
  220. loadsymbol(1,_op2,_op2ofs);
  221. end;
  222. constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  223. begin
  224. inherited create(op);
  225. ops:=2;
  226. loadsymbol(0,_op1,_op1ofs);
  227. loadref(1,_op2);
  228. end;
  229. { ****************************** newra stuff *************************** }
  230. function taicpu.is_same_reg_move: boolean;
  231. begin
  232. { allow the register allocator to remove unnecessary moves }
  233. result:=is_reg_move and (oper[0]^.reg=oper[1]^.reg);
  234. end;
  235. function taicpu.is_reg_move:boolean;
  236. begin
  237. result:=((opcode=A_MOV) or (opcode=A_MVF)) and
  238. (condition=C_None) and
  239. (ops=2) and
  240. (oper[0]^.typ=top_reg) and
  241. (oper[1]^.typ=top_reg);
  242. end;
  243. function taicpu.spilling_create_load(const ref:treference;r:tregister): tai;
  244. begin
  245. internalerror(200401261);
  246. end;
  247. function taicpu.spilling_create_store(r:tregister; const ref:treference): tai;
  248. begin
  249. internalerror(200401262);
  250. end;
  251. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  252. begin
  253. if opnr = 0 then
  254. result := operand_write
  255. else
  256. result:=operand_read;
  257. end;
  258. procedure InitAsm;
  259. begin
  260. end;
  261. procedure DoneAsm;
  262. begin
  263. end;
  264. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  265. begin
  266. i.oppostfix:=pf;
  267. result:=i;
  268. end;
  269. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  270. begin
  271. i.roundingmode:=rm;
  272. result:=i;
  273. end;
  274. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  275. begin
  276. i.condition:=c;
  277. result:=i;
  278. end;
  279. procedure insertpcrelativedata(list,listtoinsert : taasmoutput);
  280. var
  281. curpos : longint;
  282. lastpos : longint;
  283. curop : longint;
  284. curtai : tai;
  285. curdatatai,hp : tai;
  286. curdata : taasmoutput;
  287. l : tasmlabel;
  288. begin
  289. curdata:=taasmoutput.create;
  290. lastpos:=-1;
  291. curpos:=0;
  292. curtai:=tai(list.first);
  293. while assigned(curtai) do
  294. begin
  295. { instruction? }
  296. if curtai.typ=ait_instruction then
  297. begin
  298. { walk through all operand of the instruction }
  299. for curop:=0 to taicpu(curtai).ops-1 do
  300. begin
  301. { reference? }
  302. if (taicpu(curtai).oper[curop]^.typ=top_ref) then
  303. begin
  304. { pc relative symbol? }
  305. curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
  306. if assigned(curdatatai) then
  307. begin
  308. { if yes, insert till next symbol }
  309. repeat
  310. hp:=tai(curdatatai.next);
  311. listtoinsert.remove(curdatatai);
  312. curdata.concat(curdatatai);
  313. curdatatai:=hp;
  314. until (curdatatai=nil) or (curdatatai.typ=ait_label);
  315. if lastpos=-1 then
  316. lastpos:=curpos;
  317. end;
  318. end;
  319. end;
  320. inc(curpos);
  321. end;
  322. if (curpos-lastpos)>1020 then
  323. begin
  324. lastpos:=curpos;
  325. hp:=tai(curtai.next);
  326. objectlibrary.getlabel(l);
  327. curdata.insert(taicpu.op_sym(A_B,l));
  328. curdata.concat(tai_label.create(l));
  329. list.insertlistafter(curtai,curdata);
  330. curtai:=hp;
  331. end
  332. else
  333. curtai:=tai(curtai.next);
  334. end;
  335. list.concatlist(curdata);
  336. curdata.free;
  337. end;
  338. end.
  339. {
  340. $Log$
  341. Revision 1.25 2004-01-26 19:05:56 florian
  342. * fixed several arm issues
  343. Revision 1.24 2004/01/24 20:19:46 florian
  344. * fixed some spilling stuff
  345. + not(<int64>) implemented
  346. + small set comparisations implemented
  347. Revision 1.23 2004/01/23 15:12:49 florian
  348. * fixed generic shl/shr operations
  349. + added register allocation hook calls for arm specific operand types:
  350. register set and shifter op
  351. Revision 1.22 2004/01/21 19:01:03 florian
  352. * fixed handling of max. distance of pc relative symbols
  353. Revision 1.21 2004/01/20 21:02:55 florian
  354. * fixed symbol type writing for arm-linux
  355. * fixed assembler generation for abs
  356. Revision 1.20 2003/12/28 16:20:09 jonas
  357. - removed unused methods from old generic spilling code
  358. Revision 1.19 2003/12/26 14:02:30 peter
  359. * sparc updates
  360. * use registertype in spill_register
  361. Revision 1.18 2003/12/18 17:06:21 florian
  362. * arm compiler compilation fixed
  363. Revision 1.17 2003/12/03 17:39:05 florian
  364. * fixed several arm calling conventions issues
  365. * fixed reference reading in the assembler reader
  366. * fixed a_loadaddr_ref_reg
  367. Revision 1.16 2003/11/30 19:35:29 florian
  368. * fixed several arm related problems
  369. Revision 1.15 2003/11/29 17:36:56 peter
  370. * fixed is_move
  371. Revision 1.14 2003/11/24 15:17:37 florian
  372. * changed some types to prevend range check errors
  373. Revision 1.13 2003/11/02 14:30:03 florian
  374. * fixed ARM for new reg. allocation scheme
  375. Revision 1.12 2003/09/11 11:54:59 florian
  376. * improved arm code generation
  377. * move some protected and private field around
  378. * the temp. register for register parameters/arguments are now released
  379. before the move to the parameter register is done. This improves
  380. the code in a lot of cases.
  381. Revision 1.11 2003/09/06 11:21:49 florian
  382. * fixed stm and ldm to be usable with preindex operand
  383. Revision 1.10 2003/09/04 21:07:03 florian
  384. * ARM compiler compiles again
  385. Revision 1.9 2003/09/04 00:15:29 florian
  386. * first bunch of adaptions of arm compiler for new register type
  387. Revision 1.8 2003/09/03 11:18:37 florian
  388. * fixed arm concatcopy
  389. + arm support in the common compiler sources added
  390. * moved some generic cg code around
  391. + tfputype added
  392. * ...
  393. Revision 1.7 2003/08/29 21:36:28 florian
  394. * fixed procedure entry/exit code
  395. * started to fix reference handling
  396. Revision 1.6 2003/08/28 00:05:29 florian
  397. * today's arm patches
  398. Revision 1.5 2003/08/27 00:27:56 florian
  399. + same procedure as very day: today's work on arm
  400. Revision 1.4 2003/08/25 23:20:38 florian
  401. + started to implement FPU support for the ARM
  402. * fixed a lot of other things
  403. Revision 1.3 2003/08/24 12:27:26 florian
  404. * continued to work on the arm port
  405. Revision 1.2 2003/08/20 15:50:12 florian
  406. * more arm stuff
  407. Revision 1.1 2003/08/16 13:23:01 florian
  408. * several arm related stuff fixed
  409. }