cpuasm.pas 44 KB

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