aasmcpu.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. {*****************************************************************************
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
  4. * This code was inspired by the NASM sources
  5. The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  6. Julian Hall. All rights reserved.
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************}
  19. unit aasmcpu;
  20. {$INCLUDE fpcdefs.inc}
  21. interface
  22. uses
  23. cclasses,globals,verbose,
  24. cpuinfo,cpubase,
  25. symppu,
  26. aasmbase,aasmtai;
  27. const
  28. MaxPrefixes=4;
  29. type
  30. { alignment for operator }
  31. tai_align=class(tai_align_abstract)
  32. reg:tregister;
  33. constructor create(b:byte);
  34. constructor create_op(b:byte; _op:byte);
  35. end;
  36. taicpu = class(taicpu_abstract)
  37. opsize:topsize;
  38. constructor op_none(op:tasmop);
  39. constructor op_reg(op:tasmop;reg:tregister);
  40. constructor op_const(op:tasmop;_op1:aword);
  41. constructor op_ref(op:tasmop;const _op1:treference);
  42. constructor op_reg_reg(op:tasmop;_op1,_op2:tregister);
  43. constructor op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference);
  44. constructor op_reg_const(op:tasmop;_op1:tregister;_op2:aword);
  45. constructor op_const_reg(op:tasmop;_op1:aword;_op2:tregister);
  46. constructor op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister);
  47. constructor op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
  48. constructor op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister);
  49. constructor op_reg_const_reg(Op:TAsmOp;SrcReg:TRegister;value:aWord;DstReg:TRegister);
  50. constructor op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
  51. constructor op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
  52. { this is for Jmp instructions }
  53. constructor op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
  54. constructor op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
  55. constructor op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
  56. constructor op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
  57. constructor op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
  58. constructor op_caddr_reg(op:TAsmOp;rgb:TRegister;cnst:Integer;reg:TRegister);
  59. constructor op_raddr_reg(op:TAsmOp;rg1,rg2:TRegister;reg:TRegister);
  60. procedure changeopsize(siz:topsize);
  61. procedure loadcaddr(opidx:longint;aReg:TRegister;cnst:Integer);
  62. procedure loadraddr(opidx:longint;rg1,rg2:TRegister);
  63. private
  64. procedure init(_size:topsize);{this need to be called by all constructor}
  65. public
  66. { the next will reset all instructions that can change in pass 2 }
  67. procedure SetCondition(const c:TAsmCond);
  68. private
  69. { next fields are filled in pass1, so pass2 is faster }
  70. procedure Swatoperands;
  71. end;
  72. PROCEDURE DoneAsm;
  73. PROCEDURE InitAsm;
  74. implementation
  75. uses
  76. cutils,
  77. CpuGas;
  78. const
  79. _size=S_SW;{To be removed soon}
  80. {****************************************************************************
  81. TAI_ALIGN
  82. ****************************************************************************}
  83. constructor tai_align.create(b:byte);
  84. begin
  85. inherited create(b);
  86. reg.enum:= R_NONE;
  87. end;
  88. constructor tai_align.create_op(b:byte; _op:byte);
  89. begin
  90. inherited create_op(b,_op);
  91. reg.enum:= R_NONE;
  92. end;
  93. {*****************************************************************************
  94. Taicpu Constructors
  95. *****************************************************************************}
  96. procedure taicpu.changeopsize(siz:topsize);
  97. begin
  98. opsize:=siz;
  99. end;
  100. procedure taicpu.init(_size:topsize);
  101. begin
  102. opsize:=_size;
  103. end;
  104. constructor taicpu.op_none(op:tasmop);
  105. begin
  106. inherited create(op);
  107. init(_size);
  108. end;
  109. constructor taicpu.op_reg(op:tasmop;reg:tregister);
  110. begin
  111. inherited create(op);
  112. init(_size);
  113. ops:=1;
  114. loadreg(0,reg);
  115. end;
  116. constructor taicpu.op_const(op:tasmop;_op1:aword);
  117. begin
  118. inherited create(op);
  119. init(_size);
  120. ops:=1;
  121. loadconst(0,aword(_op1));
  122. end;
  123. constructor taicpu.op_ref(op:tasmop;const _op1:treference);
  124. begin
  125. inherited create(op);
  126. init(_size);
  127. ops:=1;
  128. loadref(0,_op1);
  129. end;
  130. constructor taicpu.op_reg_reg(op:tasmop;_op1,_op2:tregister);
  131. begin
  132. inherited create(op);
  133. init(_size);
  134. ops:=2;
  135. loadreg(0,_op1);
  136. loadreg(1,_op2);
  137. end;
  138. constructor taicpu.op_reg_const(op:tasmop;_op1:tregister; _op2:aword);
  139. begin
  140. inherited create(op);
  141. init(_size);
  142. ops:=2;
  143. loadreg(0,_op1);
  144. loadconst(1,aword(_op2));
  145. end;
  146. constructor taicpu.op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference);
  147. begin
  148. if not(Op in [A_STB..A_STDFQ])
  149. then
  150. fail;
  151. inherited Create(Op);
  152. init(_size);
  153. ops:=2;
  154. LoadReg(0,Reg);
  155. LoadRef(1,Ref);
  156. end;
  157. constructor taicpu.op_const_reg(op:tasmop;_op1:aword;_op2:tregister);
  158. begin
  159. inherited create(op);
  160. init(_size);
  161. ops:=2;
  162. loadconst(0,aword(_op1));
  163. loadreg(1,_op2);
  164. end;
  165. constructor TAiCpu.op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister);
  166. begin
  167. if not(Op in [A_JMPL,A_FLUSH,A_LDSB..A_LDDC,A_RETT,A_SWAP])
  168. then
  169. InternalError(2003042900);
  170. inherited Create(Op);
  171. Init(S_SW);
  172. Ops:=2;
  173. LoadRef(0,Ref);
  174. LoadReg(1,Reg);
  175. end;
  176. constructor taicpu.op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
  177. begin
  178. inherited create(op);
  179. init(_size);
  180. ops:=2;
  181. loadref(0,_op1);
  182. loadref(1,_op2);
  183. end;
  184. constructor taicpu.op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister);
  185. begin
  186. inherited create(op);
  187. init(_size);
  188. ops:=3;
  189. loadreg(0,_op1);
  190. loadreg(1,_op2);
  191. loadreg(2,_op3);
  192. end;
  193. constructor taicpu.op_reg_const_reg(op:TAsmOp;SrcReg:TRegister;Value:aWord;DstReg:TRegister);
  194. begin
  195. inherited Create(Op);
  196. Init(S_W);
  197. ops:=3;
  198. LoadReg(0,SrcReg);
  199. LoadConst(1,Value);
  200. LoadReg(2,DstReg);
  201. end;
  202. constructor taicpu.op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
  203. begin
  204. inherited create(op);
  205. init(_size);
  206. ops:=3;
  207. loadconst(0,aword(_op1));
  208. loadref(1,_op2);
  209. loadreg(2,_op3);
  210. end;
  211. constructor taicpu.op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
  212. begin
  213. inherited create(op);
  214. init(_size);
  215. ops:=3;
  216. loadconst(0,aword(_op1));
  217. loadreg(1,_op2);
  218. loadref(2,_op3);
  219. end;
  220. constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
  221. begin
  222. inherited create(op);
  223. init(_size);
  224. condition:=cond;
  225. ops:=1;
  226. loadsymbol(0,_op1,0);
  227. end;
  228. constructor taicpu.op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
  229. begin
  230. inherited create(op);
  231. init(_size);
  232. ops:=1;
  233. loadsymbol(0,_op1,0);
  234. end;
  235. constructor taicpu.op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
  236. begin
  237. inherited create(op);
  238. init(_size);
  239. ops:=1;
  240. loadsymbol(0,_op1,_op1ofs);
  241. end;
  242. constructor taicpu.op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
  243. begin
  244. inherited create(op);
  245. init(_size);
  246. ops:=2;
  247. loadsymbol(0,_op1,_op1ofs);
  248. loadreg(1,_op2);
  249. end;
  250. constructor taicpu.op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
  251. begin
  252. inherited create(op);
  253. init(_size);
  254. ops:=2;
  255. loadsymbol(0,_op1,_op1ofs);
  256. loadref(1,_op2);
  257. end;
  258. constructor taicpu.op_caddr_reg(op:TAsmOp;rgb:TRegister;cnst:Integer;reg:TRegister);
  259. begin
  260. inherited create(op);
  261. init(S_SW);
  262. ops:=2;
  263. loadcaddr(0,rgb,cnst);
  264. loadreg(1,reg);
  265. end;
  266. constructor taicpu.op_raddr_reg(op:TAsmOp;rg1,rg2,reg:TRegister);
  267. begin
  268. inherited create(op);
  269. init(S_SW);
  270. ops:=2;
  271. loadraddr(0,rg1,rg2);
  272. loadreg(1,reg);
  273. end;
  274. procedure taicpu.Swatoperands;
  275. var
  276. p:TOper;
  277. begin
  278. { Fix the operands which are in AT&T style and we need them in Intel style }
  279. case ops of
  280. 2:begin
  281. { 0,1 -> 1,0 }
  282. p:=oper[0];
  283. oper[0]:=oper[1];
  284. oper[1]:=p;
  285. end;
  286. 3:begin
  287. { 0,1,2 -> 2,1,0 }
  288. p:=oper[0];
  289. oper[0]:=oper[2];
  290. oper[2]:=p;
  291. end;
  292. end;
  293. end;
  294. { This check must be done with the operand in ATT order
  295. i.e.after swapping in the intel reader
  296. but before swapping in the NASM and TASM writers PM }
  297. {*****************************************************************************
  298. Assembler
  299. *****************************************************************************}
  300. procedure TAiCpu.SetCondition(const c:TAsmCond);
  301. const
  302. AsmCond2OpCode:array[TAsmCond]of TAsmOp=
  303. (A_BN,A_BNE,A_BE,A_BG,A_BLE,A_BGE,A_BL,A_BGU,A_BLEU,A_BCC,
  304. A_BCS,A_BPOS,A_NEG,A_BVC,A_BVS,A_BA,A_BNE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE);
  305. begin
  306. inherited SetCondition(c);
  307. if Opcode=A_BA
  308. then
  309. begin
  310. is_jmp:=true;
  311. Opcode:=AsmCond2OpCode[c];
  312. {$IFDEF EXTDEBUG}
  313. WriteLn('In TAiCpu.SetCondition TAsmCond=',cond2str[c],'==>',std_op2str[OpCode]);
  314. {$ENDIF EXTDEBUG}
  315. end;
  316. end;
  317. procedure taicpu.loadcaddr(opidx:longint;aReg:TRegister;cnst:Integer);
  318. begin
  319. if opidx>=ops
  320. then
  321. ops:=opidx+1;
  322. with oper[opidx] do
  323. begin
  324. typ:=top_caddr;
  325. regb:=aReg;
  326. const13:=cnst;
  327. end;
  328. end;
  329. procedure taicpu.loadraddr(opidx:longint;rg1,rg2:TRegister);
  330. begin
  331. if opidx>=ops
  332. then
  333. ops:=opidx+1;
  334. with oper[opidx] do
  335. begin
  336. typ:=top_caddr;
  337. reg1:=rg1;
  338. reg2:=rg2;
  339. end;
  340. end;
  341. procedure DoneAsm;
  342. begin
  343. end;
  344. procedure InitAsm;
  345. begin
  346. end;
  347. end.
  348. {
  349. $Log$
  350. Revision 1.25 2003-05-07 11:45:02 mazen
  351. - removed unused code
  352. Revision 1.24 2003/05/07 11:28:26 mazen
  353. - method CheckNonCommutativeOpcode removed as not used
  354. Revision 1.23 2003/05/06 20:27:43 mazen
  355. * A_BI changed to A_BL
  356. Revision 1.22 2003/05/06 15:00:36 mazen
  357. - non used code removed to bring up with powerpc changes
  358. Revision 1.21 2003/04/29 11:06:15 mazen
  359. * test of invalid opcode/operand combination gives internal error
  360. Revision 1.20 2003/04/28 09:40:47 mazen
  361. * Debug message in SetCondition more explicit.
  362. Revision 1.19 2003/03/15 22:51:58 mazen
  363. * remaking sparc rtl compile
  364. Revision 1.18 2003/03/10 21:59:54 mazen
  365. * fixing index overflow in handling new registers arrays.
  366. Revision 1.17 2003/02/18 22:00:20 mazen
  367. * asm condition generation modified by TAiCpu.SetCondition
  368. Revision 1.16 2003/01/08 18:43:58 daniel
  369. * Tregister changed into a record
  370. Revision 1.15 2003/01/05 21:32:35 mazen
  371. * fixing several bugs compiling the RTL
  372. Revision 1.14 2002/12/14 15:02:03 carl
  373. * maxoperands -> max_operands (for portability in rautils.pas)
  374. * fix some range-check errors with loadconst
  375. + add ncgadd unit to m68k
  376. * some bugfix of a_param_reg with LOC_CREFERENCE
  377. Revision 1.13 2002/11/17 16:32:04 carl
  378. * memory optimization (3-4%) : cleanup of tai fields,
  379. cleanup of tdef and tsym fields.
  380. * make it work for m68k
  381. Revision 1.12 2002/11/10 19:07:46 mazen
  382. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  383. Revision 1.11 2002/11/06 11:31:24 mazen
  384. * op_reg_reg_reg don't need any more a TOpSize parameter
  385. Revision 1.10 2002/11/05 16:15:00 mazen
  386. *** empty log message ***
  387. Revision 1.9 2002/10/28 20:59:17 mazen
  388. * TOpSize values changed S_L --> S_SW
  389. Revision 1.8 2002/10/22 13:43:01 mazen
  390. - cga.pas redueced to an empty unit
  391. Revision 1.7 2002/10/20 19:01:38 mazen
  392. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  393. Revision 1.6 2002/10/19 20:35:07 mazen
  394. * carl's patch applied
  395. Revision 1.5 2002/10/15 09:00:28 mazen
  396. * sone coding style modified
  397. Revision 1.4 2002/10/13 21:46:07 mazen
  398. * assembler output format fixed
  399. }