aasmcpu.pas 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  4. Contains the abstract assembler implementation for the i386
  5. * Portions of this code was inspired by the NASM sources
  6. The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
  7. Julian Hall. All rights reserved.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************
  20. }
  21. unit aasmcpu;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. cclasses,globals,verbose,
  26. cpuinfo,cpubase,
  27. cgbase,
  28. symppu,symtype,symsym,
  29. aasmbase,aasmtai;
  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 x86_64no.inc}
  109. {$else x86_64}
  110. instabentries = {$i i386nop.inc}
  111. {$endif x86_64}
  112. maxinfolen = 8;
  113. type
  114. TOperandOrder = (op_intel,op_att);
  115. tinsentry=packed record
  116. opcode : tasmop;
  117. ops : byte;
  118. optypes : array[0..2] of longint;
  119. code : array[0..maxinfolen] of char;
  120. flags : longint;
  121. end;
  122. pinsentry=^tinsentry;
  123. { alignment for operator }
  124. tai_align = class(tai_align_abstract)
  125. reg : tregister;
  126. constructor create(b:byte);
  127. constructor create_op(b: byte; _op: byte);
  128. function calculatefillbuf(var buf : tfillbuffer):pchar;override;
  129. end;
  130. taicpu = class(taicpu_abstract)
  131. opsize : topsize;
  132. constructor op_none(op : tasmop);
  133. constructor op_none(op : tasmop;_size : topsize);
  134. constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  135. constructor op_const(op : tasmop;_size : topsize;_op1 : aword);
  136. constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
  137. constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  138. constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
  139. constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aword);
  140. constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister);
  141. constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aword);
  142. constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference);
  143. constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
  144. constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  145. constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;_op3 : tregister);
  146. constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference;_op3 : tregister);
  147. constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; const _op3 : treference);
  148. constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;const _op3 : treference);
  149. { this is for Jmp instructions }
  150. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  151. constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  152. constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  153. constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  154. constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  155. procedure changeopsize(siz:topsize);
  156. function GetString:string;
  157. procedure CheckNonCommutativeOpcodes;
  158. private
  159. FOperandOrder : TOperandOrder;
  160. procedure init(_size : topsize); { this need to be called by all constructor }
  161. {$ifndef NOAG386BIN}
  162. public
  163. { the next will reset all instructions that can change in pass 2 }
  164. procedure ResetPass1;
  165. procedure ResetPass2;
  166. function CheckIfValid:boolean;
  167. function Pass1(offset:longint):longint;virtual;
  168. procedure Pass2(sec:TAsmObjectdata);virtual;
  169. procedure SetOperandOrder(order:TOperandOrder);
  170. function is_same_reg_move:boolean;override;
  171. function is_reg_move:boolean;override;
  172. function spill_registers(list:Taasmoutput;
  173. rt:Tregistertype;
  174. rgget:Trggetproc;
  175. rgunget:Trgungetproc;
  176. const r:Tsuperregisterset;
  177. { var unusedregsint:Tsuperregisterset;}
  178. var live_registers_int:Tsuperregisterworklist;
  179. const spilltemplist:Tspill_temp_list):boolean;override;
  180. protected
  181. procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
  182. procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
  183. procedure ppubuildderefimploper(var o:toper);override;
  184. procedure ppuderefoper(var o:toper);override;
  185. private
  186. { next fields are filled in pass1, so pass2 is faster }
  187. inssize : shortint;
  188. insoffset,
  189. LastInsOffset : longint; { need to be public to be reset }
  190. insentry : PInsEntry;
  191. function InsEnd:longint;
  192. procedure create_ot;
  193. function Matches(p:PInsEntry):longint;
  194. function calcsize(p:PInsEntry):longint;
  195. procedure gencode(sec:TAsmObjectData);
  196. function NeedAddrPrefix(opidx:byte):boolean;
  197. procedure Swapoperands;
  198. function FindInsentry:boolean;
  199. {$endif NOAG386BIN}
  200. end;
  201. procedure InitAsm;
  202. procedure DoneAsm;
  203. implementation
  204. uses
  205. cutils,
  206. itcpugas;
  207. {*****************************************************************************
  208. Instruction table
  209. *****************************************************************************}
  210. const
  211. {Instruction flags }
  212. IF_NONE = $00000000;
  213. IF_SM = $00000001; { size match first two operands }
  214. IF_SM2 = $00000002;
  215. IF_SB = $00000004; { unsized operands can't be non-byte }
  216. IF_SW = $00000008; { unsized operands can't be non-word }
  217. IF_SD = $00000010; { unsized operands can't be nondword }
  218. IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
  219. IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
  220. IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
  221. IF_ARMASK = $00000060; { mask for unsized argument spec }
  222. IF_PRIV = $00000100; { it's a privileged instruction }
  223. IF_SMM = $00000200; { it's only valid in SMM }
  224. IF_PROT = $00000400; { it's protected mode only }
  225. IF_UNDOC = $00001000; { it's an undocumented instruction }
  226. IF_FPU = $00002000; { it's an FPU instruction }
  227. IF_MMX = $00004000; { it's an MMX instruction }
  228. { it's a 3DNow! instruction }
  229. IF_3DNOW = $00008000;
  230. { it's a SSE (KNI, MMX2) instruction }
  231. IF_SSE = $00010000;
  232. { SSE2 instructions }
  233. IF_SSE2 = $00020000;
  234. { SSE3 instructions }
  235. IF_SSE3 = $00040000;
  236. { SSE64 instructions }
  237. IF_SSE64 = $00040000;
  238. { the mask for processor types }
  239. {IF_PMASK = longint($FF000000);}
  240. { the mask for disassembly "prefer" }
  241. {IF_PFMASK = longint($F001FF00);}
  242. IF_8086 = $00000000; { 8086 instruction }
  243. IF_186 = $01000000; { 186+ instruction }
  244. IF_286 = $02000000; { 286+ instruction }
  245. IF_386 = $03000000; { 386+ instruction }
  246. IF_486 = $04000000; { 486+ instruction }
  247. IF_PENT = $05000000; { Pentium instruction }
  248. IF_P6 = $06000000; { P6 instruction }
  249. IF_KATMAI = $07000000; { Katmai instructions }
  250. { Willamette instructions }
  251. IF_WILLAMETTE = $08000000;
  252. { Prescott instructions }
  253. IF_PRESCOTT = $09000000;
  254. IF_ATHLON64 = $0a000000;
  255. IF_CYRIX = $10000000; { Cyrix-specific instruction }
  256. IF_AMD = $20000000; { AMD-specific instruction }
  257. { added flags }
  258. IF_PRE = $40000000; { it's a prefix instruction }
  259. IF_PASS2 = longint($80000000); { if the instruction can change in a second pass }
  260. type
  261. TInsTabCache=array[TasmOp] of longint;
  262. PInsTabCache=^TInsTabCache;
  263. const
  264. {$ifdef x86_64}
  265. InsTab:array[0..instabentries-1] of TInsEntry={$i x86_64ta.inc}
  266. {$else x86_64}
  267. InsTab:array[0..instabentries-1] of TInsEntry={$i i386tab.inc}
  268. {$endif x86_64}
  269. var
  270. InsTabCache : PInsTabCache;
  271. const
  272. {$ifdef x86_64}
  273. { Intel style operands ! }
  274. opsize_2_type:array[0..2,topsize] of longint=(
  275. (OT_NONE,
  276. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS16,OT_BITS32,OT_BITS32,OT_BITS64,OT_BITS64,OT_BITS64,
  277. OT_BITS16,OT_BITS32,OT_BITS64,
  278. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,OT_NONE,
  279. OT_NEAR,OT_FAR,OT_SHORT
  280. ),
  281. (OT_NONE,
  282. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS8,OT_BITS8,OT_BITS16,OT_BITS8,OT_BITS16,OT_BITS32,
  283. OT_BITS16,OT_BITS32,OT_BITS64,
  284. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,OT_NONE,
  285. OT_NEAR,OT_FAR,OT_SHORT
  286. ),
  287. (OT_NONE,
  288. OT_BITS8,OT_BITS16,OT_BITS32,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,
  289. OT_BITS16,OT_BITS32,OT_BITS64,
  290. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,OT_NONE,
  291. OT_NEAR,OT_FAR,OT_SHORT
  292. )
  293. );
  294. reg_ot_table : array[tregisterindex] of longint = (
  295. {$i r8664ot.inc}
  296. );
  297. {$else x86_64}
  298. { Intel style operands ! }
  299. opsize_2_type:array[0..2,topsize] of longint=(
  300. (OT_NONE,
  301. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS16,OT_BITS32,OT_BITS32,
  302. OT_BITS16,OT_BITS32,OT_BITS64,
  303. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,OT_NONE,
  304. OT_NEAR,OT_FAR,OT_SHORT
  305. ),
  306. (OT_NONE,
  307. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS8,OT_BITS8,OT_BITS16,
  308. OT_BITS16,OT_BITS32,OT_BITS64,
  309. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,OT_NONE,
  310. OT_NEAR,OT_FAR,OT_SHORT
  311. ),
  312. (OT_NONE,
  313. OT_BITS8,OT_BITS16,OT_BITS32,OT_NONE,OT_NONE,OT_NONE,
  314. OT_BITS16,OT_BITS32,OT_BITS64,
  315. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,OT_NONE,
  316. OT_NEAR,OT_FAR,OT_SHORT
  317. )
  318. );
  319. reg_ot_table : array[tregisterindex] of longint = (
  320. {$i r386ot.inc}
  321. );
  322. {$endif x86_64}
  323. {****************************************************************************
  324. TAI_ALIGN
  325. ****************************************************************************}
  326. constructor tai_align.create(b: byte);
  327. begin
  328. inherited create(b);
  329. reg:=NR_ECX;
  330. end;
  331. constructor tai_align.create_op(b: byte; _op: byte);
  332. begin
  333. inherited create_op(b,_op);
  334. reg:=NR_NO;
  335. end;
  336. function tai_align.calculatefillbuf(var buf : tfillbuffer):pchar;
  337. const
  338. alignarray:array[0..5] of string[8]=(
  339. #$8D#$B4#$26#$00#$00#$00#$00,
  340. #$8D#$B6#$00#$00#$00#$00,
  341. #$8D#$74#$26#$00,
  342. #$8D#$76#$00,
  343. #$89#$F6,
  344. #$90
  345. );
  346. var
  347. bufptr : pchar;
  348. j : longint;
  349. begin
  350. inherited calculatefillbuf(buf);
  351. if not use_op then
  352. begin
  353. bufptr:=pchar(@buf);
  354. while (fillsize>0) do
  355. begin
  356. for j:=0 to 5 do
  357. if (fillsize>=length(alignarray[j])) then
  358. break;
  359. move(alignarray[j][1],bufptr^,length(alignarray[j]));
  360. inc(bufptr,length(alignarray[j]));
  361. dec(fillsize,length(alignarray[j]));
  362. end;
  363. end;
  364. calculatefillbuf:=pchar(@buf);
  365. end;
  366. {*****************************************************************************
  367. Taicpu Constructors
  368. *****************************************************************************}
  369. procedure taicpu.changeopsize(siz:topsize);
  370. begin
  371. opsize:=siz;
  372. end;
  373. procedure taicpu.init(_size : topsize);
  374. begin
  375. { default order is att }
  376. FOperandOrder:=op_att;
  377. segprefix:=NR_NO;
  378. opsize:=_size;
  379. {$ifndef NOAG386BIN}
  380. insentry:=nil;
  381. LastInsOffset:=-1;
  382. InsOffset:=0;
  383. InsSize:=0;
  384. {$endif}
  385. end;
  386. constructor taicpu.op_none(op : tasmop);
  387. begin
  388. inherited create(op);
  389. init(S_NO);
  390. end;
  391. constructor taicpu.op_none(op : tasmop;_size : topsize);
  392. begin
  393. inherited create(op);
  394. init(_size);
  395. end;
  396. constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  397. begin
  398. inherited create(op);
  399. init(_size);
  400. ops:=1;
  401. loadreg(0,_op1);
  402. end;
  403. constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aword);
  404. begin
  405. inherited create(op);
  406. init(_size);
  407. ops:=1;
  408. loadconst(0,_op1);
  409. end;
  410. constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
  411. begin
  412. inherited create(op);
  413. init(_size);
  414. ops:=1;
  415. loadref(0,_op1);
  416. end;
  417. constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  418. begin
  419. inherited create(op);
  420. init(_size);
  421. ops:=2;
  422. loadreg(0,_op1);
  423. loadreg(1,_op2);
  424. end;
  425. constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aword);
  426. begin
  427. inherited create(op);
  428. init(_size);
  429. ops:=2;
  430. loadreg(0,_op1);
  431. loadconst(1,_op2);
  432. end;
  433. constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
  434. begin
  435. inherited create(op);
  436. init(_size);
  437. ops:=2;
  438. loadreg(0,_op1);
  439. loadref(1,_op2);
  440. end;
  441. constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister);
  442. begin
  443. inherited create(op);
  444. init(_size);
  445. ops:=2;
  446. loadconst(0,_op1);
  447. loadreg(1,_op2);
  448. end;
  449. constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aword);
  450. begin
  451. inherited create(op);
  452. init(_size);
  453. ops:=2;
  454. loadconst(0,_op1);
  455. loadconst(1,_op2);
  456. end;
  457. constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference);
  458. begin
  459. inherited create(op);
  460. init(_size);
  461. ops:=2;
  462. loadconst(0,_op1);
  463. loadref(1,_op2);
  464. end;
  465. constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
  466. begin
  467. inherited create(op);
  468. init(_size);
  469. ops:=2;
  470. loadref(0,_op1);
  471. loadreg(1,_op2);
  472. end;
  473. constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  474. begin
  475. inherited create(op);
  476. init(_size);
  477. ops:=3;
  478. loadreg(0,_op1);
  479. loadreg(1,_op2);
  480. loadreg(2,_op3);
  481. end;
  482. constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;_op3 : tregister);
  483. begin
  484. inherited create(op);
  485. init(_size);
  486. ops:=3;
  487. loadconst(0,_op1);
  488. loadreg(1,_op2);
  489. loadreg(2,_op3);
  490. end;
  491. constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
  492. begin
  493. inherited create(op);
  494. init(_size);
  495. ops:=3;
  496. loadreg(0,_op1);
  497. loadreg(1,_op2);
  498. loadref(2,_op3);
  499. end;
  500. constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference;_op3 : tregister);
  501. begin
  502. inherited create(op);
  503. init(_size);
  504. ops:=3;
  505. loadconst(0,_op1);
  506. loadref(1,_op2);
  507. loadreg(2,_op3);
  508. end;
  509. constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;const _op3 : treference);
  510. begin
  511. inherited create(op);
  512. init(_size);
  513. ops:=3;
  514. loadconst(0,_op1);
  515. loadreg(1,_op2);
  516. loadref(2,_op3);
  517. end;
  518. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  519. begin
  520. inherited create(op);
  521. init(_size);
  522. condition:=cond;
  523. ops:=1;
  524. loadsymbol(0,_op1,0);
  525. end;
  526. constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  527. begin
  528. inherited create(op);
  529. init(_size);
  530. ops:=1;
  531. loadsymbol(0,_op1,0);
  532. end;
  533. constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  534. begin
  535. inherited create(op);
  536. init(_size);
  537. ops:=1;
  538. loadsymbol(0,_op1,_op1ofs);
  539. end;
  540. constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  541. begin
  542. inherited create(op);
  543. init(_size);
  544. ops:=2;
  545. loadsymbol(0,_op1,_op1ofs);
  546. loadreg(1,_op2);
  547. end;
  548. constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  549. begin
  550. inherited create(op);
  551. init(_size);
  552. ops:=2;
  553. loadsymbol(0,_op1,_op1ofs);
  554. loadref(1,_op2);
  555. end;
  556. function taicpu.GetString:string;
  557. var
  558. i : longint;
  559. s : string;
  560. addsize : boolean;
  561. begin
  562. s:='['+std_op2str[opcode];
  563. for i:=0 to ops-1 do
  564. begin
  565. with oper[i]^ do
  566. begin
  567. if i=0 then
  568. s:=s+' '
  569. else
  570. s:=s+',';
  571. { type }
  572. addsize:=false;
  573. if (ot and OT_XMMREG)=OT_XMMREG then
  574. s:=s+'xmmreg'
  575. else
  576. if (ot and OT_MMXREG)=OT_MMXREG then
  577. s:=s+'mmxreg'
  578. else
  579. if (ot and OT_FPUREG)=OT_FPUREG then
  580. s:=s+'fpureg'
  581. else
  582. if (ot and OT_REGISTER)=OT_REGISTER then
  583. begin
  584. s:=s+'reg';
  585. addsize:=true;
  586. end
  587. else
  588. if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  589. begin
  590. s:=s+'imm';
  591. addsize:=true;
  592. end
  593. else
  594. if (ot and OT_MEMORY)=OT_MEMORY then
  595. begin
  596. s:=s+'mem';
  597. addsize:=true;
  598. end
  599. else
  600. s:=s+'???';
  601. { size }
  602. if addsize then
  603. begin
  604. if (ot and OT_BITS8)<>0 then
  605. s:=s+'8'
  606. else
  607. if (ot and OT_BITS16)<>0 then
  608. s:=s+'16'
  609. else
  610. if (ot and OT_BITS32)<>0 then
  611. s:=s+'32'
  612. else
  613. s:=s+'??';
  614. { signed }
  615. if (ot and OT_SIGNED)<>0 then
  616. s:=s+'s';
  617. end;
  618. end;
  619. end;
  620. GetString:=s+']';
  621. end;
  622. procedure taicpu.Swapoperands;
  623. var
  624. p : POper;
  625. begin
  626. { Fix the operands which are in AT&T style and we need them in Intel style }
  627. case ops of
  628. 2 : begin
  629. { 0,1 -> 1,0 }
  630. p:=oper[0];
  631. oper[0]:=oper[1];
  632. oper[1]:=p;
  633. end;
  634. 3 : begin
  635. { 0,1,2 -> 2,1,0 }
  636. p:=oper[0];
  637. oper[0]:=oper[2];
  638. oper[2]:=p;
  639. end;
  640. end;
  641. end;
  642. procedure taicpu.SetOperandOrder(order:TOperandOrder);
  643. begin
  644. if FOperandOrder<>order then
  645. begin
  646. Swapoperands;
  647. FOperandOrder:=order;
  648. end;
  649. end;
  650. procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
  651. begin
  652. o.typ:=toptype(ppufile.getbyte);
  653. o.ot:=ppufile.getlongint;
  654. case o.typ of
  655. top_reg :
  656. ppufile.getdata(o.reg,sizeof(Tregister));
  657. top_ref :
  658. begin
  659. new(o.ref);
  660. ppufile.getdata(o.ref^.segment,sizeof(Tregister));
  661. ppufile.getdata(o.ref^.base,sizeof(Tregister));
  662. ppufile.getdata(o.ref^.index,sizeof(Tregister));
  663. o.ref^.scalefactor:=ppufile.getbyte;
  664. o.ref^.offset:=ppufile.getlongint;
  665. o.ref^.symbol:=ppufile.getasmsymbol;
  666. end;
  667. top_const :
  668. o.val:=aword(ppufile.getlongint);
  669. top_symbol :
  670. begin
  671. o.sym:=ppufile.getasmsymbol;
  672. o.symofs:=ppufile.getlongint;
  673. end;
  674. top_local :
  675. begin
  676. ppufile.getderef(o.localsymderef);
  677. o.localsymofs:=ppufile.getlongint;
  678. o.localindexreg:=tregister(ppufile.getlongint);
  679. o.localscale:=ppufile.getbyte;
  680. o.localgetoffset:=(ppufile.getbyte<>0);
  681. end;
  682. end;
  683. end;
  684. procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
  685. begin
  686. ppufile.putbyte(byte(o.typ));
  687. ppufile.putlongint(o.ot);
  688. case o.typ of
  689. top_reg :
  690. ppufile.putdata(o.reg,sizeof(Tregister));
  691. top_ref :
  692. begin
  693. ppufile.putdata(o.ref^.segment,sizeof(Tregister));
  694. ppufile.putdata(o.ref^.base,sizeof(Tregister));
  695. ppufile.putdata(o.ref^.index,sizeof(Tregister));
  696. ppufile.putbyte(o.ref^.scalefactor);
  697. ppufile.putlongint(o.ref^.offset);
  698. ppufile.putasmsymbol(o.ref^.symbol);
  699. end;
  700. top_const :
  701. ppufile.putlongint(longint(o.val));
  702. top_symbol :
  703. begin
  704. ppufile.putasmsymbol(o.sym);
  705. ppufile.putlongint(longint(o.symofs));
  706. end;
  707. top_local :
  708. begin
  709. ppufile.putderef(o.localsymderef);
  710. ppufile.putlongint(longint(o.localsymofs));
  711. ppufile.putlongint(longint(o.localindexreg));
  712. ppufile.putbyte(o.localscale);
  713. ppufile.putbyte(byte(o.localgetoffset));
  714. end;
  715. end;
  716. end;
  717. procedure taicpu.ppubuildderefimploper(var o:toper);
  718. begin
  719. case o.typ of
  720. top_local :
  721. o.localsymderef.build(tvarsym(o.localsym));
  722. end;
  723. end;
  724. procedure taicpu.ppuderefoper(var o:toper);
  725. begin
  726. case o.typ of
  727. top_ref :
  728. begin
  729. if assigned(o.ref^.symbol) then
  730. objectlibrary.derefasmsymbol(o.ref^.symbol);
  731. end;
  732. top_symbol :
  733. objectlibrary.derefasmsymbol(o.sym);
  734. top_local :
  735. o.localsym:=tvarsym(o.localsymderef.resolve);
  736. end;
  737. end;
  738. procedure taicpu.CheckNonCommutativeOpcodes;
  739. begin
  740. { we need ATT order }
  741. SetOperandOrder(op_att);
  742. if (
  743. (ops=2) and
  744. (oper[0]^.typ=top_reg) and
  745. (oper[1]^.typ=top_reg) and
  746. { if the first is ST and the second is also a register
  747. it is necessarily ST1 .. ST7 }
  748. ((oper[0]^.reg=NR_ST) or
  749. (oper[0]^.reg=NR_ST0))
  750. ) or
  751. { ((ops=1) and
  752. (oper[0]^.typ=top_reg) and
  753. (oper[0]^.reg in [R_ST1..R_ST7])) or}
  754. (ops=0) then
  755. begin
  756. if opcode=A_FSUBR then
  757. opcode:=A_FSUB
  758. else if opcode=A_FSUB then
  759. opcode:=A_FSUBR
  760. else if opcode=A_FDIVR then
  761. opcode:=A_FDIV
  762. else if opcode=A_FDIV then
  763. opcode:=A_FDIVR
  764. else if opcode=A_FSUBRP then
  765. opcode:=A_FSUBP
  766. else if opcode=A_FSUBP then
  767. opcode:=A_FSUBRP
  768. else if opcode=A_FDIVRP then
  769. opcode:=A_FDIVP
  770. else if opcode=A_FDIVP then
  771. opcode:=A_FDIVRP;
  772. end;
  773. if (
  774. (ops=1) and
  775. (oper[0]^.typ=top_reg) and
  776. (getregtype(oper[0]^.reg)=R_FPUREGISTER) and
  777. (oper[0]^.reg<>NR_ST)
  778. ) then
  779. begin
  780. if opcode=A_FSUBRP then
  781. opcode:=A_FSUBP
  782. else if opcode=A_FSUBP then
  783. opcode:=A_FSUBRP
  784. else if opcode=A_FDIVRP then
  785. opcode:=A_FDIVP
  786. else if opcode=A_FDIVP then
  787. opcode:=A_FDIVRP;
  788. end;
  789. end;
  790. {*****************************************************************************
  791. Assembler
  792. *****************************************************************************}
  793. {$ifndef NOAG386BIN}
  794. type
  795. ea=packed record
  796. sib_present : boolean;
  797. bytes : byte;
  798. size : byte;
  799. modrm : byte;
  800. sib : byte;
  801. end;
  802. procedure taicpu.create_ot;
  803. {
  804. this function will also fix some other fields which only needs to be once
  805. }
  806. var
  807. i,l,relsize : longint;
  808. begin
  809. if ops=0 then
  810. exit;
  811. { update oper[].ot field }
  812. for i:=0 to ops-1 do
  813. with oper[i]^ do
  814. begin
  815. case typ of
  816. top_reg :
  817. begin
  818. ot:=reg_ot_table[findreg_by_number(reg)];
  819. end;
  820. top_ref :
  821. begin
  822. { create ot field }
  823. if (ot and OT_SIZE_MASK)=0 then
  824. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  825. else
  826. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  827. if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
  828. ot:=ot or OT_MEM_OFFS;
  829. { fix scalefactor }
  830. if (ref^.index=NR_NO) then
  831. ref^.scalefactor:=0
  832. else
  833. if (ref^.scalefactor=0) then
  834. ref^.scalefactor:=1;
  835. end;
  836. top_local :
  837. begin
  838. if (ot and OT_SIZE_MASK)=0 then
  839. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  840. else
  841. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  842. end;
  843. top_const :
  844. begin
  845. if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then
  846. ot:=OT_IMM8 or OT_SIGNED
  847. else
  848. ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
  849. end;
  850. top_symbol :
  851. begin
  852. if LastInsOffset=-1 then
  853. l:=0
  854. else
  855. l:=InsOffset-LastInsOffset;
  856. inc(l,symofs);
  857. if assigned(sym) then
  858. inc(l,sym.address);
  859. { instruction size will then always become 2 (PFV) }
  860. relsize:=(InsOffset+2)-l;
  861. if (not assigned(sym) or
  862. ((sym.currbind<>AB_EXTERNAL) and (sym.address<>0))) and
  863. (relsize>=-128) and (relsize<=127) then
  864. ot:=OT_IMM32 or OT_SHORT
  865. else
  866. ot:=OT_IMM32 or OT_NEAR;
  867. end;
  868. end;
  869. end;
  870. end;
  871. function taicpu.InsEnd:longint;
  872. begin
  873. InsEnd:=InsOffset+InsSize;
  874. end;
  875. function taicpu.Matches(p:PInsEntry):longint;
  876. { * IF_SM stands for Size Match: any operand whose size is not
  877. * explicitly specified by the template is `really' intended to be
  878. * the same size as the first size-specified operand.
  879. * Non-specification is tolerated in the input instruction, but
  880. * _wrong_ specification is not.
  881. *
  882. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  883. * three-operand instructions such as SHLD: it implies that the
  884. * first two operands must match in size, but that the third is
  885. * required to be _unspecified_.
  886. *
  887. * IF_SB invokes Size Byte: operands with unspecified size in the
  888. * template are really bytes, and so no non-byte specification in
  889. * the input instruction will be tolerated. IF_SW similarly invokes
  890. * Size Word, and IF_SD invokes Size Doubleword.
  891. *
  892. * (The default state if neither IF_SM nor IF_SM2 is specified is
  893. * that any operand with unspecified size in the template is
  894. * required to have unspecified size in the instruction too...)
  895. }
  896. var
  897. i,j,asize,oprs : longint;
  898. siz : array[0..2] of longint;
  899. begin
  900. Matches:=100;
  901. { Check the opcode and operands }
  902. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  903. begin
  904. Matches:=0;
  905. exit;
  906. end;
  907. { Check that no spurious colons or TOs are present }
  908. for i:=0 to p^.ops-1 do
  909. if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  910. begin
  911. Matches:=0;
  912. exit;
  913. end;
  914. { Check that the operand flags all match up }
  915. for i:=0 to p^.ops-1 do
  916. begin
  917. if ((p^.optypes[i] and (not oper[i]^.ot)) or
  918. ((p^.optypes[i] and OT_SIZE_MASK) and
  919. ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
  920. begin
  921. if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
  922. (oper[i]^.ot and OT_SIZE_MASK))<>0 then
  923. begin
  924. Matches:=0;
  925. exit;
  926. end
  927. else
  928. Matches:=1;
  929. end;
  930. end;
  931. { Check operand sizes }
  932. { as default an untyped size can get all the sizes, this is different
  933. from nasm, but else we need to do a lot checking which opcodes want
  934. size or not with the automatic size generation }
  935. asize:=longint($ffffffff);
  936. if (p^.flags and IF_SB)<>0 then
  937. asize:=OT_BITS8
  938. else if (p^.flags and IF_SW)<>0 then
  939. asize:=OT_BITS16
  940. else if (p^.flags and IF_SD)<>0 then
  941. asize:=OT_BITS32;
  942. if (p^.flags and IF_ARMASK)<>0 then
  943. begin
  944. siz[0]:=0;
  945. siz[1]:=0;
  946. siz[2]:=0;
  947. if (p^.flags and IF_AR0)<>0 then
  948. siz[0]:=asize
  949. else if (p^.flags and IF_AR1)<>0 then
  950. siz[1]:=asize
  951. else if (p^.flags and IF_AR2)<>0 then
  952. siz[2]:=asize;
  953. end
  954. else
  955. begin
  956. { we can leave because the size for all operands is forced to be
  957. the same
  958. but not if IF_SB IF_SW or IF_SD is set PM }
  959. if asize=-1 then
  960. exit;
  961. siz[0]:=asize;
  962. siz[1]:=asize;
  963. siz[2]:=asize;
  964. end;
  965. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  966. begin
  967. if (p^.flags and IF_SM2)<>0 then
  968. oprs:=2
  969. else
  970. oprs:=p^.ops;
  971. for i:=0 to oprs-1 do
  972. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  973. begin
  974. for j:=0 to oprs-1 do
  975. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  976. break;
  977. end;
  978. end
  979. else
  980. oprs:=2;
  981. { Check operand sizes }
  982. for i:=0 to p^.ops-1 do
  983. begin
  984. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  985. ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  986. { Immediates can always include smaller size }
  987. ((oper[i]^.ot and OT_IMMEDIATE)=0) and
  988. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
  989. Matches:=2;
  990. end;
  991. end;
  992. procedure taicpu.ResetPass1;
  993. begin
  994. { we need to reset everything here, because the choosen insentry
  995. can be invalid for a new situation where the previously optimized
  996. insentry is not correct }
  997. InsEntry:=nil;
  998. InsSize:=0;
  999. LastInsOffset:=-1;
  1000. end;
  1001. procedure taicpu.ResetPass2;
  1002. begin
  1003. { we are here in a second pass, check if the instruction can be optimized }
  1004. if assigned(InsEntry) and
  1005. ((InsEntry^.flags and IF_PASS2)<>0) then
  1006. begin
  1007. InsEntry:=nil;
  1008. InsSize:=0;
  1009. end;
  1010. LastInsOffset:=-1;
  1011. end;
  1012. function taicpu.CheckIfValid:boolean;
  1013. begin
  1014. result:=FindInsEntry;
  1015. end;
  1016. function taicpu.FindInsentry:boolean;
  1017. var
  1018. i : longint;
  1019. begin
  1020. result:=false;
  1021. { Things which may only be done once, not when a second pass is done to
  1022. optimize }
  1023. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  1024. begin
  1025. { We need intel style operands }
  1026. SetOperandOrder(op_intel);
  1027. { create the .ot fields }
  1028. create_ot;
  1029. { set the file postion }
  1030. aktfilepos:=fileinfo;
  1031. end
  1032. else
  1033. begin
  1034. { we've already an insentry so it's valid }
  1035. result:=true;
  1036. exit;
  1037. end;
  1038. { Lookup opcode in the table }
  1039. InsSize:=-1;
  1040. i:=instabcache^[opcode];
  1041. if i=-1 then
  1042. begin
  1043. Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
  1044. exit;
  1045. end;
  1046. insentry:=@instab[i];
  1047. while (insentry^.opcode=opcode) do
  1048. begin
  1049. if matches(insentry)=100 then
  1050. begin
  1051. result:=true;
  1052. exit;
  1053. end;
  1054. inc(i);
  1055. insentry:=@instab[i];
  1056. end;
  1057. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  1058. { No instruction found, set insentry to nil and inssize to -1 }
  1059. insentry:=nil;
  1060. inssize:=-1;
  1061. end;
  1062. function taicpu.Pass1(offset:longint):longint;
  1063. begin
  1064. Pass1:=0;
  1065. { Save the old offset and set the new offset }
  1066. InsOffset:=Offset;
  1067. { Things which may only be done once, not when a second pass is done to
  1068. optimize }
  1069. if Insentry=nil then
  1070. begin
  1071. { Check if error last time then InsSize=-1 }
  1072. if InsSize=-1 then
  1073. exit;
  1074. { set the file postion }
  1075. aktfilepos:=fileinfo;
  1076. end
  1077. else
  1078. begin
  1079. {$ifdef PASS2FLAG}
  1080. { we are here in a second pass, check if the instruction can be optimized }
  1081. if (InsEntry^.flags and IF_PASS2)=0 then
  1082. begin
  1083. Pass1:=InsSize;
  1084. exit;
  1085. end;
  1086. { update the .ot fields, some top_const can be updated }
  1087. create_ot;
  1088. {$endif PASS2FLAG}
  1089. end;
  1090. { Get InsEntry }
  1091. if FindInsEntry then
  1092. begin
  1093. { Calculate instruction size }
  1094. InsSize:=calcsize(insentry);
  1095. if segprefix<>NR_NO then
  1096. inc(InsSize);
  1097. { Fix opsize if size if forced }
  1098. if (insentry^.flags and (IF_SB or IF_SW or IF_SD))<>0 then
  1099. begin
  1100. if (insentry^.flags and IF_ARMASK)=0 then
  1101. begin
  1102. if (insentry^.flags and IF_SB)<>0 then
  1103. begin
  1104. if opsize=S_NO then
  1105. opsize:=S_B;
  1106. end
  1107. else if (insentry^.flags and IF_SW)<>0 then
  1108. begin
  1109. if opsize=S_NO then
  1110. opsize:=S_W;
  1111. end
  1112. else if (insentry^.flags and IF_SD)<>0 then
  1113. begin
  1114. if opsize=S_NO then
  1115. opsize:=S_L;
  1116. end;
  1117. end;
  1118. end;
  1119. LastInsOffset:=InsOffset;
  1120. Pass1:=InsSize;
  1121. exit;
  1122. end;
  1123. LastInsOffset:=-1;
  1124. end;
  1125. procedure taicpu.Pass2(sec:TAsmObjectData);
  1126. var
  1127. c : longint;
  1128. begin
  1129. { error in pass1 ? }
  1130. if insentry=nil then
  1131. exit;
  1132. aktfilepos:=fileinfo;
  1133. { Segment override }
  1134. if (segprefix<>NR_NO) then
  1135. begin
  1136. case segprefix of
  1137. NR_CS : c:=$2e;
  1138. NR_DS : c:=$3e;
  1139. NR_ES : c:=$26;
  1140. NR_FS : c:=$64;
  1141. NR_GS : c:=$65;
  1142. NR_SS : c:=$36;
  1143. end;
  1144. sec.writebytes(c,1);
  1145. { fix the offset for GenNode }
  1146. inc(InsOffset);
  1147. end;
  1148. { Generate the instruction }
  1149. GenCode(sec);
  1150. end;
  1151. function taicpu.needaddrprefix(opidx:byte):boolean;
  1152. begin
  1153. needaddrprefix:=false;
  1154. if (OT_MEMORY and (not oper[opidx]^.ot))=0 then
  1155. begin
  1156. if (
  1157. (oper[opidx]^.ref^.index<>NR_NO) and
  1158. (getsubreg(oper[opidx]^.ref^.index)<>R_SUBD)
  1159. ) or
  1160. (
  1161. (oper[opidx]^.ref^.base<>NR_NO) and
  1162. (getsubreg(oper[opidx]^.ref^.base)<>R_SUBD)
  1163. ) then
  1164. needaddrprefix:=true;
  1165. end;
  1166. end;
  1167. function regval(r:Tregister):byte;
  1168. const
  1169. {$ifdef x86_64}
  1170. opcode_table:array[tregisterindex] of tregisterindex = (
  1171. {$i r8664op.inc}
  1172. );
  1173. {$else x86_64}
  1174. opcode_table:array[tregisterindex] of tregisterindex = (
  1175. {$i r386op.inc}
  1176. );
  1177. {$endif x86_64}
  1178. var
  1179. regidx : tregisterindex;
  1180. begin
  1181. regidx:=findreg_by_number(r);
  1182. if regidx<>0 then
  1183. result:=opcode_table[regidx]
  1184. else
  1185. begin
  1186. Message1(asmw_e_invalid_register,generic_regname(r));
  1187. result:=0;
  1188. end;
  1189. end;
  1190. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  1191. var
  1192. sym : tasmsymbol;
  1193. md,s,rv : byte;
  1194. base,index,scalefactor,
  1195. o : longint;
  1196. ir,br : Tregister;
  1197. isub,bsub : tsubregister;
  1198. begin
  1199. process_ea:=false;
  1200. {Register ?}
  1201. if (input.typ=top_reg) then
  1202. begin
  1203. rv:=regval(input.reg);
  1204. output.sib_present:=false;
  1205. output.bytes:=0;
  1206. output.modrm:=$c0 or (rfield shl 3) or rv;
  1207. output.size:=1;
  1208. process_ea:=true;
  1209. exit;
  1210. end;
  1211. {No register, so memory reference.}
  1212. if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
  1213. ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
  1214. internalerror(200301081);
  1215. ir:=input.ref^.index;
  1216. br:=input.ref^.base;
  1217. isub:=getsubreg(ir);
  1218. bsub:=getsubreg(br);
  1219. s:=input.ref^.scalefactor;
  1220. o:=input.ref^.offset;
  1221. sym:=input.ref^.symbol;
  1222. { it's direct address }
  1223. if (br=NR_NO) and (ir=NR_NO) then
  1224. begin
  1225. { it's a pure offset }
  1226. output.sib_present:=false;
  1227. output.bytes:=4;
  1228. output.modrm:=5 or (rfield shl 3);
  1229. end
  1230. else
  1231. { it's an indirection }
  1232. begin
  1233. { 16 bit address? }
  1234. if ((ir<>NR_NO) and (isub<>R_SUBD)) or
  1235. ((br<>NR_NO) and (bsub<>R_SUBD)) then
  1236. message(asmw_e_16bit_not_supported);
  1237. {$ifdef OPTEA}
  1238. { make single reg base }
  1239. if (br=NR_NO) and (s=1) then
  1240. begin
  1241. br:=ir;
  1242. ir:=NR_NO;
  1243. end;
  1244. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  1245. if (br=NR_NO) and
  1246. (((s=2) and (ir<>NR_ESP)) or
  1247. (s=3) or (s=5) or (s=9)) then
  1248. begin
  1249. br:=ir;
  1250. dec(s);
  1251. end;
  1252. { swap ESP into base if scalefactor is 1 }
  1253. if (s=1) and (ir=NR_ESP) then
  1254. begin
  1255. ir:=br;
  1256. br:=NR_ESP;
  1257. end;
  1258. {$endif OPTEA}
  1259. { wrong, for various reasons }
  1260. if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
  1261. exit;
  1262. { base }
  1263. case br of
  1264. NR_EAX : base:=0;
  1265. NR_ECX : base:=1;
  1266. NR_EDX : base:=2;
  1267. NR_EBX : base:=3;
  1268. NR_ESP : base:=4;
  1269. NR_NO,
  1270. NR_EBP : base:=5;
  1271. NR_ESI : base:=6;
  1272. NR_EDI : base:=7;
  1273. else
  1274. exit;
  1275. end;
  1276. { index }
  1277. case ir of
  1278. NR_EAX : index:=0;
  1279. NR_ECX : index:=1;
  1280. NR_EDX : index:=2;
  1281. NR_EBX : index:=3;
  1282. NR_NO : index:=4;
  1283. NR_EBP : index:=5;
  1284. NR_ESI : index:=6;
  1285. NR_EDI : index:=7;
  1286. else
  1287. exit;
  1288. end;
  1289. case s of
  1290. 0,
  1291. 1 : scalefactor:=0;
  1292. 2 : scalefactor:=1;
  1293. 4 : scalefactor:=2;
  1294. 8 : scalefactor:=3;
  1295. else
  1296. exit;
  1297. end;
  1298. if (br=NR_NO) or
  1299. ((br<>NR_EBP) and (o=0) and (sym=nil)) then
  1300. md:=0
  1301. else
  1302. if ((o>=-128) and (o<=127) and (sym=nil)) then
  1303. md:=1
  1304. else
  1305. md:=2;
  1306. if (br=NR_NO) or (md=2) then
  1307. output.bytes:=4
  1308. else
  1309. output.bytes:=md;
  1310. { SIB needed ? }
  1311. if (ir=NR_NO) and (br<>NR_ESP) then
  1312. begin
  1313. output.sib_present:=false;
  1314. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  1315. end
  1316. else
  1317. begin
  1318. output.sib_present:=true;
  1319. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  1320. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  1321. end;
  1322. end;
  1323. if output.sib_present then
  1324. output.size:=2+output.bytes
  1325. else
  1326. output.size:=1+output.bytes;
  1327. process_ea:=true;
  1328. end;
  1329. function taicpu.calcsize(p:PInsEntry):longint;
  1330. var
  1331. codes : pchar;
  1332. c : byte;
  1333. len : longint;
  1334. ea_data : ea;
  1335. begin
  1336. len:=0;
  1337. codes:=@p^.code;
  1338. repeat
  1339. c:=ord(codes^);
  1340. inc(codes);
  1341. case c of
  1342. 0 :
  1343. break;
  1344. 1,2,3 :
  1345. begin
  1346. inc(codes,c);
  1347. inc(len,c);
  1348. end;
  1349. 8,9,10 :
  1350. begin
  1351. inc(codes);
  1352. inc(len);
  1353. end;
  1354. 4,5,6,7 :
  1355. begin
  1356. if opsize=S_W then
  1357. inc(len,2)
  1358. else
  1359. inc(len);
  1360. end;
  1361. 15,
  1362. 12,13,14,
  1363. 16,17,18,
  1364. 20,21,22,
  1365. 40,41,42 :
  1366. inc(len);
  1367. 24,25,26,
  1368. 31,
  1369. 48,49,50 :
  1370. inc(len,2);
  1371. 28,29,30, { we don't have 16 bit immediates code }
  1372. 32,33,34,
  1373. 52,53,54,
  1374. 56,57,58 :
  1375. inc(len,4);
  1376. 192,193,194 :
  1377. if NeedAddrPrefix(c-192) then
  1378. inc(len);
  1379. 208 :
  1380. inc(len);
  1381. 200,
  1382. 201,
  1383. 202,
  1384. 209,
  1385. 210,
  1386. 217,218: ;
  1387. 219,220 :
  1388. inc(len);
  1389. 216 :
  1390. begin
  1391. inc(codes);
  1392. inc(len);
  1393. end;
  1394. 224,225,226 :
  1395. begin
  1396. InternalError(777002);
  1397. end;
  1398. else
  1399. begin
  1400. if (c>=64) and (c<=191) then
  1401. begin
  1402. if not process_ea(oper[(c shr 3) and 7]^, ea_data, 0) then
  1403. Message(asmw_e_invalid_effective_address)
  1404. else
  1405. inc(len,ea_data.size);
  1406. end
  1407. else
  1408. InternalError(777003);
  1409. end;
  1410. end;
  1411. until false;
  1412. calcsize:=len;
  1413. end;
  1414. procedure taicpu.GenCode(sec:TAsmObjectData);
  1415. {
  1416. * the actual codes (C syntax, i.e. octal):
  1417. * \0 - terminates the code. (Unless it's a literal of course.)
  1418. * \1, \2, \3 - that many literal bytes follow in the code stream
  1419. * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  1420. * (POP is never used for CS) depending on operand 0
  1421. * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
  1422. * on operand 0
  1423. * \10, \11, \12 - a literal byte follows in the code stream, to be added
  1424. * to the register value of operand 0, 1 or 2
  1425. * \17 - encodes the literal byte 0. (Some compilers don't take
  1426. * kindly to a zero byte in the _middle_ of a compile time
  1427. * string constant, so I had to put this hack in.)
  1428. * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  1429. * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  1430. * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
  1431. * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  1432. * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  1433. * assembly mode or the address-size override on the operand
  1434. * \37 - a word constant, from the _segment_ part of operand 0
  1435. * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  1436. * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  1437. * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  1438. * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  1439. * assembly mode or the address-size override on the operand
  1440. * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  1441. * \1ab - a ModRM, calculated on EA in operand a, with the spare
  1442. * field the register value of operand b.
  1443. * \2ab - a ModRM, calculated on EA in operand a, with the spare
  1444. * field equal to digit b.
  1445. * \30x - might be an 0x67 byte, depending on the address size of
  1446. * the memory reference in operand x.
  1447. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
  1448. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
  1449. * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
  1450. * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
  1451. * \322 - indicates that this instruction is only valid when the
  1452. * operand size is the default (instruction to disassembler,
  1453. * generates no code in the assembler)
  1454. * \330 - a literal byte follows in the code stream, to be added
  1455. * to the condition code value of the instruction.
  1456. * \340 - reserve <operand 0> bytes of uninitialised storage.
  1457. * Operand 0 had better be a segmentless constant.
  1458. }
  1459. var
  1460. currval : longint;
  1461. currsym : tasmsymbol;
  1462. procedure getvalsym(opidx:longint);
  1463. begin
  1464. case oper[opidx]^.typ of
  1465. top_ref :
  1466. begin
  1467. currval:=oper[opidx]^.ref^.offset;
  1468. currsym:=oper[opidx]^.ref^.symbol;
  1469. end;
  1470. top_const :
  1471. begin
  1472. currval:=longint(oper[opidx]^.val);
  1473. currsym:=nil;
  1474. end;
  1475. top_symbol :
  1476. begin
  1477. currval:=oper[opidx]^.symofs;
  1478. currsym:=oper[opidx]^.sym;
  1479. end;
  1480. else
  1481. Message(asmw_e_immediate_or_reference_expected);
  1482. end;
  1483. end;
  1484. const
  1485. CondVal:array[TAsmCond] of byte=($0,
  1486. $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
  1487. $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
  1488. $0, $A, $A, $B, $8, $4);
  1489. var
  1490. c : byte;
  1491. pb,
  1492. codes : pchar;
  1493. bytes : array[0..3] of byte;
  1494. rfield,
  1495. data,s,opidx : longint;
  1496. ea_data : ea;
  1497. begin
  1498. {$ifdef EXTDEBUG}
  1499. { safety check }
  1500. if sec.sects[sec.currsec].datasize<>insoffset then
  1501. internalerror(200130121);
  1502. {$endif EXTDEBUG}
  1503. { load data to write }
  1504. codes:=insentry^.code;
  1505. { Force word push/pop for registers }
  1506. if (opsize=S_W) and ((codes[0]=#4) or (codes[0]=#6) or
  1507. ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
  1508. begin
  1509. bytes[0]:=$66;
  1510. sec.writebytes(bytes,1);
  1511. end;
  1512. repeat
  1513. c:=ord(codes^);
  1514. inc(codes);
  1515. case c of
  1516. 0 :
  1517. break;
  1518. 1,2,3 :
  1519. begin
  1520. sec.writebytes(codes^,c);
  1521. inc(codes,c);
  1522. end;
  1523. 4,6 :
  1524. begin
  1525. case oper[0]^.reg of
  1526. NR_CS:
  1527. bytes[0]:=$e;
  1528. NR_NO,
  1529. NR_DS:
  1530. bytes[0]:=$1e;
  1531. NR_ES:
  1532. bytes[0]:=$6;
  1533. NR_SS:
  1534. bytes[0]:=$16;
  1535. else
  1536. internalerror(777004);
  1537. end;
  1538. if c=4 then
  1539. inc(bytes[0]);
  1540. sec.writebytes(bytes,1);
  1541. end;
  1542. 5,7 :
  1543. begin
  1544. case oper[0]^.reg of
  1545. NR_FS:
  1546. bytes[0]:=$a0;
  1547. NR_GS:
  1548. bytes[0]:=$a8;
  1549. else
  1550. internalerror(777005);
  1551. end;
  1552. if c=5 then
  1553. inc(bytes[0]);
  1554. sec.writebytes(bytes,1);
  1555. end;
  1556. 8,9,10 :
  1557. begin
  1558. bytes[0]:=ord(codes^)+regval(oper[c-8]^.reg);
  1559. inc(codes);
  1560. sec.writebytes(bytes,1);
  1561. end;
  1562. 15 :
  1563. begin
  1564. bytes[0]:=0;
  1565. sec.writebytes(bytes,1);
  1566. end;
  1567. 12,13,14 :
  1568. begin
  1569. getvalsym(c-12);
  1570. if (currval<-128) or (currval>127) then
  1571. Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
  1572. if assigned(currsym) then
  1573. sec.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
  1574. else
  1575. sec.writebytes(currval,1);
  1576. end;
  1577. 16,17,18 :
  1578. begin
  1579. getvalsym(c-16);
  1580. if (currval<-256) or (currval>255) then
  1581. Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
  1582. if assigned(currsym) then
  1583. sec.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
  1584. else
  1585. sec.writebytes(currval,1);
  1586. end;
  1587. 20,21,22 :
  1588. begin
  1589. getvalsym(c-20);
  1590. if (currval<0) or (currval>255) then
  1591. Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
  1592. if assigned(currsym) then
  1593. sec.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
  1594. else
  1595. sec.writebytes(currval,1);
  1596. end;
  1597. 24,25,26 :
  1598. begin
  1599. getvalsym(c-24);
  1600. if (currval<-65536) or (currval>65535) then
  1601. Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
  1602. if assigned(currsym) then
  1603. sec.writereloc(currval,2,currsym,RELOC_ABSOLUTE)
  1604. else
  1605. sec.writebytes(currval,2);
  1606. end;
  1607. 28,29,30 :
  1608. begin
  1609. getvalsym(c-28);
  1610. if assigned(currsym) then
  1611. sec.writereloc(currval,4,currsym,RELOC_ABSOLUTE)
  1612. else
  1613. sec.writebytes(currval,4);
  1614. end;
  1615. 32,33,34 :
  1616. begin
  1617. getvalsym(c-32);
  1618. if assigned(currsym) then
  1619. sec.writereloc(currval,4,currsym,RELOC_ABSOLUTE)
  1620. else
  1621. sec.writebytes(currval,4);
  1622. end;
  1623. 40,41,42 :
  1624. begin
  1625. getvalsym(c-40);
  1626. data:=currval-insend;
  1627. if assigned(currsym) then
  1628. inc(data,currsym.address);
  1629. if (data>127) or (data<-128) then
  1630. Message1(asmw_e_short_jmp_out_of_range,tostr(data));
  1631. sec.writebytes(data,1);
  1632. end;
  1633. 52,53,54 :
  1634. begin
  1635. getvalsym(c-52);
  1636. if assigned(currsym) then
  1637. sec.writereloc(currval,4,currsym,RELOC_RELATIVE)
  1638. else
  1639. sec.writereloc(currval-insend,4,nil,RELOC_ABSOLUTE)
  1640. end;
  1641. 56,57,58 :
  1642. begin
  1643. getvalsym(c-56);
  1644. if assigned(currsym) then
  1645. sec.writereloc(currval,4,currsym,RELOC_RELATIVE)
  1646. else
  1647. sec.writereloc(currval-insend,4,nil,RELOC_ABSOLUTE)
  1648. end;
  1649. 192,193,194 :
  1650. begin
  1651. if NeedAddrPrefix(c-192) then
  1652. begin
  1653. bytes[0]:=$67;
  1654. sec.writebytes(bytes,1);
  1655. end;
  1656. end;
  1657. 200 :
  1658. begin
  1659. bytes[0]:=$67;
  1660. sec.writebytes(bytes,1);
  1661. end;
  1662. 208 :
  1663. begin
  1664. bytes[0]:=$66;
  1665. sec.writebytes(bytes,1);
  1666. end;
  1667. 216 :
  1668. begin
  1669. bytes[0]:=ord(codes^)+condval[condition];
  1670. inc(codes);
  1671. sec.writebytes(bytes,1);
  1672. end;
  1673. 201,
  1674. 202,
  1675. 209,
  1676. 210,
  1677. 217,218 :
  1678. begin
  1679. { these are dissambler hints or 32 bit prefixes which
  1680. are not needed }
  1681. end;
  1682. 219 :
  1683. begin
  1684. bytes[0]:=$f3;
  1685. sec.writebytes(bytes,1);
  1686. end;
  1687. 220 :
  1688. begin
  1689. bytes[0]:=$f2;
  1690. sec.writebytes(bytes,1);
  1691. end;
  1692. 31,
  1693. 48,49,50,
  1694. 224,225,226 :
  1695. begin
  1696. InternalError(777006);
  1697. end
  1698. else
  1699. begin
  1700. if (c>=64) and (c<=191) then
  1701. begin
  1702. if (c<127) then
  1703. begin
  1704. if (oper[c and 7]^.typ=top_reg) then
  1705. rfield:=regval(oper[c and 7]^.reg)
  1706. else
  1707. rfield:=regval(oper[c and 7]^.ref^.base);
  1708. end
  1709. else
  1710. rfield:=c and 7;
  1711. opidx:=(c shr 3) and 7;
  1712. if not process_ea(oper[opidx]^,ea_data,rfield) then
  1713. Message(asmw_e_invalid_effective_address);
  1714. pb:=@bytes;
  1715. pb^:=chr(ea_data.modrm);
  1716. inc(pb);
  1717. if ea_data.sib_present then
  1718. begin
  1719. pb^:=chr(ea_data.sib);
  1720. inc(pb);
  1721. end;
  1722. s:=pb-pchar(@bytes);
  1723. sec.writebytes(bytes,s);
  1724. case ea_data.bytes of
  1725. 0 : ;
  1726. 1 :
  1727. begin
  1728. if (oper[opidx]^.ot and OT_MEMORY)=OT_MEMORY then
  1729. sec.writereloc(oper[opidx]^.ref^.offset,1,oper[opidx]^.ref^.symbol,RELOC_ABSOLUTE)
  1730. else
  1731. begin
  1732. bytes[0]:=oper[opidx]^.ref^.offset;
  1733. sec.writebytes(bytes,1);
  1734. end;
  1735. inc(s);
  1736. end;
  1737. 2,4 :
  1738. begin
  1739. sec.writereloc(oper[opidx]^.ref^.offset,ea_data.bytes,
  1740. oper[opidx]^.ref^.symbol,RELOC_ABSOLUTE);
  1741. inc(s,ea_data.bytes);
  1742. end;
  1743. end;
  1744. end
  1745. else
  1746. InternalError(777007);
  1747. end;
  1748. end;
  1749. until false;
  1750. end;
  1751. {$endif NOAG386BIN}
  1752. function Taicpu.is_same_reg_move:boolean;
  1753. begin
  1754. result:=(ops=2) and
  1755. (oper[0]^.typ=top_reg) and
  1756. (oper[1]^.typ=top_reg) and
  1757. (oper[0]^.reg=oper[1]^.reg) and
  1758. ((opcode=A_MOV) or (opcode=A_XCHG));
  1759. end;
  1760. function Taicpu.is_reg_move:boolean;
  1761. begin
  1762. result:=(ops=2) and
  1763. (oper[0]^.typ=top_reg) and
  1764. (oper[1]^.typ=top_reg) and
  1765. ((opcode=A_MOV) or (opcode=A_MOVZX) or (opcode=A_MOVSX));
  1766. end;
  1767. function Taicpu.spill_registers(list:Taasmoutput;
  1768. rt:Tregistertype;
  1769. rgget:Trggetproc;
  1770. rgunget:Trgungetproc;
  1771. const r:Tsuperregisterset;
  1772. var live_registers_int:Tsuperregisterworklist;
  1773. const spilltemplist:Tspill_temp_list):boolean;
  1774. {Spill the registers in r in this instruction. Returns true if any help
  1775. registers are used. This procedure has become one big hack party, because
  1776. of the huge amount of situations you can have. The irregularity of the i386
  1777. instruction set doesn't help either. (DM)}
  1778. var i:byte;
  1779. supreg:Tsuperregister;
  1780. subreg:Tsubregister;
  1781. helpreg:Tregister;
  1782. helpins:Taicpu;
  1783. op:Tasmop;
  1784. hopsize:Topsize;
  1785. pos:Tai;
  1786. begin
  1787. {Situation examples are in intel notation, so operand order:
  1788. mov eax , ebx
  1789. ^^^ ^^^
  1790. oper[1] oper[0]
  1791. (DM)}
  1792. spill_registers:=false;
  1793. case ops of
  1794. 1:
  1795. begin
  1796. if (oper[0]^.typ=top_reg) and
  1797. (getregtype(oper[0]^.reg)=rt) then
  1798. begin
  1799. supreg:=getsupreg(oper[0]^.reg);
  1800. if supregset_in(r,supreg) then
  1801. begin
  1802. {Situation example:
  1803. push r20d ; r20d must be spilled into [ebp-12]
  1804. Change into:
  1805. push [ebp-12] ; Replace register by reference }
  1806. { hopsize:=reg2opsize(oper[0].reg);}
  1807. oper[0]^.typ:=top_ref;
  1808. new(oper[0]^.ref);
  1809. oper[0]^.ref^:=spilltemplist[supreg];
  1810. { oper[0]^.ref^.size:=hopsize;}
  1811. end;
  1812. end;
  1813. if oper[0]^.typ=top_ref then
  1814. begin
  1815. supreg:=getsupreg(oper[0]^.ref^.base);
  1816. if supregset_in(r,supreg) then
  1817. begin
  1818. {Situation example:
  1819. push [r21d+4*r22d] ; r21d must be spilled into [ebp-12]
  1820. Change into:
  1821. mov r23d,[ebp-12] ; Use a help register
  1822. push [r23d+4*r22d] ; Replace register by helpregister }
  1823. subreg:=getsubreg(oper[0]^.ref^.base);
  1824. if oper[0]^.ref^.index=NR_NO then
  1825. pos:=Tai(previous)
  1826. else
  1827. pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.index),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
  1828. rgget(list,pos,subreg,helpreg);
  1829. spill_registers:=true;
  1830. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.base),spilltemplist[supreg],helpreg);
  1831. if pos=nil then
  1832. list.insertafter(helpins,list.first)
  1833. else
  1834. list.insertafter(helpins,pos.next);
  1835. rgunget(list,helpins,helpreg);
  1836. forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
  1837. oper[0]^.ref^.base:=helpreg;
  1838. end;
  1839. supreg:=getsupreg(oper[0]^.ref^.index);
  1840. if supregset_in(r,supreg) then
  1841. begin
  1842. {Situation example:
  1843. push [r21d+4*r22d] ; r22d must be spilled into [ebp-12]
  1844. Change into:
  1845. mov r23d,[ebp-12] ; Use a help register
  1846. push [r21d+4*r23d] ; Replace register by helpregister }
  1847. subreg:=getsubreg(oper[0]^.ref^.index);
  1848. if oper[0]^.ref^.base=NR_NO then
  1849. pos:=Tai(previous)
  1850. else
  1851. pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.base),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
  1852. rgget(list,pos,subreg,helpreg);
  1853. spill_registers:=true;
  1854. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.index),spilltemplist[supreg],helpreg);
  1855. if pos=nil then
  1856. list.insertafter(helpins,list.first)
  1857. else
  1858. list.insertafter(helpins,pos.next);
  1859. rgunget(list,helpins,helpreg);
  1860. forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
  1861. oper[0]^.ref^.index:=helpreg;
  1862. end;
  1863. end;
  1864. end;
  1865. 2:
  1866. begin
  1867. { First spill the registers from the references. This is
  1868. required because the reference can be moved from this instruction
  1869. to a MOV instruction when spilling of the register operand is done }
  1870. for i:=0 to 1 do
  1871. if oper[i]^.typ=top_ref then
  1872. begin
  1873. supreg:=getsupreg(oper[i]^.ref^.base);
  1874. if supregset_in(r,supreg) then
  1875. begin
  1876. {Situation example:
  1877. add r20d,[r21d+4*r22d] ; r21d must be spilled into [ebp-12]
  1878. Change into:
  1879. mov r23d,[ebp-12] ; Use a help register
  1880. add r20d,[r23d+4*r22d] ; Replace register by helpregister }
  1881. subreg:=getsubreg(oper[i]^.ref^.base);
  1882. if i=1 then
  1883. pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),
  1884. RS_INVALID,{unusedregsint}live_registers_int)
  1885. else
  1886. pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
  1887. rgget(list,pos,subreg,helpreg);
  1888. spill_registers:=true;
  1889. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
  1890. if pos=nil then
  1891. list.insertafter(helpins,list.first)
  1892. else
  1893. list.insertafter(helpins,pos.next);
  1894. oper[i]^.ref^.base:=helpreg;
  1895. rgunget(list,helpins,helpreg);
  1896. forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
  1897. end;
  1898. supreg:=getsupreg(oper[i]^.ref^.index);
  1899. if supregset_in(r,supreg) then
  1900. begin
  1901. {Situation example:
  1902. add r20d,[r21d+4*r22d] ; r22d must be spilled into [ebp-12]
  1903. Change into:
  1904. mov r23d,[ebp-12] ; Use a help register
  1905. add r20d,[r21d+4*r23d] ; Replace register by helpregister }
  1906. subreg:=getsubreg(oper[i]^.ref^.index);
  1907. if i=1 then
  1908. pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.base),getsupreg(oper[0]^.reg),
  1909. RS_INVALID,{unusedregsint}live_registers_int)
  1910. else
  1911. pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
  1912. rgget(list,pos,subreg,helpreg);
  1913. spill_registers:=true;
  1914. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
  1915. if pos=nil then
  1916. list.insertafter(helpins,list.first)
  1917. else
  1918. list.insertafter(helpins,pos.next);
  1919. oper[i]^.ref^.index:=helpreg;
  1920. rgunget(list,helpins,helpreg);
  1921. forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
  1922. end;
  1923. end;
  1924. if (oper[0]^.typ=top_reg) and
  1925. (getregtype(oper[0]^.reg)=rt) then
  1926. begin
  1927. supreg:=getsupreg(oper[0]^.reg);
  1928. subreg:=getsubreg(oper[0]^.reg);
  1929. if supregset_in(r,supreg) then
  1930. if oper[1]^.typ=top_ref then
  1931. begin
  1932. {Situation example:
  1933. add [r20d],r21d ; r21d must be spilled into [ebp-12]
  1934. Change into:
  1935. mov r22d,[ebp-12] ; Use a help register
  1936. add [r20d],r22d ; Replace register by helpregister }
  1937. pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.reg),
  1938. getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index),
  1939. {unusedregsint}live_registers_int);
  1940. rgget(list,pos,subreg,helpreg);
  1941. spill_registers:=true;
  1942. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
  1943. if pos=nil then
  1944. list.insertafter(helpins,list.first)
  1945. else
  1946. list.insertafter(helpins,pos.next);
  1947. oper[0]^.reg:=helpreg;
  1948. rgunget(list,helpins,helpreg);
  1949. forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
  1950. end
  1951. else
  1952. begin
  1953. {Situation example:
  1954. add r20d,r21d ; r21d must be spilled into [ebp-12]
  1955. Change into:
  1956. add r20d,[ebp-12] ; Replace register by reference }
  1957. oper[0]^.typ:=top_ref;
  1958. new(oper[0]^.ref);
  1959. oper[0]^.ref^:=spilltemplist[supreg];
  1960. end;
  1961. end;
  1962. if (oper[1]^.typ=top_reg) and
  1963. (getregtype(oper[1]^.reg)=rt) then
  1964. begin
  1965. supreg:=getsupreg(oper[1]^.reg);
  1966. subreg:=getsubreg(oper[1]^.reg);
  1967. if supregset_in(r,supreg) then
  1968. begin
  1969. if oper[0]^.typ=top_ref then
  1970. begin
  1971. {Situation example:
  1972. add r20d,[r21d] ; r20d must be spilled into [ebp-12]
  1973. Change into:
  1974. mov r22d,[r21d] ; Use a help register
  1975. add [ebp-12],r22d ; Replace register by helpregister }
  1976. pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.base),
  1977. getsupreg(oper[0]^.ref^.index),RS_INVALID,{unusedregsint}live_registers_int);
  1978. rgget(list,pos,subreg,helpreg);
  1979. spill_registers:=true;
  1980. op:=A_MOV;
  1981. hopsize:=opsize; {Save old value...}
  1982. if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
  1983. begin
  1984. {Because 'movzx memory,register' does not exist...}
  1985. op:=opcode;
  1986. opcode:=A_MOV;
  1987. opsize:=reg2opsize(oper[1]^.reg);
  1988. end;
  1989. helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
  1990. if pos=nil then
  1991. list.insertafter(helpins,list.first)
  1992. else
  1993. list.insertafter(helpins,pos.next);
  1994. dispose(oper[0]^.ref);
  1995. oper[0]^.typ:=top_reg;
  1996. oper[0]^.reg:=helpreg;
  1997. oper[1]^.typ:=top_ref;
  1998. new(oper[1]^.ref);
  1999. oper[1]^.ref^:=spilltemplist[supreg];
  2000. rgunget(list,helpins,helpreg);
  2001. forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
  2002. end
  2003. else
  2004. begin
  2005. {Situation example:
  2006. add r20d,r21d ; r20d must be spilled into [ebp-12]
  2007. Change into:
  2008. add [ebp-12],r21d ; Replace register by reference }
  2009. if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
  2010. begin
  2011. {Because 'movzx memory,register' does not exist...}
  2012. spill_registers:=true;
  2013. op:=opcode;
  2014. hopsize:=opsize;
  2015. opcode:=A_MOV;
  2016. opsize:=reg2opsize(oper[1]^.reg);
  2017. pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
  2018. rgget(list,pos,subreg,helpreg);
  2019. helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0]^.reg,helpreg);
  2020. if pos=nil then
  2021. list.insertafter(helpins,list.first)
  2022. else
  2023. list.insertafter(helpins,pos.next);
  2024. oper[0]^.reg:=helpreg;
  2025. rgunget(list,helpins,helpreg);
  2026. forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
  2027. end;
  2028. oper[1]^.typ:=top_ref;
  2029. new(oper[1]^.ref);
  2030. oper[1]^.ref^:=spilltemplist[supreg];
  2031. end;
  2032. end;
  2033. end;
  2034. { The i386 instruction set never gets boring...
  2035. some opcodes do not support a memory location as destination }
  2036. if (oper[1]^.typ=top_ref) and
  2037. (
  2038. (oper[0]^.typ=top_const) or
  2039. ((oper[0]^.typ=top_reg) and
  2040. (getregtype(oper[0]^.reg)=rt))
  2041. ) then
  2042. begin
  2043. case opcode of
  2044. A_IMUL :
  2045. begin
  2046. {Yikes! We just changed the destination register into
  2047. a memory location above here.
  2048. Situation examples:
  2049. imul [ebp-12],r21d ; We need a help register
  2050. imul [ebp-12],<const> ; We need a help register
  2051. Change into:
  2052. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  2053. imul r22d,r21d ; Replace reference by helpregister
  2054. mov [ebp-12],r22d ; Use another help instruction}
  2055. rgget(list,Tai(previous),subreg,helpreg);
  2056. spill_registers:=true;
  2057. {First help instruction.}
  2058. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
  2059. if previous=nil then
  2060. list.insert(helpins)
  2061. else
  2062. list.insertafter(helpins,previous);
  2063. {Second help instruction.}
  2064. helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
  2065. dispose(oper[1]^.ref);
  2066. oper[1]^.typ:=top_reg;
  2067. oper[1]^.reg:=helpreg;
  2068. list.insertafter(helpins,self);
  2069. rgunget(list,self,helpreg);
  2070. end;
  2071. end;
  2072. end;
  2073. { The i386 instruction set never gets boring...
  2074. some opcodes do not support a memory location as source }
  2075. if (oper[0]^.typ=top_ref) and
  2076. (oper[1]^.typ=top_reg) and
  2077. (getregtype(oper[1]^.reg)=rt) then
  2078. begin
  2079. case opcode of
  2080. A_BT,A_BTS,
  2081. A_BTC,A_BTR :
  2082. begin
  2083. {Yikes! We just changed the source register into
  2084. a memory location above here.
  2085. Situation example:
  2086. bt r21d,[ebp-12] ; We need a help register
  2087. Change into:
  2088. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  2089. bt r21d,r22d ; Replace reference by helpregister}
  2090. rgget(list,Tai(previous),subreg,helpreg);
  2091. spill_registers:=true;
  2092. {First help instruction.}
  2093. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
  2094. if previous=nil then
  2095. list.insert(helpins)
  2096. else
  2097. list.insertafter(helpins,previous);
  2098. dispose(oper[0]^.ref);
  2099. oper[0]^.typ:=top_reg;
  2100. oper[0]^.reg:=helpreg;
  2101. rgunget(list,helpins,helpreg);
  2102. end;
  2103. end;
  2104. end;
  2105. end;
  2106. 3:
  2107. begin
  2108. {$warning todo!!}
  2109. end;
  2110. end;
  2111. end;
  2112. {*****************************************************************************
  2113. Instruction table
  2114. *****************************************************************************}
  2115. procedure BuildInsTabCache;
  2116. {$ifndef NOAG386BIN}
  2117. var
  2118. i : longint;
  2119. {$endif}
  2120. begin
  2121. {$ifndef NOAG386BIN}
  2122. new(instabcache);
  2123. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  2124. i:=0;
  2125. while (i<InsTabEntries) do
  2126. begin
  2127. if InsTabCache^[InsTab[i].OPcode]=-1 then
  2128. InsTabCache^[InsTab[i].OPcode]:=i;
  2129. inc(i);
  2130. end;
  2131. {$endif NOAG386BIN}
  2132. end;
  2133. procedure InitAsm;
  2134. begin
  2135. {$ifndef NOAG386BIN}
  2136. if not assigned(instabcache) then
  2137. BuildInsTabCache;
  2138. {$endif NOAG386BIN}
  2139. end;
  2140. procedure DoneAsm;
  2141. begin
  2142. {$ifndef NOAG386BIN}
  2143. if assigned(instabcache) then
  2144. begin
  2145. dispose(instabcache);
  2146. instabcache:=nil;
  2147. end;
  2148. {$endif NOAG386BIN}
  2149. end;
  2150. end.
  2151. {
  2152. $Log$
  2153. Revision 1.43 2003-12-26 14:02:30 peter
  2154. * sparc updates
  2155. * use registertype in spill_register
  2156. Revision 1.42 2003/12/25 12:01:35 florian
  2157. + possible sse2 unit usage for double calculations
  2158. * some sse2 assembler issues fixed
  2159. Revision 1.41 2003/12/25 01:07:09 florian
  2160. + $fputype directive support
  2161. + single data type operations with sse unit
  2162. * fixed more x86-64 stuff
  2163. Revision 1.40 2003/12/15 21:25:49 peter
  2164. * reg allocations for imaginary register are now inserted just
  2165. before reg allocation
  2166. * tregister changed to enum to allow compile time check
  2167. * fixed several tregister-tsuperregister errors
  2168. Revision 1.39 2003/12/14 20:24:28 daniel
  2169. * Register allocator speed optimizations
  2170. - Worklist no longer a ringbuffer
  2171. - No find operations are left
  2172. - Simplify now done in constant time
  2173. - unusedregs is now a Tsuperregisterworklist
  2174. - Microoptimizations
  2175. Revision 1.38 2003/11/12 16:05:40 florian
  2176. * assembler readers OOPed
  2177. + typed currency constants
  2178. + typed 128 bit float constants if the CPU supports it
  2179. Revision 1.37 2003/10/30 19:59:00 peter
  2180. * support scalefactor for opr_local
  2181. * support reference with opr_local set, fixes tw2631
  2182. Revision 1.36 2003/10/29 15:40:20 peter
  2183. * support indexing and offset retrieval for locals
  2184. Revision 1.35 2003/10/23 14:44:07 peter
  2185. * splitted buildderef and buildderefimpl to fix interface crc
  2186. calculation
  2187. Revision 1.34 2003/10/22 20:40:00 peter
  2188. * write derefdata in a separate ppu entry
  2189. Revision 1.33 2003/10/21 15:15:36 peter
  2190. * taicpu_abstract.oper[] changed to pointers
  2191. Revision 1.32 2003/10/17 14:38:32 peter
  2192. * 64k registers supported
  2193. * fixed some memory leaks
  2194. Revision 1.31 2003/10/09 21:31:37 daniel
  2195. * Register allocator splitted, ans abstract now
  2196. Revision 1.30 2003/10/01 20:34:50 peter
  2197. * procinfo unit contains tprocinfo
  2198. * cginfo renamed to cgbase
  2199. * moved cgmessage to verbose
  2200. * fixed ppc and sparc compiles
  2201. Revision 1.29 2003/09/29 20:58:56 peter
  2202. * optimized releasing of registers
  2203. Revision 1.28 2003/09/28 21:49:30 peter
  2204. * fixed invalid opcode handling in spill registers
  2205. Revision 1.27 2003/09/28 13:37:07 peter
  2206. * give error for wrong register number
  2207. Revision 1.26 2003/09/24 21:15:49 florian
  2208. * fixed make cycle
  2209. Revision 1.25 2003/09/24 17:12:36 florian
  2210. * x86-64 adaptions
  2211. Revision 1.24 2003/09/23 17:56:06 peter
  2212. * locals and paras are allocated in the code generation
  2213. * tvarsym.localloc contains the location of para/local when
  2214. generating code for the current procedure
  2215. Revision 1.23 2003/09/14 14:22:51 daniel
  2216. * Fixed incorrect movzx spilling
  2217. Revision 1.22 2003/09/12 20:25:17 daniel
  2218. * Add BTR to destination memory location check in spilling
  2219. Revision 1.21 2003/09/10 19:14:31 daniel
  2220. * Failed attempt to restore broken fastspill functionality
  2221. Revision 1.20 2003/09/10 11:23:09 marco
  2222. * fix from peter for bts reg32,mem32 problem
  2223. Revision 1.19 2003/09/09 12:54:45 florian
  2224. * x86 instruction table updated to nasm 0.98.37:
  2225. - sse3 aka prescott support
  2226. - small fixes
  2227. Revision 1.18 2003/09/07 22:09:35 peter
  2228. * preparations for different default calling conventions
  2229. * various RA fixes
  2230. Revision 1.17 2003/09/03 15:55:02 peter
  2231. * NEWRA branch merged
  2232. Revision 1.16.2.4 2003/08/31 15:46:26 peter
  2233. * more updates for tregister
  2234. Revision 1.16.2.3 2003/08/29 17:29:00 peter
  2235. * next batch of updates
  2236. Revision 1.16.2.2 2003/08/28 18:35:08 peter
  2237. * tregister changed to cardinal
  2238. Revision 1.16.2.1 2003/08/27 19:55:54 peter
  2239. * first tregister patch
  2240. Revision 1.16 2003/08/21 17:20:19 peter
  2241. * first spill the registers of top_ref before spilling top_reg
  2242. Revision 1.15 2003/08/21 14:48:36 peter
  2243. * fix reg-supreg range check error
  2244. Revision 1.14 2003/08/20 16:52:01 daniel
  2245. * Some old register convention code removed
  2246. * A few changes to eliminate a few lines of code
  2247. Revision 1.13 2003/08/20 09:07:00 daniel
  2248. * New register coding now mandatory, some more convert_registers calls
  2249. removed.
  2250. Revision 1.12 2003/08/20 07:48:04 daniel
  2251. * Made internal assembler use new register coding
  2252. Revision 1.11 2003/08/19 13:58:33 daniel
  2253. * Corrected a comment.
  2254. Revision 1.10 2003/08/15 14:44:20 daniel
  2255. * Fixed newra compilation
  2256. Revision 1.9 2003/08/11 21:18:20 peter
  2257. * start of sparc support for newra
  2258. Revision 1.8 2003/08/09 18:56:54 daniel
  2259. * cs_regalloc renamed to cs_regvars to avoid confusion with register
  2260. allocator
  2261. * Some preventive changes to i386 spillinh code
  2262. Revision 1.7 2003/07/06 15:31:21 daniel
  2263. * Fixed register allocator. *Lots* of fixes.
  2264. Revision 1.6 2003/06/14 14:53:50 jonas
  2265. * fixed newra cycle for x86
  2266. * added constants for indicating source and destination operands of the
  2267. "move reg,reg" instruction to aasmcpu (and use those in rgobj)
  2268. Revision 1.5 2003/06/03 13:01:59 daniel
  2269. * Register allocator finished
  2270. Revision 1.4 2003/05/30 23:57:08 peter
  2271. * more sparc cleanup
  2272. * accumulator removed, splitted in function_return_reg (called) and
  2273. function_result_reg (caller)
  2274. Revision 1.3 2003/05/22 21:33:31 peter
  2275. * removed some unit dependencies
  2276. Revision 1.2 2002/04/25 16:12:09 florian
  2277. * fixed more problems with cpubase and x86-64
  2278. Revision 1.1 2003/04/25 12:43:40 florian
  2279. * merged i386/aasmcpu and x86_64/aasmcpu to x86/aasmcpu
  2280. Revision 1.18 2003/04/25 12:04:31 florian
  2281. * merged agx64att and ag386att to x86/agx86att
  2282. Revision 1.17 2003/04/22 14:33:38 peter
  2283. * removed some notes/hints
  2284. Revision 1.16 2003/04/22 10:09:35 daniel
  2285. + Implemented the actual register allocator
  2286. + Scratch registers unavailable when new register allocator used
  2287. + maybe_save/maybe_restore unavailable when new register allocator used
  2288. Revision 1.15 2003/03/26 12:50:54 armin
  2289. * avoid problems with the ide in init/dome
  2290. Revision 1.14 2003/03/08 08:59:07 daniel
  2291. + $define newra will enable new register allocator
  2292. + getregisterint will return imaginary registers with $newra
  2293. + -sr switch added, will skip register allocation so you can see
  2294. the direct output of the code generator before register allocation
  2295. Revision 1.13 2003/02/25 07:41:54 daniel
  2296. * Properly fixed reversed operands bug
  2297. Revision 1.12 2003/02/19 22:00:15 daniel
  2298. * Code generator converted to new register notation
  2299. - Horribily outdated todo.txt removed
  2300. Revision 1.11 2003/01/09 20:40:59 daniel
  2301. * Converted some code in cgx86.pas to new register numbering
  2302. Revision 1.10 2003/01/08 18:43:57 daniel
  2303. * Tregister changed into a record
  2304. Revision 1.9 2003/01/05 13:36:53 florian
  2305. * x86-64 compiles
  2306. + very basic support for float128 type (x86-64 only)
  2307. Revision 1.8 2002/11/17 16:31:58 carl
  2308. * memory optimization (3-4%) : cleanup of tai fields,
  2309. cleanup of tdef and tsym fields.
  2310. * make it work for m68k
  2311. Revision 1.7 2002/11/15 01:58:54 peter
  2312. * merged changes from 1.0.7 up to 04-11
  2313. - -V option for generating bug report tracing
  2314. - more tracing for option parsing
  2315. - errors for cdecl and high()
  2316. - win32 import stabs
  2317. - win32 records<=8 are returned in eax:edx (turned off by default)
  2318. - heaptrc update
  2319. - more info for temp management in .s file with EXTDEBUG
  2320. Revision 1.6 2002/10/31 13:28:32 pierre
  2321. * correct last wrong fix for tw2158
  2322. Revision 1.5 2002/10/30 17:10:00 pierre
  2323. * merge of fix for tw2158 bug
  2324. Revision 1.4 2002/08/15 19:10:36 peter
  2325. * first things tai,tnode storing in ppu
  2326. Revision 1.3 2002/08/13 18:01:52 carl
  2327. * rename swatoperands to swapoperands
  2328. + m68k first compilable version (still needs a lot of testing):
  2329. assembler generator, system information , inline
  2330. assembler reader.
  2331. Revision 1.2 2002/07/20 11:57:59 florian
  2332. * types.pas renamed to defbase.pas because D6 contains a types
  2333. unit so this would conflicts if D6 programms are compiled
  2334. + Willamette/SSE2 instructions to assembler added
  2335. Revision 1.1 2002/07/01 18:46:29 peter
  2336. * internal linker
  2337. * reorganized aasm layer
  2338. }