aasmcpu.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  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 CheckNonCommutativeOpcodes;
  62. procedure loadcaddr(opidx:longint;aReg:TRegister;cnst:Integer);
  63. procedure loadraddr(opidx:longint;rg1,rg2:TRegister);
  64. private
  65. procedure init(_size:topsize);{this need to be called by all constructor}
  66. public
  67. { the next will reset all instructions that can change in pass 2 }
  68. procedure SetCondition(const c:TAsmCond);
  69. private
  70. { next fields are filled in pass1, so pass2 is faster }
  71. insentry : PInsEntry;
  72. insoffset,
  73. inssize : longint;
  74. LastInsOffset : longint; { need to be public to be reset }
  75. function InsEnd:longint;
  76. function calcsize(p:PInsEntry):longint;
  77. function NeedAddrPrefix(opidx:byte):boolean;
  78. procedure Swatoperands;
  79. end;
  80. PROCEDURE DoneAsm;
  81. PROCEDURE InitAsm;
  82. implementation
  83. uses
  84. cutils,
  85. CpuGas;
  86. const
  87. _size=S_SW;{To be removed soon}
  88. {****************************************************************************
  89. TAI_ALIGN
  90. ****************************************************************************}
  91. constructor tai_align.create(b:byte);
  92. begin
  93. inherited create(b);
  94. reg.enum:= R_NONE;
  95. end;
  96. constructor tai_align.create_op(b:byte; _op:byte);
  97. begin
  98. inherited create_op(b,_op);
  99. reg.enum:= R_NONE;
  100. end;
  101. {*****************************************************************************
  102. Taicpu Constructors
  103. *****************************************************************************}
  104. procedure taicpu.changeopsize(siz:topsize);
  105. begin
  106. opsize:=siz;
  107. end;
  108. procedure taicpu.init(_size:topsize);
  109. begin
  110. opsize:=_size;
  111. end;
  112. constructor taicpu.op_none(op:tasmop);
  113. begin
  114. inherited create(op);
  115. init(_size);
  116. end;
  117. constructor taicpu.op_reg(op:tasmop;reg:tregister);
  118. begin
  119. inherited create(op);
  120. init(_size);
  121. ops:=1;
  122. loadreg(0,reg);
  123. end;
  124. constructor taicpu.op_const(op:tasmop;_op1:aword);
  125. begin
  126. inherited create(op);
  127. init(_size);
  128. ops:=1;
  129. loadconst(0,aword(_op1));
  130. end;
  131. constructor taicpu.op_ref(op:tasmop;const _op1:treference);
  132. begin
  133. inherited create(op);
  134. init(_size);
  135. ops:=1;
  136. loadref(0,_op1);
  137. end;
  138. constructor taicpu.op_reg_reg(op:tasmop;_op1,_op2:tregister);
  139. begin
  140. inherited create(op);
  141. init(_size);
  142. ops:=2;
  143. loadreg(0,_op1);
  144. loadreg(1,_op2);
  145. end;
  146. constructor taicpu.op_reg_const(op:tasmop;_op1:tregister; _op2:aword);
  147. begin
  148. inherited create(op);
  149. init(_size);
  150. ops:=2;
  151. loadreg(0,_op1);
  152. loadconst(1,aword(_op2));
  153. end;
  154. constructor taicpu.op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference);
  155. begin
  156. if not(Op in [A_STB..A_STDFQ])
  157. then
  158. fail;
  159. inherited Create(Op);
  160. init(_size);
  161. ops:=2;
  162. LoadReg(0,Reg);
  163. LoadRef(1,Ref);
  164. end;
  165. constructor taicpu.op_const_reg(op:tasmop;_op1:aword;_op2:tregister);
  166. begin
  167. inherited create(op);
  168. init(_size);
  169. ops:=2;
  170. loadconst(0,aword(_op1));
  171. loadreg(1,_op2);
  172. end;
  173. constructor TAiCpu.op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister);
  174. begin
  175. if not(Op in [A_JMPL,A_FLUSH,A_LDSB..A_LDDC,A_RETT,A_SWAP])
  176. then
  177. InternalError(2003042900);
  178. inherited Create(Op);
  179. Init(S_SW);
  180. Ops:=2;
  181. LoadRef(0,Ref);
  182. LoadReg(1,Reg);
  183. end;
  184. constructor taicpu.op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
  185. begin
  186. inherited create(op);
  187. init(_size);
  188. ops:=2;
  189. loadref(0,_op1);
  190. loadref(1,_op2);
  191. end;
  192. constructor taicpu.op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister);
  193. begin
  194. inherited create(op);
  195. init(_size);
  196. ops:=3;
  197. loadreg(0,_op1);
  198. loadreg(1,_op2);
  199. loadreg(2,_op3);
  200. end;
  201. constructor taicpu.op_reg_const_reg(op:TAsmOp;SrcReg:TRegister;Value:aWord;DstReg:TRegister);
  202. begin
  203. inherited Create(Op);
  204. Init(S_W);
  205. ops:=3;
  206. LoadReg(0,SrcReg);
  207. LoadConst(1,Value);
  208. LoadReg(2,DstReg);
  209. end;
  210. constructor taicpu.op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
  211. begin
  212. inherited create(op);
  213. init(_size);
  214. ops:=3;
  215. loadconst(0,aword(_op1));
  216. loadref(1,_op2);
  217. loadreg(2,_op3);
  218. end;
  219. constructor taicpu.op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
  220. begin
  221. inherited create(op);
  222. init(_size);
  223. ops:=3;
  224. loadconst(0,aword(_op1));
  225. loadreg(1,_op2);
  226. loadref(2,_op3);
  227. end;
  228. constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
  229. begin
  230. inherited create(op);
  231. init(_size);
  232. condition:=cond;
  233. ops:=1;
  234. loadsymbol(0,_op1,0);
  235. end;
  236. constructor taicpu.op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
  237. begin
  238. inherited create(op);
  239. init(_size);
  240. ops:=1;
  241. loadsymbol(0,_op1,0);
  242. end;
  243. constructor taicpu.op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
  244. begin
  245. inherited create(op);
  246. init(_size);
  247. ops:=1;
  248. loadsymbol(0,_op1,_op1ofs);
  249. end;
  250. constructor taicpu.op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
  251. begin
  252. inherited create(op);
  253. init(_size);
  254. ops:=2;
  255. loadsymbol(0,_op1,_op1ofs);
  256. loadreg(1,_op2);
  257. end;
  258. constructor taicpu.op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
  259. begin
  260. inherited create(op);
  261. init(_size);
  262. ops:=2;
  263. loadsymbol(0,_op1,_op1ofs);
  264. loadref(1,_op2);
  265. end;
  266. constructor taicpu.op_caddr_reg(op:TAsmOp;rgb:TRegister;cnst:Integer;reg:TRegister);
  267. begin
  268. inherited create(op);
  269. init(S_SW);
  270. ops:=2;
  271. loadcaddr(0,rgb,cnst);
  272. loadreg(1,reg);
  273. end;
  274. constructor taicpu.op_raddr_reg(op:TAsmOp;rg1,rg2,reg:TRegister);
  275. begin
  276. inherited create(op);
  277. init(S_SW);
  278. ops:=2;
  279. loadraddr(0,rg1,rg2);
  280. loadreg(1,reg);
  281. end;
  282. procedure taicpu.Swatoperands;
  283. var
  284. p:TOper;
  285. begin
  286. { Fix the operands which are in AT&T style and we need them in Intel style }
  287. case ops of
  288. 2:begin
  289. { 0,1 -> 1,0 }
  290. p:=oper[0];
  291. oper[0]:=oper[1];
  292. oper[1]:=p;
  293. end;
  294. 3:begin
  295. { 0,1,2 -> 2,1,0 }
  296. p:=oper[0];
  297. oper[0]:=oper[2];
  298. oper[2]:=p;
  299. end;
  300. end;
  301. end;
  302. { This check must be done with the operand in ATT order
  303. i.e.after swapping in the intel reader
  304. but before swapping in the NASM and TASM writers PM }
  305. procedure taicpu.CheckNonCommutativeOpcodes;
  306. begin
  307. { if ((ops=2) and
  308. (oper[0].typ=top_reg) and
  309. (oper[1].typ=top_reg) and
  310. (oper[0].reg IN [R_F0..RF31])) or
  311. (ops=0) then
  312. if opcode=A_FSUBR then
  313. opcode:=A_FSUB
  314. else if opcode=A_FSUB then
  315. opcode:=A_FSUBR
  316. else if opcode=A_FDIVR then
  317. opcode:=A_FDIV
  318. else if opcode=A_FDIV then
  319. opcode:=A_FDIVR
  320. else if opcode=A_FSUBRP then
  321. opcode:=A_FSUBP
  322. else if opcode=A_FSUBP then
  323. opcode:=A_FSUBRP
  324. else if opcode=A_FDIVRP then
  325. opcode:=A_FDIVP
  326. else if opcode=A_FDIVP then
  327. opcode:=A_FDIVRP;
  328. if ((ops=1) and
  329. (oper[0].typ=top_reg) and
  330. (oper[0].reg in [R_ST1..R_ST7])) then
  331. if opcode=A_FSUBRP then
  332. opcode:=A_FSUBP
  333. else if opcode=A_FSUBP then
  334. opcode:=A_FSUBRP
  335. else if opcode=A_FDIVRP then
  336. opcode:=A_FDIVP
  337. else if opcode=A_FDIVP then
  338. opcode:=A_FDIVRP;}
  339. end;
  340. {*****************************************************************************
  341. Assembler
  342. *****************************************************************************}
  343. type
  344. ea=packed record
  345. sib_present:boolean;
  346. bytes:byte;
  347. size:byte;
  348. modrm:byte;
  349. sib:byte;
  350. end;
  351. function taicpu.InsEnd:longint;
  352. begin
  353. InsEnd:=InsOffset+InsSize;
  354. end;
  355. procedure TAiCpu.SetCondition(const c:TAsmCond);
  356. const
  357. AsmCond2OpCode:array[TAsmCond]of TAsmOp=
  358. (A_BN,A_BNE,A_BE,A_BG,A_BLE,A_BGE,A_BL,A_BGU,A_BLEU,A_BCC,
  359. 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);
  360. begin
  361. inherited SetCondition(c);
  362. if Opcode=A_BA
  363. then
  364. begin
  365. is_jmp:=true;
  366. Opcode:=AsmCond2OpCode[c];
  367. {$IFDEF EXTDEBUG}
  368. WriteLn('In TAiCpu.SetCondition TAsmCond=',cond2str[c],'==>',std_op2str[OpCode]);
  369. {$ENDIF EXTDEBUG}
  370. end;
  371. end;
  372. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  373. var
  374. i,b:tregister;
  375. begin
  376. { if (OT_MEMORY and (not oper[opidx].ot))=0 then
  377. begin
  378. i:=oper[opidx].ref^.index;
  379. b:=oper[opidx].ref^.base;
  380. if not(i in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) or
  381. not(b in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) then
  382. begin
  383. NeedAddrPrefix:=true;
  384. exit;
  385. end;
  386. end;}
  387. NeedAddrPrefix:=false;
  388. end;
  389. function regval(r:tregister):byte;
  390. begin
  391. {case r of
  392. R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0,R_XMM0:
  393. regval:=0;
  394. R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1,R_XMM1:
  395. regval:=1;
  396. R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2,R_XMM2:
  397. regval:=2;
  398. R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3,R_XMM3:
  399. regval:=3;
  400. R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4,R_XMM4:
  401. regval:=4;
  402. R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5,R_XMM5:
  403. regval:=5;
  404. R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6,R_XMM6:
  405. regval:=6;
  406. R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7,R_XMM7:
  407. regval:=7;
  408. else}
  409. begin
  410. internalerror(777001);
  411. regval:=0;
  412. end;
  413. { end;}
  414. end;
  415. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  416. {const
  417. regs:array[0..63] of tregister=(
  418. R_MM0, R_EAX, R_AX, R_AL, R_XMM0, R_NONE, R_NONE, R_NONE,
  419. R_MM1, R_ECX, R_CX, R_CL, R_XMM1, R_NONE, R_NONE, R_NONE,
  420. R_MM2, R_EDX, R_DX, R_DL, R_XMM2, R_NONE, R_NONE, R_NONE,
  421. R_MM3, R_EBX, R_BX, R_BL, R_XMM3, R_NONE, R_NONE, R_NONE,
  422. R_MM4, R_ESP, R_SP, R_AH, R_XMM4, R_NONE, R_NONE, R_NONE,
  423. R_MM5, R_EBP, R_BP, R_CH, R_XMM5, R_NONE, R_NONE, R_NONE,
  424. R_MM6, R_ESI, R_SI, R_DH, R_XMM6, R_NONE, R_NONE, R_NONE,
  425. R_MM7, R_EDI, R_DI, R_BH, R_XMM7, R_NONE, R_NONE, R_NONE
  426. );}
  427. var
  428. j:longint;
  429. i,b:tregister;
  430. sym:tasmsymbol;
  431. md,s:byte;
  432. base,index,scalefactor,
  433. o:longint;
  434. begin
  435. process_ea:=false;
  436. { register ? }
  437. { if (input.typ=top_reg) then
  438. begin
  439. j:=0;
  440. while (j<=high(regs)) do
  441. begin
  442. if input.reg=regs[j] then
  443. break;
  444. inc(j);
  445. end;
  446. if j<=high(regs) then
  447. begin
  448. output.sib_present:=false;
  449. output.bytes:=0;
  450. output.modrm:=$c0 or (rfield shl 3) or (j shr 3);
  451. output.size:=1;
  452. process_ea:=true;
  453. end;
  454. exit;
  455. end;}
  456. { memory reference }
  457. i:=input.ref^.index;
  458. b:=input.ref^.base;
  459. s:=input.ref^.scalefactor;
  460. o:=input.ref^.offset+input.ref^.offsetfixup;
  461. sym:=input.ref^.symbol;
  462. { it's direct address }
  463. if (b.enum=R_NONE) and (i.enum=R_NONE) then
  464. begin
  465. { it's a pure offset }
  466. output.sib_present:=false;
  467. output.bytes:=4;
  468. output.modrm:=5 or (rfield shl 3);
  469. end
  470. else
  471. { it's an indirection }
  472. begin
  473. { 16 bit address? }
  474. { if not((i in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) and
  475. (b in [R_NONE,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI])) then
  476. Message(asmw_e_16bit_not_supported);}
  477. {$ifdef OPTEA}
  478. { make single reg base }
  479. if (b=R_NONE) and (s=1) then
  480. begin
  481. b:=i;
  482. i:=R_NONE;
  483. end;
  484. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  485. { if (b=R_NONE) and
  486. (((s=2) and (i<>R_ESP)) or
  487. (s=3) or (s=5) or (s=9)) then
  488. begin
  489. b:=i;
  490. dec(s);
  491. end;}
  492. { swap ESP into base if scalefactor is 1 }
  493. { if (s=1) and (i=R_ESP) then
  494. begin
  495. i:=b;
  496. b:=R_ESP;
  497. end;}
  498. {$endif}
  499. { wrong, for various reasons }
  500. { if (i=R_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (i<>R_NONE)) then
  501. exit;}
  502. { base }
  503. { case b of
  504. R_EAX:base:=0;
  505. R_ECX:base:=1;
  506. R_EDX:base:=2;
  507. R_EBX:base:=3;
  508. R_ESP:base:=4;
  509. R_NONE,
  510. R_EBP:base:=5;
  511. R_ESI:base:=6;
  512. R_EDI:base:=7;
  513. else
  514. exit;
  515. end;}
  516. { index }
  517. { case i of
  518. R_EAX:index:=0;
  519. R_ECX:index:=1;
  520. R_EDX:index:=2;
  521. R_EBX:index:=3;
  522. R_NONE:index:=4;
  523. R_EBP:index:=5;
  524. R_ESI:index:=6;
  525. R_EDI:index:=7;
  526. else
  527. exit;
  528. end;
  529. case s of
  530. 0,
  531. 1:scalefactor:=0;
  532. 2:scalefactor:=1;
  533. 4:scalefactor:=2;
  534. 8:scalefactor:=3;
  535. else
  536. exit;
  537. end;
  538. if (b=R_NONE) or
  539. ((b<>R_EBP) and (o=0) and (sym=nil)) then
  540. md:=0
  541. else
  542. if ((o>=-128) and (o<=127) and (sym=nil)) then
  543. md:=1
  544. else
  545. md:=2;
  546. if (b=R_NONE) or (md=2) then
  547. output.bytes:=4
  548. else
  549. output.bytes:=md;}
  550. { SIB needed ? }
  551. { if (i=R_NONE) and (b<>R_ESP) then
  552. begin
  553. output.sib_present:=false;
  554. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  555. end
  556. else
  557. begin
  558. output.sib_present:=true;
  559. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  560. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  561. end;}
  562. end;
  563. if output.sib_present then
  564. output.size:=2+output.bytes
  565. else
  566. output.size:=1+output.bytes;
  567. process_ea:=true;
  568. end;
  569. function taicpu.calcsize(p:PInsEntry):longint;
  570. var
  571. codes:pchar;
  572. c:byte;
  573. len:longint;
  574. ea_data:ea;
  575. begin
  576. len:=0;
  577. codes:=@p^.code;
  578. repeat
  579. c:=ord(codes^);
  580. inc(codes);
  581. case c of
  582. 0:
  583. break;
  584. 1,2,3:
  585. begin
  586. inc(codes,c);
  587. inc(len,c);
  588. end;
  589. 8,9,10:
  590. begin
  591. inc(codes);
  592. inc(len);
  593. end;
  594. 4,5,6,7:
  595. begin
  596. if opsize=S_W then
  597. inc(len,2)
  598. else
  599. inc(len);
  600. end;
  601. 15,
  602. 12,13,14,
  603. 16,17,18,
  604. 20,21,22,
  605. 40,41,42:
  606. inc(len);
  607. 24,25,26,
  608. 31,
  609. 48,49,50:
  610. inc(len,2);
  611. 28,29,30, { we don't have 16 bit immediates code }
  612. 32,33,34,
  613. 52,53,54,
  614. 56,57,58:
  615. inc(len,4);
  616. 192,193,194:
  617. if NeedAddrPrefix(c-192) then
  618. inc(len);
  619. 208:
  620. inc(len);
  621. 200,
  622. 201,
  623. 202,
  624. 209,
  625. 210,
  626. 217,218,219:;
  627. 216:
  628. begin
  629. inc(codes);
  630. inc(len);
  631. end;
  632. 224,225,226:
  633. begin
  634. InternalError(777002);
  635. end;
  636. else
  637. begin
  638. if (c>=64) and (c<=191) then
  639. begin
  640. if not process_ea(oper[(c shr 3) and 7], ea_data, 0) then
  641. Message(asmw_e_invalid_effective_address)
  642. else
  643. inc(len,ea_data.size);
  644. end
  645. else
  646. InternalError(777003);
  647. end;
  648. end;
  649. until false;
  650. calcsize:=len;
  651. end;
  652. procedure taicpu.loadcaddr(opidx:longint;aReg:TRegister;cnst:Integer);
  653. begin
  654. if opidx>=ops
  655. then
  656. ops:=opidx+1;
  657. with oper[opidx] do
  658. begin
  659. typ:=top_caddr;
  660. regb:=aReg;
  661. const13:=cnst;
  662. end;
  663. end;
  664. procedure taicpu.loadraddr(opidx:longint;rg1,rg2:TRegister);
  665. begin
  666. if opidx>=ops
  667. then
  668. ops:=opidx+1;
  669. with oper[opidx] do
  670. begin
  671. typ:=top_caddr;
  672. reg1:=rg1;
  673. reg2:=rg2;
  674. end;
  675. end;
  676. procedure DoneAsm;
  677. begin
  678. end;
  679. procedure InitAsm;
  680. begin
  681. end;
  682. end.
  683. {
  684. $Log$
  685. Revision 1.23 2003-05-06 20:27:43 mazen
  686. * A_BI changed to A_BL
  687. Revision 1.22 2003/05/06 15:00:36 mazen
  688. - non used code removed to bring up with powerpc changes
  689. Revision 1.21 2003/04/29 11:06:15 mazen
  690. * test of invalid opcode/operand combination gives internal error
  691. Revision 1.20 2003/04/28 09:40:47 mazen
  692. * Debug message in SetCondition more explicit.
  693. Revision 1.19 2003/03/15 22:51:58 mazen
  694. * remaking sparc rtl compile
  695. Revision 1.18 2003/03/10 21:59:54 mazen
  696. * fixing index overflow in handling new registers arrays.
  697. Revision 1.17 2003/02/18 22:00:20 mazen
  698. * asm condition generation modified by TAiCpu.SetCondition
  699. Revision 1.16 2003/01/08 18:43:58 daniel
  700. * Tregister changed into a record
  701. Revision 1.15 2003/01/05 21:32:35 mazen
  702. * fixing several bugs compiling the RTL
  703. Revision 1.14 2002/12/14 15:02:03 carl
  704. * maxoperands -> max_operands (for portability in rautils.pas)
  705. * fix some range-check errors with loadconst
  706. + add ncgadd unit to m68k
  707. * some bugfix of a_param_reg with LOC_CREFERENCE
  708. Revision 1.13 2002/11/17 16:32:04 carl
  709. * memory optimization (3-4%) : cleanup of tai fields,
  710. cleanup of tdef and tsym fields.
  711. * make it work for m68k
  712. Revision 1.12 2002/11/10 19:07:46 mazen
  713. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  714. Revision 1.11 2002/11/06 11:31:24 mazen
  715. * op_reg_reg_reg don't need any more a TOpSize parameter
  716. Revision 1.10 2002/11/05 16:15:00 mazen
  717. *** empty log message ***
  718. Revision 1.9 2002/10/28 20:59:17 mazen
  719. * TOpSize values changed S_L --> S_SW
  720. Revision 1.8 2002/10/22 13:43:01 mazen
  721. - cga.pas redueced to an empty unit
  722. Revision 1.7 2002/10/20 19:01:38 mazen
  723. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  724. Revision 1.6 2002/10/19 20:35:07 mazen
  725. * carl's patch applied
  726. Revision 1.5 2002/10/15 09:00:28 mazen
  727. * sone coding style modified
  728. Revision 1.4 2002/10/13 21:46:07 mazen
  729. * assembler output format fixed
  730. }