aasmcpu.pas 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  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. function getfillbuf:pchar;override;
  36. end;
  37. taicpu = class(taicpu_abstract)
  38. opsize:topsize;
  39. constructor op_none(op:tasmop);
  40. constructor op_reg(op:tasmop;reg:tregister);
  41. constructor op_const(op:tasmop;_op1:aword);
  42. constructor op_ref(op:tasmop;const _op1:treference);
  43. constructor op_reg_reg(op:tasmop;_op1,_op2:tregister);
  44. constructor op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference);
  45. constructor op_reg_const(op:tasmop;_op1:tregister;_op2:aword);
  46. constructor op_const_reg(op:tasmop;_op1:aword;_op2:tregister);
  47. constructor op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister);
  48. constructor op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
  49. constructor op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister);
  50. constructor op_reg_const_reg(Op:TAsmOp;SrcReg:TRegister;value:aWord;DstReg:TRegister);
  51. constructor op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
  52. constructor op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
  53. { this is for Jmp instructions }
  54. constructor op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
  55. constructor op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
  56. constructor op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
  57. constructor op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
  58. constructor op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
  59. constructor op_caddr_reg(op:TAsmOp;rgb:TRegister;cnst:Integer;reg:TRegister);
  60. constructor op_raddr_reg(op:TAsmOp;rg1,rg2:TRegister;reg:TRegister);
  61. procedure changeopsize(siz:topsize);
  62. function GetString:string;
  63. procedure CheckNonCommutativeOpcodes;
  64. procedure loadcaddr(opidx:longint;aReg:TRegister;cnst:Integer);
  65. procedure loadraddr(opidx:longint;rg1,rg2:TRegister);
  66. private
  67. procedure init(_size:topsize);{this need to be called by all constructor}
  68. public
  69. { the next will reset all instructions that can change in pass 2 }
  70. procedure ResetPass1;
  71. procedure ResetPass2;
  72. function CheckIfValid:boolean;
  73. function Pass1(offset:longint):longint;virtual;
  74. private
  75. { next fields are filled in pass1, so pass2 is faster }
  76. insentry : PInsEntry;
  77. insoffset,
  78. inssize : longint;
  79. LastInsOffset : longint; { need to be public to be reset }
  80. function InsEnd:longint;
  81. procedure create_ot;
  82. function Matches(p:PInsEntry):longint;
  83. function calcsize(p:PInsEntry):longint;
  84. function NeedAddrPrefix(opidx:byte):boolean;
  85. procedure Swatoperands;
  86. end;
  87. PROCEDURE DoneAsm;
  88. PROCEDURE InitAsm;
  89. implementation
  90. uses
  91. cutils,
  92. CpuGas;
  93. const
  94. _size=S_SW;{To be removed soon}
  95. {****************************************************************************
  96. TAI_ALIGN
  97. ****************************************************************************}
  98. constructor tai_align.create(b:byte);
  99. begin
  100. inherited create(b);
  101. reg:= R_NONE;
  102. end;
  103. constructor tai_align.create_op(b:byte; _op:byte);
  104. begin
  105. inherited create_op(b,_op);
  106. reg:= R_NONE;
  107. end;
  108. function tai_align.getfillbuf:pchar;
  109. const
  110. alignarray:array[0..5] of string[8]=(
  111. #$8D#$B4#$26#$00#$00#$00#$00,
  112. #$8D#$B6#$00#$00#$00#$00,
  113. #$8D#$74#$26#$00,
  114. #$8D#$76#$00,
  115. #$89#$F6,
  116. #$90
  117. );
  118. var
  119. bufptr:pchar;
  120. j:longint;
  121. begin
  122. if not use_op then
  123. begin
  124. bufptr:=@buf;
  125. while (fillsize>0) do
  126. begin
  127. for j:=0 to 5 do
  128. if (fillsize>=length(alignarray[j])) then
  129. break;
  130. move(alignarray[j][1],bufptr^,length(alignarray[j]));
  131. inc(bufptr,length(alignarray[j]));
  132. dec(fillsize,length(alignarray[j]));
  133. end;
  134. end;
  135. getfillbuf:=pchar(@buf);
  136. end;
  137. {*****************************************************************************
  138. Taicpu Constructors
  139. *****************************************************************************}
  140. procedure taicpu.changeopsize(siz:topsize);
  141. begin
  142. opsize:=siz;
  143. end;
  144. procedure taicpu.init(_size:topsize);
  145. begin
  146. opsize:=_size;
  147. end;
  148. constructor taicpu.op_none(op:tasmop);
  149. begin
  150. inherited create(op);
  151. init(_size);
  152. end;
  153. constructor taicpu.op_reg(op:tasmop;reg:tregister);
  154. begin
  155. inherited create(op);
  156. init(_size);
  157. ops:=1;
  158. loadreg(0,reg);
  159. end;
  160. constructor taicpu.op_const(op:tasmop;_op1:aword);
  161. begin
  162. inherited create(op);
  163. init(_size);
  164. ops:=1;
  165. loadconst(0,_op1);
  166. end;
  167. constructor taicpu.op_ref(op:tasmop;const _op1:treference);
  168. begin
  169. inherited create(op);
  170. init(_size);
  171. ops:=1;
  172. loadref(0,_op1);
  173. end;
  174. constructor taicpu.op_reg_reg(op:tasmop;_op1,_op2:tregister);
  175. begin
  176. inherited create(op);
  177. init(_size);
  178. ops:=2;
  179. loadreg(0,_op1);
  180. loadreg(1,_op2);
  181. end;
  182. constructor taicpu.op_reg_const(op:tasmop;_op1:tregister; _op2:aword);
  183. begin
  184. inherited create(op);
  185. init(_size);
  186. ops:=2;
  187. loadreg(0,_op1);
  188. loadconst(1,_op2);
  189. end;
  190. constructor taicpu.op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference);
  191. begin
  192. if not(Op in [A_STB..A_STDFQ])
  193. then
  194. fail;
  195. inherited Create(Op);
  196. init(_size);
  197. ops:=2;
  198. LoadReg(0,Reg);
  199. LoadRef(1,Ref);
  200. end;
  201. constructor taicpu.op_const_reg(op:tasmop;_op1:aword;_op2:tregister);
  202. begin
  203. inherited create(op);
  204. init(_size);
  205. ops:=2;
  206. loadconst(0,_op1);
  207. loadreg(1,_op2);
  208. end;
  209. constructor TAiCpu.op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister);
  210. begin
  211. if not(Op in [A_JMPL,A_FLUSH,A_LDSB..A_LDDC,A_RETT,A_SWAP])
  212. then
  213. fail;
  214. inherited Create(Op);
  215. Init(S_SW);
  216. Ops:=2;
  217. LoadRef(0,Ref);
  218. LoadReg(1,Reg);
  219. end;
  220. constructor taicpu.op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
  221. begin
  222. inherited create(op);
  223. init(_size);
  224. ops:=2;
  225. loadref(0,_op1);
  226. loadref(1,_op2);
  227. end;
  228. constructor taicpu.op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister);
  229. begin
  230. inherited create(op);
  231. init(_size);
  232. ops:=3;
  233. loadreg(0,_op1);
  234. loadreg(1,_op2);
  235. loadreg(2,_op3);
  236. end;
  237. constructor taicpu.op_reg_const_reg(op:TAsmOp;SrcReg:TRegister;Value:aWord;DstReg:TRegister);
  238. begin
  239. inherited Create(Op);
  240. Init(S_W);
  241. ops:=3;
  242. LoadReg(0,SrcReg);
  243. LoadConst(1,Value);
  244. LoadReg(2,DstReg);
  245. end;
  246. constructor taicpu.op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
  247. begin
  248. inherited create(op);
  249. init(_size);
  250. ops:=3;
  251. loadconst(0,_op1);
  252. loadref(1,_op2);
  253. loadreg(2,_op3);
  254. end;
  255. constructor taicpu.op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
  256. begin
  257. inherited create(op);
  258. init(_size);
  259. ops:=3;
  260. loadconst(0,_op1);
  261. loadreg(1,_op2);
  262. loadref(2,_op3);
  263. end;
  264. constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
  265. begin
  266. inherited create(op);
  267. init(_size);
  268. condition:=cond;
  269. ops:=1;
  270. loadsymbol(0,_op1,0);
  271. end;
  272. constructor taicpu.op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
  273. begin
  274. inherited create(op);
  275. init(_size);
  276. ops:=1;
  277. loadsymbol(0,_op1,0);
  278. end;
  279. constructor taicpu.op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
  280. begin
  281. inherited create(op);
  282. init(_size);
  283. ops:=1;
  284. loadsymbol(0,_op1,_op1ofs);
  285. end;
  286. constructor taicpu.op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
  287. begin
  288. inherited create(op);
  289. init(_size);
  290. ops:=2;
  291. loadsymbol(0,_op1,_op1ofs);
  292. loadreg(1,_op2);
  293. end;
  294. constructor taicpu.op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
  295. begin
  296. inherited create(op);
  297. init(_size);
  298. ops:=2;
  299. loadsymbol(0,_op1,_op1ofs);
  300. loadref(1,_op2);
  301. end;
  302. constructor taicpu.op_caddr_reg(op:TAsmOp;rgb:TRegister;cnst:Integer;reg:TRegister);
  303. begin
  304. inherited create(op);
  305. init(S_SW);
  306. ops:=2;
  307. WriteLn(1,std_reg2str[rgb]);
  308. loadcaddr(0,rgb,cnst);
  309. WriteLn(2,std_reg2str[rgb]);
  310. loadreg(1,reg);
  311. end;
  312. constructor taicpu.op_raddr_reg(op:TAsmOp;rg1,rg2,reg:TRegister);
  313. begin
  314. inherited create(op);
  315. init(S_SW);
  316. ops:=2;
  317. loadraddr(0,rg1,rg2);
  318. loadreg(1,reg);
  319. end;
  320. function taicpu.GetString:string;
  321. var
  322. i:longint;
  323. s:string;
  324. addsize:boolean;
  325. begin
  326. s:='['+std_op2str[opcode];
  327. for i:=1to ops do
  328. begin
  329. if i=1 then
  330. s:=s+' '
  331. else
  332. s:=s+',';
  333. { type }
  334. addsize:=false;
  335. if (oper[i-1].ot and OT_XMMREG)=OT_XMMREG then
  336. s:=s+'xmmreg'
  337. else
  338. if (oper[i-1].ot and OT_MMXREG)=OT_MMXREG then
  339. s:=s+'mmxreg'
  340. else
  341. if (oper[i-1].ot and OT_FPUREG)=OT_FPUREG then
  342. s:=s+'fpureg'
  343. else
  344. if (oper[i-1].ot and OT_REGISTER)=OT_REGISTER then
  345. begin
  346. s:=s+'reg';
  347. addsize:=true;
  348. end
  349. else
  350. if (oper[i-1].ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  351. begin
  352. s:=s+'imm';
  353. addsize:=true;
  354. end
  355. else
  356. if (oper[i-1].ot and OT_MEMORY)=OT_MEMORY then
  357. begin
  358. s:=s+'mem';
  359. addsize:=true;
  360. end
  361. else
  362. s:=s+'???';
  363. { size }
  364. if addsize then
  365. begin
  366. if (oper[i-1].ot and OT_BITS8)<>0 then
  367. s:=s+'8'
  368. else
  369. if (oper[i-1].ot and OT_BITS16)<>0 then
  370. s:=s+'16'
  371. else
  372. if (oper[i-1].ot and OT_BITS32)<>0 then
  373. s:=s+'32'
  374. else
  375. s:=s+'??';
  376. { signed }
  377. if (oper[i-1].ot and OT_SIGNED)<>0 then
  378. s:=s+'s';
  379. end;
  380. end;
  381. GetString:=s+']';
  382. end;
  383. procedure taicpu.Swatoperands;
  384. var
  385. p:TOper;
  386. begin
  387. { Fix the operands which are in AT&T style and we need them in Intel style }
  388. case ops of
  389. 2:begin
  390. { 0,1 -> 1,0 }
  391. p:=oper[0];
  392. oper[0]:=oper[1];
  393. oper[1]:=p;
  394. end;
  395. 3:begin
  396. { 0,1,2 -> 2,1,0 }
  397. p:=oper[0];
  398. oper[0]:=oper[2];
  399. oper[2]:=p;
  400. end;
  401. end;
  402. end;
  403. { This check must be done with the operand in ATT order
  404. i.e.after swapping in the intel reader
  405. but before swapping in the NASM and TASM writers PM }
  406. procedure taicpu.CheckNonCommutativeOpcodes;
  407. begin
  408. { if ((ops=2) and
  409. (oper[0].typ=top_reg) and
  410. (oper[1].typ=top_reg) and
  411. (oper[0].reg IN [R_F0..RF31])) or
  412. (ops=0) then
  413. if opcode=A_FSUBR then
  414. opcode:=A_FSUB
  415. else if opcode=A_FSUB then
  416. opcode:=A_FSUBR
  417. else if opcode=A_FDIVR then
  418. opcode:=A_FDIV
  419. else if opcode=A_FDIV then
  420. opcode:=A_FDIVR
  421. else if opcode=A_FSUBRP then
  422. opcode:=A_FSUBP
  423. else if opcode=A_FSUBP then
  424. opcode:=A_FSUBRP
  425. else if opcode=A_FDIVRP then
  426. opcode:=A_FDIVP
  427. else if opcode=A_FDIVP then
  428. opcode:=A_FDIVRP;
  429. if ((ops=1) and
  430. (oper[0].typ=top_reg) and
  431. (oper[0].reg in [R_ST1..R_ST7])) then
  432. if opcode=A_FSUBRP then
  433. opcode:=A_FSUBP
  434. else if opcode=A_FSUBP then
  435. opcode:=A_FSUBRP
  436. else if opcode=A_FDIVRP then
  437. opcode:=A_FDIVP
  438. else if opcode=A_FDIVP then
  439. opcode:=A_FDIVRP;}
  440. end;
  441. {*****************************************************************************
  442. Assembler
  443. *****************************************************************************}
  444. type
  445. ea=packed record
  446. sib_present:boolean;
  447. bytes:byte;
  448. size:byte;
  449. modrm:byte;
  450. sib:byte;
  451. end;
  452. procedure taicpu.create_ot;
  453. {
  454. this function will also fix some other fields which only needs to be once
  455. }
  456. var
  457. i,l,relsize:longint;
  458. begin
  459. if ops=0 then
  460. exit;
  461. { update oper[].ot field }
  462. for i:=0 to ops-1 do
  463. with oper[i] do
  464. begin
  465. case typ of
  466. top_reg:
  467. {ot:=reg2type[reg]};
  468. top_ref:
  469. begin
  470. { create ot field }
  471. {if (ot and OT_SIZE_MASK)=0 then
  472. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  473. else
  474. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  475. if (ref^.base=R_NONE) and (ref^.index=R_NONE) then
  476. ot:=ot or OT_MEM_OFFS;}
  477. { fix scalefactor }
  478. if (ref^.index=R_NONE) then
  479. ref^.scalefactor:=0
  480. else
  481. if (ref^.scalefactor=0) then
  482. ref^.scalefactor:=1;
  483. end;
  484. top_const:
  485. begin
  486. if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then
  487. ot:=OT_IMM8 or OT_SIGNED
  488. else
  489. ot:=OT_IMMEDIATE {or opsize_2_type[i,opsize];}
  490. end;
  491. top_symbol:
  492. begin
  493. if LastInsOffset=-1 then
  494. l:=0
  495. else
  496. l:=InsOffset-LastInsOffset;
  497. inc(l,symofs);
  498. if assigned(sym) then
  499. inc(l,sym.address);
  500. { instruction size will then always become 2 (PFV) }
  501. relsize:=(InsOffset+2)-l;
  502. if (not assigned(sym) or
  503. ((sym.currbind<>AB_EXTERNAL) and (sym.address<>0))) and
  504. (relsize>=-128) and (relsize<=127) then
  505. ot:=OT_IMM32 or OT_SHORT
  506. else
  507. ot:=OT_IMM32 or OT_NEAR;
  508. end;
  509. end;
  510. end;
  511. end;
  512. function taicpu.InsEnd:longint;
  513. begin
  514. InsEnd:=InsOffset+InsSize;
  515. end;
  516. function taicpu.Matches(p:PInsEntry):longint;
  517. { * IF_SM stands for Size Match:any operand whose size is not
  518. * explicitly specified by the template is `really' intended to be
  519. * the same size as the first size-specified operand.
  520. * Non-specification is tolerated in the input instruction, but
  521. * _wrong_ specification is not.
  522. *
  523. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  524. * three-operand instructions such as SHLD:it implies that the
  525. * first two operands must match in size, but that the third is
  526. * required to be _unspecified_.
  527. *
  528. * IF_SB invokes Size Byte:operands with unspecified size in the
  529. * template are really bytes, and so no non-byte specification in
  530. * the input instruction will be tolerated. IF_SW similarly invokes
  531. * Size Word, and IF_SD invokes Size Doubleword.
  532. *
  533. * (The default state if neither IF_SM nor IF_SM2 is specified is
  534. * that any operand with unspecified size in the template is
  535. * required to have unspecified size in the instruction too...)
  536. }
  537. var
  538. i,j,asize,oprs:longint;
  539. siz:array[0..2] of longint;
  540. begin
  541. Matches:=100;
  542. { Check the opcode and operands }
  543. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  544. begin
  545. Matches:=0;
  546. exit;
  547. end;
  548. { Check that no spurious colons or TOs are present }
  549. for i:=0 to p^.ops-1 do
  550. if (oper[i].ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  551. begin
  552. Matches:=0;
  553. exit;
  554. end;
  555. { Check that the operand flags all match up }
  556. for i:=0 to p^.ops-1 do
  557. begin
  558. if ((p^.optypes[i] and (not oper[i].ot)) or
  559. ((p^.optypes[i] and OT_SIZE_MASK) and
  560. ((p^.optypes[i] xor oper[i].ot) and OT_SIZE_MASK)))<>0 then
  561. begin
  562. if ((p^.optypes[i] and (not oper[i].ot) and OT_NON_SIZE) or
  563. (oper[i].ot and OT_SIZE_MASK))<>0 then
  564. begin
  565. Matches:=0;
  566. exit;
  567. end
  568. else
  569. Matches:=1;
  570. end;
  571. end;
  572. { Check operand sizes }
  573. { as default an untyped size can get all the sizes, this is different
  574. from nasm, but else we need to do a lot checking which opcodes want
  575. size or not with the automatic size generation }
  576. asize:=longint($ffffffff);
  577. if (p^.flags and IF_SB)<>0 then
  578. asize:=OT_BITS8
  579. else if (p^.flags and IF_SW)<>0 then
  580. asize:=OT_BITS16
  581. else if (p^.flags and IF_SD)<>0 then
  582. asize:=OT_BITS32;
  583. if (p^.flags and IF_ARMASK)<>0 then
  584. begin
  585. siz[0]:=0;
  586. siz[1]:=0;
  587. siz[2]:=0;
  588. if (p^.flags and IF_AR0)<>0 then
  589. siz[0]:=asize
  590. else if (p^.flags and IF_AR1)<>0 then
  591. siz[1]:=asize
  592. else if (p^.flags and IF_AR2)<>0 then
  593. siz[2]:=asize;
  594. end
  595. else
  596. begin
  597. { we can leave because the size for all operands is forced to be
  598. the same
  599. but not if IF_SB IF_SW or IF_SD is set PM }
  600. if asize=-1 then
  601. exit;
  602. siz[0]:=asize;
  603. siz[1]:=asize;
  604. siz[2]:=asize;
  605. end;
  606. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  607. begin
  608. if (p^.flags and IF_SM2)<>0 then
  609. oprs:=2
  610. else
  611. oprs:=p^.ops;
  612. for i:=0 to oprs-1 do
  613. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  614. begin
  615. for j:=0 to oprs-1 do
  616. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  617. break;
  618. end;
  619. end
  620. else
  621. oprs:=2;
  622. { Check operand sizes }
  623. for i:=0 to p^.ops-1 do
  624. begin
  625. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  626. ((oper[i].ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  627. { Immediates can always include smaller size }
  628. ((oper[i].ot and OT_IMMEDIATE)=0) and
  629. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i].ot and OT_SIZE_MASK)) then
  630. Matches:=2;
  631. end;
  632. end;
  633. procedure taicpu.ResetPass1;
  634. begin
  635. { we need to reset everything here, because the choosen insentry
  636. can be invalid for a new situation where the previously optimized
  637. insentry is not correct }
  638. InsEntry:=nil;
  639. InsSize:=0;
  640. LastInsOffset:=-1;
  641. end;
  642. procedure taicpu.ResetPass2;
  643. begin
  644. { we are here in a second pass, check if the instruction can be optimized }
  645. if assigned(InsEntry) and
  646. ((InsEntry^.flags and IF_PASS2)<>0) then
  647. begin
  648. InsEntry:=nil;
  649. InsSize:=0;
  650. end;
  651. LastInsOffset:=-1;
  652. end;
  653. function taicpu.CheckIfValid:boolean;
  654. var
  655. m,i:longint;
  656. begin
  657. CheckIfValid:=false;
  658. { Things which may only be done once, not when a second pass is done to
  659. optimize }
  660. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  661. begin
  662. { create the .ot fields }
  663. create_ot;
  664. { set the file postion }
  665. aktfilepos:=fileinfo;
  666. end
  667. else
  668. begin
  669. { we've already an insentry so it's valid }
  670. CheckIfValid:=true;
  671. exit;
  672. end;
  673. { Lookup opcode in the table }
  674. InsSize:=-1;
  675. i:=instabcache^[opcode];
  676. if i=-1 then
  677. begin
  678. {$ifdef TP}
  679. Message1(asmw_e_opcode_not_in_table,'');
  680. {$else}
  681. Message1(asmw_e_opcode_not_in_table,std_op2str[opcode]);
  682. {$endif}
  683. exit;
  684. end;
  685. // insentry:=@instab[i];
  686. while (insentry^.opcode=opcode) do
  687. begin
  688. m:=matches(insentry);
  689. if m=100 then
  690. begin
  691. InsSize:=calcsize(insentry);
  692. {if (segprefix<>R_NONE) then
  693. inc(InsSize);}{No segprefix!}
  694. { For opsize if size if forced }
  695. if (insentry^.flags and (IF_SB or IF_SW or IF_SD))<>0 then
  696. begin
  697. if (insentry^.flags and IF_ARMASK)=0 then
  698. begin
  699. if (insentry^.flags and IF_SB)<>0 then
  700. begin
  701. if opsize=S_NO then
  702. opsize:=S_B;
  703. end
  704. else if (insentry^.flags and IF_SW)<>0 then
  705. begin
  706. if opsize=S_NO then
  707. opsize:=S_W;
  708. end
  709. else if (insentry^.flags and IF_SD)<>0 then
  710. begin
  711. if opsize=S_NO then
  712. opsize:=S_SW;
  713. end;
  714. end;
  715. end;
  716. CheckIfValid:=true;
  717. exit;
  718. end;
  719. inc(i);
  720. // insentry:=@instab[i];
  721. end;
  722. if insentry^.opcode<>opcode then
  723. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  724. { No instruction found, set insentry to nil and inssize to -1 }
  725. insentry:=nil;
  726. inssize:=-1;
  727. end;
  728. function taicpu.Pass1(offset:longint):longint;
  729. begin
  730. Pass1:=0;
  731. { Save the old offset and set the new offset }
  732. InsOffset:=Offset;
  733. { Things which may only be done once, not when a second pass is done to
  734. optimize }
  735. if Insentry=nil then
  736. begin
  737. { Check if error last time then InsSize=-1 }
  738. if InsSize=-1 then
  739. exit;
  740. { set the file postion }
  741. aktfilepos:=fileinfo;
  742. end
  743. else
  744. begin
  745. {$ifdef PASS2FLAG}
  746. { we are here in a second pass, check if the instruction can be optimized }
  747. if (InsEntry^.flags and IF_PASS2)=0 then
  748. begin
  749. Pass1:=InsSize;
  750. exit;
  751. end;
  752. { update the .ot fields, some top_const can be updated }
  753. create_ot;
  754. {$endif}
  755. end;
  756. { Check if it's a valid instruction }
  757. if CheckIfValid then
  758. begin
  759. LastInsOffset:=InsOffset;
  760. Pass1:=InsSize;
  761. exit;
  762. end;
  763. LastInsOffset:=-1;
  764. end;
  765. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  766. var
  767. i,b:tregister;
  768. begin
  769. { if (OT_MEMORY and (not oper[opidx].ot))=0 then
  770. begin
  771. i:=oper[opidx].ref^.index;
  772. b:=oper[opidx].ref^.base;
  773. if not(i in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) or
  774. not(b in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) then
  775. begin
  776. NeedAddrPrefix:=true;
  777. exit;
  778. end;
  779. end;}
  780. NeedAddrPrefix:=false;
  781. end;
  782. function regval(r:tregister):byte;
  783. begin
  784. {case r of
  785. R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0,R_XMM0:
  786. regval:=0;
  787. R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1,R_XMM1:
  788. regval:=1;
  789. R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2,R_XMM2:
  790. regval:=2;
  791. R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3,R_XMM3:
  792. regval:=3;
  793. R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4,R_XMM4:
  794. regval:=4;
  795. R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5,R_XMM5:
  796. regval:=5;
  797. R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6,R_XMM6:
  798. regval:=6;
  799. R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7,R_XMM7:
  800. regval:=7;
  801. else}
  802. begin
  803. internalerror(777001);
  804. regval:=0;
  805. end;
  806. { end;}
  807. end;
  808. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  809. {const
  810. regs:array[0..63] of tregister=(
  811. R_MM0, R_EAX, R_AX, R_AL, R_XMM0, R_NONE, R_NONE, R_NONE,
  812. R_MM1, R_ECX, R_CX, R_CL, R_XMM1, R_NONE, R_NONE, R_NONE,
  813. R_MM2, R_EDX, R_DX, R_DL, R_XMM2, R_NONE, R_NONE, R_NONE,
  814. R_MM3, R_EBX, R_BX, R_BL, R_XMM3, R_NONE, R_NONE, R_NONE,
  815. R_MM4, R_ESP, R_SP, R_AH, R_XMM4, R_NONE, R_NONE, R_NONE,
  816. R_MM5, R_EBP, R_BP, R_CH, R_XMM5, R_NONE, R_NONE, R_NONE,
  817. R_MM6, R_ESI, R_SI, R_DH, R_XMM6, R_NONE, R_NONE, R_NONE,
  818. R_MM7, R_EDI, R_DI, R_BH, R_XMM7, R_NONE, R_NONE, R_NONE
  819. );}
  820. var
  821. j:longint;
  822. i,b:tregister;
  823. sym:tasmsymbol;
  824. md,s:byte;
  825. base,index,scalefactor,
  826. o:longint;
  827. begin
  828. process_ea:=false;
  829. { register ? }
  830. { if (input.typ=top_reg) then
  831. begin
  832. j:=0;
  833. while (j<=high(regs)) do
  834. begin
  835. if input.reg=regs[j] then
  836. break;
  837. inc(j);
  838. end;
  839. if j<=high(regs) then
  840. begin
  841. output.sib_present:=false;
  842. output.bytes:=0;
  843. output.modrm:=$c0 or (rfield shl 3) or (j shr 3);
  844. output.size:=1;
  845. process_ea:=true;
  846. end;
  847. exit;
  848. end;}
  849. { memory reference }
  850. i:=input.ref^.index;
  851. b:=input.ref^.base;
  852. s:=input.ref^.scalefactor;
  853. o:=input.ref^.offset+input.ref^.offsetfixup;
  854. sym:=input.ref^.symbol;
  855. { it's direct address }
  856. if (b=R_NONE) and (i=R_NONE) then
  857. begin
  858. { it's a pure offset }
  859. output.sib_present:=false;
  860. output.bytes:=4;
  861. output.modrm:=5 or (rfield shl 3);
  862. end
  863. else
  864. { it's an indirection }
  865. begin
  866. { 16 bit address? }
  867. { if not((i in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) and
  868. (b in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI])) then
  869. Message(asmw_e_16bit_not_supported);}
  870. {$ifdef OPTEA}
  871. { make single reg base }
  872. if (b=R_NONE) and (s=1) then
  873. begin
  874. b:=i;
  875. i:=R_NONE;
  876. end;
  877. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  878. { if (b=R_NONE) and
  879. (((s=2) and (i<>R_ESP)) or
  880. (s=3) or (s=5) or (s=9)) then
  881. begin
  882. b:=i;
  883. dec(s);
  884. end;}
  885. { swap ESP into base if scalefactor is 1 }
  886. { if (s=1) and (i=R_ESP) then
  887. begin
  888. i:=b;
  889. b:=R_ESP;
  890. end;}
  891. {$endif}
  892. { wrong, for various reasons }
  893. { if (i=R_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (i<>R_NONE)) then
  894. exit;}
  895. { base }
  896. { case b of
  897. R_EAX:base:=0;
  898. R_ECX:base:=1;
  899. R_EDX:base:=2;
  900. R_EBX:base:=3;
  901. R_ESP:base:=4;
  902. R_NONE,
  903. R_EBP:base:=5;
  904. R_ESI:base:=6;
  905. R_EDI:base:=7;
  906. else
  907. exit;
  908. end;}
  909. { index }
  910. { case i of
  911. R_EAX:index:=0;
  912. R_ECX:index:=1;
  913. R_EDX:index:=2;
  914. R_EBX:index:=3;
  915. R_NONE:index:=4;
  916. R_EBP:index:=5;
  917. R_ESI:index:=6;
  918. R_EDI:index:=7;
  919. else
  920. exit;
  921. end;
  922. case s of
  923. 0,
  924. 1:scalefactor:=0;
  925. 2:scalefactor:=1;
  926. 4:scalefactor:=2;
  927. 8:scalefactor:=3;
  928. else
  929. exit;
  930. end;
  931. if (b=R_NONE) or
  932. ((b<>R_EBP) and (o=0) and (sym=nil)) then
  933. md:=0
  934. else
  935. if ((o>=-128) and (o<=127) and (sym=nil)) then
  936. md:=1
  937. else
  938. md:=2;
  939. if (b=R_NONE) or (md=2) then
  940. output.bytes:=4
  941. else
  942. output.bytes:=md;}
  943. { SIB needed ? }
  944. { if (i=R_NONE) and (b<>R_ESP) then
  945. begin
  946. output.sib_present:=false;
  947. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  948. end
  949. else
  950. begin
  951. output.sib_present:=true;
  952. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  953. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  954. end;}
  955. end;
  956. if output.sib_present then
  957. output.size:=2+output.bytes
  958. else
  959. output.size:=1+output.bytes;
  960. process_ea:=true;
  961. end;
  962. function taicpu.calcsize(p:PInsEntry):longint;
  963. var
  964. codes:pchar;
  965. c:byte;
  966. len:longint;
  967. ea_data:ea;
  968. begin
  969. len:=0;
  970. codes:=@p^.code;
  971. repeat
  972. c:=ord(codes^);
  973. inc(codes);
  974. case c of
  975. 0:
  976. break;
  977. 1,2,3:
  978. begin
  979. inc(codes,c);
  980. inc(len,c);
  981. end;
  982. 8,9,10:
  983. begin
  984. inc(codes);
  985. inc(len);
  986. end;
  987. 4,5,6,7:
  988. begin
  989. if opsize=S_W then
  990. inc(len,2)
  991. else
  992. inc(len);
  993. end;
  994. 15,
  995. 12,13,14,
  996. 16,17,18,
  997. 20,21,22,
  998. 40,41,42:
  999. inc(len);
  1000. 24,25,26,
  1001. 31,
  1002. 48,49,50:
  1003. inc(len,2);
  1004. 28,29,30, { we don't have 16 bit immediates code }
  1005. 32,33,34,
  1006. 52,53,54,
  1007. 56,57,58:
  1008. inc(len,4);
  1009. 192,193,194:
  1010. if NeedAddrPrefix(c-192) then
  1011. inc(len);
  1012. 208:
  1013. inc(len);
  1014. 200,
  1015. 201,
  1016. 202,
  1017. 209,
  1018. 210,
  1019. 217,218,219:;
  1020. 216:
  1021. begin
  1022. inc(codes);
  1023. inc(len);
  1024. end;
  1025. 224,225,226:
  1026. begin
  1027. InternalError(777002);
  1028. end;
  1029. else
  1030. begin
  1031. if (c>=64) and (c<=191) then
  1032. begin
  1033. if not process_ea(oper[(c shr 3) and 7], ea_data, 0) then
  1034. Message(asmw_e_invalid_effective_address)
  1035. else
  1036. inc(len,ea_data.size);
  1037. end
  1038. else
  1039. InternalError(777003);
  1040. end;
  1041. end;
  1042. until false;
  1043. calcsize:=len;
  1044. end;
  1045. procedure taicpu.loadcaddr(opidx:longint;aReg:TRegister;cnst:Integer);
  1046. begin
  1047. if opidx>=ops
  1048. then
  1049. ops:=opidx+1;
  1050. with oper[opidx] do
  1051. begin
  1052. typ:=top_caddr;
  1053. regb:=aReg;
  1054. const13:=cnst;
  1055. end;
  1056. end;
  1057. procedure taicpu.loadraddr(opidx:longint;rg1,rg2:TRegister);
  1058. begin
  1059. if opidx>=ops
  1060. then
  1061. ops:=opidx+1;
  1062. with oper[opidx] do
  1063. begin
  1064. typ:=top_caddr;
  1065. reg1:=rg1;
  1066. reg2:=rg2;
  1067. end;
  1068. end;
  1069. procedure DoneAsm;
  1070. begin
  1071. end;
  1072. procedure InitAsm;
  1073. begin
  1074. end;
  1075. end.
  1076. {
  1077. $Log$
  1078. Revision 1.12 2002-11-10 19:07:46 mazen
  1079. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1080. Revision 1.11 2002/11/06 11:31:24 mazen
  1081. * op_reg_reg_reg don't need any more a TOpSize parameter
  1082. Revision 1.10 2002/11/05 16:15:00 mazen
  1083. *** empty log message ***
  1084. Revision 1.9 2002/10/28 20:59:17 mazen
  1085. * TOpSize values changed S_L --> S_SW
  1086. Revision 1.8 2002/10/22 13:43:01 mazen
  1087. - cga.pas redueced to an empty unit
  1088. Revision 1.7 2002/10/20 19:01:38 mazen
  1089. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  1090. Revision 1.6 2002/10/19 20:35:07 mazen
  1091. * carl's patch applied
  1092. Revision 1.5 2002/10/15 09:00:28 mazen
  1093. * sone coding style modified
  1094. Revision 1.4 2002/10/13 21:46:07 mazen
  1095. * assembler output format fixed
  1096. }