aasmcpu.pas 74 KB

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