aasmcpu.pas 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  3. Contains the abstract assembler implementation for the i386
  4. * Portions of this code was inspired by the NASM sources
  5. The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
  6. Julian Hall. All rights reserved.
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. unit aasmcpu;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globtype,globals,verbose,
  25. cpubase,
  26. cgbase,cgutils,
  27. symtype,
  28. aasmbase,aasmtai,
  29. ogbase;
  30. const
  31. { "mov reg,reg" source operand number }
  32. O_MOV_SOURCE = 0;
  33. { "mov reg,reg" destination operand number }
  34. O_MOV_DEST = 1;
  35. { Operand types }
  36. OT_NONE = $00000000;
  37. OT_BITS8 = $00000001; { size, and other attributes, of the operand }
  38. OT_BITS16 = $00000002;
  39. OT_BITS32 = $00000004;
  40. OT_BITS64 = $00000008; { FPU only }
  41. OT_BITS80 = $00000010;
  42. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  43. OT_NEAR = $00000040;
  44. OT_SHORT = $00000080;
  45. OT_SIZE_MASK = $000000FF; { all the size attributes }
  46. OT_NON_SIZE = longint(not OT_SIZE_MASK);
  47. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  48. OT_TO = $00000200; { operand is followed by a colon }
  49. { reverse effect in FADD, FSUB &c }
  50. OT_COLON = $00000400;
  51. OT_REGISTER = $00001000;
  52. OT_IMMEDIATE = $00002000;
  53. OT_IMM8 = $00002001;
  54. OT_IMM16 = $00002002;
  55. OT_IMM32 = $00002004;
  56. OT_IMM64 = $00002008;
  57. OT_IMM80 = $00002010;
  58. OT_REGMEM = $00200000; { for r/m, ie EA, operands }
  59. OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
  60. OT_REG8 = $00201001;
  61. OT_REG16 = $00201002;
  62. OT_REG32 = $00201004;
  63. OT_REG64 = $00201008;
  64. OT_MMXREG = $00201008; { MMX registers }
  65. OT_XMMREG = $00201010; { Katmai registers }
  66. OT_MEMORY = $00204000; { register number in 'basereg' }
  67. OT_MEM8 = $00204001;
  68. OT_MEM16 = $00204002;
  69. OT_MEM32 = $00204004;
  70. OT_MEM64 = $00204008;
  71. OT_MEM80 = $00204010;
  72. OT_FPUREG = $01000000; { floating point stack registers }
  73. OT_FPU0 = $01000800; { FPU stack register zero }
  74. OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
  75. { a mask for the following }
  76. OT_REG_ACCUM = $00211000; { FUNCTION_RETURN_REG: AL, AX or EAX }
  77. OT_REG_AL = $00211001; { REG_ACCUM | BITSxx }
  78. OT_REG_AX = $00211002; { ditto }
  79. OT_REG_EAX = $00211004; { and again }
  80. {$ifdef x86_64}
  81. OT_REG_RAX = $00211008;
  82. {$endif x86_64}
  83. OT_REG_COUNT = $00221000; { counter: CL, CX or ECX }
  84. OT_REG_CL = $00221001; { REG_COUNT | BITSxx }
  85. OT_REG_CX = $00221002; { ditto }
  86. OT_REG_ECX = $00221004; { another one }
  87. {$ifdef x86_64}
  88. OT_REG_RCX = $00221008;
  89. {$endif x86_64}
  90. OT_REG_DX = $00241002;
  91. OT_REG_EDX = $00241004;
  92. OT_REG_SREG = $00081002; { any segment register }
  93. OT_REG_CS = $01081002; { CS }
  94. OT_REG_DESS = $02081002; { DS, ES, SS (non-CS 86 registers) }
  95. OT_REG_FSGS = $04081002; { FS, GS (386 extended registers) }
  96. OT_REG_CDT = $00101004; { CRn, DRn and TRn }
  97. OT_REG_CREG = $08101004; { CRn }
  98. OT_REG_CR4 = $08101404; { CR4 (Pentium only) }
  99. OT_REG_DREG = $10101004; { DRn }
  100. OT_REG_TREG = $20101004; { TRn }
  101. OT_MEM_OFFS = $00604000; { special type of EA }
  102. { simple [address] offset }
  103. OT_ONENESS = $00800000; { special type of immediate operand }
  104. { so UNITY == IMMEDIATE | ONENESS }
  105. OT_UNITY = $00802000; { for shift/rotate instructions }
  106. { Size of the instruction table converted by nasmconv.pas }
  107. {$ifdef x86_64}
  108. instabentries = {$i x8664nop.inc}
  109. {$else x86_64}
  110. instabentries = {$i i386nop.inc}
  111. {$endif x86_64}
  112. maxinfolen = 8;
  113. MaxInsChanges = 3; { Max things a instruction can change }
  114. type
  115. { What an instruction can change. Needed for optimizer and spilling code.
  116. Note: The order of this enumeration is should not be changed! }
  117. TInsChange = (Ch_None,
  118. {Read from a register}
  119. Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
  120. {write from a register}
  121. Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
  122. {read and write from/to a register}
  123. Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
  124. {modify the contents of a register with the purpose of using
  125. this changed content afterwards (add/sub/..., but e.g. not rep
  126. or movsd)}
  127. Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
  128. Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
  129. Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
  130. Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
  131. Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
  132. Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
  133. Ch_WMemEDI,
  134. Ch_All,
  135. { x86_64 registers }
  136. Ch_RRAX, Ch_RRCX, Ch_RRDX, Ch_RRBX, Ch_RRSP, Ch_RRBP, Ch_RRSI, Ch_RRDI,
  137. Ch_WRAX, Ch_WRCX, Ch_WRDX, Ch_WRBX, Ch_WRSP, Ch_WRBP, Ch_WRSI, Ch_WRDI,
  138. Ch_RWRAX, Ch_RWRCX, Ch_RWRDX, Ch_RWRBX, Ch_RWRSP, Ch_RWRBP, Ch_RWRSI, Ch_RWRDI,
  139. Ch_MRAX, Ch_MRCX, Ch_MRDX, Ch_MRBX, Ch_MRSP, Ch_MRBP, Ch_MRSI, Ch_MRDI
  140. );
  141. TInsProp = packed record
  142. Ch : Array[1..MaxInsChanges] of TInsChange;
  143. end;
  144. const
  145. InsProp : array[tasmop] of TInsProp =
  146. {$ifdef x86_64}
  147. {$i x8664pro.inc}
  148. {$else x86_64}
  149. {$i i386prop.inc}
  150. {$endif x86_64}
  151. type
  152. TOperandOrder = (op_intel,op_att);
  153. tinsentry=packed record
  154. opcode : tasmop;
  155. ops : byte;
  156. optypes : array[0..2] of longint;
  157. code : array[0..maxinfolen] of char;
  158. flags : longint;
  159. end;
  160. pinsentry=^tinsentry;
  161. { alignment for operator }
  162. tai_align = class(tai_align_abstract)
  163. reg : tregister;
  164. constructor create(b:byte);override;
  165. constructor create_op(b: byte; _op: byte);override;
  166. function calculatefillbuf(var buf : tfillbuffer):pchar;override;
  167. end;
  168. taicpu = class(tai_cpu_abstract)
  169. opsize : topsize;
  170. constructor op_none(op : tasmop);
  171. constructor op_none(op : tasmop;_size : topsize);
  172. constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  173. constructor op_const(op : tasmop;_size : topsize;_op1 : aint);
  174. constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
  175. constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  176. constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
  177. constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
  178. constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
  179. constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
  180. constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
  181. constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
  182. constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  183. constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
  184. constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
  185. constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; const _op3 : treference);
  186. constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
  187. { this is for Jmp instructions }
  188. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  189. constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  190. constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  191. constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  192. constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  193. procedure changeopsize(siz:topsize);
  194. function GetString:string;
  195. procedure CheckNonCommutativeOpcodes;
  196. private
  197. FOperandOrder : TOperandOrder;
  198. procedure init(_size : topsize); { this need to be called by all constructor }
  199. {$ifndef NOAG386BIN}
  200. public
  201. { the next will reset all instructions that can change in pass 2 }
  202. procedure ResetPass1;override;
  203. procedure ResetPass2;override;
  204. function CheckIfValid:boolean;
  205. function Pass1(objdata:TObjData):longint;override;
  206. procedure Pass2(objdata:TObjData);override;
  207. procedure SetOperandOrder(order:TOperandOrder);
  208. function is_same_reg_move(regtype: Tregistertype):boolean;override;
  209. { register spilling code }
  210. function spilling_get_operation_type(opnr: longint): topertype;override;
  211. protected
  212. procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
  213. procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
  214. procedure ppubuildderefimploper(var o:toper);override;
  215. procedure ppuderefoper(var o:toper);override;
  216. private
  217. { next fields are filled in pass1, so pass2 is faster }
  218. inssize : shortint;
  219. insoffset : longint;
  220. LastInsOffset : longint; { need to be public to be reset }
  221. insentry : PInsEntry;
  222. function InsEnd:longint;
  223. procedure create_ot(objdata:TObjData);
  224. function Matches(p:PInsEntry):longint;
  225. function calcsize(p:PInsEntry):shortint;
  226. procedure gencode(objdata:TObjData);
  227. function NeedAddrPrefix(opidx:byte):boolean;
  228. procedure Swapoperands;
  229. function FindInsentry(objdata:TObjData):boolean;
  230. {$endif NOAG386BIN}
  231. end;
  232. function spilling_create_load(const ref:treference;r:tregister): tai;
  233. function spilling_create_store(r:tregister; const ref:treference): tai;
  234. procedure InitAsm;
  235. procedure DoneAsm;
  236. implementation
  237. uses
  238. cutils,
  239. itcpugas,
  240. symsym;
  241. {*****************************************************************************
  242. Instruction table
  243. *****************************************************************************}
  244. const
  245. {Instruction flags }
  246. IF_NONE = $00000000;
  247. IF_SM = $00000001; { size match first two operands }
  248. IF_SM2 = $00000002;
  249. IF_SB = $00000004; { unsized operands can't be non-byte }
  250. IF_SW = $00000008; { unsized operands can't be non-word }
  251. IF_SD = $00000010; { unsized operands can't be nondword }
  252. IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
  253. IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
  254. IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
  255. IF_ARMASK = $00000060; { mask for unsized argument spec }
  256. IF_PRIV = $00000100; { it's a privileged instruction }
  257. IF_SMM = $00000200; { it's only valid in SMM }
  258. IF_PROT = $00000400; { it's protected mode only }
  259. IF_NOX86_64 = $00000800; { removed instruction in x86_64 }
  260. IF_UNDOC = $00001000; { it's an undocumented instruction }
  261. IF_FPU = $00002000; { it's an FPU instruction }
  262. IF_MMX = $00004000; { it's an MMX instruction }
  263. { it's a 3DNow! instruction }
  264. IF_3DNOW = $00008000;
  265. { it's a SSE (KNI, MMX2) instruction }
  266. IF_SSE = $00010000;
  267. { SSE2 instructions }
  268. IF_SSE2 = $00020000;
  269. { SSE3 instructions }
  270. IF_SSE3 = $00040000;
  271. { SSE64 instructions }
  272. IF_SSE64 = $00080000;
  273. { the mask for processor types }
  274. {IF_PMASK = longint($FF000000);}
  275. { the mask for disassembly "prefer" }
  276. {IF_PFMASK = longint($F001FF00);}
  277. { SVM instructions }
  278. IF_SVM = $00100000;
  279. IF_8086 = $00000000; { 8086 instruction }
  280. IF_186 = $01000000; { 186+ instruction }
  281. IF_286 = $02000000; { 286+ instruction }
  282. IF_386 = $03000000; { 386+ instruction }
  283. IF_486 = $04000000; { 486+ instruction }
  284. IF_PENT = $05000000; { Pentium instruction }
  285. IF_P6 = $06000000; { P6 instruction }
  286. IF_KATMAI = $07000000; { Katmai instructions }
  287. { Willamette instructions }
  288. IF_WILLAMETTE = $08000000;
  289. { Prescott instructions }
  290. IF_PRESCOTT = $09000000;
  291. IF_X86_64 = $0a000000;
  292. IF_CYRIX = $0b000000; { Cyrix-specific instruction }
  293. IF_AMD = $0c000000; { AMD-specific instruction }
  294. IF_CENTAUR = $0d000000; { centaur-specific instruction }
  295. { added flags }
  296. IF_PRE = $40000000; { it's a prefix instruction }
  297. IF_PASS2 = longint($80000000); { if the instruction can change in a second pass }
  298. type
  299. TInsTabCache=array[TasmOp] of longint;
  300. PInsTabCache=^TInsTabCache;
  301. const
  302. {$ifdef x86_64}
  303. InsTab:array[0..instabentries-1] of TInsEntry={$i x8664tab.inc}
  304. {$else x86_64}
  305. InsTab:array[0..instabentries-1] of TInsEntry={$i i386tab.inc}
  306. {$endif x86_64}
  307. var
  308. InsTabCache : PInsTabCache;
  309. const
  310. {$ifdef x86_64}
  311. { Intel style operands ! }
  312. opsize_2_type:array[0..2,topsize] of longint=(
  313. (OT_NONE,
  314. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,OT_BITS64,OT_BITS64,OT_BITS64,
  315. OT_BITS16,OT_BITS32,OT_BITS64,
  316. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  317. OT_BITS64,
  318. OT_NEAR,OT_FAR,OT_SHORT,
  319. OT_NONE,
  320. OT_NONE
  321. ),
  322. (OT_NONE,
  323. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,OT_BITS8,OT_BITS16,OT_BITS32,
  324. OT_BITS16,OT_BITS32,OT_BITS64,
  325. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  326. OT_BITS64,
  327. OT_NEAR,OT_FAR,OT_SHORT,
  328. OT_NONE,
  329. OT_NONE
  330. ),
  331. (OT_NONE,
  332. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,
  333. OT_BITS16,OT_BITS32,OT_BITS64,
  334. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  335. OT_BITS64,
  336. OT_NEAR,OT_FAR,OT_SHORT,
  337. OT_NONE,
  338. OT_NONE
  339. )
  340. );
  341. reg_ot_table : array[tregisterindex] of longint = (
  342. {$i r8664ot.inc}
  343. );
  344. {$else x86_64}
  345. { Intel style operands ! }
  346. opsize_2_type:array[0..2,topsize] of longint=(
  347. (OT_NONE,
  348. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,
  349. OT_BITS16,OT_BITS32,OT_BITS64,
  350. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  351. OT_BITS64,
  352. OT_NEAR,OT_FAR,OT_SHORT,
  353. OT_NONE,
  354. OT_NONE
  355. ),
  356. (OT_NONE,
  357. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,
  358. OT_BITS16,OT_BITS32,OT_BITS64,
  359. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  360. OT_BITS64,
  361. OT_NEAR,OT_FAR,OT_SHORT,
  362. OT_NONE,
  363. OT_NONE
  364. ),
  365. (OT_NONE,
  366. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,
  367. OT_BITS16,OT_BITS32,OT_BITS64,
  368. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  369. OT_BITS64,
  370. OT_NEAR,OT_FAR,OT_SHORT,
  371. OT_NONE,
  372. OT_NONE
  373. )
  374. );
  375. reg_ot_table : array[tregisterindex] of longint = (
  376. {$i r386ot.inc}
  377. );
  378. {$endif x86_64}
  379. { Operation type for spilling code }
  380. type
  381. toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
  382. var
  383. operation_type_table : ^toperation_type_table;
  384. {****************************************************************************
  385. TAI_ALIGN
  386. ****************************************************************************}
  387. constructor tai_align.create(b: byte);
  388. begin
  389. inherited create(b);
  390. reg:=NR_ECX;
  391. end;
  392. constructor tai_align.create_op(b: byte; _op: byte);
  393. begin
  394. inherited create_op(b,_op);
  395. reg:=NR_NO;
  396. end;
  397. function tai_align.calculatefillbuf(var buf : tfillbuffer):pchar;
  398. const
  399. alignarray:array[0..5] of string[8]=(
  400. #$8D#$B4#$26#$00#$00#$00#$00,
  401. #$8D#$B6#$00#$00#$00#$00,
  402. #$8D#$74#$26#$00,
  403. #$8D#$76#$00,
  404. #$89#$F6,
  405. #$90
  406. );
  407. var
  408. bufptr : pchar;
  409. j : longint;
  410. begin
  411. inherited calculatefillbuf(buf);
  412. if not use_op then
  413. begin
  414. bufptr:=pchar(@buf);
  415. while (fillsize>0) do
  416. begin
  417. for j:=0 to 5 do
  418. if (fillsize>=length(alignarray[j])) then
  419. break;
  420. move(alignarray[j][1],bufptr^,length(alignarray[j]));
  421. inc(bufptr,length(alignarray[j]));
  422. dec(fillsize,length(alignarray[j]));
  423. end;
  424. end;
  425. calculatefillbuf:=pchar(@buf);
  426. end;
  427. {*****************************************************************************
  428. Taicpu Constructors
  429. *****************************************************************************}
  430. procedure taicpu.changeopsize(siz:topsize);
  431. begin
  432. opsize:=siz;
  433. end;
  434. procedure taicpu.init(_size : topsize);
  435. begin
  436. { default order is att }
  437. FOperandOrder:=op_att;
  438. segprefix:=NR_NO;
  439. opsize:=_size;
  440. {$ifndef NOAG386BIN}
  441. insentry:=nil;
  442. LastInsOffset:=-1;
  443. InsOffset:=0;
  444. InsSize:=0;
  445. {$endif}
  446. end;
  447. constructor taicpu.op_none(op : tasmop);
  448. begin
  449. inherited create(op);
  450. init(S_NO);
  451. end;
  452. constructor taicpu.op_none(op : tasmop;_size : topsize);
  453. begin
  454. inherited create(op);
  455. init(_size);
  456. end;
  457. constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  458. begin
  459. inherited create(op);
  460. init(_size);
  461. ops:=1;
  462. loadreg(0,_op1);
  463. end;
  464. constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aint);
  465. begin
  466. inherited create(op);
  467. init(_size);
  468. ops:=1;
  469. loadconst(0,_op1);
  470. end;
  471. constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
  472. begin
  473. inherited create(op);
  474. init(_size);
  475. ops:=1;
  476. loadref(0,_op1);
  477. end;
  478. constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  479. begin
  480. inherited create(op);
  481. init(_size);
  482. ops:=2;
  483. loadreg(0,_op1);
  484. loadreg(1,_op2);
  485. end;
  486. constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
  487. begin
  488. inherited create(op);
  489. init(_size);
  490. ops:=2;
  491. loadreg(0,_op1);
  492. loadconst(1,_op2);
  493. end;
  494. constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
  495. begin
  496. inherited create(op);
  497. init(_size);
  498. ops:=2;
  499. loadreg(0,_op1);
  500. loadref(1,_op2);
  501. end;
  502. constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
  503. begin
  504. inherited create(op);
  505. init(_size);
  506. ops:=2;
  507. loadconst(0,_op1);
  508. loadreg(1,_op2);
  509. end;
  510. constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
  511. begin
  512. inherited create(op);
  513. init(_size);
  514. ops:=2;
  515. loadconst(0,_op1);
  516. loadconst(1,_op2);
  517. end;
  518. constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
  519. begin
  520. inherited create(op);
  521. init(_size);
  522. ops:=2;
  523. loadconst(0,_op1);
  524. loadref(1,_op2);
  525. end;
  526. constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
  527. begin
  528. inherited create(op);
  529. init(_size);
  530. ops:=2;
  531. loadref(0,_op1);
  532. loadreg(1,_op2);
  533. end;
  534. constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  535. begin
  536. inherited create(op);
  537. init(_size);
  538. ops:=3;
  539. loadreg(0,_op1);
  540. loadreg(1,_op2);
  541. loadreg(2,_op3);
  542. end;
  543. constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
  544. begin
  545. inherited create(op);
  546. init(_size);
  547. ops:=3;
  548. loadconst(0,_op1);
  549. loadreg(1,_op2);
  550. loadreg(2,_op3);
  551. end;
  552. constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
  553. begin
  554. inherited create(op);
  555. init(_size);
  556. ops:=3;
  557. loadreg(0,_op1);
  558. loadreg(1,_op2);
  559. loadref(2,_op3);
  560. end;
  561. constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
  562. begin
  563. inherited create(op);
  564. init(_size);
  565. ops:=3;
  566. loadconst(0,_op1);
  567. loadref(1,_op2);
  568. loadreg(2,_op3);
  569. end;
  570. constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
  571. begin
  572. inherited create(op);
  573. init(_size);
  574. ops:=3;
  575. loadconst(0,_op1);
  576. loadreg(1,_op2);
  577. loadref(2,_op3);
  578. end;
  579. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  580. begin
  581. inherited create(op);
  582. init(_size);
  583. condition:=cond;
  584. ops:=1;
  585. loadsymbol(0,_op1,0);
  586. end;
  587. constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  588. begin
  589. inherited create(op);
  590. init(_size);
  591. ops:=1;
  592. loadsymbol(0,_op1,0);
  593. end;
  594. constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  595. begin
  596. inherited create(op);
  597. init(_size);
  598. ops:=1;
  599. loadsymbol(0,_op1,_op1ofs);
  600. end;
  601. constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  602. begin
  603. inherited create(op);
  604. init(_size);
  605. ops:=2;
  606. loadsymbol(0,_op1,_op1ofs);
  607. loadreg(1,_op2);
  608. end;
  609. constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  610. begin
  611. inherited create(op);
  612. init(_size);
  613. ops:=2;
  614. loadsymbol(0,_op1,_op1ofs);
  615. loadref(1,_op2);
  616. end;
  617. function taicpu.GetString:string;
  618. var
  619. i : longint;
  620. s : string;
  621. addsize : boolean;
  622. begin
  623. s:='['+std_op2str[opcode];
  624. for i:=0 to ops-1 do
  625. begin
  626. with oper[i]^ do
  627. begin
  628. if i=0 then
  629. s:=s+' '
  630. else
  631. s:=s+',';
  632. { type }
  633. addsize:=false;
  634. if (ot and OT_XMMREG)=OT_XMMREG then
  635. s:=s+'xmmreg'
  636. else
  637. if (ot and OT_MMXREG)=OT_MMXREG then
  638. s:=s+'mmxreg'
  639. else
  640. if (ot and OT_FPUREG)=OT_FPUREG then
  641. s:=s+'fpureg'
  642. else
  643. if (ot and OT_REGISTER)=OT_REGISTER then
  644. begin
  645. s:=s+'reg';
  646. addsize:=true;
  647. end
  648. else
  649. if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  650. begin
  651. s:=s+'imm';
  652. addsize:=true;
  653. end
  654. else
  655. if (ot and OT_MEMORY)=OT_MEMORY then
  656. begin
  657. s:=s+'mem';
  658. addsize:=true;
  659. end
  660. else
  661. s:=s+'???';
  662. { size }
  663. if addsize then
  664. begin
  665. if (ot and OT_BITS8)<>0 then
  666. s:=s+'8'
  667. else
  668. if (ot and OT_BITS16)<>0 then
  669. s:=s+'16'
  670. else
  671. if (ot and OT_BITS32)<>0 then
  672. s:=s+'32'
  673. else
  674. {$ifdef x86_64}
  675. if (ot and OT_BITS32)<>0 then
  676. s:=s+'64'
  677. else
  678. {$endif x86_64}
  679. s:=s+'??';
  680. { signed }
  681. if (ot and OT_SIGNED)<>0 then
  682. s:=s+'s';
  683. end;
  684. end;
  685. end;
  686. GetString:=s+']';
  687. end;
  688. procedure taicpu.Swapoperands;
  689. var
  690. p : POper;
  691. begin
  692. { Fix the operands which are in AT&T style and we need them in Intel style }
  693. case ops of
  694. 2 : begin
  695. { 0,1 -> 1,0 }
  696. p:=oper[0];
  697. oper[0]:=oper[1];
  698. oper[1]:=p;
  699. end;
  700. 3 : begin
  701. { 0,1,2 -> 2,1,0 }
  702. p:=oper[0];
  703. oper[0]:=oper[2];
  704. oper[2]:=p;
  705. end;
  706. end;
  707. end;
  708. procedure taicpu.SetOperandOrder(order:TOperandOrder);
  709. begin
  710. if FOperandOrder<>order then
  711. begin
  712. Swapoperands;
  713. FOperandOrder:=order;
  714. end;
  715. end;
  716. procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
  717. begin
  718. o.typ:=toptype(ppufile.getbyte);
  719. o.ot:=ppufile.getlongint;
  720. case o.typ of
  721. top_reg :
  722. ppufile.getdata(o.reg,sizeof(Tregister));
  723. top_ref :
  724. begin
  725. new(o.ref);
  726. ppufile.getdata(o.ref^.segment,sizeof(Tregister));
  727. ppufile.getdata(o.ref^.base,sizeof(Tregister));
  728. ppufile.getdata(o.ref^.index,sizeof(Tregister));
  729. o.ref^.scalefactor:=ppufile.getbyte;
  730. o.ref^.offset:=ppufile.getaint;
  731. o.ref^.symbol:=ppufile.getasmsymbol;
  732. o.ref^.relsymbol:=ppufile.getasmsymbol;
  733. end;
  734. top_const :
  735. o.val:=ppufile.getaint;
  736. top_local :
  737. begin
  738. new(o.localoper);
  739. with o.localoper^ do
  740. begin
  741. ppufile.getderef(localsymderef);
  742. localsymofs:=ppufile.getaint;
  743. localindexreg:=tregister(ppufile.getlongint);
  744. localscale:=ppufile.getbyte;
  745. localgetoffset:=(ppufile.getbyte<>0);
  746. end;
  747. end;
  748. end;
  749. end;
  750. procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
  751. begin
  752. ppufile.putbyte(byte(o.typ));
  753. ppufile.putlongint(o.ot);
  754. case o.typ of
  755. top_reg :
  756. ppufile.putdata(o.reg,sizeof(Tregister));
  757. top_ref :
  758. begin
  759. ppufile.putdata(o.ref^.segment,sizeof(Tregister));
  760. ppufile.putdata(o.ref^.base,sizeof(Tregister));
  761. ppufile.putdata(o.ref^.index,sizeof(Tregister));
  762. ppufile.putbyte(o.ref^.scalefactor);
  763. ppufile.putaint(o.ref^.offset);
  764. ppufile.putasmsymbol(o.ref^.symbol);
  765. ppufile.putasmsymbol(o.ref^.relsymbol);
  766. end;
  767. top_const :
  768. ppufile.putaint(o.val);
  769. top_local :
  770. begin
  771. with o.localoper^ do
  772. begin
  773. ppufile.putderef(localsymderef);
  774. ppufile.putaint(localsymofs);
  775. ppufile.putlongint(longint(localindexreg));
  776. ppufile.putbyte(localscale);
  777. ppufile.putbyte(byte(localgetoffset));
  778. end;
  779. end;
  780. end;
  781. end;
  782. procedure taicpu.ppubuildderefimploper(var o:toper);
  783. begin
  784. case o.typ of
  785. top_local :
  786. o.localoper^.localsymderef.build(tlocalvarsym(o.localoper^.localsym));
  787. end;
  788. end;
  789. procedure taicpu.ppuderefoper(var o:toper);
  790. begin
  791. case o.typ of
  792. top_ref :
  793. begin
  794. end;
  795. top_local :
  796. o.localoper^.localsym:=tlocalvarsym(o.localoper^.localsymderef.resolve);
  797. end;
  798. end;
  799. procedure taicpu.CheckNonCommutativeOpcodes;
  800. begin
  801. { we need ATT order }
  802. SetOperandOrder(op_att);
  803. if (
  804. (ops=2) and
  805. (oper[0]^.typ=top_reg) and
  806. (oper[1]^.typ=top_reg) and
  807. { if the first is ST and the second is also a register
  808. it is necessarily ST1 .. ST7 }
  809. ((oper[0]^.reg=NR_ST) or
  810. (oper[0]^.reg=NR_ST0))
  811. ) or
  812. { ((ops=1) and
  813. (oper[0]^.typ=top_reg) and
  814. (oper[0]^.reg in [R_ST1..R_ST7])) or}
  815. (ops=0) then
  816. begin
  817. if opcode=A_FSUBR then
  818. opcode:=A_FSUB
  819. else if opcode=A_FSUB then
  820. opcode:=A_FSUBR
  821. else if opcode=A_FDIVR then
  822. opcode:=A_FDIV
  823. else if opcode=A_FDIV then
  824. opcode:=A_FDIVR
  825. else if opcode=A_FSUBRP then
  826. opcode:=A_FSUBP
  827. else if opcode=A_FSUBP then
  828. opcode:=A_FSUBRP
  829. else if opcode=A_FDIVRP then
  830. opcode:=A_FDIVP
  831. else if opcode=A_FDIVP then
  832. opcode:=A_FDIVRP;
  833. end;
  834. if (
  835. (ops=1) and
  836. (oper[0]^.typ=top_reg) and
  837. (getregtype(oper[0]^.reg)=R_FPUREGISTER) and
  838. (oper[0]^.reg<>NR_ST)
  839. ) then
  840. begin
  841. if opcode=A_FSUBRP then
  842. opcode:=A_FSUBP
  843. else if opcode=A_FSUBP then
  844. opcode:=A_FSUBRP
  845. else if opcode=A_FDIVRP then
  846. opcode:=A_FDIVP
  847. else if opcode=A_FDIVP then
  848. opcode:=A_FDIVRP;
  849. end;
  850. end;
  851. {*****************************************************************************
  852. Assembler
  853. *****************************************************************************}
  854. {$ifndef NOAG386BIN}
  855. type
  856. ea=packed record
  857. sib_present : boolean;
  858. bytes : byte;
  859. size : byte;
  860. modrm : byte;
  861. sib : byte;
  862. end;
  863. procedure taicpu.create_ot(objdata:TObjData);
  864. {
  865. this function will also fix some other fields which only needs to be once
  866. }
  867. var
  868. i,l,relsize : longint;
  869. currsym : TObjSymbol;
  870. begin
  871. if ops=0 then
  872. exit;
  873. { update oper[].ot field }
  874. for i:=0 to ops-1 do
  875. with oper[i]^ do
  876. begin
  877. case typ of
  878. top_reg :
  879. begin
  880. ot:=reg_ot_table[findreg_by_number(reg)];
  881. end;
  882. top_ref :
  883. begin
  884. if ref^.refaddr=addr_no then
  885. begin
  886. { create ot field }
  887. if (ot and OT_SIZE_MASK)=0 then
  888. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  889. else
  890. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  891. if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
  892. ot:=ot or OT_MEM_OFFS;
  893. { fix scalefactor }
  894. if (ref^.index=NR_NO) then
  895. ref^.scalefactor:=0
  896. else
  897. if (ref^.scalefactor=0) then
  898. ref^.scalefactor:=1;
  899. end
  900. else
  901. begin
  902. if assigned(objdata) then
  903. begin
  904. currsym:=objdata.symbolref(ref^.symbol);
  905. l:=ref^.offset;
  906. if assigned(currsym) then
  907. inc(l,currsym.address);
  908. { when it is a forward jump we need to compensate the
  909. offset of the instruction since the previous time,
  910. because the symbol address is then still using the
  911. 'old-style' addressing.
  912. For backwards jumps this is not required because the
  913. address of the symbol is already adjusted to the
  914. new offset }
  915. if (l>InsOffset) and (LastInsOffset<>-1) then
  916. inc(l,InsOffset-LastInsOffset);
  917. { instruction size will then always become 2 (PFV) }
  918. relsize:=(InsOffset+2)-l;
  919. if (not assigned(currsym) or
  920. ((currsym.bind<>AB_EXTERNAL) and (currsym.address<>0))) and
  921. (relsize>=-128) and (relsize<=127) then
  922. ot:=OT_IMM32 or OT_SHORT
  923. else
  924. ot:=OT_IMM32 or OT_NEAR;
  925. end
  926. else
  927. ot:=OT_IMM32 or OT_NEAR;
  928. end;
  929. end;
  930. top_local :
  931. begin
  932. if (ot and OT_SIZE_MASK)=0 then
  933. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  934. else
  935. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  936. end;
  937. top_const :
  938. begin
  939. if opsize=S_NO then
  940. message(asmr_e_invalid_opcode_and_operand);
  941. if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then
  942. ot:=OT_IMM8 or OT_SIGNED
  943. else
  944. ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
  945. end;
  946. top_none :
  947. begin
  948. { generated when there was an error in the
  949. assembler reader. It never happends when generating
  950. assembler }
  951. end;
  952. else
  953. internalerror(200402261);
  954. end;
  955. end;
  956. end;
  957. function taicpu.InsEnd:longint;
  958. begin
  959. InsEnd:=InsOffset+InsSize;
  960. end;
  961. function taicpu.Matches(p:PInsEntry):longint;
  962. { * IF_SM stands for Size Match: any operand whose size is not
  963. * explicitly specified by the template is `really' intended to be
  964. * the same size as the first size-specified operand.
  965. * Non-specification is tolerated in the input instruction, but
  966. * _wrong_ specification is not.
  967. *
  968. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  969. * three-operand instructions such as SHLD: it implies that the
  970. * first two operands must match in size, but that the third is
  971. * required to be _unspecified_.
  972. *
  973. * IF_SB invokes Size Byte: operands with unspecified size in the
  974. * template are really bytes, and so no non-byte specification in
  975. * the input instruction will be tolerated. IF_SW similarly invokes
  976. * Size Word, and IF_SD invokes Size Doubleword.
  977. *
  978. * (The default state if neither IF_SM nor IF_SM2 is specified is
  979. * that any operand with unspecified size in the template is
  980. * required to have unspecified size in the instruction too...)
  981. }
  982. var
  983. i,j,asize,oprs : longint;
  984. siz : array[0..2] of longint;
  985. begin
  986. Matches:=100;
  987. { Check the opcode and operands }
  988. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  989. begin
  990. Matches:=0;
  991. exit;
  992. end;
  993. { Check that no spurious colons or TOs are present }
  994. for i:=0 to p^.ops-1 do
  995. if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  996. begin
  997. Matches:=0;
  998. exit;
  999. end;
  1000. { Check that the operand flags all match up }
  1001. for i:=0 to p^.ops-1 do
  1002. begin
  1003. if ((p^.optypes[i] and (not oper[i]^.ot)) or
  1004. ((p^.optypes[i] and OT_SIZE_MASK) and
  1005. ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
  1006. begin
  1007. if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
  1008. (oper[i]^.ot and OT_SIZE_MASK))<>0 then
  1009. begin
  1010. Matches:=0;
  1011. exit;
  1012. end
  1013. else
  1014. Matches:=1;
  1015. end;
  1016. end;
  1017. { Check operand sizes }
  1018. { as default an untyped size can get all the sizes, this is different
  1019. from nasm, but else we need to do a lot checking which opcodes want
  1020. size or not with the automatic size generation }
  1021. asize:=longint($ffffffff);
  1022. if (p^.flags and IF_SB)<>0 then
  1023. asize:=OT_BITS8
  1024. else if (p^.flags and IF_SW)<>0 then
  1025. asize:=OT_BITS16
  1026. else if (p^.flags and IF_SD)<>0 then
  1027. asize:=OT_BITS32;
  1028. if (p^.flags and IF_ARMASK)<>0 then
  1029. begin
  1030. siz[0]:=0;
  1031. siz[1]:=0;
  1032. siz[2]:=0;
  1033. if (p^.flags and IF_AR0)<>0 then
  1034. siz[0]:=asize
  1035. else if (p^.flags and IF_AR1)<>0 then
  1036. siz[1]:=asize
  1037. else if (p^.flags and IF_AR2)<>0 then
  1038. siz[2]:=asize;
  1039. end
  1040. else
  1041. begin
  1042. { we can leave because the size for all operands is forced to be
  1043. the same
  1044. but not if IF_SB IF_SW or IF_SD is set PM }
  1045. if asize=-1 then
  1046. exit;
  1047. siz[0]:=asize;
  1048. siz[1]:=asize;
  1049. siz[2]:=asize;
  1050. end;
  1051. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  1052. begin
  1053. if (p^.flags and IF_SM2)<>0 then
  1054. oprs:=2
  1055. else
  1056. oprs:=p^.ops;
  1057. for i:=0 to oprs-1 do
  1058. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  1059. begin
  1060. for j:=0 to oprs-1 do
  1061. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  1062. break;
  1063. end;
  1064. end
  1065. else
  1066. oprs:=2;
  1067. { Check operand sizes }
  1068. for i:=0 to p^.ops-1 do
  1069. begin
  1070. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  1071. ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  1072. { Immediates can always include smaller size }
  1073. ((oper[i]^.ot and OT_IMMEDIATE)=0) and
  1074. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
  1075. Matches:=2;
  1076. end;
  1077. end;
  1078. procedure taicpu.ResetPass1;
  1079. begin
  1080. { we need to reset everything here, because the choosen insentry
  1081. can be invalid for a new situation where the previously optimized
  1082. insentry is not correct }
  1083. InsEntry:=nil;
  1084. InsSize:=0;
  1085. LastInsOffset:=-1;
  1086. end;
  1087. procedure taicpu.ResetPass2;
  1088. begin
  1089. { we are here in a second pass, check if the instruction can be optimized }
  1090. if assigned(InsEntry) and
  1091. ((InsEntry^.flags and IF_PASS2)<>0) then
  1092. begin
  1093. InsEntry:=nil;
  1094. InsSize:=0;
  1095. end;
  1096. LastInsOffset:=-1;
  1097. end;
  1098. function taicpu.CheckIfValid:boolean;
  1099. begin
  1100. result:=FindInsEntry(nil);
  1101. end;
  1102. function taicpu.FindInsentry(objdata:TObjData):boolean;
  1103. var
  1104. i : longint;
  1105. begin
  1106. result:=false;
  1107. { Things which may only be done once, not when a second pass is done to
  1108. optimize }
  1109. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  1110. begin
  1111. { We need intel style operands }
  1112. SetOperandOrder(op_intel);
  1113. { create the .ot fields }
  1114. create_ot(objdata);
  1115. { set the file postion }
  1116. aktfilepos:=fileinfo;
  1117. end
  1118. else
  1119. begin
  1120. { we've already an insentry so it's valid }
  1121. result:=true;
  1122. exit;
  1123. end;
  1124. { Lookup opcode in the table }
  1125. InsSize:=-1;
  1126. i:=instabcache^[opcode];
  1127. if i=-1 then
  1128. begin
  1129. Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
  1130. exit;
  1131. end;
  1132. insentry:=@instab[i];
  1133. while (insentry^.opcode=opcode) do
  1134. begin
  1135. if matches(insentry)=100 then
  1136. begin
  1137. result:=true;
  1138. exit;
  1139. end;
  1140. inc(i);
  1141. insentry:=@instab[i];
  1142. end;
  1143. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  1144. { No instruction found, set insentry to nil and inssize to -1 }
  1145. insentry:=nil;
  1146. inssize:=-1;
  1147. end;
  1148. function taicpu.Pass1(objdata:TObjData):longint;
  1149. begin
  1150. Pass1:=0;
  1151. { Save the old offset and set the new offset }
  1152. InsOffset:=ObjData.CurrObjSec.Size;
  1153. { Error? }
  1154. if (Insentry=nil) and (InsSize=-1) then
  1155. exit;
  1156. { set the file postion }
  1157. aktfilepos:=fileinfo;
  1158. { Get InsEntry }
  1159. if FindInsEntry(ObjData) then
  1160. begin
  1161. { Calculate instruction size }
  1162. InsSize:=calcsize(insentry);
  1163. if segprefix<>NR_NO then
  1164. inc(InsSize);
  1165. { Fix opsize if size if forced }
  1166. if (insentry^.flags and (IF_SB or IF_SW or IF_SD))<>0 then
  1167. begin
  1168. if (insentry^.flags and IF_ARMASK)=0 then
  1169. begin
  1170. if (insentry^.flags and IF_SB)<>0 then
  1171. begin
  1172. if opsize=S_NO then
  1173. opsize:=S_B;
  1174. end
  1175. else if (insentry^.flags and IF_SW)<>0 then
  1176. begin
  1177. if opsize=S_NO then
  1178. opsize:=S_W;
  1179. end
  1180. else if (insentry^.flags and IF_SD)<>0 then
  1181. begin
  1182. if opsize=S_NO then
  1183. opsize:=S_L;
  1184. end;
  1185. end;
  1186. end;
  1187. LastInsOffset:=InsOffset;
  1188. Pass1:=InsSize;
  1189. exit;
  1190. end;
  1191. LastInsOffset:=-1;
  1192. end;
  1193. procedure taicpu.Pass2(objdata:TObjData);
  1194. var
  1195. c : longint;
  1196. begin
  1197. { error in pass1 ? }
  1198. if insentry=nil then
  1199. exit;
  1200. aktfilepos:=fileinfo;
  1201. { Segment override }
  1202. if (segprefix<>NR_NO) then
  1203. begin
  1204. case segprefix of
  1205. NR_CS : c:=$2e;
  1206. NR_DS : c:=$3e;
  1207. NR_ES : c:=$26;
  1208. NR_FS : c:=$64;
  1209. NR_GS : c:=$65;
  1210. NR_SS : c:=$36;
  1211. end;
  1212. objdata.writebytes(c,1);
  1213. { fix the offset for GenNode }
  1214. inc(InsOffset);
  1215. end;
  1216. { Generate the instruction }
  1217. GenCode(objdata);
  1218. end;
  1219. function taicpu.needaddrprefix(opidx:byte):boolean;
  1220. begin
  1221. result:=(oper[opidx]^.typ=top_ref) and
  1222. (oper[opidx]^.ref^.refaddr=addr_no) and
  1223. (
  1224. (
  1225. (oper[opidx]^.ref^.index<>NR_NO) and
  1226. (getsubreg(oper[opidx]^.ref^.index)<>R_SUBADDR)
  1227. ) or
  1228. (
  1229. (oper[opidx]^.ref^.base<>NR_NO) and
  1230. (getsubreg(oper[opidx]^.ref^.base)<>R_SUBADDR)
  1231. )
  1232. );
  1233. end;
  1234. function regval(r:Tregister):byte;
  1235. const
  1236. {$ifdef x86_64}
  1237. opcode_table:array[tregisterindex] of tregisterindex = (
  1238. {$i r8664op.inc}
  1239. );
  1240. {$else x86_64}
  1241. opcode_table:array[tregisterindex] of tregisterindex = (
  1242. {$i r386op.inc}
  1243. );
  1244. {$endif x86_64}
  1245. var
  1246. regidx : tregisterindex;
  1247. begin
  1248. regidx:=findreg_by_number(r);
  1249. if regidx<>0 then
  1250. result:=opcode_table[regidx]
  1251. else
  1252. begin
  1253. Message1(asmw_e_invalid_register,generic_regname(r));
  1254. result:=0;
  1255. end;
  1256. end;
  1257. {$ifdef x86_64}
  1258. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  1259. var
  1260. sym : tasmsymbol;
  1261. md,s,rv : byte;
  1262. base,index,scalefactor,
  1263. o : longint;
  1264. ir,br : Tregister;
  1265. isub,bsub : tsubregister;
  1266. begin
  1267. process_ea:=false;
  1268. {Register ?}
  1269. if (input.typ=top_reg) then
  1270. begin
  1271. rv:=regval(input.reg);
  1272. output.sib_present:=false;
  1273. output.bytes:=0;
  1274. output.modrm:=$c0 or (rfield shl 3) or rv;
  1275. output.size:=1;
  1276. process_ea:=true;
  1277. exit;
  1278. end;
  1279. {No register, so memory reference.}
  1280. if (input.typ<>top_ref) then
  1281. internalerror(200409262);
  1282. if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
  1283. ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
  1284. internalerror(200301081);
  1285. ir:=input.ref^.index;
  1286. br:=input.ref^.base;
  1287. isub:=getsubreg(ir);
  1288. bsub:=getsubreg(br);
  1289. s:=input.ref^.scalefactor;
  1290. o:=input.ref^.offset;
  1291. sym:=input.ref^.symbol;
  1292. { it's direct address }
  1293. if (br=NR_NO) and (ir=NR_NO) then
  1294. begin
  1295. { it's a pure offset }
  1296. output.sib_present:=false;
  1297. output.bytes:=4;
  1298. output.modrm:=5 or (rfield shl 3);
  1299. end
  1300. else
  1301. { it's an indirection }
  1302. begin
  1303. { 16 bit address? }
  1304. if ((ir<>NR_NO) and (isub<>R_SUBADDR)) or
  1305. ((br<>NR_NO) and (bsub<>R_SUBADDR)) then
  1306. {$ifdef x86_64}
  1307. message(asmw_e_16bit_32bit_not_supported);
  1308. {$else x86_64}
  1309. message(asmw_e_16bit_not_supported);
  1310. {$endif x86_64}
  1311. {$ifdef OPTEA}
  1312. { make single reg base }
  1313. if (br=NR_NO) and (s=1) then
  1314. begin
  1315. br:=ir;
  1316. ir:=NR_NO;
  1317. end;
  1318. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  1319. if (br=NR_NO) and
  1320. (((s=2) and (ir<>NR_ESP)) or
  1321. (s=3) or (s=5) or (s=9)) then
  1322. begin
  1323. br:=ir;
  1324. dec(s);
  1325. end;
  1326. { swap ESP into base if scalefactor is 1 }
  1327. if (s=1) and (ir=NR_ESP) then
  1328. begin
  1329. ir:=br;
  1330. br:=NR_ESP;
  1331. end;
  1332. {$endif OPTEA}
  1333. { wrong, for various reasons }
  1334. if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
  1335. exit;
  1336. { base }
  1337. case br of
  1338. NR_RAX : base:=0;
  1339. NR_RCX : base:=1;
  1340. NR_RDX : base:=2;
  1341. NR_RBX : base:=3;
  1342. NR_RSP : base:=4;
  1343. NR_NO,
  1344. NR_RBP : base:=5;
  1345. NR_RSI : base:=6;
  1346. NR_RDI : base:=7;
  1347. else
  1348. exit;
  1349. end;
  1350. { index }
  1351. case ir of
  1352. NR_EAX : index:=0;
  1353. NR_ECX : index:=1;
  1354. NR_EDX : index:=2;
  1355. NR_EBX : index:=3;
  1356. NR_NO : index:=4;
  1357. NR_EBP : index:=5;
  1358. NR_ESI : index:=6;
  1359. NR_EDI : index:=7;
  1360. else
  1361. exit;
  1362. end;
  1363. case s of
  1364. 0,
  1365. 1 : scalefactor:=0;
  1366. 2 : scalefactor:=1;
  1367. 4 : scalefactor:=2;
  1368. 8 : scalefactor:=3;
  1369. else
  1370. exit;
  1371. end;
  1372. if (br=NR_NO) or
  1373. ((br<>NR_EBP) and (o=0) and (sym=nil)) then
  1374. md:=0
  1375. else
  1376. if ((o>=-128) and (o<=127) and (sym=nil)) then
  1377. md:=1
  1378. else
  1379. md:=2;
  1380. if (br=NR_NO) or (md=2) then
  1381. output.bytes:=4
  1382. else
  1383. output.bytes:=md;
  1384. { SIB needed ? }
  1385. if (ir=NR_NO) and (br<>NR_ESP) then
  1386. begin
  1387. output.sib_present:=false;
  1388. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  1389. end
  1390. else
  1391. begin
  1392. output.sib_present:=true;
  1393. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  1394. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  1395. end;
  1396. end;
  1397. if output.sib_present then
  1398. output.size:=2+output.bytes
  1399. else
  1400. output.size:=1+output.bytes;
  1401. process_ea:=true;
  1402. end;
  1403. {$else x86_64}
  1404. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  1405. var
  1406. sym : tasmsymbol;
  1407. md,s,rv : byte;
  1408. base,index,scalefactor,
  1409. o : longint;
  1410. ir,br : Tregister;
  1411. isub,bsub : tsubregister;
  1412. begin
  1413. process_ea:=false;
  1414. {Register ?}
  1415. if (input.typ=top_reg) then
  1416. begin
  1417. rv:=regval(input.reg);
  1418. output.sib_present:=false;
  1419. output.bytes:=0;
  1420. output.modrm:=$c0 or (rfield shl 3) or rv;
  1421. output.size:=1;
  1422. process_ea:=true;
  1423. exit;
  1424. end;
  1425. {No register, so memory reference.}
  1426. if (input.typ<>top_ref) then
  1427. internalerror(200409262);
  1428. if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
  1429. ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
  1430. internalerror(200301081);
  1431. ir:=input.ref^.index;
  1432. br:=input.ref^.base;
  1433. isub:=getsubreg(ir);
  1434. bsub:=getsubreg(br);
  1435. s:=input.ref^.scalefactor;
  1436. o:=input.ref^.offset;
  1437. sym:=input.ref^.symbol;
  1438. { it's direct address }
  1439. if (br=NR_NO) and (ir=NR_NO) then
  1440. begin
  1441. { it's a pure offset }
  1442. output.sib_present:=false;
  1443. output.bytes:=4;
  1444. output.modrm:=5 or (rfield shl 3);
  1445. end
  1446. else
  1447. { it's an indirection }
  1448. begin
  1449. { 16 bit address? }
  1450. if ((ir<>NR_NO) and (isub<>R_SUBADDR)) or
  1451. ((br<>NR_NO) and (bsub<>R_SUBADDR)) then
  1452. message(asmw_e_16bit_not_supported);
  1453. {$ifdef OPTEA}
  1454. { make single reg base }
  1455. if (br=NR_NO) and (s=1) then
  1456. begin
  1457. br:=ir;
  1458. ir:=NR_NO;
  1459. end;
  1460. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  1461. if (br=NR_NO) and
  1462. (((s=2) and (ir<>NR_ESP)) or
  1463. (s=3) or (s=5) or (s=9)) then
  1464. begin
  1465. br:=ir;
  1466. dec(s);
  1467. end;
  1468. { swap ESP into base if scalefactor is 1 }
  1469. if (s=1) and (ir=NR_ESP) then
  1470. begin
  1471. ir:=br;
  1472. br:=NR_ESP;
  1473. end;
  1474. {$endif OPTEA}
  1475. { wrong, for various reasons }
  1476. if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
  1477. exit;
  1478. { base }
  1479. case br of
  1480. NR_EAX : base:=0;
  1481. NR_ECX : base:=1;
  1482. NR_EDX : base:=2;
  1483. NR_EBX : base:=3;
  1484. NR_ESP : base:=4;
  1485. NR_NO,
  1486. NR_EBP : base:=5;
  1487. NR_ESI : base:=6;
  1488. NR_EDI : base:=7;
  1489. else
  1490. exit;
  1491. end;
  1492. { index }
  1493. case ir of
  1494. NR_EAX : index:=0;
  1495. NR_ECX : index:=1;
  1496. NR_EDX : index:=2;
  1497. NR_EBX : index:=3;
  1498. NR_NO : index:=4;
  1499. NR_EBP : index:=5;
  1500. NR_ESI : index:=6;
  1501. NR_EDI : index:=7;
  1502. else
  1503. exit;
  1504. end;
  1505. case s of
  1506. 0,
  1507. 1 : scalefactor:=0;
  1508. 2 : scalefactor:=1;
  1509. 4 : scalefactor:=2;
  1510. 8 : scalefactor:=3;
  1511. else
  1512. exit;
  1513. end;
  1514. if (br=NR_NO) or
  1515. ((br<>NR_EBP) and (o=0) and (sym=nil)) then
  1516. md:=0
  1517. else
  1518. if ((o>=-128) and (o<=127) and (sym=nil)) then
  1519. md:=1
  1520. else
  1521. md:=2;
  1522. if (br=NR_NO) or (md=2) then
  1523. output.bytes:=4
  1524. else
  1525. output.bytes:=md;
  1526. { SIB needed ? }
  1527. if (ir=NR_NO) and (br<>NR_ESP) then
  1528. begin
  1529. output.sib_present:=false;
  1530. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  1531. end
  1532. else
  1533. begin
  1534. output.sib_present:=true;
  1535. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  1536. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  1537. end;
  1538. end;
  1539. if output.sib_present then
  1540. output.size:=2+output.bytes
  1541. else
  1542. output.size:=1+output.bytes;
  1543. process_ea:=true;
  1544. end;
  1545. {$endif x86_64}
  1546. function taicpu.calcsize(p:PInsEntry):shortint;
  1547. var
  1548. codes : pchar;
  1549. c : byte;
  1550. len : shortint;
  1551. ea_data : ea;
  1552. begin
  1553. len:=0;
  1554. codes:=@p^.code;
  1555. repeat
  1556. c:=ord(codes^);
  1557. inc(codes);
  1558. case c of
  1559. 0 :
  1560. break;
  1561. 1,2,3 :
  1562. begin
  1563. inc(codes,c);
  1564. inc(len,c);
  1565. end;
  1566. 8,9,10 :
  1567. begin
  1568. inc(codes);
  1569. inc(len);
  1570. end;
  1571. 4,5,6,7 :
  1572. begin
  1573. if opsize=S_W then
  1574. inc(len,2)
  1575. else
  1576. inc(len);
  1577. end;
  1578. 15,
  1579. 12,13,14,
  1580. 16,17,18,
  1581. 20,21,22,
  1582. 40,41,42 :
  1583. inc(len);
  1584. 24,25,26,
  1585. 31,
  1586. 48,49,50 :
  1587. inc(len,2);
  1588. 28,29,30, { we don't have 16 bit immediates code }
  1589. 32,33,34,
  1590. 52,53,54,
  1591. 56,57,58 :
  1592. inc(len,4);
  1593. 192,193,194 :
  1594. if NeedAddrPrefix(c-192) then
  1595. inc(len);
  1596. 208,
  1597. 210 :
  1598. inc(len);
  1599. 200,
  1600. 201,
  1601. 202,
  1602. 209,
  1603. 211,
  1604. 217,218: ;
  1605. 219,220 :
  1606. inc(len);
  1607. 216 :
  1608. begin
  1609. inc(codes);
  1610. inc(len);
  1611. end;
  1612. 224,225,226 :
  1613. begin
  1614. InternalError(777002);
  1615. end;
  1616. else
  1617. begin
  1618. if (c>=64) and (c<=191) then
  1619. begin
  1620. if not process_ea(oper[(c shr 3) and 7]^, ea_data, 0) then
  1621. Message(asmw_e_invalid_effective_address)
  1622. else
  1623. inc(len,ea_data.size);
  1624. end
  1625. else
  1626. InternalError(777003);
  1627. end;
  1628. end;
  1629. until false;
  1630. calcsize:=len;
  1631. end;
  1632. procedure taicpu.GenCode(objdata:TObjData);
  1633. {
  1634. * the actual codes (C syntax, i.e. octal):
  1635. * \0 - terminates the code. (Unless it's a literal of course.)
  1636. * \1, \2, \3 - that many literal bytes follow in the code stream
  1637. * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  1638. * (POP is never used for CS) depending on operand 0
  1639. * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
  1640. * on operand 0
  1641. * \10, \11, \12 - a literal byte follows in the code stream, to be added
  1642. * to the register value of operand 0, 1 or 2
  1643. * \17 - encodes the literal byte 0. (Some compilers don't take
  1644. * kindly to a zero byte in the _middle_ of a compile time
  1645. * string constant, so I had to put this hack in.)
  1646. * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  1647. * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  1648. * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
  1649. * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  1650. * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  1651. * assembly mode or the address-size override on the operand
  1652. * \37 - a word constant, from the _segment_ part of operand 0
  1653. * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  1654. * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  1655. * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  1656. * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  1657. * assembly mode or the address-size override on the operand
  1658. * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  1659. * \1ab - a ModRM, calculated on EA in operand a, with the spare
  1660. * field the register value of operand b.
  1661. * \2ab - a ModRM, calculated on EA in operand a, with the spare
  1662. * field equal to digit b.
  1663. * \30x - might be an 0x67 byte, depending on the address size of
  1664. * the memory reference in operand x.
  1665. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
  1666. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
  1667. * \312 - indicates fixed 64-bit address size, i.e. optional 0x48.
  1668. * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
  1669. * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
  1670. * \322 - indicates fixed 64-bit operand size, i.e. optional 0x48.
  1671. * \323 - indicates that this instruction is only valid when the
  1672. * operand size is the default (instruction to disassembler,
  1673. * generates no code in the assembler)
  1674. * \330 - a literal byte follows in the code stream, to be added
  1675. * to the condition code value of the instruction.
  1676. * \340 - reserve <operand 0> bytes of uninitialised storage.
  1677. * Operand 0 had better be a segmentless constant.
  1678. }
  1679. var
  1680. currval : longint;
  1681. currsym : tobjsymbol;
  1682. procedure getvalsym(opidx:longint);
  1683. begin
  1684. case oper[opidx]^.typ of
  1685. top_ref :
  1686. begin
  1687. currval:=oper[opidx]^.ref^.offset;
  1688. currsym:=ObjData.symbolref(oper[opidx]^.ref^.symbol);
  1689. end;
  1690. top_const :
  1691. begin
  1692. currval:=longint(oper[opidx]^.val);
  1693. currsym:=nil;
  1694. end;
  1695. else
  1696. Message(asmw_e_immediate_or_reference_expected);
  1697. end;
  1698. end;
  1699. const
  1700. CondVal:array[TAsmCond] of byte=($0,
  1701. $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
  1702. $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
  1703. $0, $A, $A, $B, $8, $4);
  1704. var
  1705. c : byte;
  1706. pb,
  1707. codes : pchar;
  1708. bytes : array[0..3] of byte;
  1709. rfield,
  1710. data,s,opidx : longint;
  1711. ea_data : ea;
  1712. begin
  1713. { safety check }
  1714. if objdata.currobjsec.size<>insoffset then
  1715. internalerror(200130121);
  1716. { load data to write }
  1717. codes:=insentry^.code;
  1718. { Force word push/pop for registers }
  1719. if (opsize=S_W) and ((codes[0]=#4) or (codes[0]=#6) or
  1720. ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
  1721. begin
  1722. bytes[0]:=$66;
  1723. objdata.writebytes(bytes,1);
  1724. end;
  1725. repeat
  1726. c:=ord(codes^);
  1727. inc(codes);
  1728. case c of
  1729. 0 :
  1730. break;
  1731. 1,2,3 :
  1732. begin
  1733. objdata.writebytes(codes^,c);
  1734. inc(codes,c);
  1735. end;
  1736. 4,6 :
  1737. begin
  1738. case oper[0]^.reg of
  1739. NR_CS:
  1740. bytes[0]:=$e;
  1741. NR_NO,
  1742. NR_DS:
  1743. bytes[0]:=$1e;
  1744. NR_ES:
  1745. bytes[0]:=$6;
  1746. NR_SS:
  1747. bytes[0]:=$16;
  1748. else
  1749. internalerror(777004);
  1750. end;
  1751. if c=4 then
  1752. inc(bytes[0]);
  1753. objdata.writebytes(bytes,1);
  1754. end;
  1755. 5,7 :
  1756. begin
  1757. case oper[0]^.reg of
  1758. NR_FS:
  1759. bytes[0]:=$a0;
  1760. NR_GS:
  1761. bytes[0]:=$a8;
  1762. else
  1763. internalerror(777005);
  1764. end;
  1765. if c=5 then
  1766. inc(bytes[0]);
  1767. objdata.writebytes(bytes,1);
  1768. end;
  1769. 8,9,10 :
  1770. begin
  1771. bytes[0]:=ord(codes^)+regval(oper[c-8]^.reg);
  1772. inc(codes);
  1773. objdata.writebytes(bytes,1);
  1774. end;
  1775. 15 :
  1776. begin
  1777. bytes[0]:=0;
  1778. objdata.writebytes(bytes,1);
  1779. end;
  1780. 12,13,14 :
  1781. begin
  1782. getvalsym(c-12);
  1783. if (currval<-128) or (currval>127) then
  1784. Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
  1785. if assigned(currsym) then
  1786. objdata.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
  1787. else
  1788. objdata.writebytes(currval,1);
  1789. end;
  1790. 16,17,18 :
  1791. begin
  1792. getvalsym(c-16);
  1793. if (currval<-256) or (currval>255) then
  1794. Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
  1795. if assigned(currsym) then
  1796. objdata.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
  1797. else
  1798. objdata.writebytes(currval,1);
  1799. end;
  1800. 20,21,22 :
  1801. begin
  1802. getvalsym(c-20);
  1803. if (currval<0) or (currval>255) then
  1804. Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
  1805. if assigned(currsym) then
  1806. objdata.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
  1807. else
  1808. objdata.writebytes(currval,1);
  1809. end;
  1810. 24,25,26 :
  1811. begin
  1812. getvalsym(c-24);
  1813. if (currval<-65536) or (currval>65535) then
  1814. Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
  1815. if assigned(currsym) then
  1816. objdata.writereloc(currval,2,currsym,RELOC_ABSOLUTE)
  1817. else
  1818. objdata.writebytes(currval,2);
  1819. end;
  1820. 28,29,30 :
  1821. begin
  1822. getvalsym(c-28);
  1823. if assigned(currsym) then
  1824. objdata.writereloc(currval,4,currsym,RELOC_ABSOLUTE)
  1825. else
  1826. objdata.writebytes(currval,4);
  1827. end;
  1828. 32,33,34 :
  1829. begin
  1830. getvalsym(c-32);
  1831. if assigned(currsym) then
  1832. objdata.writereloc(currval,4,currsym,RELOC_ABSOLUTE)
  1833. else
  1834. objdata.writebytes(currval,4);
  1835. end;
  1836. 40,41,42 :
  1837. begin
  1838. getvalsym(c-40);
  1839. data:=currval-insend;
  1840. if assigned(currsym) then
  1841. inc(data,currsym.address);
  1842. if (data>127) or (data<-128) then
  1843. Message1(asmw_e_short_jmp_out_of_range,tostr(data));
  1844. objdata.writebytes(data,1);
  1845. end;
  1846. 52,53,54 :
  1847. begin
  1848. getvalsym(c-52);
  1849. if assigned(currsym) then
  1850. objdata.writereloc(currval,4,currsym,RELOC_RELATIVE)
  1851. else
  1852. objdata.writereloc(currval-insend,4,nil,RELOC_ABSOLUTE)
  1853. end;
  1854. 56,57,58 :
  1855. begin
  1856. getvalsym(c-56);
  1857. if assigned(currsym) then
  1858. objdata.writereloc(currval,4,currsym,RELOC_RELATIVE)
  1859. else
  1860. objdata.writereloc(currval-insend,4,nil,RELOC_ABSOLUTE)
  1861. end;
  1862. 192,193,194 :
  1863. begin
  1864. if NeedAddrPrefix(c-192) then
  1865. begin
  1866. bytes[0]:=$67;
  1867. objdata.writebytes(bytes,1);
  1868. end;
  1869. end;
  1870. 200 :
  1871. begin
  1872. bytes[0]:=$67;
  1873. objdata.writebytes(bytes,1);
  1874. end;
  1875. 208 :
  1876. begin
  1877. bytes[0]:=$66;
  1878. objdata.writebytes(bytes,1);
  1879. end;
  1880. 210 :
  1881. begin
  1882. bytes[0]:=$48;
  1883. objdata.writebytes(bytes,1);
  1884. end;
  1885. 216 :
  1886. begin
  1887. bytes[0]:=ord(codes^)+condval[condition];
  1888. inc(codes);
  1889. objdata.writebytes(bytes,1);
  1890. end;
  1891. 201,
  1892. 202,
  1893. 209,
  1894. 211,
  1895. 217,218 :
  1896. begin
  1897. { these are dissambler hints or 32 bit prefixes which
  1898. are not needed }
  1899. end;
  1900. 219 :
  1901. begin
  1902. bytes[0]:=$f3;
  1903. objdata.writebytes(bytes,1);
  1904. end;
  1905. 220 :
  1906. begin
  1907. bytes[0]:=$f2;
  1908. objdata.writebytes(bytes,1);
  1909. end;
  1910. 31,
  1911. 48,49,50,
  1912. 224,225,226 :
  1913. begin
  1914. InternalError(777006);
  1915. end
  1916. else
  1917. begin
  1918. if (c>=64) and (c<=191) then
  1919. begin
  1920. if (c<127) then
  1921. begin
  1922. if (oper[c and 7]^.typ=top_reg) then
  1923. rfield:=regval(oper[c and 7]^.reg)
  1924. else
  1925. rfield:=regval(oper[c and 7]^.ref^.base);
  1926. end
  1927. else
  1928. rfield:=c and 7;
  1929. opidx:=(c shr 3) and 7;
  1930. if not process_ea(oper[opidx]^,ea_data,rfield) then
  1931. Message(asmw_e_invalid_effective_address);
  1932. pb:=@bytes;
  1933. pb^:=chr(ea_data.modrm);
  1934. inc(pb);
  1935. if ea_data.sib_present then
  1936. begin
  1937. pb^:=chr(ea_data.sib);
  1938. inc(pb);
  1939. end;
  1940. s:=pb-pchar(@bytes);
  1941. objdata.writebytes(bytes,s);
  1942. case ea_data.bytes of
  1943. 0 : ;
  1944. 1 :
  1945. begin
  1946. if (oper[opidx]^.ot and OT_MEMORY)=OT_MEMORY then
  1947. begin
  1948. currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
  1949. objdata.writereloc(oper[opidx]^.ref^.offset,1,currsym,RELOC_ABSOLUTE)
  1950. end
  1951. else
  1952. begin
  1953. bytes[0]:=oper[opidx]^.ref^.offset;
  1954. objdata.writebytes(bytes,1);
  1955. end;
  1956. inc(s);
  1957. end;
  1958. 2,4 :
  1959. begin
  1960. objdata.writereloc(oper[opidx]^.ref^.offset,ea_data.bytes,
  1961. objdata.symbolref(oper[opidx]^.ref^.symbol),RELOC_ABSOLUTE);
  1962. inc(s,ea_data.bytes);
  1963. end;
  1964. end;
  1965. end
  1966. else
  1967. InternalError(777007);
  1968. end;
  1969. end;
  1970. until false;
  1971. end;
  1972. {$endif NOAG386BIN}
  1973. function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
  1974. begin
  1975. result:=(((opcode=A_MOV) or (opcode=A_XCHG)) and
  1976. (regtype = R_INTREGISTER) and
  1977. (ops=2) and
  1978. (oper[0]^.typ=top_reg) and
  1979. (oper[1]^.typ=top_reg) and
  1980. (oper[0]^.reg=oper[1]^.reg)
  1981. ) or
  1982. (((opcode=A_MOVSS) or (opcode=A_MOVSD)) and
  1983. (regtype = R_MMREGISTER) and
  1984. (ops=2) and
  1985. (oper[0]^.typ=top_reg) and
  1986. (oper[1]^.typ=top_reg) and
  1987. (oper[0]^.reg=oper[1]^.reg)
  1988. );
  1989. end;
  1990. procedure build_spilling_operation_type_table;
  1991. var
  1992. opcode : tasmop;
  1993. i : integer;
  1994. begin
  1995. new(operation_type_table);
  1996. fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
  1997. for opcode:=low(tasmop) to high(tasmop) do
  1998. begin
  1999. for i:=1 to MaxInsChanges do
  2000. begin
  2001. case InsProp[opcode].Ch[i] of
  2002. Ch_Rop1 :
  2003. operation_type_table^[opcode,0]:=operand_read;
  2004. Ch_Wop1 :
  2005. operation_type_table^[opcode,0]:=operand_write;
  2006. Ch_RWop1,
  2007. Ch_Mop1 :
  2008. operation_type_table^[opcode,0]:=operand_readwrite;
  2009. Ch_Rop2 :
  2010. operation_type_table^[opcode,1]:=operand_read;
  2011. Ch_Wop2 :
  2012. operation_type_table^[opcode,1]:=operand_write;
  2013. Ch_RWop2,
  2014. Ch_Mop2 :
  2015. operation_type_table^[opcode,1]:=operand_readwrite;
  2016. Ch_Rop3 :
  2017. operation_type_table^[opcode,2]:=operand_read;
  2018. Ch_Wop3 :
  2019. operation_type_table^[opcode,2]:=operand_write;
  2020. Ch_RWop3,
  2021. Ch_Mop3 :
  2022. operation_type_table^[opcode,2]:=operand_readwrite;
  2023. end;
  2024. end;
  2025. end;
  2026. { Special cases that can't be decoded from the InsChanges flags }
  2027. operation_type_table^[A_IMUL,1]:=operand_readwrite;
  2028. end;
  2029. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  2030. begin
  2031. { the information in the instruction table is made for the string copy
  2032. operation MOVSD so hack here (FK)
  2033. }
  2034. if (opcode=A_MOVSD) and (ops=2) then
  2035. begin
  2036. case opnr of
  2037. 0:
  2038. result:=operand_read;
  2039. 1:
  2040. result:=operand_write;
  2041. else
  2042. internalerror(200506055);
  2043. end
  2044. end
  2045. else
  2046. result:=operation_type_table^[opcode,opnr];
  2047. end;
  2048. function spilling_create_load(const ref:treference;r:tregister): tai;
  2049. begin
  2050. case getregtype(r) of
  2051. R_INTREGISTER :
  2052. result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r);
  2053. R_MMREGISTER :
  2054. case getsubreg(r) of
  2055. R_SUBMMD:
  2056. result:=taicpu.op_ref_reg(A_MOVSD,reg2opsize(r),ref,r);
  2057. R_SUBMMS:
  2058. result:=taicpu.op_ref_reg(A_MOVSS,reg2opsize(r),ref,r);
  2059. else
  2060. internalerror(200506043);
  2061. end;
  2062. else
  2063. internalerror(200401041);
  2064. end;
  2065. end;
  2066. function spilling_create_store(r:tregister; const ref:treference): tai;
  2067. begin
  2068. case getregtype(r) of
  2069. R_INTREGISTER :
  2070. result:=taicpu.op_reg_ref(A_MOV,reg2opsize(r),r,ref);
  2071. R_MMREGISTER :
  2072. case getsubreg(r) of
  2073. R_SUBMMD:
  2074. result:=taicpu.op_reg_ref(A_MOVSD,reg2opsize(r),r,ref);
  2075. R_SUBMMS:
  2076. result:=taicpu.op_reg_ref(A_MOVSS,reg2opsize(r),r,ref);
  2077. else
  2078. internalerror(200506042);
  2079. end;
  2080. else
  2081. internalerror(200401041);
  2082. end;
  2083. end;
  2084. {*****************************************************************************
  2085. Instruction table
  2086. *****************************************************************************}
  2087. procedure BuildInsTabCache;
  2088. {$ifndef NOAG386BIN}
  2089. var
  2090. i : longint;
  2091. {$endif}
  2092. begin
  2093. {$ifndef NOAG386BIN}
  2094. new(instabcache);
  2095. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  2096. i:=0;
  2097. while (i<InsTabEntries) do
  2098. begin
  2099. if InsTabCache^[InsTab[i].OPcode]=-1 then
  2100. InsTabCache^[InsTab[i].OPcode]:=i;
  2101. inc(i);
  2102. end;
  2103. {$endif NOAG386BIN}
  2104. end;
  2105. procedure InitAsm;
  2106. begin
  2107. build_spilling_operation_type_table;
  2108. {$ifndef NOAG386BIN}
  2109. if not assigned(instabcache) then
  2110. BuildInsTabCache;
  2111. {$endif NOAG386BIN}
  2112. end;
  2113. procedure DoneAsm;
  2114. begin
  2115. if assigned(operation_type_table) then
  2116. begin
  2117. dispose(operation_type_table);
  2118. operation_type_table:=nil;
  2119. end;
  2120. {$ifndef NOAG386BIN}
  2121. if assigned(instabcache) then
  2122. begin
  2123. dispose(instabcache);
  2124. instabcache:=nil;
  2125. end;
  2126. {$endif NOAG386BIN}
  2127. end;
  2128. begin
  2129. cai_align:=tai_align;
  2130. cai_cpu:=taicpu;
  2131. end.