cpuasm.pas 43 KB

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