cpuasm.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
  4. Contains the assembler object for the i386
  5. * This code was inspired by the NASM sources
  6. The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  7. Julian Hall. All rights reserved.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************
  20. }
  21. unit cpuasm;
  22. {$i defines.inc}
  23. { Optimize addressing and skip already passed nodes }
  24. {$ifndef NASMDEBUG}
  25. {$define OPTEA}
  26. {$define PASS2FLAG}
  27. {$endif ndef NASMDEBUG}
  28. { Give warnings when an immediate is found in the reference struct }
  29. {.$define REF_IMMEDIATE_WARN}
  30. interface
  31. uses
  32. cclasses,tainst,
  33. aasm,globals,verbose,
  34. cpubase;
  35. const
  36. MaxPrefixes=4;
  37. type
  38. TOperandOrder = (op_intel,op_att);
  39. { alignment for operator }
  40. tai_align = class(tai_align_abstract)
  41. reg : tregister;
  42. constructor create(b:byte);
  43. constructor create_op(b: byte; _op: byte);
  44. function getfillbuf:pchar;
  45. end;
  46. taicpu = class(tainstruction)
  47. opsize : topsize;
  48. constructor op_none(op : tasmop;_size : topsize);
  49. constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  50. constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
  51. constructor op_ref(op : tasmop;_size : topsize;_op1 : preference);
  52. constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  53. constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
  54. constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
  55. constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
  56. constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
  57. constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
  58. constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
  59. { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
  60. constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
  61. constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  62. constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
  63. constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
  64. constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : preference);
  65. constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
  66. { this is for Jmp instructions }
  67. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  68. constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  69. constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  70. constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  71. constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
  72. procedure changeopsize(siz:topsize);
  73. function GetString:string;
  74. procedure CheckNonCommutativeOpcodes;
  75. private
  76. FOperandOrder : TOperandOrder;
  77. procedure init(_size : topsize); { this need to be called by all constructor }
  78. {$ifndef NOAG386BIN}
  79. public
  80. { the next will reset all instructions that can change in pass 2 }
  81. procedure ResetPass1;
  82. procedure ResetPass2;
  83. function CheckIfValid:boolean;
  84. function Pass1(offset:longint):longint;virtual;
  85. procedure Pass2;virtual;
  86. procedure SetOperandOrder(order:TOperandOrder);
  87. private
  88. { next fields are filled in pass1, so pass2 is faster }
  89. insentry : PInsEntry;
  90. insoffset,
  91. inssize : longint;
  92. LastInsOffset : longint; { need to be public to be reset }
  93. function InsEnd:longint;
  94. procedure create_ot;
  95. function Matches(p:PInsEntry):longint;
  96. function calcsize(p:PInsEntry):longint;
  97. procedure gencode;
  98. function NeedAddrPrefix(opidx:byte):boolean;
  99. procedure Swatoperands;
  100. {$endif NOAG386BIN}
  101. end;
  102. implementation
  103. uses
  104. cutils,
  105. ogbase;
  106. {****************************************************************************
  107. TAI_ALIGN
  108. ****************************************************************************}
  109. constructor tai_align.create(b: byte);
  110. begin
  111. inherited create(b);
  112. reg := R_ECX;
  113. end;
  114. constructor tai_align.create_op(b: byte; _op: byte);
  115. begin
  116. inherited create_op(b,_op);
  117. reg := R_NO;
  118. end;
  119. function tai_align.getfillbuf:pchar;
  120. const
  121. alignarray:array[0..5] of string[8]=(
  122. #$8D#$B4#$26#$00#$00#$00#$00,
  123. #$8D#$B6#$00#$00#$00#$00,
  124. #$8D#$74#$26#$00,
  125. #$8D#$76#$00,
  126. #$89#$F6,
  127. #$90
  128. );
  129. var
  130. bufptr : pchar;
  131. j : longint;
  132. begin
  133. if not use_op then
  134. begin
  135. bufptr:=@buf;
  136. while (fillsize>0) do
  137. begin
  138. for j:=0 to 5 do
  139. if (fillsize>=length(alignarray[j])) then
  140. break;
  141. move(alignarray[j][1],bufptr^,length(alignarray[j]));
  142. inc(bufptr,length(alignarray[j]));
  143. dec(fillsize,length(alignarray[j]));
  144. end;
  145. end;
  146. getfillbuf:=pchar(@buf);
  147. end;
  148. {*****************************************************************************
  149. Taicpu Constructors
  150. *****************************************************************************}
  151. procedure taicpu.changeopsize(siz:topsize);
  152. begin
  153. opsize:=siz;
  154. end;
  155. procedure taicpu.init(_size : topsize);
  156. begin
  157. { default order is att }
  158. FOperandOrder:=op_att;
  159. segprefix:=R_NO;
  160. opsize:=_size;
  161. {$ifndef NOAG386BIN}
  162. insentry:=nil;
  163. LastInsOffset:=-1;
  164. InsOffset:=0;
  165. InsSize:=0;
  166. {$endif}
  167. end;
  168. constructor taicpu.op_none(op : tasmop;_size : topsize);
  169. begin
  170. inherited create(op);
  171. init(_size);
  172. end;
  173. constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  174. begin
  175. inherited create(op);
  176. init(_size);
  177. ops:=1;
  178. loadreg(0,_op1);
  179. end;
  180. constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
  181. begin
  182. inherited create(op);
  183. init(_size);
  184. ops:=1;
  185. loadconst(0,_op1);
  186. end;
  187. constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : preference);
  188. begin
  189. inherited create(op);
  190. init(_size);
  191. ops:=1;
  192. loadref(0,_op1);
  193. end;
  194. constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  195. begin
  196. inherited create(op);
  197. init(_size);
  198. ops:=2;
  199. loadreg(0,_op1);
  200. loadreg(1,_op2);
  201. end;
  202. constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
  203. begin
  204. inherited create(op);
  205. init(_size);
  206. ops:=2;
  207. loadreg(0,_op1);
  208. loadconst(1,_op2);
  209. end;
  210. constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
  211. begin
  212. inherited create(op);
  213. init(_size);
  214. ops:=2;
  215. loadreg(0,_op1);
  216. loadref(1,_op2);
  217. end;
  218. constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
  219. begin
  220. inherited create(op);
  221. init(_size);
  222. ops:=2;
  223. loadconst(0,_op1);
  224. loadreg(1,_op2);
  225. end;
  226. constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
  227. begin
  228. inherited create(op);
  229. init(_size);
  230. ops:=2;
  231. loadconst(0,_op1);
  232. loadconst(1,_op2);
  233. end;
  234. constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
  235. begin
  236. inherited create(op);
  237. init(_size);
  238. ops:=2;
  239. loadconst(0,_op1);
  240. loadref(1,_op2);
  241. end;
  242. constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
  243. begin
  244. inherited create(op);
  245. init(_size);
  246. ops:=2;
  247. loadref(0,_op1);
  248. loadreg(1,_op2);
  249. end;
  250. constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
  251. begin
  252. inherited create(op);
  253. init(_size);
  254. ops:=2;
  255. loadref(0,_op1);
  256. loadref(1,_op2);
  257. end;
  258. constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  259. begin
  260. inherited create(op);
  261. init(_size);
  262. ops:=3;
  263. loadreg(0,_op1);
  264. loadreg(1,_op2);
  265. loadreg(2,_op3);
  266. end;
  267. constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
  268. begin
  269. inherited create(op);
  270. init(_size);
  271. ops:=3;
  272. loadconst(0,_op1);
  273. loadreg(1,_op2);
  274. loadreg(2,_op3);
  275. end;
  276. constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;_op3 : preference);
  277. begin
  278. inherited create(op);
  279. init(_size);
  280. ops:=3;
  281. loadreg(0,_op1);
  282. loadreg(1,_op2);
  283. loadref(2,_op3);
  284. end;
  285. constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
  286. begin
  287. inherited create(op);
  288. init(_size);
  289. ops:=3;
  290. loadconst(0,_op1);
  291. loadref(1,_op2);
  292. loadreg(2,_op3);
  293. end;
  294. constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
  295. begin
  296. inherited create(op);
  297. init(_size);
  298. ops:=3;
  299. loadconst(0,_op1);
  300. loadreg(1,_op2);
  301. loadref(2,_op3);
  302. end;
  303. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  304. begin
  305. inherited create(op);
  306. init(_size);
  307. condition:=cond;
  308. ops:=1;
  309. loadsymbol(0,_op1,0);
  310. end;
  311. constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  312. begin
  313. inherited create(op);
  314. init(_size);
  315. ops:=1;
  316. loadsymbol(0,_op1,0);
  317. end;
  318. constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  319. begin
  320. inherited create(op);
  321. init(_size);
  322. ops:=1;
  323. loadsymbol(0,_op1,_op1ofs);
  324. end;
  325. constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  326. begin
  327. inherited create(op);
  328. init(_size);
  329. ops:=2;
  330. loadsymbol(0,_op1,_op1ofs);
  331. loadreg(1,_op2);
  332. end;
  333. constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
  334. begin
  335. inherited create(op);
  336. init(_size);
  337. ops:=2;
  338. loadsymbol(0,_op1,_op1ofs);
  339. loadref(1,_op2);
  340. end;
  341. function taicpu.GetString:string;
  342. var
  343. i : longint;
  344. s : string;
  345. addsize : boolean;
  346. begin
  347. s:='['+int_op2str[opcode];
  348. for i:=1to ops do
  349. begin
  350. if i=1 then
  351. s:=s+' '
  352. else
  353. s:=s+',';
  354. { type }
  355. addsize:=false;
  356. if (oper[i-1].ot and OT_XMMREG)=OT_XMMREG then
  357. s:=s+'xmmreg'
  358. else
  359. if (oper[i-1].ot and OT_MMXREG)=OT_MMXREG then
  360. s:=s+'mmxreg'
  361. else
  362. if (oper[i-1].ot and OT_FPUREG)=OT_FPUREG then
  363. s:=s+'fpureg'
  364. else
  365. if (oper[i-1].ot and OT_REGISTER)=OT_REGISTER then
  366. begin
  367. s:=s+'reg';
  368. addsize:=true;
  369. end
  370. else
  371. if (oper[i-1].ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  372. begin
  373. s:=s+'imm';
  374. addsize:=true;
  375. end
  376. else
  377. if (oper[i-1].ot and OT_MEMORY)=OT_MEMORY then
  378. begin
  379. s:=s+'mem';
  380. addsize:=true;
  381. end
  382. else
  383. s:=s+'???';
  384. { size }
  385. if addsize then
  386. begin
  387. if (oper[i-1].ot and OT_BITS8)<>0 then
  388. s:=s+'8'
  389. else
  390. if (oper[i-1].ot and OT_BITS16)<>0 then
  391. s:=s+'16'
  392. else
  393. if (oper[i-1].ot and OT_BITS32)<>0 then
  394. s:=s+'32'
  395. else
  396. s:=s+'??';
  397. { signed }
  398. if (oper[i-1].ot and OT_SIGNED)<>0 then
  399. s:=s+'s';
  400. end;
  401. end;
  402. GetString:=s+']';
  403. end;
  404. procedure taicpu.Swatoperands;
  405. var
  406. p : TOper;
  407. begin
  408. { Fix the operands which are in AT&T style and we need them in Intel style }
  409. case ops of
  410. 2 : begin
  411. { 0,1 -> 1,0 }
  412. p:=oper[0];
  413. oper[0]:=oper[1];
  414. oper[1]:=p;
  415. end;
  416. 3 : begin
  417. { 0,1,2 -> 2,1,0 }
  418. p:=oper[0];
  419. oper[0]:=oper[2];
  420. oper[2]:=p;
  421. end;
  422. end;
  423. end;
  424. procedure taicpu.SetOperandOrder(order:TOperandOrder);
  425. begin
  426. if FOperandOrder<>order then
  427. begin
  428. Swatoperands;
  429. FOperandOrder:=order;
  430. end;
  431. end;
  432. { This check must be done with the operand in ATT order
  433. i.e.after swapping in the intel reader
  434. but before swapping in the NASM and TASM writers PM }
  435. procedure taicpu.CheckNonCommutativeOpcodes;
  436. begin
  437. if ((ops=2) and
  438. (oper[0].typ=top_reg) and
  439. (oper[1].typ=top_reg) and
  440. { if the first is ST and the second is also a register
  441. it is necessarily ST1 .. ST7 }
  442. (oper[0].reg=R_ST)) or
  443. { ((ops=1) and
  444. (oper[0].typ=top_reg) and
  445. (oper[0].reg in [R_ST1..R_ST7])) or}
  446. (ops=0) then
  447. if opcode=A_FSUBR then
  448. opcode:=A_FSUB
  449. else if opcode=A_FSUB then
  450. opcode:=A_FSUBR
  451. else if opcode=A_FDIVR then
  452. opcode:=A_FDIV
  453. else if opcode=A_FDIV then
  454. opcode:=A_FDIVR
  455. else if opcode=A_FSUBRP then
  456. opcode:=A_FSUBP
  457. else if opcode=A_FSUBP then
  458. opcode:=A_FSUBRP
  459. else if opcode=A_FDIVRP then
  460. opcode:=A_FDIVP
  461. else if opcode=A_FDIVP then
  462. opcode:=A_FDIVRP;
  463. if ((ops=1) and
  464. (oper[0].typ=top_reg) and
  465. (oper[0].reg in [R_ST1..R_ST7])) then
  466. if opcode=A_FSUBRP then
  467. opcode:=A_FSUBP
  468. else if opcode=A_FSUBP then
  469. opcode:=A_FSUBRP
  470. else if opcode=A_FDIVRP then
  471. opcode:=A_FDIVP
  472. else if opcode=A_FDIVP then
  473. opcode:=A_FDIVRP;
  474. end;
  475. {*****************************************************************************
  476. Assembler
  477. *****************************************************************************}
  478. {$ifndef NOAG386BIN}
  479. type
  480. ea=packed record
  481. sib_present : boolean;
  482. bytes : byte;
  483. size : byte;
  484. modrm : byte;
  485. sib : byte;
  486. end;
  487. procedure taicpu.create_ot;
  488. {
  489. this function will also fix some other fields which only needs to be once
  490. }
  491. var
  492. i,l,relsize : longint;
  493. begin
  494. if ops=0 then
  495. exit;
  496. { update oper[].ot field }
  497. for i:=0 to ops-1 do
  498. with oper[i] do
  499. begin
  500. case typ of
  501. top_reg :
  502. ot:=reg_2_type[reg];
  503. top_ref :
  504. begin
  505. { create ot field }
  506. if (ot and OT_SIZE_MASK)=0 then
  507. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  508. else
  509. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  510. if (ref^.base=R_NO) and (ref^.index=R_NO) then
  511. ot:=ot or OT_MEM_OFFS;
  512. { fix scalefactor }
  513. if (ref^.index=R_NO) then
  514. ref^.scalefactor:=0
  515. else
  516. if (ref^.scalefactor=0) then
  517. ref^.scalefactor:=1;
  518. end;
  519. top_const :
  520. begin
  521. if (opsize<>S_W) and (val>=-128) and (val<=127) then
  522. ot:=OT_IMM8 or OT_SIGNED
  523. else
  524. ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
  525. end;
  526. top_symbol :
  527. begin
  528. if LastInsOffset=-1 then
  529. l:=0
  530. else
  531. l:=InsOffset-LastInsOffset;
  532. inc(l,symofs);
  533. if assigned(sym) then
  534. inc(l,sym.address);
  535. { instruction size will then always become 2 (PFV) }
  536. relsize:=(InsOffset+2)-l;
  537. if (not assigned(sym) or
  538. ((sym.bind<>AB_EXTERNAL) and (sym.address<>0))) and
  539. (relsize>=-128) and (relsize<=127) then
  540. ot:=OT_IMM32 or OT_SHORT
  541. else
  542. ot:=OT_IMM32 or OT_NEAR;
  543. end;
  544. end;
  545. end;
  546. end;
  547. function taicpu.InsEnd:longint;
  548. begin
  549. InsEnd:=InsOffset+InsSize;
  550. end;
  551. function taicpu.Matches(p:PInsEntry):longint;
  552. { * IF_SM stands for Size Match: any operand whose size is not
  553. * explicitly specified by the template is `really' intended to be
  554. * the same size as the first size-specified operand.
  555. * Non-specification is tolerated in the input instruction, but
  556. * _wrong_ specification is not.
  557. *
  558. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  559. * three-operand instructions such as SHLD: it implies that the
  560. * first two operands must match in size, but that the third is
  561. * required to be _unspecified_.
  562. *
  563. * IF_SB invokes Size Byte: operands with unspecified size in the
  564. * template are really bytes, and so no non-byte specification in
  565. * the input instruction will be tolerated. IF_SW similarly invokes
  566. * Size Word, and IF_SD invokes Size Doubleword.
  567. *
  568. * (The default state if neither IF_SM nor IF_SM2 is specified is
  569. * that any operand with unspecified size in the template is
  570. * required to have unspecified size in the instruction too...)
  571. }
  572. var
  573. i,j,asize,oprs : longint;
  574. siz : array[0..2] of longint;
  575. begin
  576. Matches:=100;
  577. { Check the opcode and operands }
  578. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  579. begin
  580. Matches:=0;
  581. exit;
  582. end;
  583. { Check that no spurious colons or TOs are present }
  584. for i:=0 to p^.ops-1 do
  585. if (oper[i].ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  586. begin
  587. Matches:=0;
  588. exit;
  589. end;
  590. { Check that the operand flags all match up }
  591. for i:=0 to p^.ops-1 do
  592. begin
  593. if ((p^.optypes[i] and (not oper[i].ot)) or
  594. ((p^.optypes[i] and OT_SIZE_MASK) and
  595. ((p^.optypes[i] xor oper[i].ot) and OT_SIZE_MASK)))<>0 then
  596. begin
  597. if ((p^.optypes[i] and (not oper[i].ot) and OT_NON_SIZE) or
  598. (oper[i].ot and OT_SIZE_MASK))<>0 then
  599. begin
  600. Matches:=0;
  601. exit;
  602. end
  603. else
  604. Matches:=1;
  605. end;
  606. end;
  607. { Check operand sizes }
  608. { as default an untyped size can get all the sizes, this is different
  609. from nasm, but else we need to do a lot checking which opcodes want
  610. size or not with the automatic size generation }
  611. asize:=longint($ffffffff);
  612. if (p^.flags and IF_SB)<>0 then
  613. asize:=OT_BITS8
  614. else if (p^.flags and IF_SW)<>0 then
  615. asize:=OT_BITS16
  616. else if (p^.flags and IF_SD)<>0 then
  617. asize:=OT_BITS32;
  618. if (p^.flags and IF_ARMASK)<>0 then
  619. begin
  620. siz[0]:=0;
  621. siz[1]:=0;
  622. siz[2]:=0;
  623. if (p^.flags and IF_AR0)<>0 then
  624. siz[0]:=asize
  625. else if (p^.flags and IF_AR1)<>0 then
  626. siz[1]:=asize
  627. else if (p^.flags and IF_AR2)<>0 then
  628. siz[2]:=asize;
  629. end
  630. else
  631. begin
  632. { we can leave because the size for all operands is forced to be
  633. the same
  634. but not if IF_SB IF_SW or IF_SD is set PM }
  635. if asize=-1 then
  636. exit;
  637. siz[0]:=asize;
  638. siz[1]:=asize;
  639. siz[2]:=asize;
  640. end;
  641. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  642. begin
  643. if (p^.flags and IF_SM2)<>0 then
  644. oprs:=2
  645. else
  646. oprs:=p^.ops;
  647. for i:=0 to oprs-1 do
  648. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  649. begin
  650. for j:=0 to oprs-1 do
  651. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  652. break;
  653. end;
  654. end
  655. else
  656. oprs:=2;
  657. { Check operand sizes }
  658. for i:=0 to p^.ops-1 do
  659. begin
  660. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  661. ((oper[i].ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  662. { Immediates can always include smaller size }
  663. ((oper[i].ot and OT_IMMEDIATE)=0) and
  664. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i].ot and OT_SIZE_MASK)) then
  665. Matches:=2;
  666. end;
  667. end;
  668. procedure taicpu.ResetPass1;
  669. begin
  670. { we need to reset everything here, because the choosen insentry
  671. can be invalid for a new situation where the previously optimized
  672. insentry is not correct }
  673. InsEntry:=nil;
  674. InsSize:=0;
  675. LastInsOffset:=-1;
  676. end;
  677. procedure taicpu.ResetPass2;
  678. begin
  679. { we are here in a second pass, check if the instruction can be optimized }
  680. if assigned(InsEntry) and
  681. ((InsEntry^.flags and IF_PASS2)<>0) then
  682. begin
  683. InsEntry:=nil;
  684. InsSize:=0;
  685. end;
  686. LastInsOffset:=-1;
  687. end;
  688. function taicpu.CheckIfValid:boolean;
  689. var
  690. m,i : longint;
  691. begin
  692. CheckIfValid:=false;
  693. { Things which may only be done once, not when a second pass is done to
  694. optimize }
  695. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  696. begin
  697. { We need intel style operands }
  698. SetOperandOrder(op_intel);
  699. { create the .ot fields }
  700. create_ot;
  701. { set the file postion }
  702. aktfilepos:=fileinfo;
  703. end
  704. else
  705. begin
  706. { we've already an insentry so it's valid }
  707. CheckIfValid:=true;
  708. exit;
  709. end;
  710. { Lookup opcode in the table }
  711. InsSize:=-1;
  712. i:=instabcache^[opcode];
  713. if i=-1 then
  714. begin
  715. {$ifdef TP}
  716. Message1(asmw_e_opcode_not_in_table,'');
  717. {$else}
  718. Message1(asmw_e_opcode_not_in_table,att_op2str[opcode]);
  719. {$endif}
  720. exit;
  721. end;
  722. insentry:=@instab[i];
  723. while (insentry^.opcode=opcode) do
  724. begin
  725. m:=matches(insentry);
  726. if m=100 then
  727. begin
  728. InsSize:=calcsize(insentry);
  729. if (segprefix<>R_NO) then
  730. inc(InsSize);
  731. { For opsize if size if forced }
  732. if (insentry^.flags and (IF_SB or IF_SW or IF_SD))<>0 then
  733. begin
  734. if (insentry^.flags and IF_ARMASK)=0 then
  735. begin
  736. if (insentry^.flags and IF_SB)<>0 then
  737. begin
  738. if opsize=S_NO then
  739. opsize:=S_B;
  740. end
  741. else if (insentry^.flags and IF_SW)<>0 then
  742. begin
  743. if opsize=S_NO then
  744. opsize:=S_W;
  745. end
  746. else if (insentry^.flags and IF_SD)<>0 then
  747. begin
  748. if opsize=S_NO then
  749. opsize:=S_L;
  750. end;
  751. end;
  752. end;
  753. CheckIfValid:=true;
  754. exit;
  755. end;
  756. inc(i);
  757. insentry:=@instab[i];
  758. end;
  759. if insentry^.opcode<>opcode then
  760. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  761. { No instruction found, set insentry to nil and inssize to -1 }
  762. insentry:=nil;
  763. inssize:=-1;
  764. end;
  765. function taicpu.Pass1(offset:longint):longint;
  766. begin
  767. Pass1:=0;
  768. { Save the old offset and set the new offset }
  769. InsOffset:=Offset;
  770. { Things which may only be done once, not when a second pass is done to
  771. optimize }
  772. if Insentry=nil then
  773. begin
  774. { Check if error last time then InsSize=-1 }
  775. if InsSize=-1 then
  776. exit;
  777. { set the file postion }
  778. aktfilepos:=fileinfo;
  779. end
  780. else
  781. begin
  782. {$ifdef PASS2FLAG}
  783. { we are here in a second pass, check if the instruction can be optimized }
  784. if (InsEntry^.flags and IF_PASS2)=0 then
  785. begin
  786. Pass1:=InsSize;
  787. exit;
  788. end;
  789. { update the .ot fields, some top_const can be updated }
  790. create_ot;
  791. {$endif}
  792. end;
  793. { Check if it's a valid instruction }
  794. if CheckIfValid then
  795. begin
  796. LastInsOffset:=InsOffset;
  797. Pass1:=InsSize;
  798. exit;
  799. end;
  800. LastInsOffset:=-1;
  801. end;
  802. procedure taicpu.Pass2;
  803. var
  804. c : longint;
  805. begin
  806. { error in pass1 ? }
  807. if insentry=nil then
  808. exit;
  809. aktfilepos:=fileinfo;
  810. { Segment override }
  811. if (segprefix<>R_NO) then
  812. begin
  813. case segprefix of
  814. R_CS : c:=$2e;
  815. R_DS : c:=$3e;
  816. R_ES : c:=$26;
  817. R_FS : c:=$64;
  818. R_GS : c:=$65;
  819. R_SS : c:=$36;
  820. end;
  821. objectdata.writebytes(c,1);
  822. { fix the offset for GenNode }
  823. inc(InsOffset);
  824. end;
  825. { Generate the instruction }
  826. GenCode;
  827. end;
  828. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  829. var
  830. i,b : tregister;
  831. begin
  832. if (OT_MEMORY and (not oper[opidx].ot))=0 then
  833. begin
  834. i:=oper[opidx].ref^.index;
  835. b:=oper[opidx].ref^.base;
  836. if not(i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) or
  837. not(b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) then
  838. begin
  839. NeedAddrPrefix:=true;
  840. exit;
  841. end;
  842. end;
  843. NeedAddrPrefix:=false;
  844. end;
  845. function regval(r:tregister):byte;
  846. begin
  847. case r of
  848. R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0,R_XMM0 :
  849. regval:=0;
  850. R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1,R_XMM1 :
  851. regval:=1;
  852. R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2,R_XMM2 :
  853. regval:=2;
  854. R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3,R_XMM3 :
  855. regval:=3;
  856. R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4,R_XMM4 :
  857. regval:=4;
  858. R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5,R_XMM5 :
  859. regval:=5;
  860. R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6,R_XMM6 :
  861. regval:=6;
  862. R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7,R_XMM7 :
  863. regval:=7;
  864. else
  865. begin
  866. internalerror(777001);
  867. regval:=0;
  868. end;
  869. end;
  870. end;
  871. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  872. const
  873. regs : array[0..63] of tregister=(
  874. R_MM0, R_EAX, R_AX, R_AL, R_XMM0, R_NO, R_NO, R_NO,
  875. R_MM1, R_ECX, R_CX, R_CL, R_XMM1, R_NO, R_NO, R_NO,
  876. R_MM2, R_EDX, R_DX, R_DL, R_XMM2, R_NO, R_NO, R_NO,
  877. R_MM3, R_EBX, R_BX, R_BL, R_XMM3, R_NO, R_NO, R_NO,
  878. R_MM4, R_ESP, R_SP, R_AH, R_XMM4, R_NO, R_NO, R_NO,
  879. R_MM5, R_EBP, R_BP, R_CH, R_XMM5, R_NO, R_NO, R_NO,
  880. R_MM6, R_ESI, R_SI, R_DH, R_XMM6, R_NO, R_NO, R_NO,
  881. R_MM7, R_EDI, R_DI, R_BH, R_XMM7, R_NO, R_NO, R_NO
  882. );
  883. var
  884. j : longint;
  885. i,b : tregister;
  886. sym : tasmsymbol;
  887. md,s : byte;
  888. base,index,scalefactor,
  889. o : longint;
  890. begin
  891. process_ea:=false;
  892. { register ? }
  893. if (input.typ=top_reg) then
  894. begin
  895. j:=0;
  896. while (j<=high(regs)) do
  897. begin
  898. if input.reg=regs[j] then
  899. break;
  900. inc(j);
  901. end;
  902. if j<=high(regs) then
  903. begin
  904. output.sib_present:=false;
  905. output.bytes:=0;
  906. output.modrm:=$c0 or (rfield shl 3) or (j shr 3);
  907. output.size:=1;
  908. process_ea:=true;
  909. end;
  910. exit;
  911. end;
  912. { memory reference }
  913. i:=input.ref^.index;
  914. b:=input.ref^.base;
  915. s:=input.ref^.scalefactor;
  916. o:=input.ref^.offset+input.ref^.offsetfixup;
  917. sym:=input.ref^.symbol;
  918. { it's direct address }
  919. if (b=R_NO) and (i=R_NO) then
  920. begin
  921. { it's a pure offset }
  922. output.sib_present:=false;
  923. output.bytes:=4;
  924. output.modrm:=5 or (rfield shl 3);
  925. end
  926. else
  927. { it's an indirection }
  928. begin
  929. { 16 bit address? }
  930. if not((i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) and
  931. (b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI])) then
  932. Message(asmw_e_16bit_not_supported);
  933. {$ifdef OPTEA}
  934. { make single reg base }
  935. if (b=R_NO) and (s=1) then
  936. begin
  937. b:=i;
  938. i:=R_NO;
  939. end;
  940. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  941. if (b=R_NO) and
  942. (((s=2) and (i<>R_ESP)) or
  943. (s=3) or (s=5) or (s=9)) then
  944. begin
  945. b:=i;
  946. dec(s);
  947. end;
  948. { swap ESP into base if scalefactor is 1 }
  949. if (s=1) and (i=R_ESP) then
  950. begin
  951. i:=b;
  952. b:=R_ESP;
  953. end;
  954. {$endif}
  955. { wrong, for various reasons }
  956. if (i=R_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (i<>R_NO)) then
  957. exit;
  958. { base }
  959. case b of
  960. R_EAX : base:=0;
  961. R_ECX : base:=1;
  962. R_EDX : base:=2;
  963. R_EBX : base:=3;
  964. R_ESP : base:=4;
  965. R_NO,
  966. R_EBP : base:=5;
  967. R_ESI : base:=6;
  968. R_EDI : base:=7;
  969. else
  970. exit;
  971. end;
  972. { index }
  973. case i of
  974. R_EAX : index:=0;
  975. R_ECX : index:=1;
  976. R_EDX : index:=2;
  977. R_EBX : index:=3;
  978. R_NO : index:=4;
  979. R_EBP : index:=5;
  980. R_ESI : index:=6;
  981. R_EDI : index:=7;
  982. else
  983. exit;
  984. end;
  985. case s of
  986. 0,
  987. 1 : scalefactor:=0;
  988. 2 : scalefactor:=1;
  989. 4 : scalefactor:=2;
  990. 8 : scalefactor:=3;
  991. else
  992. exit;
  993. end;
  994. if (b=R_NO) or
  995. ((b<>R_EBP) and (o=0) and (sym=nil)) then
  996. md:=0
  997. else
  998. if ((o>=-128) and (o<=127) and (sym=nil)) then
  999. md:=1
  1000. else
  1001. md:=2;
  1002. if (b=R_NO) or (md=2) then
  1003. output.bytes:=4
  1004. else
  1005. output.bytes:=md;
  1006. { SIB needed ? }
  1007. if (i=R_NO) and (b<>R_ESP) then
  1008. begin
  1009. output.sib_present:=false;
  1010. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  1011. end
  1012. else
  1013. begin
  1014. output.sib_present:=true;
  1015. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  1016. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  1017. end;
  1018. end;
  1019. if output.sib_present then
  1020. output.size:=2+output.bytes
  1021. else
  1022. output.size:=1+output.bytes;
  1023. process_ea:=true;
  1024. end;
  1025. function taicpu.calcsize(p:PInsEntry):longint;
  1026. var
  1027. codes : pchar;
  1028. c : byte;
  1029. len : longint;
  1030. ea_data : ea;
  1031. begin
  1032. len:=0;
  1033. codes:=@p^.code;
  1034. repeat
  1035. c:=ord(codes^);
  1036. inc(codes);
  1037. case c of
  1038. 0 :
  1039. break;
  1040. 1,2,3 :
  1041. begin
  1042. inc(codes,c);
  1043. inc(len,c);
  1044. end;
  1045. 8,9,10 :
  1046. begin
  1047. inc(codes);
  1048. inc(len);
  1049. end;
  1050. 4,5,6,7 :
  1051. begin
  1052. if opsize=S_W then
  1053. inc(len,2)
  1054. else
  1055. inc(len);
  1056. end;
  1057. 15,
  1058. 12,13,14,
  1059. 16,17,18,
  1060. 20,21,22,
  1061. 40,41,42 :
  1062. inc(len);
  1063. 24,25,26,
  1064. 31,
  1065. 48,49,50 :
  1066. inc(len,2);
  1067. 28,29,30, { we don't have 16 bit immediates code }
  1068. 32,33,34,
  1069. 52,53,54,
  1070. 56,57,58 :
  1071. inc(len,4);
  1072. 192,193,194 :
  1073. if NeedAddrPrefix(c-192) then
  1074. inc(len);
  1075. 208 :
  1076. inc(len);
  1077. 200,
  1078. 201,
  1079. 202,
  1080. 209,
  1081. 210,
  1082. 217,218,219 : ;
  1083. 216 :
  1084. begin
  1085. inc(codes);
  1086. inc(len);
  1087. end;
  1088. 224,225,226 :
  1089. begin
  1090. InternalError(777002);
  1091. end;
  1092. else
  1093. begin
  1094. if (c>=64) and (c<=191) then
  1095. begin
  1096. if not process_ea(oper[(c shr 3) and 7], ea_data, 0) then
  1097. Message(asmw_e_invalid_effective_address)
  1098. else
  1099. inc(len,ea_data.size);
  1100. end
  1101. else
  1102. InternalError(777003);
  1103. end;
  1104. end;
  1105. until false;
  1106. calcsize:=len;
  1107. end;
  1108. procedure taicpu.GenCode;
  1109. {
  1110. * the actual codes (C syntax, i.e. octal):
  1111. * \0 - terminates the code. (Unless it's a literal of course.)
  1112. * \1, \2, \3 - that many literal bytes follow in the code stream
  1113. * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  1114. * (POP is never used for CS) depending on operand 0
  1115. * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
  1116. * on operand 0
  1117. * \10, \11, \12 - a literal byte follows in the code stream, to be added
  1118. * to the register value of operand 0, 1 or 2
  1119. * \17 - encodes the literal byte 0. (Some compilers don't take
  1120. * kindly to a zero byte in the _middle_ of a compile time
  1121. * string constant, so I had to put this hack in.)
  1122. * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  1123. * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  1124. * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
  1125. * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  1126. * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  1127. * assembly mode or the address-size override on the operand
  1128. * \37 - a word constant, from the _segment_ part of operand 0
  1129. * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  1130. * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  1131. * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  1132. * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  1133. * assembly mode or the address-size override on the operand
  1134. * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  1135. * \1ab - a ModRM, calculated on EA in operand a, with the spare
  1136. * field the register value of operand b.
  1137. * \2ab - a ModRM, calculated on EA in operand a, with the spare
  1138. * field equal to digit b.
  1139. * \30x - might be an 0x67 byte, depending on the address size of
  1140. * the memory reference in operand x.
  1141. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
  1142. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
  1143. * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
  1144. * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
  1145. * \322 - indicates that this instruction is only valid when the
  1146. * operand size is the default (instruction to disassembler,
  1147. * generates no code in the assembler)
  1148. * \330 - a literal byte follows in the code stream, to be added
  1149. * to the condition code value of the instruction.
  1150. * \340 - reserve <operand 0> bytes of uninitialised storage.
  1151. * Operand 0 had better be a segmentless constant.
  1152. }
  1153. var
  1154. currval : longint;
  1155. currsym : tasmsymbol;
  1156. procedure getvalsym(opidx:longint);
  1157. begin
  1158. case oper[opidx].typ of
  1159. top_ref :
  1160. begin
  1161. currval:=oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup;
  1162. currsym:=oper[opidx].ref^.symbol;
  1163. end;
  1164. top_const :
  1165. begin
  1166. currval:=oper[opidx].val;
  1167. currsym:=nil;
  1168. end;
  1169. top_symbol :
  1170. begin
  1171. currval:=oper[opidx].symofs;
  1172. currsym:=oper[opidx].sym;
  1173. end;
  1174. else
  1175. Message(asmw_e_immediate_or_reference_expected);
  1176. end;
  1177. end;
  1178. const
  1179. CondVal:array[TAsmCond] of byte=($0,
  1180. $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
  1181. $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
  1182. $0, $A, $A, $B, $8, $4);
  1183. var
  1184. c : byte;
  1185. pb,
  1186. codes : pchar;
  1187. bytes : array[0..3] of byte;
  1188. rfield,
  1189. data,s,opidx : longint;
  1190. ea_data : ea;
  1191. begin
  1192. {$ifdef EXTDEBUG}
  1193. { safety check }
  1194. if objectdata.currsectionsize<>insoffset then
  1195. internalerror(200130121);
  1196. {$endif EXTDEBUG}
  1197. { load data to write }
  1198. codes:=insentry^.code;
  1199. { Force word push/pop for registers }
  1200. if (opsize=S_W) and ((codes[0]=#4) or (codes[0]=#6) or
  1201. ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
  1202. begin
  1203. bytes[0]:=$66;
  1204. objectdata.writebytes(bytes,1);
  1205. end;
  1206. repeat
  1207. c:=ord(codes^);
  1208. inc(codes);
  1209. case c of
  1210. 0 :
  1211. break;
  1212. 1,2,3 :
  1213. begin
  1214. objectdata.writebytes(codes^,c);
  1215. inc(codes,c);
  1216. end;
  1217. 4,6 :
  1218. begin
  1219. case oper[0].reg of
  1220. R_CS :
  1221. begin
  1222. if c=4 then
  1223. bytes[0]:=$f
  1224. else
  1225. bytes[0]:=$e;
  1226. end;
  1227. R_NO,
  1228. R_DS :
  1229. begin
  1230. if c=4 then
  1231. bytes[0]:=$1f
  1232. else
  1233. bytes[0]:=$1e;
  1234. end;
  1235. R_ES :
  1236. begin
  1237. if c=4 then
  1238. bytes[0]:=$7
  1239. else
  1240. bytes[0]:=$6;
  1241. end;
  1242. R_SS :
  1243. begin
  1244. if c=4 then
  1245. bytes[0]:=$17
  1246. else
  1247. bytes[0]:=$16;
  1248. end;
  1249. else
  1250. InternalError(777004);
  1251. end;
  1252. objectdata.writebytes(bytes,1);
  1253. end;
  1254. 5,7 :
  1255. begin
  1256. case oper[0].reg of
  1257. R_FS :
  1258. begin
  1259. if c=5 then
  1260. bytes[0]:=$a1
  1261. else
  1262. bytes[0]:=$a0;
  1263. end;
  1264. R_GS :
  1265. begin
  1266. if c=5 then
  1267. bytes[0]:=$a9
  1268. else
  1269. bytes[0]:=$a8;
  1270. end;
  1271. else
  1272. InternalError(777005);
  1273. end;
  1274. objectdata.writebytes(bytes,1);
  1275. end;
  1276. 8,9,10 :
  1277. begin
  1278. bytes[0]:=ord(codes^)+regval(oper[c-8].reg);
  1279. inc(codes);
  1280. objectdata.writebytes(bytes,1);
  1281. end;
  1282. 15 :
  1283. begin
  1284. bytes[0]:=0;
  1285. objectdata.writebytes(bytes,1);
  1286. end;
  1287. 12,13,14 :
  1288. begin
  1289. getvalsym(c-12);
  1290. if (currval<-128) or (currval>127) then
  1291. Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
  1292. if assigned(currsym) then
  1293. objectdata.writereloc(currval,1,currsym,relative_false)
  1294. else
  1295. objectdata.writebytes(currval,1);
  1296. end;
  1297. 16,17,18 :
  1298. begin
  1299. getvalsym(c-16);
  1300. if (currval<-256) or (currval>255) then
  1301. Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
  1302. if assigned(currsym) then
  1303. objectdata.writereloc(currval,1,currsym,relative_false)
  1304. else
  1305. objectdata.writebytes(currval,1);
  1306. end;
  1307. 20,21,22 :
  1308. begin
  1309. getvalsym(c-20);
  1310. if (currval<0) or (currval>255) then
  1311. Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
  1312. if assigned(currsym) then
  1313. objectdata.writereloc(currval,1,currsym,relative_false)
  1314. else
  1315. objectdata.writebytes(currval,1);
  1316. end;
  1317. 24,25,26 :
  1318. begin
  1319. getvalsym(c-24);
  1320. if (currval<-65536) or (currval>65535) then
  1321. Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
  1322. if assigned(currsym) then
  1323. objectdata.writereloc(currval,2,currsym,relative_false)
  1324. else
  1325. objectdata.writebytes(currval,2);
  1326. end;
  1327. 28,29,30 :
  1328. begin
  1329. getvalsym(c-28);
  1330. if assigned(currsym) then
  1331. objectdata.writereloc(currval,4,currsym,relative_false)
  1332. else
  1333. objectdata.writebytes(currval,4);
  1334. end;
  1335. 32,33,34 :
  1336. begin
  1337. getvalsym(c-32);
  1338. if assigned(currsym) then
  1339. objectdata.writereloc(currval,4,currsym,relative_false)
  1340. else
  1341. objectdata.writebytes(currval,4);
  1342. end;
  1343. 40,41,42 :
  1344. begin
  1345. getvalsym(c-40);
  1346. data:=currval-insend;
  1347. if assigned(currsym) then
  1348. inc(data,currsym.address);
  1349. if (data>127) or (data<-128) then
  1350. Message1(asmw_e_short_jmp_out_of_range,tostr(data));
  1351. objectdata.writebytes(data,1);
  1352. end;
  1353. 52,53,54 :
  1354. begin
  1355. getvalsym(c-52);
  1356. if assigned(currsym) then
  1357. objectdata.writereloc(currval,4,currsym,relative_true)
  1358. else
  1359. objectdata.writereloc(currval-insend,4,nil,relative_false)
  1360. end;
  1361. 56,57,58 :
  1362. begin
  1363. getvalsym(c-56);
  1364. if assigned(currsym) then
  1365. objectdata.writereloc(currval,4,currsym,relative_true)
  1366. else
  1367. objectdata.writereloc(currval-insend,4,nil,relative_false)
  1368. end;
  1369. 192,193,194 :
  1370. begin
  1371. if NeedAddrPrefix(c-192) then
  1372. begin
  1373. bytes[0]:=$67;
  1374. objectdata.writebytes(bytes,1);
  1375. end;
  1376. end;
  1377. 200 :
  1378. begin
  1379. bytes[0]:=$67;
  1380. objectdata.writebytes(bytes,1);
  1381. end;
  1382. 208 :
  1383. begin
  1384. bytes[0]:=$66;
  1385. objectdata.writebytes(bytes,1);
  1386. end;
  1387. 216 :
  1388. begin
  1389. bytes[0]:=ord(codes^)+condval[condition];
  1390. inc(codes);
  1391. objectdata.writebytes(bytes,1);
  1392. end;
  1393. 201,
  1394. 202,
  1395. 209,
  1396. 210,
  1397. 217,218,219 :
  1398. begin
  1399. { these are dissambler hints or 32 bit prefixes which
  1400. are not needed }
  1401. end;
  1402. 31,
  1403. 48,49,50,
  1404. 224,225,226 :
  1405. begin
  1406. InternalError(777006);
  1407. end
  1408. else
  1409. begin
  1410. if (c>=64) and (c<=191) then
  1411. begin
  1412. if (c<127) then
  1413. begin
  1414. if (oper[c and 7].typ=top_reg) then
  1415. rfield:=regval(oper[c and 7].reg)
  1416. else
  1417. rfield:=regval(oper[c and 7].ref^.base);
  1418. end
  1419. else
  1420. rfield:=c and 7;
  1421. opidx:=(c shr 3) and 7;
  1422. if not process_ea(oper[opidx], ea_data, rfield) then
  1423. Message(asmw_e_invalid_effective_address);
  1424. pb:=@bytes;
  1425. pb^:=chr(ea_data.modrm);
  1426. inc(pb);
  1427. if ea_data.sib_present then
  1428. begin
  1429. pb^:=chr(ea_data.sib);
  1430. inc(pb);
  1431. end;
  1432. s:=pb-pchar(@bytes);
  1433. objectdata.writebytes(bytes,s);
  1434. case ea_data.bytes of
  1435. 0 : ;
  1436. 1 :
  1437. begin
  1438. if (oper[opidx].ot and OT_MEMORY)=OT_MEMORY then
  1439. objectdata.writereloc(oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup,1,oper[opidx].ref^.symbol,relative_false)
  1440. else
  1441. begin
  1442. bytes[0]:=oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup;
  1443. objectdata.writebytes(bytes,1);
  1444. end;
  1445. inc(s);
  1446. end;
  1447. 2,4 :
  1448. begin
  1449. objectdata.writereloc(oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup,ea_data.bytes,
  1450. oper[opidx].ref^.symbol,relative_false);
  1451. inc(s,ea_data.bytes);
  1452. end;
  1453. end;
  1454. end
  1455. else
  1456. InternalError(777007);
  1457. end;
  1458. end;
  1459. until false;
  1460. end;
  1461. {$endif NOAG386BIN}
  1462. end.
  1463. {
  1464. $Log$
  1465. Revision 1.17 2001-12-31 16:59:43 peter
  1466. * protected/private symbols parsing fixed
  1467. Revision 1.16 2001/12/29 15:29:59 jonas
  1468. * powerpc/cgcpu.pas compiles :)
  1469. * several powerpc-related fixes
  1470. * cpuasm unit is now based on common tainst unit
  1471. + nppcmat unit for powerpc (almost complete)
  1472. Revision 1.15 2001/04/21 12:13:15 peter
  1473. * restore correct pass2 handling bug 1425 (merged)
  1474. Revision 1.14 2001/04/13 01:22:18 peter
  1475. * symtable change to classes
  1476. * range check generation and errors fixed, make cycle DEBUG=1 works
  1477. * memory leaks fixed
  1478. Revision 1.13 2001/04/05 21:33:45 peter
  1479. * movd and opsize fix merged
  1480. Revision 1.12 2001/03/25 12:29:45 peter
  1481. * offset_fixup fixes (merged)
  1482. Revision 1.11 2001/02/20 21:51:36 peter
  1483. * fpu fixes (merged)
  1484. Revision 1.10 2001/01/13 20:24:24 peter
  1485. * fixed operand order that got mixed up for external writers after
  1486. my previous assembler block valid instruction check
  1487. Revision 1.9 2001/01/12 19:18:42 peter
  1488. * check for valid asm instructions
  1489. Revision 1.8 2001/01/07 15:48:56 jonas
  1490. * references to symbols were only decreased in taicpu.done for jmps, fixed
  1491. Revision 1.7 2000/12/26 15:56:17 peter
  1492. * unrolled loops in taicpu.destroy
  1493. Revision 1.6 2000/12/25 00:07:31 peter
  1494. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1495. tlinkedlist objects)
  1496. Revision 1.5 2000/12/23 19:59:35 peter
  1497. * object to class for ow/og objects
  1498. * split objectdata from objectoutput
  1499. Revision 1.4 2000/12/07 17:19:45 jonas
  1500. * new constant handling: from now on, hex constants >$7fffffff are
  1501. parsed as unsigned constants (otherwise, $80000000 got sign extended
  1502. and became $ffffffff80000000), all constants in the longint range
  1503. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  1504. are cardinals and the rest are int64's.
  1505. * added lots of longint typecast to prevent range check errors in the
  1506. compiler and rtl
  1507. * type casts of symbolic ordinal constants are now preserved
  1508. * fixed bug where the original resulttype wasn't restored correctly
  1509. after doing a 64bit rangecheck
  1510. Revision 1.3 2000/11/12 22:20:37 peter
  1511. * create generic toutputsection for binary writers
  1512. Revision 1.2 2000/10/15 10:50:46 florian
  1513. * fixed xmm register access
  1514. Revision 1.1 2000/10/15 09:39:37 peter
  1515. * moved cpu*.pas to i386/
  1516. * renamed n386 to common cpunode
  1517. Revision 1.5 2000/09/24 15:06:14 peter
  1518. * use defines.inc
  1519. Revision 1.4 2000/08/27 16:11:50 peter
  1520. * moved some util functions from globals,cobjects to cutils
  1521. * splitted files into finput,fmodule
  1522. Revision 1.3 2000/07/13 12:08:25 michael
  1523. + patched to 1.1.0 with former 1.09patch from peter
  1524. Revision 1.2 2000/07/13 11:32:38 michael
  1525. + removed logs
  1526. }