cpuasm.pas 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647
  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. interface
  23. uses
  24. cobjects,
  25. aasm,globals,verbose,
  26. cpubase;
  27. {$ifndef NASMDEBUG}
  28. {$define OPTEA}
  29. {$define PASS2FLAG}
  30. {$endif ndef NASMDEBUG}
  31. {$ifndef TP}
  32. {$define ASMDEBUG}
  33. {$endif}
  34. const
  35. MaxPrefixes=4;
  36. type
  37. pairegalloc = ^tairegalloc;
  38. tairegalloc = object(tai)
  39. allocation : boolean;
  40. reg : tregister;
  41. constructor alloc(r : tregister);
  42. constructor dealloc(r : tregister);
  43. end;
  44. { alignment for operator }
  45. pai_align = ^tai_align;
  46. tai_align = object(tai_align_abstract)
  47. reg : tregister;
  48. constructor init(b:byte);
  49. constructor init_op(b: byte; _op: byte);
  50. function getfillbuf:pchar;
  51. end;
  52. paicpu = ^taicpu;
  53. taicpu = object(tai)
  54. is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
  55. opcode : tasmop;
  56. opsize : topsize;
  57. condition : TAsmCond;
  58. ops : longint;
  59. oper : array[0..2] of toper;
  60. constructor op_none(op : tasmop;_size : topsize);
  61. constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  62. constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
  63. constructor op_ref(op : tasmop;_size : topsize;_op1 : preference);
  64. constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  65. constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
  66. constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
  67. constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
  68. constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
  69. constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
  70. constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
  71. { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
  72. constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
  73. constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  74. constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
  75. constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
  76. constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : preference);
  77. constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
  78. { this is for Jmp instructions }
  79. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : pasmsymbol);
  80. constructor op_sym(op : tasmop;_size : topsize;_op1 : pasmsymbol);
  81. constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint);
  82. constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : tregister);
  83. constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : preference);
  84. procedure loadconst(opidx:longint;l:longint);
  85. procedure loadsymbol(opidx:longint;s:pasmsymbol;sofs:longint);
  86. procedure loadref(opidx:longint;p:preference);
  87. procedure loadreg(opidx:longint;r:tregister);
  88. procedure loadoper(opidx:longint;o:toper);
  89. procedure changeopsize(siz:topsize);
  90. procedure SetCondition(c:TAsmCond);
  91. destructor done;virtual;
  92. function getcopy:plinkedlist_item;virtual;
  93. function GetString:string;
  94. procedure SwapOperands;
  95. private
  96. segprefix : tregister;
  97. procedure init(op : tasmop;_size : topsize); { this need to be called by all constructor }
  98. {$ifndef NOAG386BIN}
  99. public
  100. { the next will reset all instructions that can change in pass 2 }
  101. procedure ResetPass2;
  102. function Pass1(offset:longint):longint;virtual;
  103. procedure Pass2;virtual;
  104. private
  105. { next fields are filled in pass1, so pass2 is faster }
  106. insentry : PInsEntry;
  107. insoffset,
  108. inssize : longint;
  109. LastInsOffset : longint; { need to be public to be reset }
  110. function InsEnd:longint;
  111. procedure create_ot;
  112. function Matches(p:PInsEntry):longint;
  113. function calcsize(p:PInsEntry):longint;
  114. procedure gencode;
  115. function NeedAddrPrefix(opidx:byte):boolean;
  116. {$endif NOAG386BIN}
  117. end;
  118. implementation
  119. uses
  120. og386;
  121. {*****************************************************************************
  122. TaiRegAlloc
  123. *****************************************************************************}
  124. constructor tairegalloc.alloc(r : tregister);
  125. begin
  126. inherited init;
  127. typ:=ait_regalloc;
  128. allocation:=true;
  129. reg:=r;
  130. end;
  131. constructor tairegalloc.dealloc(r : tregister);
  132. begin
  133. inherited init;
  134. typ:=ait_regalloc;
  135. allocation:=false;
  136. reg:=r;
  137. end;
  138. {****************************************************************************
  139. TAI_ALIGN
  140. ****************************************************************************}
  141. constructor tai_align.init(b: byte);
  142. begin
  143. inherited init(b);
  144. reg := R_ECX;
  145. end;
  146. constructor tai_align.init_op(b: byte; _op: byte);
  147. begin
  148. inherited init_op(b,_op);
  149. reg := R_NO;
  150. end;
  151. function tai_align.getfillbuf:pchar;
  152. const
  153. alignarray:array[0..5] of string[8]=(
  154. #$8D#$B4#$26#$00#$00#$00#$00,
  155. #$8D#$B6#$00#$00#$00#$00,
  156. #$8D#$74#$26#$00,
  157. #$8D#$76#$00,
  158. #$89#$F6,
  159. #$90
  160. );
  161. var
  162. bufptr : pchar;
  163. j : longint;
  164. begin
  165. if not use_op then
  166. begin
  167. bufptr:=@buf;
  168. while (fillsize>0) do
  169. begin
  170. for j:=0 to 5 do
  171. if (fillsize>=length(alignarray[j])) then
  172. break;
  173. move(alignarray[j][1],bufptr^,length(alignarray[j]));
  174. inc(bufptr,length(alignarray[j]));
  175. dec(fillsize,length(alignarray[j]));
  176. end;
  177. end;
  178. getfillbuf:=pchar(@buf);
  179. end;
  180. {*****************************************************************************
  181. Taicpu Constructors
  182. *****************************************************************************}
  183. procedure taicpu.loadconst(opidx:longint;l:longint);
  184. begin
  185. if opidx>=ops then
  186. ops:=opidx+1;
  187. with oper[opidx] do
  188. begin
  189. if typ=top_ref then
  190. disposereference(ref);
  191. val:=l;
  192. typ:=top_const;
  193. end;
  194. end;
  195. procedure taicpu.loadsymbol(opidx:longint;s:pasmsymbol;sofs:longint);
  196. begin
  197. if opidx>=ops then
  198. ops:=opidx+1;
  199. with oper[opidx] do
  200. begin
  201. if typ=top_ref then
  202. disposereference(ref);
  203. sym:=s;
  204. symofs:=sofs;
  205. typ:=top_symbol;
  206. end;
  207. { Mark the symbol as used }
  208. if assigned(s) then
  209. inc(s^.refs);
  210. end;
  211. procedure taicpu.loadref(opidx:longint;p:preference);
  212. begin
  213. if opidx>=ops then
  214. ops:=opidx+1;
  215. with oper[opidx] do
  216. begin
  217. if typ=top_ref then
  218. disposereference(ref);
  219. if p^.is_immediate then
  220. begin
  221. {$ifdef ASMDEBUG1}
  222. Comment(V_Warning,'Reference immediate');
  223. {$endif}
  224. val:=p^.offset;
  225. disposereference(p);
  226. typ:=top_const;
  227. end
  228. else
  229. begin
  230. ref:=p;
  231. if not(ref^.segment in [R_DS,R_NO]) then
  232. segprefix:=ref^.segment;
  233. typ:=top_ref;
  234. { mark symbol as used }
  235. if assigned(ref^.symbol) then
  236. inc(ref^.symbol^.refs);
  237. end;
  238. end;
  239. end;
  240. procedure taicpu.loadreg(opidx:longint;r:tregister);
  241. begin
  242. if opidx>=ops then
  243. ops:=opidx+1;
  244. with oper[opidx] do
  245. begin
  246. if typ=top_ref then
  247. disposereference(ref);
  248. reg:=r;
  249. typ:=top_reg;
  250. end;
  251. end;
  252. procedure taicpu.loadoper(opidx:longint;o:toper);
  253. begin
  254. if opidx>=ops then
  255. ops:=opidx+1;
  256. if oper[opidx].typ=top_ref then
  257. disposereference(oper[opidx].ref);
  258. oper[opidx]:=o;
  259. { copy also the reference }
  260. if oper[opidx].typ=top_ref then
  261. oper[opidx].ref:=newreference(o.ref^);
  262. end;
  263. procedure taicpu.changeopsize(siz:topsize);
  264. begin
  265. opsize:=siz;
  266. end;
  267. procedure taicpu.init(op : tasmop;_size : topsize);
  268. begin
  269. typ:=ait_instruction;
  270. is_jmp:=false;
  271. segprefix:=R_NO;
  272. opcode:=op;
  273. opsize:=_size;
  274. ops:=0;
  275. condition:=c_none;
  276. fillchar(oper,sizeof(oper),0);
  277. {$ifndef NOAG386BIN}
  278. insentry:=nil;
  279. LastInsOffset:=-1;
  280. InsOffset:=0;
  281. InsSize:=0;
  282. {$endif}
  283. end;
  284. constructor taicpu.op_none(op : tasmop;_size : topsize);
  285. begin
  286. inherited init;
  287. init(op,_size);
  288. end;
  289. constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  290. begin
  291. inherited init;
  292. init(op,_size);
  293. ops:=1;
  294. loadreg(0,_op1);
  295. end;
  296. constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
  297. begin
  298. inherited init;
  299. init(op,_size);
  300. ops:=1;
  301. loadconst(0,_op1);
  302. end;
  303. constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : preference);
  304. begin
  305. inherited init;
  306. init(op,_size);
  307. ops:=1;
  308. loadref(0,_op1);
  309. end;
  310. constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  311. begin
  312. inherited init;
  313. init(op,_size);
  314. ops:=2;
  315. loadreg(0,_op1);
  316. loadreg(1,_op2);
  317. end;
  318. constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
  319. begin
  320. inherited init;
  321. init(op,_size);
  322. ops:=2;
  323. loadreg(0,_op1);
  324. loadconst(1,_op2);
  325. end;
  326. constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
  327. begin
  328. inherited init;
  329. init(op,_size);
  330. ops:=2;
  331. loadreg(0,_op1);
  332. loadref(1,_op2);
  333. end;
  334. constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
  335. begin
  336. inherited init;
  337. init(op,_size);
  338. ops:=2;
  339. loadconst(0,_op1);
  340. loadreg(1,_op2);
  341. end;
  342. constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
  343. begin
  344. inherited init;
  345. init(op,_size);
  346. ops:=2;
  347. loadconst(0,_op1);
  348. loadconst(1,_op2);
  349. end;
  350. constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
  351. begin
  352. inherited init;
  353. init(op,_size);
  354. ops:=2;
  355. loadconst(0,_op1);
  356. loadref(1,_op2);
  357. end;
  358. constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
  359. begin
  360. inherited init;
  361. init(op,_size);
  362. ops:=2;
  363. loadref(0,_op1);
  364. loadreg(1,_op2);
  365. end;
  366. constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
  367. begin
  368. inherited init;
  369. init(op,_size);
  370. ops:=2;
  371. loadref(0,_op1);
  372. loadref(1,_op2);
  373. end;
  374. constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  375. begin
  376. inherited init;
  377. init(op,_size);
  378. ops:=3;
  379. loadreg(0,_op1);
  380. loadreg(1,_op2);
  381. loadreg(2,_op3);
  382. end;
  383. constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
  384. begin
  385. inherited init;
  386. init(op,_size);
  387. ops:=3;
  388. loadconst(0,_op1);
  389. loadreg(1,_op2);
  390. loadreg(2,_op3);
  391. end;
  392. constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;_op3 : preference);
  393. begin
  394. inherited init;
  395. init(op,_size);
  396. ops:=3;
  397. loadreg(0,_op1);
  398. loadreg(1,_op2);
  399. loadref(2,_op3);
  400. end;
  401. constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
  402. begin
  403. inherited init;
  404. init(op,_size);
  405. ops:=3;
  406. loadconst(0,_op1);
  407. loadref(1,_op2);
  408. loadreg(2,_op3);
  409. end;
  410. constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
  411. begin
  412. inherited init;
  413. init(op,_size);
  414. ops:=3;
  415. loadconst(0,_op1);
  416. loadreg(1,_op2);
  417. loadref(2,_op3);
  418. end;
  419. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : pasmsymbol);
  420. begin
  421. inherited init;
  422. init(op,_size);
  423. condition:=cond;
  424. ops:=1;
  425. loadsymbol(0,_op1,0);
  426. end;
  427. constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : pasmsymbol);
  428. begin
  429. inherited init;
  430. init(op,_size);
  431. ops:=1;
  432. loadsymbol(0,_op1,0);
  433. end;
  434. constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint);
  435. begin
  436. inherited init;
  437. init(op,_size);
  438. ops:=1;
  439. loadsymbol(0,_op1,_op1ofs);
  440. end;
  441. constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : tregister);
  442. begin
  443. inherited init;
  444. init(op,_size);
  445. ops:=2;
  446. loadsymbol(0,_op1,_op1ofs);
  447. loadreg(1,_op2);
  448. end;
  449. constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : preference);
  450. begin
  451. inherited init;
  452. init(op,_size);
  453. ops:=2;
  454. loadsymbol(0,_op1,_op1ofs);
  455. loadref(1,_op2);
  456. end;
  457. destructor taicpu.done;
  458. var
  459. i : longint;
  460. begin
  461. {$ifndef nojmpfix}
  462. if is_jmp then
  463. dec(PasmLabel(oper[0].sym)^.refs)
  464. else
  465. {$endif nojmpfix}
  466. for i:=1 to ops do
  467. if (oper[i-1].typ=top_ref) then
  468. dispose(oper[i-1].ref);
  469. inherited done;
  470. end;
  471. function taicpu.getcopy:plinkedlist_item;
  472. var
  473. i : longint;
  474. p : plinkedlist_item;
  475. begin
  476. p:=inherited getcopy;
  477. { make a copy of the references }
  478. for i:=1 to ops do
  479. if (paicpu(p)^.oper[i-1].typ=top_ref) then
  480. begin
  481. new(paicpu(p)^.oper[i-1].ref);
  482. paicpu(p)^.oper[i-1].ref^:=oper[i-1].ref^;
  483. end;
  484. getcopy:=p;
  485. end;
  486. procedure taicpu.SetCondition(c:TAsmCond);
  487. begin
  488. condition:=c;
  489. end;
  490. function taicpu.GetString:string;
  491. {$ifdef ASMDEBUG}
  492. var
  493. i : longint;
  494. s : string;
  495. addsize : boolean;
  496. {$endif}
  497. begin
  498. {$ifdef ASMDEBUG}
  499. s:='['+int_op2str[opcode];
  500. for i:=1to ops do
  501. begin
  502. if i=1 then
  503. s:=s+' '
  504. else
  505. s:=s+',';
  506. { type }
  507. addsize:=false;
  508. if (oper[i-1].ot and OT_XMMREG)=OT_XMMREG then
  509. s:=s+'xmmreg'
  510. else
  511. if (oper[i-1].ot and OT_MMXREG)=OT_MMXREG then
  512. s:=s+'mmxreg'
  513. else
  514. if (oper[i-1].ot and OT_FPUREG)=OT_FPUREG then
  515. s:=s+'fpureg'
  516. else
  517. if (oper[i-1].ot and OT_REGISTER)=OT_REGISTER then
  518. begin
  519. s:=s+'reg';
  520. addsize:=true;
  521. end
  522. else
  523. if (oper[i-1].ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  524. begin
  525. s:=s+'imm';
  526. addsize:=true;
  527. end
  528. else
  529. if (oper[i-1].ot and OT_MEMORY)=OT_MEMORY then
  530. begin
  531. s:=s+'mem';
  532. addsize:=true;
  533. end
  534. else
  535. s:=s+'???';
  536. { size }
  537. if addsize then
  538. begin
  539. if (oper[i-1].ot and OT_BITS8)<>0 then
  540. s:=s+'8'
  541. else
  542. if (oper[i-1].ot and OT_BITS16)<>0 then
  543. s:=s+'16'
  544. else
  545. if (oper[i-1].ot and OT_BITS32)<>0 then
  546. s:=s+'32'
  547. else
  548. s:=s+'??';
  549. { signed }
  550. if (oper[i-1].ot and OT_SIGNED)<>0 then
  551. s:=s+'s';
  552. end;
  553. end;
  554. GetString:=s+']';
  555. {$else}
  556. GetString:='';
  557. {$endif ASMDEBUG}
  558. end;
  559. procedure taicpu.SwapOperands;
  560. var
  561. p : TOper;
  562. begin
  563. { Fix the operands which are in AT&T style and we need them in Intel style }
  564. case ops of
  565. 2 : begin
  566. { 0,1 -> 1,0 }
  567. p:=oper[0];
  568. oper[0]:=oper[1];
  569. oper[1]:=p;
  570. end;
  571. 3 : begin
  572. { 0,1,2 -> 2,1,0 }
  573. p:=oper[0];
  574. oper[0]:=oper[2];
  575. oper[2]:=p;
  576. end;
  577. end;
  578. end;
  579. {*****************************************************************************
  580. Assembler
  581. *****************************************************************************}
  582. {$ifndef NOAG386BIN}
  583. type
  584. ea=packed record
  585. sib_present : boolean;
  586. bytes : byte;
  587. size : byte;
  588. modrm : byte;
  589. sib : byte;
  590. end;
  591. procedure taicpu.create_ot;
  592. {
  593. this function will also fix some other fields which only needs to be once
  594. }
  595. var
  596. i,l,relsize : longint;
  597. begin
  598. if ops=0 then
  599. exit;
  600. { update oper[].ot field }
  601. for i:=0 to ops-1 do
  602. with oper[i] do
  603. begin
  604. case typ of
  605. top_reg :
  606. ot:=reg_2_type[reg];
  607. top_ref :
  608. begin
  609. { create ot field }
  610. ot:=OT_MEMORY or opsize_2_type[i,opsize];
  611. if (ref^.base=R_NO) and (ref^.index=R_NO) then
  612. ot:=ot or OT_MEM_OFFS;
  613. { handle also the offsetfixup }
  614. inc(ref^.offset,ref^.offsetfixup);
  615. ref^.offsetfixup:=0;
  616. { fix scalefactor }
  617. if (ref^.index=R_NO) then
  618. ref^.scalefactor:=0
  619. else
  620. if (ref^.scalefactor=0) then
  621. ref^.scalefactor:=1;
  622. end;
  623. top_const :
  624. begin
  625. if (opsize<>S_W) and (val>=-128) and (val<=127) then
  626. ot:=OT_IMM8 or OT_SIGNED
  627. else
  628. ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
  629. end;
  630. top_symbol :
  631. begin
  632. if LastInsOffset=-1 then
  633. l:=0
  634. else
  635. l:=InsOffset-LastInsOffset;
  636. inc(l,symofs);
  637. if assigned(sym) then
  638. inc(l,sym^.address);
  639. { instruction size will then always become 2 (PFV) }
  640. relsize:=(InsOffset+2)-l;
  641. if (not assigned(sym) or
  642. ((sym^.typ<>AS_EXTERNAL) and (sym^.address<>0))) and
  643. (relsize>=-128) and (relsize<=127) then
  644. ot:=OT_IMM32 or OT_SHORT
  645. else
  646. ot:=OT_IMM32 or OT_NEAR;
  647. end;
  648. end;
  649. end;
  650. end;
  651. function taicpu.InsEnd:longint;
  652. begin
  653. InsEnd:=InsOffset+InsSize;
  654. end;
  655. function taicpu.Matches(p:PInsEntry):longint;
  656. { * IF_SM stands for Size Match: any operand whose size is not
  657. * explicitly specified by the template is `really' intended to be
  658. * the same size as the first size-specified operand.
  659. * Non-specification is tolerated in the input instruction, but
  660. * _wrong_ specification is not.
  661. *
  662. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  663. * three-operand instructions such as SHLD: it implies that the
  664. * first two operands must match in size, but that the third is
  665. * required to be _unspecified_.
  666. *
  667. * IF_SB invokes Size Byte: operands with unspecified size in the
  668. * template are really bytes, and so no non-byte specification in
  669. * the input instruction will be tolerated. IF_SW similarly invokes
  670. * Size Word, and IF_SD invokes Size Doubleword.
  671. *
  672. * (The default state if neither IF_SM nor IF_SM2 is specified is
  673. * that any operand with unspecified size in the template is
  674. * required to have unspecified size in the instruction too...)
  675. }
  676. var
  677. i,siz,oprs : longint;
  678. begin
  679. Matches:=100;
  680. { Check the opcode and operands }
  681. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  682. begin
  683. Matches:=0;
  684. exit;
  685. end;
  686. { Check that no spurious colons or TOs are present }
  687. for i:=0 to p^.ops-1 do
  688. if (oper[i].ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  689. begin
  690. Matches:=0;
  691. exit;
  692. end;
  693. { Check that the operand flags all match up }
  694. for i:=0 to p^.ops-1 do
  695. begin
  696. if (p^.optypes[i] and (not oper[i].ot) or
  697. ((p^.optypes[i] and OT_SIZE_MASK) and
  698. ((p^.optypes[i] xor oper[i].ot) and OT_SIZE_MASK)))<>0 then
  699. begin
  700. if ((p^.optypes[i] and (not oper[i].ot) and OT_NON_SIZE) or
  701. (oper[i].ot and OT_SIZE_MASK))<>0 then
  702. begin
  703. Matches:=0;
  704. exit;
  705. end
  706. else
  707. Matches:=1;
  708. end;
  709. end;
  710. { Check operand sizes }
  711. { as default an untyped size can get all the sizes, this is different
  712. from nasm, but else we need to do a lot checking which opcodes want
  713. size or not with the automatic size generation }
  714. siz:=$ffffffff;
  715. if (p^.flags and IF_SB)<>0 then
  716. siz:=OT_BITS8
  717. else if (p^.flags and IF_SW)<>0 then
  718. siz:=OT_BITS16
  719. else if (p^.flags and IF_SD)<>0 then
  720. siz:=OT_BITS32
  721. else if (p^.flags and (IF_SM or IF_SM2))<>0 then
  722. begin
  723. if (p^.flags and IF_SM2)<>0 then
  724. oprs:=2
  725. else
  726. oprs:=p^.ops;
  727. for i:=0 to oprs-1 do
  728. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  729. begin
  730. siz:=p^.optypes[i] and OT_SIZE_MASK;
  731. break;
  732. end;
  733. end;
  734. { Check operand sizes }
  735. for i:=0to p^.ops-1 do
  736. begin
  737. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  738. ((oper[i].ot and OT_SIZE_MASK and (not siz))<>0) and
  739. { Immediates can always include smaller size }
  740. ((oper[i].ot and OT_IMMEDIATE)=0) and
  741. (((p^.optypes[i] and OT_SIZE_MASK) or siz)<(oper[i].ot and OT_SIZE_MASK)) then
  742. Matches:=2;
  743. end;
  744. end;
  745. procedure taicpu.ResetPass2;
  746. begin
  747. { we are here in a second pass, check if the instruction can be optimized }
  748. if assigned(InsEntry) and
  749. ((InsEntry^.flags and IF_PASS2)<>0) then
  750. begin
  751. InsEntry:=nil;
  752. InsSize:=0;
  753. end;
  754. LastInsOffset:=-1;
  755. end;
  756. function taicpu.Pass1(offset:longint):longint;
  757. var
  758. m,i : longint;
  759. begin
  760. Pass1:=0;
  761. { Save the old offset and set the new offset }
  762. InsOffset:=Offset;
  763. { Things which may only be done once, not when a second pass is done to
  764. optimize }
  765. if Insentry=nil then
  766. begin
  767. { Check if error last time then InsSize=-1 }
  768. if InsSize=-1 then
  769. exit;
  770. { We need intel style operands }
  771. SwapOperands;
  772. { create the .ot fields }
  773. create_ot;
  774. { set the file postion }
  775. aktfilepos:=fileinfo;
  776. end
  777. else
  778. begin
  779. {$ifdef PASS2FLAG}
  780. { we are here in a second pass, check if the instruction can be optimized }
  781. if (InsEntry^.flags and IF_PASS2)=0 then
  782. begin
  783. Pass1:=InsSize;
  784. exit;
  785. end;
  786. { update the .ot fields, some top_const can be updated }
  787. create_ot;
  788. {$endif}
  789. end;
  790. { Lookup opcode in the table }
  791. InsSize:=-1;
  792. i:=instabcache^[opcode];
  793. if i=-1 then
  794. begin
  795. {$ifdef TP}
  796. Message1(asmw_e_opcode_not_in_table,'');
  797. {$else}
  798. Message1(asmw_e_opcode_not_in_table,att_op2str[opcode]);
  799. {$endif}
  800. exit;
  801. end;
  802. insentry:=@instab[i];
  803. while (insentry^.opcode=opcode) do
  804. begin
  805. m:=matches(insentry);
  806. if m=100 then
  807. begin
  808. InsSize:=calcsize(insentry);
  809. if (segprefix<>R_NO) then
  810. inc(InsSize);
  811. Pass1:=InsSize;
  812. LastInsOffset:=InsOffset;
  813. exit;
  814. end;
  815. inc(i);
  816. insentry:=@instab[i];
  817. end;
  818. if insentry^.opcode<>opcode then
  819. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  820. { No instruction found, set insentry to nil and inssize to -1 }
  821. insentry:=nil;
  822. inssize:=-1;
  823. LastInsOffset:=-1;
  824. end;
  825. procedure taicpu.Pass2;
  826. var
  827. c : longint;
  828. begin
  829. { error in pass1 ? }
  830. if insentry=nil then
  831. exit;
  832. aktfilepos:=fileinfo;
  833. { Segment override }
  834. if (segprefix<>R_NO) then
  835. begin
  836. case segprefix of
  837. R_CS : c:=$2e;
  838. R_DS : c:=$3e;
  839. R_ES : c:=$26;
  840. R_FS : c:=$64;
  841. R_GS : c:=$65;
  842. R_SS : c:=$36;
  843. end;
  844. objectoutput^.writebytes(c,1);
  845. { fix the offset for GenNode }
  846. inc(InsOffset);
  847. end;
  848. { Generate the instruction }
  849. GenCode;
  850. end;
  851. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  852. var
  853. i,b : tregister;
  854. begin
  855. if (OT_MEMORY and (not oper[opidx].ot))=0 then
  856. begin
  857. i:=oper[opidx].ref^.index;
  858. b:=oper[opidx].ref^.base;
  859. if not(i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) or
  860. not(b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) then
  861. begin
  862. NeedAddrPrefix:=true;
  863. exit;
  864. end;
  865. end;
  866. NeedAddrPrefix:=false;
  867. end;
  868. function regval(r:tregister):byte;
  869. begin
  870. case r of
  871. R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0 :
  872. regval:=0;
  873. R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1 :
  874. regval:=1;
  875. R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2 :
  876. regval:=2;
  877. R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3 :
  878. regval:=3;
  879. R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4 :
  880. regval:=4;
  881. R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5 :
  882. regval:=5;
  883. R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6 :
  884. regval:=6;
  885. R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7 :
  886. regval:=7;
  887. else
  888. begin
  889. internalerror(777001);
  890. regval:=0;
  891. end;
  892. end;
  893. end;
  894. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  895. const
  896. regs : array[0..31] of tregister=(
  897. R_MM0, R_EAX, R_AX, R_AL, R_MM1, R_ECX, R_CX, R_CL,
  898. R_MM2, R_EDX, R_DX, R_DL, R_MM3, R_EBX, R_BX, R_BL,
  899. R_MM4, R_ESP, R_SP, R_AH, R_MM5, R_EBP, R_BP, R_CH,
  900. R_MM6, R_ESI, R_SI, R_DH, R_MM7, R_EDI, R_DI, R_BH
  901. );
  902. var
  903. j : longint;
  904. i,b : tregister;
  905. sym : pasmsymbol;
  906. md,s : byte;
  907. base,index,scalefactor,
  908. o : longint;
  909. begin
  910. process_ea:=false;
  911. { register ? }
  912. if (input.typ=top_reg) then
  913. begin
  914. j:=0;
  915. while (j<=high(regs)) do
  916. begin
  917. if input.reg=regs[j] then
  918. break;
  919. inc(j);
  920. end;
  921. if j<=high(regs) then
  922. begin
  923. output.sib_present:=false;
  924. output.bytes:=0;
  925. output.modrm:=$c0 or (rfield shl 3) or (j shr 2);
  926. output.size:=1;
  927. process_ea:=true;
  928. end;
  929. exit;
  930. end;
  931. { memory reference }
  932. i:=input.ref^.index;
  933. b:=input.ref^.base;
  934. s:=input.ref^.scalefactor;
  935. o:=input.ref^.offset;
  936. sym:=input.ref^.symbol;
  937. { it's direct address }
  938. if (b=R_NO) and (i=R_NO) then
  939. begin
  940. { it's a pure offset }
  941. output.sib_present:=false;
  942. output.bytes:=4;
  943. output.modrm:=5 or (rfield shl 3);
  944. end
  945. else
  946. { it's an indirection }
  947. begin
  948. { 16 bit address? }
  949. if not((i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) and
  950. (b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI])) then
  951. Message(asmw_e_16bit_not_supported);
  952. {$ifdef OPTEA}
  953. { make single reg base }
  954. if (b=R_NO) and (s=1) then
  955. begin
  956. b:=i;
  957. i:=R_NO;
  958. end;
  959. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  960. if (b=R_NO) and
  961. (((s=2) and (i<>R_ESP)) or
  962. (s=3) or (s=5) or (s=9)) then
  963. begin
  964. b:=i;
  965. dec(s);
  966. end;
  967. { swap ESP into base if scalefactor is 1 }
  968. if (s=1) and (i=R_ESP) then
  969. begin
  970. i:=b;
  971. b:=R_ESP;
  972. end;
  973. {$endif}
  974. { wrong, for various reasons }
  975. if (i=R_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (i<>R_NO)) then
  976. exit;
  977. { base }
  978. case b of
  979. R_EAX : base:=0;
  980. R_ECX : base:=1;
  981. R_EDX : base:=2;
  982. R_EBX : base:=3;
  983. R_ESP : base:=4;
  984. R_NO,
  985. R_EBP : base:=5;
  986. R_ESI : base:=6;
  987. R_EDI : base:=7;
  988. else
  989. exit;
  990. end;
  991. { index }
  992. case i of
  993. R_EAX : index:=0;
  994. R_ECX : index:=1;
  995. R_EDX : index:=2;
  996. R_EBX : index:=3;
  997. R_NO : index:=4;
  998. R_EBP : index:=5;
  999. R_ESI : index:=6;
  1000. R_EDI : index:=7;
  1001. else
  1002. exit;
  1003. end;
  1004. case s of
  1005. 0,
  1006. 1 : scalefactor:=0;
  1007. 2 : scalefactor:=1;
  1008. 4 : scalefactor:=2;
  1009. 8 : scalefactor:=3;
  1010. else
  1011. exit;
  1012. end;
  1013. if (b=R_NO) or
  1014. ((b<>R_EBP) and (o=0) and (sym=nil)) then
  1015. md:=0
  1016. else
  1017. if ((o>=-128) and (o<=127) and (sym=nil)) then
  1018. md:=1
  1019. else
  1020. md:=2;
  1021. if (b=R_NO) or (md=2) then
  1022. output.bytes:=4
  1023. else
  1024. output.bytes:=md;
  1025. { SIB needed ? }
  1026. if (i=R_NO) and (b<>R_ESP) then
  1027. begin
  1028. output.sib_present:=false;
  1029. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  1030. end
  1031. else
  1032. begin
  1033. output.sib_present:=true;
  1034. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  1035. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  1036. end;
  1037. end;
  1038. if output.sib_present then
  1039. output.size:=2+output.bytes
  1040. else
  1041. output.size:=1+output.bytes;
  1042. process_ea:=true;
  1043. end;
  1044. function taicpu.calcsize(p:PInsEntry):longint;
  1045. var
  1046. codes : pchar;
  1047. c : byte;
  1048. len : longint;
  1049. ea_data : ea;
  1050. begin
  1051. len:=0;
  1052. codes:=@p^.code;
  1053. repeat
  1054. c:=ord(codes^);
  1055. inc(codes);
  1056. case c of
  1057. 0 :
  1058. break;
  1059. 1,2,3 :
  1060. begin
  1061. inc(codes,c);
  1062. inc(len,c);
  1063. end;
  1064. 8,9,10 :
  1065. begin
  1066. inc(codes);
  1067. inc(len);
  1068. end;
  1069. 4,5,6,7,
  1070. 15,
  1071. 12,13,14,
  1072. 16,17,18,
  1073. 20,21,22,
  1074. 40,41,42 :
  1075. inc(len);
  1076. 24,25,26,
  1077. 31,
  1078. 48,49,50 :
  1079. inc(len,2);
  1080. 28,29,30, { we don't have 16 bit immediates code }
  1081. 32,33,34,
  1082. 52,53,54,
  1083. 56,57,58 :
  1084. inc(len,4);
  1085. 192,193,194 :
  1086. if NeedAddrPrefix(c-192) then
  1087. inc(len);
  1088. 208 :
  1089. inc(len);
  1090. 200,
  1091. 201,
  1092. 202,
  1093. 209,
  1094. 210,
  1095. 217,218,219 : ;
  1096. 216 :
  1097. begin
  1098. inc(codes);
  1099. inc(len);
  1100. end;
  1101. 224,225,226 :
  1102. begin
  1103. InternalError(777002);
  1104. end;
  1105. else
  1106. begin
  1107. if (c>=64) and (c<=191) then
  1108. begin
  1109. if not process_ea(oper[(c shr 3) and 7], ea_data, 0) then
  1110. Message(asmw_e_invalid_effective_address)
  1111. else
  1112. inc(len,ea_data.size);
  1113. end
  1114. else
  1115. InternalError(777003);
  1116. end;
  1117. end;
  1118. until false;
  1119. calcsize:=len;
  1120. end;
  1121. procedure taicpu.GenCode;
  1122. {
  1123. * the actual codes (C syntax, i.e. octal):
  1124. * \0 - terminates the code. (Unless it's a literal of course.)
  1125. * \1, \2, \3 - that many literal bytes follow in the code stream
  1126. * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  1127. * (POP is never used for CS) depending on operand 0
  1128. * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
  1129. * on operand 0
  1130. * \10, \11, \12 - a literal byte follows in the code stream, to be added
  1131. * to the register value of operand 0, 1 or 2
  1132. * \17 - encodes the literal byte 0. (Some compilers don't take
  1133. * kindly to a zero byte in the _middle_ of a compile time
  1134. * string constant, so I had to put this hack in.)
  1135. * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  1136. * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  1137. * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
  1138. * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  1139. * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  1140. * assembly mode or the address-size override on the operand
  1141. * \37 - a word constant, from the _segment_ part of operand 0
  1142. * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  1143. * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  1144. * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  1145. * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  1146. * assembly mode or the address-size override on the operand
  1147. * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  1148. * \1ab - a ModRM, calculated on EA in operand a, with the spare
  1149. * field the register value of operand b.
  1150. * \2ab - a ModRM, calculated on EA in operand a, with the spare
  1151. * field equal to digit b.
  1152. * \30x - might be an 0x67 byte, depending on the address size of
  1153. * the memory reference in operand x.
  1154. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
  1155. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
  1156. * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
  1157. * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
  1158. * \322 - indicates that this instruction is only valid when the
  1159. * operand size is the default (instruction to disassembler,
  1160. * generates no code in the assembler)
  1161. * \330 - a literal byte follows in the code stream, to be added
  1162. * to the condition code value of the instruction.
  1163. * \340 - reserve <operand 0> bytes of uninitialised storage.
  1164. * Operand 0 had better be a segmentless constant.
  1165. }
  1166. var
  1167. currval : longint;
  1168. currsym : pasmsymbol;
  1169. procedure getvalsym(opidx:longint);
  1170. begin
  1171. case oper[opidx].typ of
  1172. top_ref :
  1173. begin
  1174. currval:=oper[opidx].ref^.offset;
  1175. currsym:=oper[opidx].ref^.symbol;
  1176. end;
  1177. top_const :
  1178. begin
  1179. currval:=oper[opidx].val;
  1180. currsym:=nil;
  1181. end;
  1182. top_symbol :
  1183. begin
  1184. currval:=oper[opidx].symofs;
  1185. currsym:=oper[opidx].sym;
  1186. end;
  1187. else
  1188. Message(asmw_e_immediate_or_reference_expected);
  1189. end;
  1190. end;
  1191. const
  1192. CondVal:array[TAsmCond] of byte=($0,
  1193. $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
  1194. $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
  1195. $0, $A, $A, $B, $8, $4);
  1196. var
  1197. c : byte;
  1198. pb,
  1199. codes : pchar;
  1200. bytes : array[0..3] of byte;
  1201. rfield,
  1202. data,s,opidx : longint;
  1203. ea_data : ea;
  1204. begin
  1205. codes:=insentry^.code;
  1206. repeat
  1207. c:=ord(codes^);
  1208. inc(codes);
  1209. case c of
  1210. 0 :
  1211. break;
  1212. 1,2,3 :
  1213. begin
  1214. objectoutput^.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. objectoutput^.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. objectoutput^.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. objectoutput^.writebytes(bytes,1);
  1281. end;
  1282. 15 :
  1283. begin
  1284. bytes[0]:=0;
  1285. objectoutput^.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. objectoutput^.writereloc(currval,1,currsym,relative_false)
  1294. else
  1295. objectoutput^.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. objectoutput^.writereloc(currval,1,currsym,relative_false)
  1304. else
  1305. objectoutput^.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. objectoutput^.writereloc(currval,1,currsym,relative_false)
  1314. else
  1315. objectoutput^.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. objectoutput^.writereloc(currval,2,currsym,relative_false)
  1324. else
  1325. objectoutput^.writebytes(currval,2);
  1326. end;
  1327. 28,29,30 :
  1328. begin
  1329. getvalsym(c-28);
  1330. if assigned(currsym) then
  1331. objectoutput^.writereloc(currval,4,currsym,relative_false)
  1332. else
  1333. objectoutput^.writebytes(currval,4);
  1334. end;
  1335. 32,33,34 :
  1336. begin
  1337. getvalsym(c-32);
  1338. if assigned(currsym) then
  1339. objectoutput^.writereloc(currval,4,currsym,relative_false)
  1340. else
  1341. objectoutput^.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. objectoutput^.writebytes(data,1);
  1352. end;
  1353. 52,53,54 :
  1354. begin
  1355. getvalsym(c-52);
  1356. if assigned(currsym) then
  1357. objectoutput^.writereloc(currval,4,currsym,relative_true)
  1358. else
  1359. objectoutput^.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. objectoutput^.writereloc(currval,4,currsym,relative_true)
  1366. else
  1367. objectoutput^.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. objectoutput^.writebytes(bytes,1);
  1375. end;
  1376. end;
  1377. 200 :
  1378. begin
  1379. bytes[0]:=$67;
  1380. objectoutput^.writebytes(bytes,1);
  1381. end;
  1382. 208 :
  1383. begin
  1384. bytes[0]:=$66;
  1385. objectoutput^.writebytes(bytes,1);
  1386. end;
  1387. 216 :
  1388. begin
  1389. bytes[0]:=ord(codes^)+condval[condition];
  1390. inc(codes);
  1391. objectoutput^.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. objectoutput^.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. objectoutput^.writereloc(oper[opidx].ref^.offset,1,oper[opidx].ref^.symbol,relative_false)
  1440. else
  1441. begin
  1442. bytes[0]:=oper[opidx].ref^.offset;
  1443. objectoutput^.writebytes(bytes,1);
  1444. end;
  1445. inc(s);
  1446. end;
  1447. 2,4 :
  1448. begin
  1449. objectoutput^.writereloc(oper[opidx].ref^.offset,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.12 2000-02-09 13:22:51 peter
  1466. * log truncated
  1467. Revision 1.11 2000/01/23 21:29:14 florian
  1468. * CMOV support in optimizer (in define USECMOV)
  1469. + start of support of exceptions in constructors
  1470. Revision 1.10 2000/01/12 10:38:18 peter
  1471. * smartlinking fixes for binary writer
  1472. * release alignreg code and moved instruction writing align to cpuasm,
  1473. but it doesn't use the specified register yet
  1474. Revision 1.9 2000/01/07 01:14:23 peter
  1475. * updated copyright to 2000
  1476. Revision 1.8 2000/01/07 00:07:24 peter
  1477. * display fpu,mmx,xmm names instead of reg??
  1478. Revision 1.7 1999/12/24 15:22:52 peter
  1479. * reset insentry/lastinsoffset so writing smartlink works correct for
  1480. short jmps
  1481. Revision 1.6 1999/11/30 10:40:43 peter
  1482. + ttype, tsymlist
  1483. Revision 1.5 1999/11/06 14:34:20 peter
  1484. * truncated log to 20 revs
  1485. Revision 1.4 1999/11/05 16:01:46 jonas
  1486. + first implementation of choosing least used register for alignment code
  1487. (not yet working, between ifdef alignreg)
  1488. Revision 1.3 1999/08/25 11:59:57 jonas
  1489. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  1490. Revision 1.2 1999/08/12 14:36:01 peter
  1491. + KNI instructions
  1492. Revision 1.1 1999/08/04 00:22:57 florian
  1493. * renamed i386asm and i386base to cpuasm and cpubase
  1494. Revision 1.17 1999/08/01 23:55:53 michael
  1495. * Moved taitempalloc
  1496. }