ra386att.pas 150 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771
  1. {
  2. $Id$
  3. Copyright (c) 1997-98 by Carl Eric Codere
  4. Does the parsing for the AT&T styled inline assembler.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit Ra386att;
  19. {$ifdef TP}
  20. {$N+,E+}
  21. {$endif TP}
  22. {**********************************************************************}
  23. { WARNING }
  24. {**********************************************************************}
  25. { Any modification in the order or removal of terms in the tables }
  26. { in i386.pas and intasmi3.pas will BREAK the code in this unit, }
  27. { unless the appropriate changes are made to this unit. Addition }
  28. { of terms though, will not change the code herein. }
  29. {**********************************************************************}
  30. {--------------------------------------------------------------------}
  31. { LEFT TO DO: }
  32. {--------------------------------------------------------------------}
  33. { o Handle record offsets }
  34. { o Add support imul,shld and shrd. }
  35. { o Add support for nor operators. }
  36. { o Bugfix of ao_imm8s for IMUL. (Currently the 3 operand imul will }
  37. { be considered as invalid because I use ao_imm8 and the table }
  38. { uses ao_imm8s). }
  39. { o In ConcatOpCode add more checking regarding suffixes and }
  40. { destination registers. (started but unfinished). }
  41. {--------------------------------------------------------------------}
  42. Interface
  43. uses
  44. i386,tree;
  45. function assemble: ptree;
  46. const
  47. { this variable is TRUE if the lookup tables have already been setup }
  48. { for fast access. On the first call to assemble the tables are setup }
  49. { and stay set up. }
  50. _asmsorted: boolean = FALSE;
  51. firstreg = R_EAX;
  52. lastreg = R_ST7;
  53. { Hack to support all opcodes in the i386 table }
  54. { only tokens up to and including lastop_in_table }
  55. { are checked for validity, otherwise... }
  56. lastop_in_table = A_POPFD;
  57. type
  58. tiasmops = array[firstop..lastop] of string[7];
  59. piasmops = ^tiasmops;
  60. var
  61. { sorted tables of opcodes }
  62. iasmops: piasmops;
  63. { uppercased tables of registers }
  64. iasmregs: array[firstreg..lastreg] of string[6];
  65. Implementation
  66. Uses
  67. files,aasm,globals,AsmUtils,strings,hcodegen,scanner,systems,
  68. cobjects,verbose,symtable,types;
  69. type
  70. tinteltoken = (
  71. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_HEXNUM,AS_OCTALNUM,
  72. AS_BINNUM,AS_REALNUM,AS_COMMA,AS_LPAREN,
  73. AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,AS_INTNUM,
  74. AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
  75. {------------------ Assembler directives --------------------}
  76. AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,AS_ALIGN,AS_ASCII,
  77. AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,
  78. AS_DATA,AS_TEXT,AS_END,
  79. {------------------ Assembler Operators --------------------}
  80. AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR);
  81. tasmkeyword = string[8];
  82. const
  83. { These tokens should be modified accordingly to the modifications }
  84. { in the different enumerations. }
  85. firstdirective = AS_DB;
  86. lastdirective = AS_END;
  87. firstsreg = R_CS;
  88. lastsreg = R_SS;
  89. _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  90. _count_asmprefixes = 5;
  91. _count_asmspecialops = 25;
  92. _count_asmoverrides = 3;
  93. _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  94. ('.byte','.word','.long','.quad','.globl','.align','.ascii',
  95. '.asciz','.lcomm','.comm','.single','.double','.tfloat',
  96. '.data','.text','END');
  97. {------------------ Missing opcodes from std list ----------------}
  98. _asmprefixes: array[0.._count_asmprefixes] of tasmkeyword = (
  99. 'REPNE','REPE','REP','REPZ','REPNZ','LOCK');
  100. _prefixtokens: array[0.._count_asmprefixes] of tasmop = (
  101. A_REPNE,A_REPE,A_REP,A_REPE,A_REPNE,A_LOCK);
  102. _specialops: array[0.._count_asmspecialops] of tasmkeyword = (
  103. 'CMPSB','CMPSW','CMPSL','INSB','INSW','INSL','OUTSB','OUTSW','OUTSL',
  104. 'SCASB','SCASW','SCASL','STOSB','STOSW','STOSL','MOVSB','MOVSW','MOVSL',
  105. 'LODSB','LODSW','LODSL','LOCK','SEGCS','SEGDS','SEGES','SEGSS');
  106. _specialopstokens: array[0.._count_asmspecialops] of tasmop = (
  107. A_CMPS,A_CMPS,A_CMPS,A_INS,A_INS,A_INS,A_OUTS,A_OUTS,A_OUTS,
  108. A_SCAS,A_SCAS,A_SCAS,A_STOS,A_STOS,A_STOS,A_MOVS,A_MOVS,A_MOVS,
  109. A_LODS,A_LODS,A_LODS,A_LOCK,A_NONE,A_NONE,A_NONE,A_NONE);
  110. {------------------------------------------------------------------}
  111. { register type definition table for easier searching }
  112. _regtypes:array[firstreg..lastreg] of longint =
  113. (ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,
  114. ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,
  115. ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,
  116. ao_none,ao_sreg2,ao_sreg2,ao_sreg2,ao_sreg3,ao_sreg3,ao_sreg2,
  117. ao_floatacc,ao_floatacc,ao_floatreg,ao_floatreg,ao_floatreg,ao_floatreg,
  118. ao_floatreg,ao_floatreg,ao_floatreg);
  119. _regsizes: array[firstreg..lastreg] of topsize =
  120. (S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  121. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  122. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  123. { segment register }
  124. S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  125. { can also be S_S or S_T - must be checked at run-time }
  126. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL);
  127. {topsize = (S_NO,S_B,S_W,S_L,S_BW,S_BL,S_WL,
  128. S_IS,S_IL,S_IQ,S_FS,S_FL,S_FX,S_D);}
  129. _constsizes: array[S_NO..S_FS] of longint =
  130. (0,ao_imm8,ao_imm16,ao_imm32,0,0,0,ao_imm16,ao_imm32,0,ao_imm32);
  131. { converts from AT&T style to non-specific style... }
  132. _fpusizes:array[A_FILDQ..A_FIDIVRS] of topsize = (
  133. {'fildq','filds',}
  134. S_IQ,S_IS,
  135. {'fildl','fldl','fldt','fistq','fists','fistl','fstl','fsts',}
  136. S_IL,S_FL,S_FX,S_IQ,S_IS,S_IL,S_FL,S_FS,
  137. {'fstps','fistpl','fstpl','fistps','fistpq','fstpt','fcomps',}
  138. S_FS,S_IL,S_FL,S_IS,S_IQ,S_FX,S_FS,
  139. {'ficompl','fcompl','ficomps','fcoms','ficoml','fcoml','ficoms',}
  140. S_IL,S_FL,S_IS,S_FS,S_IL,S_FL,S_IS,
  141. {'fiaddl','faddl','fiadds','fisubl','fsubl','fisubs','fsubs',}
  142. S_IL,S_FL,S_IS,S_IL,S_FL,S_FS,S_IS,S_FS,
  143. {'fsubr','fsubrs','fisubrl','fsubrl','fisubrs','fmuls','fimull',}
  144. S_NO,S_FS,S_IL,S_FL,S_IS,S_FS,S_IL,
  145. {'fmull','fimuls','fdivs','fidivl','fdivl','fidivs','fdivrs',}
  146. S_FL,S_IL,S_FS,S_IL,S_FL,S_IS,S_FS,
  147. {'fidivrl','fdivrl',}
  148. S_IL,S_FL);
  149. _fpuopcodes:array[A_FILDQ..A_FIDIVRS] of tasmop = (
  150. A_FILD,A_FILD,A_FILD,A_FLD,A_FLD,A_FIST,A_FIST,A_FIST,A_FST,A_FST,
  151. A_FSTP,A_FISTP,A_FSTP,A_FISTP,A_FISTP,A_FSTP,
  152. A_FCOMP,A_FICOMP,A_FCOMP,A_FICOMP,
  153. A_FCOM,A_FICOM,A_FCOM,A_FICOM,A_FIADD,A_FADD,A_FIADD,
  154. A_FISUB,A_FSUB,A_FISUB,A_FSUB,A_FSUB,A_FSUBR,A_FISUBR,
  155. A_FSUBR,A_FISUBR,A_FMUL,A_FIMUL,A_FMUL,A_FIMUL,A_FDIV,A_FIDIV,
  156. A_FDIV,A_FIDIV,A_FDIVR,A_FIDIVR,A_FDIVR,A_FIDIVR);
  157. const
  158. newline = #10;
  159. firsttoken : boolean = TRUE;
  160. operandnum : byte = 0;
  161. charcount: byte = 0;
  162. var
  163. p : paasmoutput;
  164. actasmtoken: tinteltoken;
  165. actasmpattern: string;
  166. c: char;
  167. Instr: TInstruction;
  168. labellist: TAsmLabelList;
  169. line: string; { CHanged from const to var, there is a bug in 0.9.1 which
  170. doesn't allow 255-char constant strings. MVC}
  171. Procedure SetupTables;
  172. { creates uppercased symbol tables. }
  173. var
  174. i: tasmop;
  175. j: tregister;
  176. Begin
  177. Message(assem_d_creating_lookup_tables);
  178. { opcodes }
  179. new(iasmops);
  180. for i:=firstop to lastop do
  181. iasmops^[i] := upper(att_op2str[i]);
  182. { opcodes }
  183. for j:=firstreg to lastreg do
  184. iasmregs[j] := upper(att_reg2str[j]);
  185. end;
  186. {---------------------------------------------------------------------}
  187. { Routines for the tokenizing }
  188. {---------------------------------------------------------------------}
  189. function is_asmopcode(const s: string):Boolean;
  190. {*********************************************************************}
  191. { FUNCTION is_asmopcode(s: string):Boolean }
  192. { Description: Determines if the s string is a valid opcode }
  193. { if so returns TRUE otherwise returns FALSE. }
  194. {*********************************************************************}
  195. var
  196. i: tasmop;
  197. j: byte;
  198. hs: topsize;
  199. hid: string;
  200. Begin
  201. is_asmopcode := FALSE;
  202. { first search for extended opcodes }
  203. for j:=0 to _count_asmspecialops do
  204. Begin
  205. if s = _specialops[j] then
  206. Begin
  207. is_asmopcode:=TRUE;
  208. exit;
  209. end;
  210. end;
  211. for i:=firstop to lastop do
  212. Begin
  213. if s=iasmops^[i] then
  214. begin
  215. is_asmopcode := TRUE;
  216. exit
  217. end;
  218. end;
  219. { not found yet ... }
  220. { search for all possible suffixes }
  221. for hs:=S_WL downto S_B do
  222. if copy(s,length(s)-length(att_opsize2str[hs])+1,
  223. length(att_opsize2str[hs]))=upper(att_opsize2str[hs]) then
  224. begin
  225. { here we search the entire table... }
  226. hid:=copy(s,1,length(s)-length(att_opsize2str[hs]));
  227. for i:=firstop to lastop do
  228. if (length(hid) > 0) and (hid=iasmops^[i]) then
  229. begin
  230. is_asmopcode := TRUE;
  231. exit;
  232. end;
  233. end;
  234. end;
  235. Procedure is_asmdirective(const s: string; var token: tinteltoken);
  236. {*********************************************************************}
  237. { FUNCTION is_asmdirective(s: string; var token: tinteltoken):Boolean }
  238. { Description: Determines if the s string is a valid directive }
  239. { (an operator can occur in operand fields, while a directive cannot) }
  240. { if so returns the directive token, otherwise does not change token.}
  241. {*********************************************************************}
  242. var
  243. i:byte;
  244. Begin
  245. for i:=0 to _count_asmdirectives do
  246. begin
  247. if s=_asmdirectives[i] then
  248. begin
  249. token := tinteltoken(longint(firstdirective)+i);
  250. exit;
  251. end;
  252. end;
  253. end;
  254. Procedure is_register(const s: string; var token: tinteltoken);
  255. {*********************************************************************}
  256. { PROCEDURE is_register(s: string; var token: tinteltoken); }
  257. { Description: Determines if the s string is a valid register, if }
  258. { so return token equal to A_REGISTER, otherwise does not change token}
  259. {*********************************************************************}
  260. Var
  261. i: tregister;
  262. Begin
  263. for i:=firstreg to lastreg do
  264. begin
  265. if s=iasmregs[i] then
  266. begin
  267. token := AS_REGISTER;
  268. exit;
  269. end;
  270. end;
  271. end;
  272. Function GetToken: tinteltoken;
  273. {*********************************************************************}
  274. { FUNCTION GetToken: tinteltoken; }
  275. { Description: This routine returns intel assembler tokens and }
  276. { does some minor syntax error checking. }
  277. {*********************************************************************}
  278. var
  279. token: tinteltoken;
  280. forcelabel: boolean;
  281. errorflag : boolean;
  282. temp: string;
  283. code: integer;
  284. value: byte;
  285. begin
  286. errorflag := FALSE;
  287. forcelabel := FALSE;
  288. actasmpattern :='';
  289. {* INIT TOKEN TO NOTHING *}
  290. token := AS_NONE;
  291. { while space and tab , continue scan... }
  292. while c in [' ',#9] do
  293. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  294. { Possiblities for first token in a statement: }
  295. { Local Label, Label, Directive, Prefix or Opcode.... }
  296. {$ifdef NEWINPUT}current_scanner^.{$endif}gettokenpos;
  297. if firsttoken and not (c in [newline,#13,'{',';']) then
  298. begin
  299. firsttoken := FALSE;
  300. { directive or local labe }
  301. if c = '.' then
  302. begin
  303. actasmpattern := c;
  304. { Let us point to the next character }
  305. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  306. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  307. begin
  308. actasmpattern := actasmpattern + c;
  309. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  310. end;
  311. { this is a local label... }
  312. if (actasmpattern[2] = 'L') and (c = ':') then
  313. Begin
  314. { local variables are case sensitive }
  315. gettoken := AS_LLABEL;
  316. { delete .L }
  317. delete(actasmpattern,1,2);
  318. { point to next character ... }
  319. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  320. exit;
  321. end
  322. { must be a directive }
  323. else
  324. Begin
  325. { directives are case sensitive!! }
  326. is_asmdirective(actasmpattern, token);
  327. if (token <> AS_NONE) then
  328. Begin
  329. gettoken := token;
  330. exit;
  331. end
  332. else
  333. Message1(assem_e_not_directive_or_local_symbol,actasmpattern);
  334. end;
  335. end; { endif }
  336. {$ifndef NEWINPUT}
  337. if c='/' then
  338. begin
  339. c:=asmgetchar;
  340. { att styled comment }
  341. if c='/' then
  342. begin
  343. repeat
  344. c:=asmgetchar;
  345. until c=newline;
  346. firsttoken := TRUE;
  347. gettoken:=AS_SEPARATOR;
  348. c:=asmgetchar;
  349. exit;
  350. end
  351. else
  352. Message(assem_e_slash_at_begin_of_line_not_allowed);
  353. end;
  354. {$endif}
  355. { only opcodes and global labels are allowed now. }
  356. while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  357. begin
  358. actasmpattern := actasmpattern + c;
  359. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  360. end;
  361. if c = ':' then
  362. begin
  363. { uppervar(actasmpattern);
  364. Carl, you cannot change the label to upper
  365. if you want to be able to read in system unit
  366. don't forget that ATT syntax is case sensitive
  367. for labels !! (PM) }
  368. token := AS_LABEL;
  369. { let us point to the next character }
  370. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  371. gettoken := token;
  372. exit;
  373. end;
  374. If is_asmopcode(upper(actasmpattern)) then
  375. Begin
  376. uppervar(actasmpattern);
  377. gettoken := AS_OPCODE;
  378. exit;
  379. end
  380. else
  381. if upper(actasmpattern) = 'END' then
  382. begin
  383. gettoken := AS_END;
  384. exit;
  385. end
  386. else
  387. begin
  388. gettoken := AS_NONE;
  389. Message(assem_e_invalid_operand);
  390. end;
  391. end
  392. else { else firsttoken }
  393. { Here we must handle all possible cases }
  394. begin
  395. case c of
  396. '.': { possiblities : - local label reference , such as in jmp @local1 }
  397. { - directive. }
  398. begin
  399. actasmpattern := c;
  400. c:= {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  401. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  402. begin
  403. actasmpattern := actasmpattern + c;
  404. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  405. end;
  406. is_asmdirective(actasmpattern,token);
  407. { if directive }
  408. if (token <> AS_NONE) then
  409. begin
  410. gettoken := token;
  411. exit;
  412. end;
  413. { local label references and directives }
  414. { are case sensitive }
  415. gettoken := AS_ID;
  416. exit;
  417. end;
  418. { identifier, register, opcode, prefix or directive }
  419. '_','A'..'Z','a'..'z': begin
  420. actasmpattern := c;
  421. c:= {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  422. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  423. begin
  424. actasmpattern := actasmpattern + c;
  425. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  426. end;
  427. { pascal is not case sensitive! }
  428. { therefore variables which are }
  429. { outside the scope of the asm }
  430. { block, should not be made case }
  431. { sensitive... !!!!! }
  432. uppervar(actasmpattern);
  433. If is_asmopcode(actasmpattern) then
  434. Begin
  435. gettoken := AS_OPCODE;
  436. exit;
  437. end;
  438. { we handle this directive separately from }
  439. { others. }
  440. if actasmpattern = 'END' then
  441. Begin
  442. gettoken := AS_END;
  443. exit;
  444. end;
  445. { if found }
  446. if (token <> AS_NONE) then
  447. begin
  448. gettoken := token;
  449. exit;
  450. end
  451. { this is surely an identifier }
  452. else
  453. token := AS_ID;
  454. gettoken := token;
  455. exit;
  456. end;
  457. '&': begin
  458. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  459. gettoken := AS_AND;
  460. end;
  461. { character }
  462. '''' : begin
  463. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  464. if c = '\' then
  465. Begin
  466. { escape sequence }
  467. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  468. case c of
  469. newline: Message(scan_f_string_exceeds_line);
  470. 't': actasmpattern:=#09;
  471. 'b': actasmpattern:=#08;
  472. '\': actasmpattern:='\';
  473. 'f': actasmpattern:=#12;
  474. 'n': actasmpattern:=#10;
  475. 'r': actasmpattern:=#13;
  476. '"': actasmpattern:='"';
  477. { octal number }
  478. '0'..'7':
  479. begin
  480. temp:=c;
  481. temp:=temp+{$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  482. temp:=temp+{$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  483. val(octaltodec(temp),value,code);
  484. if (code <> 0) then
  485. Message1(assem_e_error_in_octal_const,temp);
  486. actasmpattern:=chr(value);
  487. end;
  488. { hexadecimal number }
  489. 'x':
  490. begin
  491. temp:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  492. temp:=temp+{$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  493. val(hextodec(temp),value,code);
  494. if (code <> 0) then
  495. Message1(assem_e_error_in_hex_const,temp);
  496. actasmpattern:=chr(value);
  497. end;
  498. else
  499. Begin
  500. Message(assem_e_escape_seq_ignored);
  501. actasmpattern:=c;
  502. end
  503. end; { end case }
  504. end
  505. else
  506. actasmpattern:=c;
  507. gettoken := AS_STRING;
  508. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  509. exit;
  510. end;
  511. { string }
  512. '"' :
  513. begin
  514. actasmpattern:='';
  515. while true do
  516. Begin
  517. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  518. case c of
  519. '\': Begin
  520. { escape sequences }
  521. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  522. case c of
  523. newline: Message(scan_f_string_exceeds_line);
  524. 't': actasmpattern:=actasmpattern+#09;
  525. 'b': actasmpattern:=actasmpattern+#08;
  526. '\': actasmpattern:=actasmpattern+'\';
  527. 'f': actasmpattern:=actasmpattern+#12;
  528. 'n': actasmpattern:=actasmpattern+#10;
  529. 'r': actasmpattern:=actasmpattern+#13;
  530. '"': actasmpattern:=actasmpattern+'"';
  531. { octal number }
  532. '0'..'7':
  533. begin
  534. temp:=c;
  535. temp:=temp+{$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  536. temp:=temp+{$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  537. val(octaltodec(temp),value,code);
  538. if (code <> 0) then
  539. Message1(assem_e_error_in_octal_const,temp);
  540. actasmpattern:=actasmpattern+chr(value);
  541. end;
  542. { hexadecimal number }
  543. 'x':
  544. begin
  545. temp:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  546. temp:=temp+{$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  547. val(hextodec(temp),value,code);
  548. if (code <> 0) then
  549. Message1(assem_e_error_in_hex_const,temp);
  550. actasmpattern:=actasmpattern+chr(value);
  551. end;
  552. else
  553. Begin
  554. Message(assem_e_escape_seq_ignored);
  555. actasmpattern:=actasmpattern+c;
  556. end
  557. end; { end case }
  558. end;
  559. '"': begin
  560. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  561. break;
  562. end;
  563. newline: Message(scan_f_string_exceeds_line);
  564. else
  565. actasmpattern:=actasmpattern+c;
  566. end;
  567. end; { end case }
  568. token := AS_STRING;
  569. gettoken := token;
  570. exit;
  571. end;
  572. '$' : begin
  573. gettoken := AS_DOLLAR;
  574. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  575. exit;
  576. end;
  577. ',' : begin
  578. gettoken := AS_COMMA;
  579. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  580. exit;
  581. end;
  582. '<' : begin
  583. gettoken := AS_SHL;
  584. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  585. if c = '<' then
  586. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  587. exit;
  588. end;
  589. '>' : begin
  590. gettoken := AS_SHL;
  591. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  592. if c = '>' then
  593. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  594. exit;
  595. end;
  596. '|' : begin
  597. gettoken := AS_OR;
  598. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  599. exit;
  600. end;
  601. '^' : begin
  602. gettoken := AS_XOR;
  603. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  604. exit;
  605. end;
  606. '!' : begin
  607. Message(assem_e_nor_not_supported);
  608. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  609. gettoken := AS_NONE;
  610. exit;
  611. end;
  612. '(' : begin
  613. gettoken := AS_LPAREN;
  614. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  615. exit;
  616. end;
  617. ')' : begin
  618. gettoken := AS_RPAREN;
  619. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  620. exit;
  621. end;
  622. ':' : begin
  623. gettoken := AS_COLON;
  624. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  625. exit;
  626. end;
  627. '+' : begin
  628. gettoken := AS_PLUS;
  629. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  630. exit;
  631. end;
  632. '-' : begin
  633. gettoken := AS_MINUS;
  634. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  635. exit;
  636. end;
  637. '*' : begin
  638. gettoken := AS_STAR;
  639. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  640. exit;
  641. end;
  642. '/' : begin
  643. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  644. { att styled comment }
  645. if c='/' then
  646. begin
  647. repeat
  648. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  649. until c=newline;
  650. firsttoken := TRUE;
  651. gettoken:=AS_SEPARATOR;
  652. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  653. exit;
  654. end
  655. else
  656. begin
  657. gettoken := AS_SLASH;
  658. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  659. exit;
  660. end;
  661. end;
  662. { register or modulo }
  663. { only register supported }
  664. { for the moment. }
  665. '%' : begin
  666. actasmpattern := c;
  667. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  668. while c in ['a'..'z','A'..'Z','0'..'9'] do
  669. Begin
  670. actasmpattern := actasmpattern + c;
  671. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  672. end;
  673. token := AS_NONE;
  674. uppervar(actasmpattern);
  675. if (actasmpattern = '%ST') and (c='(') then
  676. Begin
  677. actasmpattern:=actasmpattern+c;
  678. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  679. if c in ['0'..'9'] then
  680. actasmpattern := actasmpattern + c
  681. else
  682. Message(assem_e_invalid_fpu_register);
  683. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  684. if c <> ')' then
  685. Message(assem_e_invalid_fpu_register)
  686. else
  687. Begin
  688. actasmpattern := actasmpattern + c;
  689. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar; { let us point to next character. }
  690. end;
  691. end;
  692. is_register(actasmpattern, token);
  693. { if found }
  694. if (token <> AS_NONE) then
  695. begin
  696. gettoken := token;
  697. exit;
  698. end
  699. else
  700. Message(assem_w_modulo_not_supported);
  701. end;
  702. { integer number }
  703. '1'..'9': begin
  704. actasmpattern := c;
  705. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  706. while c in ['0'..'9'] do
  707. Begin
  708. actasmpattern := actasmpattern + c;
  709. c:= {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  710. end;
  711. gettoken := AS_INTNUM;
  712. exit;
  713. end;
  714. '0': begin
  715. { octal,hexa,real or binary number. }
  716. actasmpattern := c;
  717. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  718. case upcase(c) of
  719. { binary }
  720. 'B': Begin
  721. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  722. while c in ['0','1'] do
  723. Begin
  724. actasmpattern := actasmpattern + c;
  725. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  726. end;
  727. gettoken := AS_BINNUM;
  728. exit;
  729. end;
  730. { real }
  731. 'D': Begin
  732. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  733. { get ridd of the 0d }
  734. if (c='+') or (c='-') then
  735. begin
  736. actasmpattern:=c;
  737. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  738. end
  739. else
  740. actasmpattern:='';
  741. while c in ['0'..'9'] do
  742. Begin
  743. actasmpattern := actasmpattern + c;
  744. c:= {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  745. end;
  746. if c='.' then
  747. begin
  748. actasmpattern := actasmpattern + c;
  749. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  750. while c in ['0'..'9'] do
  751. Begin
  752. actasmpattern := actasmpattern + c;
  753. c:= {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  754. end;
  755. if upcase(c) = 'E' then
  756. begin
  757. actasmpattern := actasmpattern + c;
  758. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  759. if (c = '+') or (c = '-') then
  760. begin
  761. actasmpattern := actasmpattern + c;
  762. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  763. end;
  764. while c in ['0'..'9'] do
  765. Begin
  766. actasmpattern := actasmpattern + c;
  767. c:= {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  768. end;
  769. end;
  770. gettoken := AS_REALNUM;
  771. exit;
  772. end
  773. else
  774. Message1(assem_e_invalid_float_const,actasmpattern+c);
  775. end;
  776. { hexadecimal }
  777. 'X': Begin
  778. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  779. while c in ['0'..'9','a'..'f','A'..'F'] do
  780. Begin
  781. actasmpattern := actasmpattern + c;
  782. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  783. end;
  784. gettoken := AS_HEXNUM;
  785. exit;
  786. end;
  787. { octal }
  788. '1'..'7': begin
  789. actasmpattern := actasmpattern + c;
  790. while c in ['0'..'7'] do
  791. Begin
  792. actasmpattern := actasmpattern + c;
  793. c := {$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  794. end;
  795. gettoken := AS_OCTALNUM;
  796. exit;
  797. end;
  798. else { octal number zero value...}
  799. Begin
  800. gettoken := AS_OCTALNUM;
  801. exit;
  802. end;
  803. end; { end case }
  804. end;
  805. '{',#13,newline,';' : begin
  806. { the comment is read by asmgetchar }
  807. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  808. firsttoken := TRUE;
  809. gettoken:=AS_SEPARATOR;
  810. end;
  811. else
  812. Begin
  813. Message(scan_f_illegal_char);
  814. end;
  815. end; { end case }
  816. end; { end else if }
  817. end;
  818. {---------------------------------------------------------------------}
  819. { Routines for the output }
  820. {---------------------------------------------------------------------}
  821. { looks for internal names of variables and routines }
  822. Function SearchDirectVar(var Instr: TInstruction; const hs:string;operandnum:byte): Boolean;
  823. var
  824. p : pai_external;
  825. Begin
  826. SearchDirectVar:=false;
  827. { search in the list of internals }
  828. p:=search_assembler_symbol(internals,hs,EXT_ANY);
  829. if p=nil then
  830. p:=search_assembler_symbol(externals,hs,EXT_ANY);
  831. if p<>nil then
  832. begin
  833. { get symbol name }
  834. { free the memory before changing the symbol name. }
  835. if assigned(instr.operands[operandnum].ref.symbol) then
  836. FreeMem(instr.operands[operandnum].ref.symbol,
  837. length(instr.operands[operandnum].ref.symbol^)+1);
  838. instr.operands[operandnum].ref.symbol:=newpasstr(strpas(p^.name));
  839. case p^.exttyp of
  840. EXT_BYTE : instr.operands[operandnum].size := S_B;
  841. EXT_WORD : instr.operands[operandnum].size := S_W;
  842. EXT_NEAR,EXT_FAR,EXT_PROC,EXT_DWORD,EXT_CODEPTR,EXT_DATAPTR:
  843. instr.operands[operandnum].size := S_L;
  844. EXT_QWORD : instr.operands[operandnum].size := S_FL;
  845. EXT_TBYTE : instr.operands[operandnum].size := S_FX;
  846. else
  847. { this is in the case where the instruction is LEA }
  848. { or something like that, in that case size is not }
  849. { important. }
  850. instr.operands[operandnum].size := S_NO;
  851. end;
  852. SearchDirectVar := TRUE;
  853. Exit;
  854. end;
  855. end;
  856. { returns an appropriate ao_xxxx flag indicating the type }
  857. { of operand. }
  858. function findtype(Var Opr: TOperand): longint;
  859. Begin
  860. With Opr do
  861. Begin
  862. case operandtype of
  863. OPR_REFERENCE: Begin
  864. if assigned(ref.symbol) then
  865. { check if in local label list }
  866. { if so then it is considered }
  867. { as a displacement. }
  868. Begin
  869. if labellist.search(ref.symbol^) <> nil then
  870. findtype := ao_disp
  871. else
  872. findtype := ao_mem; { probably a mem ref. }
  873. end
  874. else
  875. findtype := ao_mem;
  876. end;
  877. OPR_CONSTANT: Begin
  878. { check if there is not already a default size }
  879. if opr.size <> S_NO then
  880. Begin
  881. findtype := _constsizes[opr.size];
  882. exit;
  883. end;
  884. if val < $ff then
  885. Begin
  886. findtype := ao_imm8;
  887. opr.size := S_B;
  888. end
  889. else if val < $ffff then
  890. Begin
  891. findtype := ao_imm16;
  892. opr.size := S_W;
  893. end
  894. else
  895. Begin
  896. findtype := ao_imm32;
  897. opr.size := S_L;
  898. end
  899. end;
  900. OPR_REGISTER: Begin
  901. findtype := _regtypes[reg];
  902. exit;
  903. end;
  904. OPR_SYMBOL: Begin
  905. findtype := ao_jumpabsolute;
  906. end;
  907. OPR_NONE: Begin
  908. findtype := 0;
  909. end;
  910. else
  911. Begin
  912. Message(assem_f_internal_error_in_findtype);
  913. end;
  914. end;
  915. end;
  916. end;
  917. Procedure HandleExtend(var instr: TInstruction);
  918. { Handles MOVZX, MOVSX ... }
  919. var
  920. instruc: tasmop;
  921. opsize: topsize;
  922. Begin
  923. instruc:=instr.getinstruction;
  924. { if we have A_MOVZX/A_MOVSX here, there is a big problem }
  925. { it should never happen, because it is already replaced }
  926. { by ConcatOpcode! }
  927. if (instruc in [A_MOVZX,A_MOVSX]) then
  928. Message(assem_f_internal_error_in_handleextend)
  929. else
  930. if (instruc = A_MOVSB) or (instruc = A_MOVSBL)
  931. or (instruc = A_MOVSBW) or (instruc = A_MOVSWL) then
  932. instruc := A_MOVSX
  933. else
  934. if (instruc = A_MOVZB) or (instruc = A_MOVZWL) then
  935. instruc := A_MOVZX;
  936. With instr do
  937. Begin
  938. if operands[1].size = S_B then
  939. Begin
  940. if operands[2].size = S_L then
  941. opsize := S_BL
  942. else
  943. if operands[2].size = S_W then
  944. opsize := S_BW
  945. else
  946. begin
  947. Message(assem_e_invalid_size_movzx);
  948. exit;
  949. end;
  950. end
  951. else
  952. if operands[1].size = S_W then
  953. Begin
  954. if operands[2].size = S_L then
  955. opsize := S_WL
  956. else
  957. begin
  958. Message(assem_e_invalid_size_movzx);
  959. exit;
  960. end;
  961. end
  962. else
  963. begin
  964. Message(assem_e_invalid_size_movzx);
  965. exit;
  966. end;
  967. if operands[1].operandtype = OPR_REGISTER then
  968. Begin
  969. if operands[2].operandtype <> OPR_REGISTER then
  970. Message(assem_e_invalid_opcode) { exit...}
  971. else
  972. p^.concat(new(pai386,op_reg_reg(instruc,opsize,
  973. operands[1].reg,operands[2].reg)));
  974. end
  975. else
  976. if operands[1].operandtype = OPR_REFERENCE then
  977. Begin
  978. if operands[2].operandtype <> OPR_REGISTER then
  979. Message(assem_e_invalid_opcode) {exit...}
  980. else
  981. p^.concat(new(pai386,op_ref_reg(instruc,opsize,
  982. newreference(operands[1].ref),operands[2].reg)));
  983. end
  984. end; { end with }
  985. end;
  986. Procedure ConcatOpCode(var instr: TInstruction);
  987. {*********************************************************************}
  988. { First Pass: }
  989. { - If this is a three operand opcode: }
  990. { imul,shld,and shrd -> check them manually. }
  991. {*********************************************************************}
  992. var
  993. fits : boolean;
  994. i: longint;
  995. opsize: topsize;
  996. optyp1, optyp2, optyp3: longint;
  997. instruc: tasmop;
  998. Begin
  999. fits := FALSE;
  1000. for i:=1 to instr.numops do
  1001. Begin
  1002. case instr.operands[i].operandtype of
  1003. OPR_REGISTER: instr.operands[i].size :=
  1004. _regsizes[instr.operands[i].reg];
  1005. end; { end case }
  1006. end; { endif }
  1007. { setup specific instructions for first pass }
  1008. instruc := instr.getinstruction;
  1009. if (instruc in [A_LEA,A_LDS,A_LSS,A_LES,A_LFS,A_LGS]) then
  1010. Begin
  1011. if instr.operands[2].size <> S_L then
  1012. Begin
  1013. Message(assem_e_16bit_base_in_32bit_segment);
  1014. exit;
  1015. end; { endif }
  1016. end;
  1017. With instr do
  1018. Begin
  1019. for i:=1 to numops do
  1020. Begin
  1021. With operands[i] do
  1022. Begin
  1023. { check for 16-bit bases/indexes and emit an error. }
  1024. { we cannot only emit a warning since gas does not }
  1025. { accept 16-bit indexes and bases. }
  1026. if (operandtype = OPR_REFERENCE) and
  1027. ((ref.base <> R_NO) or
  1028. (ref.index <> R_NO)) then
  1029. Begin
  1030. { index or base defined. }
  1031. if (ref.base <> R_NO) then
  1032. Begin
  1033. if not (ref.base in
  1034. [R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESI,R_EDI,R_ESP]) then
  1035. Message(assem_e_16bit_base_in_32bit_segment);
  1036. end;
  1037. { index or base defined. }
  1038. if (ref.index <> R_NO) then
  1039. Begin
  1040. if not (ref.index in
  1041. [R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESI,R_EDI,R_ESP]) then
  1042. Message(assem_e_16bit_index_in_32bit_segment);
  1043. end;
  1044. end;
  1045. { Check for constants without bases/indexes in memory }
  1046. { references. }
  1047. if (operandtype = OPR_REFERENCE) and
  1048. (ref.base = R_NO) and
  1049. (ref.index = R_NO) and
  1050. (ref.symbol = nil) and
  1051. (ref.offset <> 0) then
  1052. Begin
  1053. ref.isintvalue := TRUE;
  1054. Message(assem_e_const_ref_not_allowed);
  1055. end;
  1056. opinfo := findtype(operands[i]);
  1057. end; { end with }
  1058. end; {endfor}
  1059. { TAKE CARE OF SPECIAL OPCODES, TAKE CARE OF THEM INDIVUALLY. }
  1060. { ALL THE REST ARE TAKEN CARE BY OPCODE TABLE AND THIRD PASS. }
  1061. { is this right for ratti386 ? (PM) }
  1062. { almost... here we check for the size of registers and references }
  1063. { to determine the correct gas opcode to use, because if the token }
  1064. { is A_MOVSX or A_MOVZX then that means that the person forgot to }
  1065. { specify the size.. }
  1066. { if memory size is not specified, will of course give out an error}
  1067. if instruc = A_MOVSX then
  1068. Begin
  1069. if numops = 2 then
  1070. begin
  1071. if stropsize = S_BL then
  1072. begin
  1073. operands[1].size := S_B;
  1074. stropsize := S_NO;
  1075. operands[2].size := S_L;
  1076. addinstr(A_MOVSBL)
  1077. end
  1078. else
  1079. if stropsize = S_WL then
  1080. begin
  1081. operands[1].size := S_W;
  1082. stropsize := S_NO;
  1083. operands[2].size := S_L;
  1084. addinstr(A_MOVSWL)
  1085. end
  1086. else
  1087. if stropsize = S_BW then
  1088. begin
  1089. operands[1].size := S_B;
  1090. stropsize := S_NO;
  1091. operands[2].size := S_W;
  1092. addinstr(A_MOVSBW)
  1093. end
  1094. else
  1095. if (operands[1].size = S_B) and (operands[2].size = S_W) then
  1096. addinstr(A_MOVSBW)
  1097. else
  1098. if (operands[1].size = S_B) and (operands[2].size = S_L) then
  1099. addinstr(A_MOVSBL)
  1100. else
  1101. if (operands[1].size = S_W) and (operands[2].size = S_L) then
  1102. addinstr(A_MOVSWL)
  1103. else
  1104. begin
  1105. Message(assem_e_invalid_size_movzx);
  1106. exit;
  1107. end;
  1108. instruc := getinstruction; { reload instruction }
  1109. end
  1110. else
  1111. begin
  1112. Message(assem_e_too_many_operands);
  1113. exit;
  1114. end;
  1115. end
  1116. else
  1117. if instruc = A_MOVZX then
  1118. Begin
  1119. if numops = 2 then
  1120. Begin
  1121. if stropsize = S_BW then
  1122. begin
  1123. operands[1].size := S_B;
  1124. stropsize := S_NO;
  1125. operands[2].size := S_W;
  1126. addinstr(A_MOVZB)
  1127. end
  1128. else
  1129. if stropsize = S_BL then
  1130. begin
  1131. operands[1].size := S_B;
  1132. stropsize := S_NO;
  1133. operands[2].size := S_L;
  1134. addinstr(A_MOVZB)
  1135. end
  1136. else
  1137. if stropsize = S_WL then
  1138. begin
  1139. operands[1].size := S_W;
  1140. stropsize := S_NO;
  1141. operands[2].size := S_L;
  1142. addinstr(A_MOVZWL)
  1143. end
  1144. else
  1145. { change the instruction to conform to GAS }
  1146. if (operands[1].size = S_B) and (operands[2].size in [S_W,S_L]) then
  1147. addinstr(A_MOVZB)
  1148. else
  1149. if (operands[1].size = S_W) and (operands[2].size = S_L) then
  1150. addinstr(A_MOVZWL)
  1151. else
  1152. begin
  1153. Message(assem_e_invalid_size_movzx);
  1154. exit;
  1155. end;
  1156. instruc := getinstruction; { reload instruction }
  1157. end
  1158. else
  1159. Begin
  1160. Message(assem_e_too_many_operands);
  1161. exit;
  1162. end;
  1163. end
  1164. else
  1165. if instruc = A_FWAIT then
  1166. FWaitWarning
  1167. else
  1168. if (instruc in [A_BT,A_BTC,A_BTR,A_BTS]) then
  1169. Begin
  1170. if numops = 2 then
  1171. Begin
  1172. if (operands[1].operandtype = OPR_CONSTANT)
  1173. and (operands[1].val <= $ff) then
  1174. Begin
  1175. operands[1].opinfo := ao_imm8;
  1176. { no operand size if using constant. }
  1177. operands[1].size := S_NO;
  1178. fits := TRUE;
  1179. end
  1180. end
  1181. else
  1182. Begin
  1183. Message(assem_e_invalid_opcode_and_operand);
  1184. exit;
  1185. end;
  1186. end
  1187. else
  1188. if instruc = A_ENTER then
  1189. Begin
  1190. if numops =2 then
  1191. Begin
  1192. if (operands[1].operandtype = OPR_CONSTANT) and
  1193. (operands[1].val <= $ffff) then
  1194. Begin
  1195. operands[1].opinfo := ao_imm16;
  1196. end { endif }
  1197. end { endif }
  1198. else
  1199. Begin
  1200. Message(assem_e_invalid_opcode_and_operand);
  1201. exit;
  1202. end
  1203. end { endif }
  1204. else
  1205. { Handle special opcodes for the opcode }
  1206. { table. Set them up correctly. }
  1207. if (instruc in [A_INS,A_IN]) then
  1208. Begin
  1209. if numops =2 then
  1210. Begin
  1211. if (operands[1].operandtype = OPR_REGISTER) and (operands[1].reg = R_DX)
  1212. then
  1213. Begin
  1214. operands[1].opinfo := ao_inoutportreg;
  1215. if (operands[2].operandtype = OPR_REGISTER) and
  1216. (operands[2].reg in [R_EAX,R_AX,R_AL]) and
  1217. (instruc = A_IN) then
  1218. Begin
  1219. operands[2].opinfo := ao_acc;
  1220. end
  1221. end
  1222. else
  1223. if (operands[1].operandtype = OPR_CONSTANT) and (operands[1].val <= $ff)
  1224. and (instruc = A_IN) then
  1225. Begin
  1226. operands[1].opinfo := ao_imm8;
  1227. operands[1].size := S_B;
  1228. if (operands[2].operandtype = OPR_REGISTER) and
  1229. (operands[2].reg in [R_EAX,R_AX,R_AL]) and
  1230. (instruc = A_IN) then
  1231. Begin
  1232. operands[2].opinfo := ao_acc;
  1233. end
  1234. end;
  1235. end
  1236. else
  1237. Begin
  1238. Message(assem_e_invalid_opcode_and_operand);
  1239. exit;
  1240. end;
  1241. end
  1242. else
  1243. if (instruc in [A_OUTS,A_OUT]) then
  1244. Begin
  1245. if numops =2 then
  1246. Begin
  1247. if (operands[2].operandtype = OPR_REGISTER) and (operands[2].reg = R_DX)
  1248. then
  1249. Begin
  1250. operands[2].opinfo := ao_inoutportreg;
  1251. if (operands[1].operandtype = OPR_REGISTER) and
  1252. (operands[1].reg in [R_EAX,R_AX,R_AL]) and
  1253. (instruc = A_OUT) then
  1254. Begin
  1255. operands[1].opinfo := ao_acc;
  1256. fits := TRUE;
  1257. end
  1258. end
  1259. else
  1260. if (operands[2].operandtype = OPR_CONSTANT) and (operands[2].val <= $ff)
  1261. and (instruc = A_OUT) then
  1262. Begin
  1263. operands[2].opinfo := ao_imm8;
  1264. operands[2].size := S_B;
  1265. if (operands[1].operandtype = OPR_REGISTER) and
  1266. (operands[1].reg in [R_EAX,R_AX,R_AL]) and
  1267. (instruc = A_OUT) then
  1268. Begin
  1269. operands[1].opinfo := ao_acc;
  1270. fits := TRUE;
  1271. end
  1272. end;
  1273. end
  1274. else
  1275. Begin
  1276. Message(assem_e_invalid_opcode_and_operand);
  1277. exit;
  1278. end;
  1279. end
  1280. else
  1281. if instruc in [A_RCL,A_RCR,A_ROL,A_ROR,A_SAL,A_SAR,A_SHL,A_SHR] then
  1282. { if RCL,ROL,... }
  1283. Begin
  1284. if numops =2 then
  1285. Begin
  1286. if (operands[1].operandtype = OPR_REGISTER) and (operands[1].reg = R_CL)
  1287. then
  1288. Begin
  1289. operands[1].opinfo := ao_shiftcount
  1290. end
  1291. else
  1292. if (operands[1].operandtype = OPR_CONSTANT) and
  1293. (operands[1].val <= $ff) then
  1294. Begin
  1295. operands[1].opinfo := ao_imm8;
  1296. operands[1].size := S_B;
  1297. end;
  1298. end
  1299. else { if numops = 2 }
  1300. Begin
  1301. Message(assem_e_invalid_opcode_and_operand);
  1302. exit;
  1303. end;
  1304. end
  1305. { endif ROL,RCL ... }
  1306. else
  1307. { this did not work (PM) }
  1308. if instruc in [A_DIV, A_IDIV] then
  1309. Begin
  1310. if (operands[2].operandtype = OPR_REGISTER) and
  1311. (operands[2].reg in [R_AL,R_AX,R_EAX]) then
  1312. operands[2].opinfo := ao_acc;
  1313. end
  1314. else
  1315. if (instruc = A_FNSTSW) or (instruc = A_FSTSW) then
  1316. Begin
  1317. { %ax can be omitted in ATT syntax }
  1318. if numops = 0 then
  1319. Begin
  1320. numops:=1;
  1321. operands[1].operandtype:=OPR_REGISTER;
  1322. operands[1].reg:=R_AX;
  1323. operands[1].opinfo := ao_acc;
  1324. end
  1325. else if numops = 1 then
  1326. Begin
  1327. if (operands[1].operandtype = OPR_REGISTER) and
  1328. (operands[1].reg = R_AX) then
  1329. operands[1].opinfo := ao_acc;
  1330. end
  1331. else
  1332. Begin
  1333. Message(assem_e_invalid_opcode_and_operand);
  1334. exit;
  1335. end;
  1336. end
  1337. else
  1338. if (instruc = A_SHLD) or (instruc = A_SHRD) then
  1339. { these instruction are fully parsed individually on pass three }
  1340. { so we just do a summary checking here. }
  1341. Begin
  1342. if numops = 3 then
  1343. Begin
  1344. if (operands[3].operandtype = OPR_CONSTANT)
  1345. and (operands[3].val <= $ff) then
  1346. Begin
  1347. operands[3].opinfo := ao_imm8;
  1348. operands[3].size := S_B;
  1349. end;
  1350. end
  1351. else
  1352. Begin
  1353. Message(assem_e_invalid_opcode_and_operand);
  1354. exit;
  1355. end;
  1356. end
  1357. else
  1358. if instruc = A_INT then
  1359. Begin
  1360. if numops = 1 then
  1361. Begin
  1362. if (operands[1].operandtype = OPR_CONSTANT) and
  1363. (operands[1].val <= $ff) then
  1364. operands[1].opinfo := ao_imm8;
  1365. end
  1366. end
  1367. else
  1368. if instruc = A_RET then
  1369. Begin
  1370. if numops =1 then
  1371. Begin
  1372. if (operands[1].operandtype = OPR_CONSTANT) and
  1373. (operands[1].val <= $ffff) then
  1374. operands[1].opinfo := ao_imm16;
  1375. end
  1376. end; { endif }
  1377. { all string instructions have default memory }
  1378. { location which are ignored. Take care of }
  1379. { those. }
  1380. { Here could be added the code for segment }
  1381. { overrides. }
  1382. if instruc in [A_SCAS,A_CMPS,A_STOS,A_LODS] then
  1383. Begin
  1384. if numops =1 then
  1385. Begin
  1386. if (operands[1].operandtype = OPR_REFERENCE) and
  1387. (assigned(operands[1].ref.symbol)) then
  1388. Freemem(operands[1].ref.symbol,length(operands[1].ref.symbol^)+1);
  1389. operands[1].operandtype := OPR_NONE;
  1390. numops := 0;
  1391. end;
  1392. end; { endif }
  1393. if instruc in [A_INS,A_MOVS,A_OUTS] then
  1394. Begin
  1395. if numops =2 then
  1396. Begin
  1397. if (operands[2].operandtype = OPR_REFERENCE) and
  1398. (assigned(operands[2].ref.symbol)) then
  1399. Freemem(operands[2].ref.symbol,length(operands[2].ref.symbol^)+1);
  1400. if (operands[1].operandtype = OPR_REFERENCE) and
  1401. (assigned(operands[1].ref.symbol)) then
  1402. Freemem(operands[1].ref.symbol,length(operands[2].ref.symbol^)+1);
  1403. operands[2].operandtype := OPR_NONE;
  1404. operands[1].operandtype := OPR_NONE;
  1405. numops := 0;
  1406. end;
  1407. end;
  1408. { handle parameter for segment overrides }
  1409. if instruc = A_XLAT then
  1410. Begin
  1411. { handle special TP syntax case for XLAT }
  1412. { here we accept XLAT, XLATB and XLAT m8 }
  1413. if (numops = 1) or (numops = 0) then
  1414. Begin
  1415. if (operands[1].operandtype = OPR_REFERENCE) and
  1416. (assigned(operands[1].ref.symbol)) then
  1417. Freemem(operands[1].ref.symbol,length(operands[1].ref.symbol^)+1);
  1418. operands[1].operandtype := OPR_NONE;
  1419. numops := 0;
  1420. { always a byte for XLAT }
  1421. instr.stropsize := S_B;
  1422. end;
  1423. end
  1424. else
  1425. { ------------------------------------------------------------------- }
  1426. { ------------------------- SIZE CHECK ------------------------------ }
  1427. { ------------- presently done only for most used opcodes ---------- }
  1428. { Checks if the suffix concords with the destination size , if }
  1429. { not gives out an error. (This check is stricter then gas but is }
  1430. { REQUIRED for intasmi3) }
  1431. if instruc in [A_MOV,A_ADD,A_SUB,A_ADC,A_SBB,A_CMP,A_AND,A_OR,A_TEST,A_XOR] then
  1432. begin
  1433. if (instr.stropsize <> S_NO) and (instr.operands[2].size <> S_NO) then
  1434. if (instr.stropsize <> instr.operands[2].size) then
  1435. begin
  1436. Message(assem_e_size_suffix_and_dest_reg_dont_match);
  1437. exit;
  1438. end;
  1439. end
  1440. else
  1441. if instruc in [A_DEC,A_INC,A_NOT,A_NEG] then
  1442. begin
  1443. if (instr.stropsize <> S_NO) and (instr.operands[1].size <> S_NO) then
  1444. if (instr.stropsize <> instr.operands[1].size) then
  1445. begin
  1446. Message(assem_e_size_suffix_and_dest_reg_dont_match);
  1447. exit;
  1448. end;
  1449. end;
  1450. { ------------------------------------------------------------------- }
  1451. { copy them to local variables }
  1452. { for faster access }
  1453. optyp1:=operands[1].opinfo;
  1454. optyp2:=operands[2].opinfo;
  1455. optyp3:=operands[3].opinfo;
  1456. end; { end with }
  1457. { after reading the operands }
  1458. { search the instruction }
  1459. { setup startvalue from cache }
  1460. if ins_cache[instruc]<>-1 then
  1461. i:=ins_cache[instruc]
  1462. else i:=0;
  1463. { I think this is too dangerous for me therefore i decided that for }
  1464. { the att version only if the processor > i386 or we are compiling }
  1465. { the system unit then this will be allowed... }
  1466. if (instruc >= lastop_in_table) and
  1467. ((cs_compilesystem in aktswitches) or (aktoptprocessor>int386)) then
  1468. begin
  1469. Message1(assem_w_opcode_not_in_table,att_op2str[instruc]);
  1470. fits:=true;
  1471. end
  1472. else while not(fits) do
  1473. begin
  1474. { set the instruction cache, if the instruction }
  1475. { occurs the first time }
  1476. if (it[i].i=instruc) and (ins_cache[instruc]=-1) then
  1477. ins_cache[instruc]:=i;
  1478. if (it[i].i=instruc) and (instr.numops=it[i].ops) then
  1479. begin
  1480. { first fit }
  1481. case instr.numops of
  1482. 0 : begin
  1483. fits:=true;
  1484. break;
  1485. end;
  1486. 1 :
  1487. Begin
  1488. if (optyp1 and it[i].o1)<>0 then
  1489. Begin
  1490. fits:=true;
  1491. break;
  1492. end;
  1493. { I consider sign-extended 8bit value to }
  1494. { be equal to immediate 8bit therefore }
  1495. { convert... }
  1496. if (optyp1 = ao_imm8) then
  1497. Begin
  1498. { check if this is a simple sign extend. }
  1499. if (it[i].o1<>ao_imm8s) then
  1500. Begin
  1501. fits:=true;
  1502. break;
  1503. end;
  1504. end;
  1505. end;
  1506. 2 : if ((optyp1 and it[i].o1)<>0) and
  1507. ((optyp2 and it[i].o2)<>0) then
  1508. Begin
  1509. fits:=true;
  1510. break;
  1511. end
  1512. { if the operands can be swaped }
  1513. { then swap them }
  1514. else if ((it[i].m and af_d)<>0) and
  1515. ((optyp1 and it[i].o2)<>0) and
  1516. ((optyp2 and it[i].o1)<>0) then
  1517. begin
  1518. fits:=true;
  1519. break;
  1520. end;
  1521. 3 : if ((optyp1 and it[i].o1)<>0) and
  1522. ((optyp2 and it[i].o2)<>0) and
  1523. ((optyp3 and it[i].o3)<>0) then
  1524. Begin
  1525. fits:=true;
  1526. break;
  1527. end;
  1528. end; { end case }
  1529. end; { endif }
  1530. if it[i].i=A_NONE then
  1531. begin
  1532. { NO MATCH! }
  1533. Message(assem_e_invalid_opcode_and_operand);
  1534. exit;
  1535. end;
  1536. inc(i);
  1537. end; { end while }
  1538. { We add the opcode to the opcode linked list }
  1539. if fits then
  1540. Begin
  1541. if instr.getprefix <> A_NONE then
  1542. Begin
  1543. p^.concat(new(pai386,op_none(instr.getprefix,S_NO)));
  1544. end;
  1545. { change from AT&T styled floating point to }
  1546. { intel styled floating point with valid size }
  1547. { we use these instructions so it does not }
  1548. { mess up intasmi3 }
  1549. if (instruc >= A_FILDQ) and (instruc <= A_FIDIVRS) then
  1550. Begin
  1551. instr.stropsize := _fpusizes[instruc];
  1552. instr.addinstr(_fpuopcodes[instruc]);
  1553. instruc := instr.getinstruction;
  1554. end;
  1555. case instr.numops of
  1556. 0:
  1557. if instr.stropsize <> S_NO then
  1558. { is this a string operation opcode or xlat then check }
  1559. { the size of the operation. }
  1560. p^.concat(new(pai386,op_none(instruc,instr.stropsize)))
  1561. else
  1562. p^.concat(new(pai386,op_none(instruc,S_NO)));
  1563. 1: Begin
  1564. case instr.operands[1].operandtype of
  1565. { all one operand opcodes with constant have no defined sizes }
  1566. { at least that is what it seems in the tasm 2.0 manual. }
  1567. OPR_CONSTANT:
  1568. p^.concat(new(pai386,op_const(instruc,
  1569. S_NO, instr.operands[1].val)));
  1570. { was missing !!! }
  1571. OPR_REGISTER:
  1572. Begin
  1573. p^.concat(new(pai386,op_reg(instruc,
  1574. instr.stropsize, instr.operands[1].reg)));
  1575. End;
  1576. OPR_SYMBOL:
  1577. Begin
  1578. p^.concat(new(pai386,op_csymbol(instruc,
  1579. instr.stropsize, newcsymbol(instr.operands[1].symbol^,0))));
  1580. End;
  1581. OPR_REFERENCE:
  1582. { now first check suffix ... }
  1583. if instr.stropsize <> S_NO then
  1584. Begin
  1585. p^.concat(new(pai386,op_ref(instruc,
  1586. instr.stropsize,newreference(instr.operands[1].ref))));
  1587. end
  1588. { no suffix... therefore resort using intel styled checking .. }
  1589. else if (instr.operands[1].size <> S_NO) and NOT (instruc in [A_CALL,A_JMP]) then
  1590. Begin
  1591. p^.concat(new(pai386,op_ref(instruc,
  1592. instr.operands[1].size,newreference(instr.operands[1].ref))));
  1593. end
  1594. else
  1595. Begin
  1596. { special jmp and call case with }
  1597. { symbolic references. }
  1598. if (instruc in [A_CALL,A_JMP]) or
  1599. (instruc = A_FNSTCW) or
  1600. (instruc = A_FSTCW) or
  1601. (instruc = A_FLDCW) or
  1602. (instruc = A_FNSTSW) or
  1603. (instruc = A_FSTSW) or
  1604. (instruc = A_FLDENV) or
  1605. (instruc = A_FSTENV) or
  1606. (instruc = A_FNSAVE) or
  1607. (instruc = A_FSAVE) then
  1608. Begin
  1609. p^.concat(new(pai386,op_ref(instruc,
  1610. S_NO,newreference(instr.operands[1].ref))));
  1611. end
  1612. else
  1613. Message(assem_e_invalid_opcode_and_operand);
  1614. end;
  1615. { This either crashed the compiler or the symbol would always be nil! }
  1616. { The problem is here is I didn't see any way of adding the labeled }
  1617. { symbol in the internal list, since i think from what i see in aasm }
  1618. { that these will automatically be declared as external ?? }
  1619. { if (instruc in [A_JO,A_JNO,A_JB,A_JC,A_JNAE,
  1620. A_JNB,A_JNC,A_JAE,A_JE,A_JZ,A_JNE,A_JNZ,A_JBE,A_JNA,A_JNBE,
  1621. A_JA,A_JS,A_JNS,A_JP,A_JPE,A_JNP,A_JPO,A_JL,A_JNGE,A_JNL,A_JGE,
  1622. A_JLE,A_JNG,A_JNLE,A_JG,A_JCXZ,A_JECXZ,A_LOOP,A_LOOPZ,A_LOOPE,
  1623. A_LOOPNZ,A_LOOPNE,A_JMP,A_CALL]) then
  1624. Begin
  1625. if assigned(instr.operands[1].ref.symbol) then
  1626. p^.concat(new(pai386,op_csymbol(instruc,
  1627. S_NO,newcsymbol(instr.operands[1].ref.symbol^,instr.operands[1].ref.offset))))
  1628. else
  1629. Message(assem_e_invalid_opcode_and_operand);
  1630. end
  1631. else
  1632. else
  1633. Message(assem_e_invalid_opcode_and_operand);
  1634. end;}
  1635. OPR_NONE: Begin
  1636. Message(assem_f_internal_error_in_concatopcode);
  1637. end;
  1638. else
  1639. Begin
  1640. Message(assem_f_internal_error_in_concatopcode);
  1641. end;
  1642. end;
  1643. end;
  1644. 2:
  1645. Begin
  1646. if instruc in [A_MOVSX,A_MOVZX,A_MOVSB,A_MOVSBL,A_MOVSBW,
  1647. A_MOVSWL,A_MOVZB,A_MOVZWL] then
  1648. { movzx and movsx }
  1649. HandleExtend(instr)
  1650. else
  1651. { other instructions }
  1652. Begin
  1653. With instr do
  1654. Begin
  1655. { source }
  1656. opsize := operands[1].size;
  1657. case operands[1].operandtype of
  1658. { reg,reg }
  1659. { reg,ref }
  1660. { const,reg -- IN/OUT }
  1661. OPR_REGISTER:
  1662. Begin
  1663. case operands[2].operandtype of
  1664. OPR_REGISTER:
  1665. { correction: according to the DJGPP FAQ, gas }
  1666. { doesn't even check correctly the size of }
  1667. { operands, therefore let us specify a size! }
  1668. { as in the GAS docs... destination tells us }
  1669. { the size! This might give out invalid output }
  1670. { in some very rare cases (because the size }
  1671. { checking is still not perfect). }
  1672. if (opsize = operands[2].size) then
  1673. begin
  1674. p^.concat(new(pai386,op_reg_reg(instruc,
  1675. opsize,operands[1].reg,operands[2].reg)));
  1676. end
  1677. else
  1678. { these do not require any size specification. }
  1679. if (instruc in [A_IN,A_OUT,A_SAL,A_SAR,A_SHL,A_SHR,A_ROL,
  1680. A_ROR,A_RCR,A_RCL]) then
  1681. { outs and ins are already taken care by }
  1682. { the first pass. }
  1683. p^.concat(new(pai386,op_reg_reg(instruc,
  1684. S_NO,operands[1].reg,operands[2].reg)))
  1685. else
  1686. if stropsize <> S_NO then
  1687. Begin
  1688. p^.concat(new(pai386,op_reg_reg(instruc,
  1689. stropsize,operands[1].reg,operands[2].reg)))
  1690. end
  1691. else
  1692. Begin
  1693. Message(assem_e_invalid_opcode_and_operand);
  1694. end;
  1695. OPR_REFERENCE:
  1696. { variable name. }
  1697. { here we must check the instruction type }
  1698. { before deciding if to use and compare }
  1699. { any sizes. }
  1700. if assigned(operands[2].ref.symbol) then
  1701. Begin
  1702. if stropsize <> S_NO then
  1703. Begin
  1704. p^.concat(new(pai386,op_reg_ref(instruc,
  1705. stropsize,operands[1].reg,newreference(operands[2].ref))))
  1706. end
  1707. else
  1708. if (opsize = operands[2].size) or (instruc in
  1709. [A_RCL,A_RCR,A_ROL,A_ROR,A_SAL,A_SAR,A_SHR,A_SHL]) then
  1710. p^.concat(new(pai386,op_reg_ref(instruc,
  1711. opsize,operands[1].reg,newreference(operands[2].ref))))
  1712. else
  1713. Message(assem_e_invalid_size_in_ref);
  1714. end
  1715. else
  1716. Begin
  1717. { register reference }
  1718. if stropsize <> S_NO then
  1719. Begin
  1720. p^.concat(new(pai386,op_reg_ref(instruc,
  1721. stropsize,operands[1].reg,newreference(operands[2].ref))))
  1722. end
  1723. else
  1724. if (opsize = operands[2].size) or (operands[2].size = S_NO) then
  1725. p^.concat(new(pai386,op_reg_ref(instruc,
  1726. opsize,operands[1].reg,newreference(operands[2].ref))))
  1727. else
  1728. Message(assem_e_invalid_size_in_ref);
  1729. end;
  1730. OPR_CONSTANT: { OUT }
  1731. begin
  1732. { determine first with suffix }
  1733. if instruc = A_OUT then
  1734. begin
  1735. if instr.stropsize <> S_NO then
  1736. p^.concat(new(pai386,op_reg_const(instruc,stropsize,
  1737. instr.operands[1].reg, instr.operands[2].val)))
  1738. else
  1739. p^.concat(new(pai386,op_reg_const(instruc,S_NO,
  1740. instr.operands[1].reg, instr.operands[2].val)));
  1741. end
  1742. else
  1743. Message(assem_e_invalid_opcode);
  1744. end;
  1745. else { else case }
  1746. Begin
  1747. Message(assem_f_internal_error_in_concatopcode);
  1748. end;
  1749. end; { end inner case }
  1750. end;
  1751. { const,reg }
  1752. { const,const }
  1753. { const,ref }
  1754. OPR_CONSTANT:
  1755. case instr.operands[2].operandtype of
  1756. { constant, constant does not have a specific size. }
  1757. OPR_CONSTANT:
  1758. p^.concat(new(pai386,op_const_const(instruc,
  1759. S_NO,operands[1].val,operands[2].val)));
  1760. OPR_REFERENCE:
  1761. Begin
  1762. { check for suffix first ... }
  1763. if (instr.stropsize <> S_NO) then
  1764. Begin
  1765. p^.concat(new(pai386,op_const_ref(instruc,
  1766. stropsize,operands[1].val,
  1767. newreference(operands[2].ref))))
  1768. end
  1769. else
  1770. { resort to intel styled checking ... }
  1771. if (operands[1].val <= $ff) and
  1772. (operands[2].size in [S_B,S_W,S_L]) then
  1773. p^.concat(new(pai386,op_const_ref(instruc,
  1774. operands[2].size,operands[1].val,
  1775. newreference(operands[2].ref))))
  1776. else
  1777. if (operands[1].val <= $ffff) and
  1778. (operands[2].size in [S_W,S_L]) then
  1779. p^.concat(new(pai386,op_const_ref(instruc,
  1780. operands[2].size,operands[1].val,
  1781. newreference(operands[2].ref))))
  1782. else
  1783. if (operands[1].val <= $7fffffff) and
  1784. (operands[2].size in [S_L]) then
  1785. p^.concat(new(pai386,op_const_ref(instruc,
  1786. operands[2].size,operands[1].val,
  1787. newreference(operands[2].ref))))
  1788. else
  1789. Message(assem_e_invalid_size_in_ref);
  1790. end;
  1791. OPR_REGISTER:
  1792. Begin
  1793. { size of opcode determined by register }
  1794. if (operands[1].val <= $ff) and
  1795. (operands[2].size in [S_B,S_W,S_L]) then
  1796. p^.concat(new(pai386,op_const_reg(instruc,
  1797. operands[2].size,operands[1].val,
  1798. operands[2].reg)))
  1799. else
  1800. if (operands[1].val <= $ffff) and
  1801. (operands[2].size in [S_W,S_L]) then
  1802. p^.concat(new(pai386,op_const_reg(instruc,
  1803. operands[2].size,operands[1].val,
  1804. operands[2].reg)))
  1805. else
  1806. if (operands[1].val <= $7fffffff) and
  1807. (operands[2].size in [S_L]) then
  1808. p^.concat(new(pai386,op_const_reg(instruc,
  1809. operands[2].size,operands[1].val,
  1810. operands[2].reg)))
  1811. else
  1812. Message(assem_e_invalid_opcode_size);
  1813. end;
  1814. else
  1815. Begin
  1816. Message(assem_f_internal_error_in_concatopcode);
  1817. end;
  1818. end; { end case }
  1819. { ref,reg }
  1820. { ref,ref }
  1821. OPR_REFERENCE:
  1822. case instr.operands[2].operandtype of
  1823. OPR_REGISTER:
  1824. if assigned(operands[1].ref.symbol) then
  1825. { global variable }
  1826. Begin
  1827. if instruc in [A_LEA,A_LDS,A_LES,A_LFS,A_LGS,A_LSS]
  1828. then
  1829. p^.concat(new(pai386,op_ref_reg(instruc,
  1830. S_NO,newreference(operands[1].ref),
  1831. operands[2].reg)))
  1832. else
  1833. if (stropsize <> S_NO) then
  1834. Begin
  1835. p^.concat(new(pai386,op_ref_reg(instruc,
  1836. stropsize,newreference(operands[1].ref),
  1837. operands[2].reg)))
  1838. end
  1839. else
  1840. if (opsize = operands[2].size) then
  1841. p^.concat(new(pai386,op_ref_reg(instruc,
  1842. opsize,newreference(operands[1].ref),
  1843. operands[2].reg)))
  1844. else
  1845. Begin
  1846. Message(assem_e_invalid_opcode_and_operand);
  1847. end;
  1848. end
  1849. else
  1850. Begin
  1851. { register reference }
  1852. { possiblities:1) local variable which }
  1853. { has been replaced by bp and offset }
  1854. { in this case size should be valid }
  1855. { 2) Indirect register }
  1856. { adressing, 2nd operand determines }
  1857. { size. }
  1858. if (stropsize <> S_NO) then
  1859. Begin
  1860. p^.concat(new(pai386,op_ref_reg(instruc,
  1861. stropsize,newreference(operands[1].ref),
  1862. operands[2].reg)))
  1863. end
  1864. else
  1865. if (opsize = operands[2].size) or (opsize = S_NO) then
  1866. Begin
  1867. p^.concat(new(pai386,op_ref_reg(instruc,
  1868. operands[2].size,newreference(operands[1].ref),
  1869. operands[2].reg)));
  1870. end
  1871. else
  1872. Message(assem_e_invalid_size_in_ref);
  1873. end;
  1874. OPR_REFERENCE: { special opcodes }
  1875. p^.concat(new(pai386,op_ref_ref(instruc,
  1876. opsize,newreference(operands[1].ref),
  1877. newreference(operands[2].ref))));
  1878. else
  1879. Begin
  1880. Message(assem_f_internal_error_in_concatopcode);
  1881. end;
  1882. end; { end inner case }
  1883. end; { end case }
  1884. end; { end with }
  1885. end; {end if movsx... }
  1886. end;
  1887. 3: Begin
  1888. { only imul, shld and shrd }
  1889. { middle must be a register }
  1890. if (instruc in [A_SHLD,A_SHRD]) and (instr.operands[2].operandtype =
  1891. OPR_REGISTER) then
  1892. Begin
  1893. case instr.operands[2].size of
  1894. S_W: if instr.operands[1].operandtype = OPR_CONSTANT then
  1895. Begin
  1896. if instr.operands[1].val <= $ff then
  1897. Begin
  1898. if instr.operands[3].size in [S_W] then
  1899. Begin
  1900. case instr.operands[3].operandtype of
  1901. OPR_REFERENCE: { MISSING !!!! } ;
  1902. OPR_REGISTER: p^.concat(new(pai386,
  1903. op_const_reg_reg(instruc, S_W,
  1904. instr.operands[1].val, instr.operands[2].reg,
  1905. instr.operands[3].reg)));
  1906. else
  1907. Message(assem_e_invalid_opcode_and_operand);
  1908. end;
  1909. end
  1910. else
  1911. Message(assem_e_invalid_opcode_and_operand);
  1912. end;
  1913. end
  1914. else
  1915. Message(assem_e_invalid_opcode_and_operand);
  1916. S_L: if instr.operands[1].operandtype = OPR_CONSTANT then
  1917. Begin
  1918. if instr.operands[1].val <= $ff then
  1919. Begin
  1920. if instr.operands[3].size in [S_L] then
  1921. Begin
  1922. case instr.operands[3].operandtype of
  1923. OPR_REFERENCE: { MISSING !!!! } ;
  1924. OPR_REGISTER: p^.concat(new(pai386,
  1925. op_const_reg_reg(instruc, S_L,
  1926. instr.operands[1].val, instr.operands[2].reg,
  1927. instr.operands[3].reg)));
  1928. else
  1929. Message(assem_e_invalid_opcode_and_operand);
  1930. end;
  1931. end
  1932. else
  1933. Message(assem_e_invalid_opcode_and_operand);
  1934. end;
  1935. end
  1936. else
  1937. Message(assem_e_invalid_opcode_and_operand);
  1938. else
  1939. Message(assem_e_invalid_opcode_and_operand);
  1940. end; { end case }
  1941. end
  1942. else
  1943. if (instruc in [A_IMUL]) and (instr.operands[3].operandtype
  1944. = OPR_REGISTER) then
  1945. Begin
  1946. case instr.operands[3].size of
  1947. S_W: if instr.operands[1].operandtype = OPR_CONSTANT then
  1948. Begin
  1949. if instr.operands[1].val <= $ffff then
  1950. Begin
  1951. if instr.operands[2].size in [S_W] then
  1952. Begin
  1953. case instr.operands[2].operandtype of
  1954. OPR_REFERENCE: { MISSING !!!! } ;
  1955. OPR_REGISTER: p^.concat(new(pai386,
  1956. op_const_reg_reg(instruc, S_W,
  1957. instr.operands[1].val, instr.operands[2].reg,
  1958. instr.operands[3].reg)));
  1959. else
  1960. Message(assem_e_invalid_opcode_and_operand);
  1961. end; { end case }
  1962. end
  1963. else
  1964. Message(assem_e_invalid_opcode_and_operand);
  1965. end;
  1966. end
  1967. else
  1968. Message(assem_e_invalid_opcode_and_operand);
  1969. S_L: if instr.operands[1].operandtype = OPR_CONSTANT then
  1970. Begin
  1971. if instr.operands[1].val <= $7fffffff then
  1972. Begin
  1973. if instr.operands[2].size in [S_L] then
  1974. Begin
  1975. case instr.operands[2].operandtype of
  1976. OPR_REFERENCE: { MISSING !!!! } ;
  1977. OPR_REGISTER: p^.concat(new(pai386,
  1978. op_const_reg_reg(instruc, S_L,
  1979. instr.operands[1].val, instr.operands[2].reg,
  1980. instr.operands[3].reg)));
  1981. else
  1982. Message(assem_e_invalid_opcode_and_operand);
  1983. end; { end case }
  1984. end
  1985. else
  1986. Message(assem_e_invalid_opcode_and_operand);
  1987. end;
  1988. end
  1989. else
  1990. Message(assem_e_invalid_opcode_and_operand);
  1991. else
  1992. Message(assem_e_invalid_middle_sized_operand);
  1993. end; { end case }
  1994. end { endif }
  1995. else
  1996. Message(assem_e_invalid_three_operand_opcode);
  1997. end;
  1998. end; { end case }
  1999. end;
  2000. end;
  2001. Procedure ConcatLabeledInstr(var instr: TInstruction);
  2002. Var instruct : tasmop;
  2003. i : longint;
  2004. Begin
  2005. instruct:=instr.getinstruction;
  2006. if (instruct in [A_JO,A_JNO,A_JB,A_JC,A_JNAE,
  2007. A_JNB,A_JNC,A_JAE,A_JE,A_JZ,A_JNE,A_JNZ,A_JBE,A_JNA,A_JNBE,
  2008. A_JA,A_JS,A_JNS,A_JP,A_JPE,A_JNP,A_JPO,A_JL,A_JNGE,A_JNL,A_JGE,
  2009. A_JLE,A_JNG,A_JNLE,A_JG,A_JCXZ,A_JECXZ,A_LOOP,A_LOOPZ,A_LOOPE,
  2010. A_LOOPNZ,A_LOOPNE,A_MOV,A_JMP,A_CALL]) then
  2011. Begin
  2012. if (instr.numops <> 1) then
  2013. Message(assem_e_invalid_labeled_opcode)
  2014. else if instr.operands[1].operandtype <> OPR_LABINSTR then
  2015. Message(assem_e_invalid_labeled_opcode)
  2016. else if assigned(instr.operands[1].hl) then
  2017. ConcatLabel(p,instruct, instr.operands[1].hl)
  2018. else
  2019. Begin
  2020. Message(assem_f_internal_error_in_concatlabeledinstr);
  2021. end;
  2022. end
  2023. else
  2024. if (cs_compilesystem in aktswitches) then
  2025. begin
  2026. for i:=1 to instr.numops do
  2027. if instr.operands[i].operandtype=OPR_LABINSTR then
  2028. begin
  2029. instr.operands[i].operandtype:=OPR_REFERENCE;
  2030. instr.operands[i].ref.symbol:=newpasstr(lab2str(instr.operands[i].hl) );
  2031. instr.operands[i].opinfo:=ao_mem;
  2032. instr.operands[i].ref.base:=R_NO;
  2033. instr.operands[i].ref.index:=R_NO;
  2034. instr.operands[i].ref.segment:=R_DEFAULT_SEG;
  2035. instr.operands[i].ref.offset:=0;
  2036. end;
  2037. { handle now as an ordinary opcode }
  2038. concatopcode(instr);
  2039. end
  2040. else
  2041. Message(assem_e_invalid_operand);
  2042. end;
  2043. {---------------------------------------------------------------------}
  2044. { Routines for the parsing }
  2045. {---------------------------------------------------------------------}
  2046. procedure consume(t : tinteltoken);
  2047. begin
  2048. if t<>actasmtoken then
  2049. Message(assem_e_syntax_error);
  2050. actasmtoken:=gettoken;
  2051. { if the token must be ignored, then }
  2052. { get another token to parse. }
  2053. if actasmtoken = AS_NONE then
  2054. actasmtoken := gettoken;
  2055. end;
  2056. function findregister(const s : string): tregister;
  2057. {*********************************************************************}
  2058. { FUNCTION findregister(s: string):tasmop; }
  2059. { Description: Determines if the s string is a valid register, }
  2060. { if so returns correct tregister token, or R_NO if not found. }
  2061. {*********************************************************************}
  2062. var
  2063. i: tregister;
  2064. begin
  2065. findregister := R_NO;
  2066. for i:=firstreg to lastreg do
  2067. if s = iasmregs[i] then
  2068. Begin
  2069. findregister := i;
  2070. exit;
  2071. end;
  2072. end;
  2073. function findprefix(const s: string; var token: tasmop): boolean;
  2074. var i: byte;
  2075. Begin
  2076. findprefix := FALSE;
  2077. for i:=0 to _count_asmprefixes do
  2078. Begin
  2079. if s = _asmprefixes[i] then
  2080. begin
  2081. token := _prefixtokens[i];
  2082. findprefix := TRUE;
  2083. exit;
  2084. end;
  2085. end;
  2086. end;
  2087. function findsegment(const s:string): tregister;
  2088. {*********************************************************************}
  2089. { FUNCTION findsegment(s: string):tasmop; }
  2090. { Description: Determines if the s string is a valid segment register}
  2091. { if so returns correct tregister token, or R_NO if not found. }
  2092. {*********************************************************************}
  2093. var
  2094. i: tregister;
  2095. Begin
  2096. findsegment := R_DEFAULT_SEG;
  2097. for i:=firstsreg to lastsreg do
  2098. if s = iasmregs[i] then
  2099. Begin
  2100. findsegment := i;
  2101. exit;
  2102. end;
  2103. end;
  2104. function findopcode(const s: string): tasmop;
  2105. {*********************************************************************}
  2106. { FUNCTION findopcode(s: string): tasmop; }
  2107. { Description: Determines if the s string is a valid opcode }
  2108. { if so returns correct tasmop token. }
  2109. {*********************************************************************}
  2110. var
  2111. i: tasmop;
  2112. j: byte;
  2113. hs: topsize;
  2114. hid: string;
  2115. Begin
  2116. findopcode := A_NONE;
  2117. { first search for extended opcodes }
  2118. { now, in this case, we must use the suffix }
  2119. { to determine the size of the instruction }
  2120. for j:=0 to _count_asmspecialops do
  2121. Begin
  2122. if s = _specialops[j] then
  2123. Begin
  2124. findopcode := _specialopstokens[j];
  2125. { set the size }
  2126. case s[length(s)] of
  2127. 'B': instr.stropsize := S_B;
  2128. 'L': instr.stropsize := S_L;
  2129. 'W': instr.stropsize := S_W;
  2130. end;
  2131. exit;
  2132. end;
  2133. end;
  2134. for i:=firstop to lastop do
  2135. Begin
  2136. if s=iasmops^[i] then
  2137. begin
  2138. findopcode := i;
  2139. instr.stropsize := S_NO;
  2140. exit;
  2141. end;
  2142. end;
  2143. { not found yet ... }
  2144. { search for all possible suffixes }
  2145. for hs:=S_WL downto S_B do
  2146. if copy(s,length(s)-length(att_opsize2str[hs])+1,
  2147. length(att_opsize2str[hs]))=upper(att_opsize2str[hs]) then
  2148. begin
  2149. hid:=copy(s,1,length(s)-length(att_opsize2str[hs]));
  2150. for i:=firstop to lastop do
  2151. if (length(hid) > 0) and (hid=iasmops^[i]) then
  2152. begin
  2153. findopcode := i;
  2154. instr.stropsize := hs;
  2155. exit;
  2156. end;
  2157. end;
  2158. end;
  2159. Function CheckPrefix(prefix: tasmop; opcode:tasmop): Boolean;
  2160. { Checks if the prefix is valid with the following instruction }
  2161. { return false if not, otherwise true }
  2162. Begin
  2163. CheckPrefix := TRUE;
  2164. Case prefix of
  2165. A_REP,A_REPNE,A_REPE: if not (opcode in [A_SCAS,A_INS,A_OUTS,A_MOVS,
  2166. A_CMPS,A_LODS,A_STOS]) then
  2167. Begin
  2168. CheckPrefix := FALSE;
  2169. exit;
  2170. end;
  2171. A_LOCK: if not (opcode in [A_BT,A_BTS,A_BTR,A_BTC,A_XCHG,A_ADD,A_OR,
  2172. A_ADC,A_SBB,A_AND,A_SUB,A_XOR,A_NOT,A_NEG,A_INC,A_DEC]) then
  2173. Begin
  2174. CheckPrefix := FALSE;
  2175. Exit;
  2176. end;
  2177. A_NONE: exit; { no prefix here }
  2178. else
  2179. CheckPrefix := FALSE;
  2180. end; { end case }
  2181. end;
  2182. Procedure InitAsmRef(var instr: TInstruction);
  2183. {*********************************************************************}
  2184. { Description: This routine first check if the instruction is of }
  2185. { type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
  2186. { If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
  2187. { the operand type to OPR_REFERENCE, as well as setting up the ref }
  2188. { to point to the default segment. }
  2189. {*********************************************************************}
  2190. Begin
  2191. With instr do
  2192. Begin
  2193. case operands[operandnum].operandtype of
  2194. OPR_REFERENCE: exit;
  2195. OPR_NONE: ;
  2196. else
  2197. Message(assem_e_invalid_operand_type);
  2198. end;
  2199. operands[operandnum].operandtype := OPR_REFERENCE;
  2200. operands[operandnum].ref.segment := R_DEFAULT_SEG;
  2201. end;
  2202. end;
  2203. Function CheckOverride(segreg: tregister; var instr: TInstruction): Boolean;
  2204. { Check if the override is valid, and if so then }
  2205. { update the instr variable accordingly. }
  2206. Begin
  2207. CheckOverride := FALSE;
  2208. if instr.getinstruction in [A_MOVS,A_XLAT,A_CMPS] then
  2209. Begin
  2210. CheckOverride := TRUE;
  2211. Message(assem_e_segment_override_not_supported);
  2212. end
  2213. end;
  2214. Function CalculateExpression(expression: string): longint;
  2215. var
  2216. expr: TExprParse;
  2217. Begin
  2218. expr.Init;
  2219. CalculateExpression := expr.Evaluate(expression);
  2220. expr.Done;
  2221. end;
  2222. Function BuildExpression: longint;
  2223. {*********************************************************************}
  2224. { FUNCTION BuildExpression: longint }
  2225. { Description: This routine calculates a constant expression to }
  2226. { a given value. The return value is the value calculated from }
  2227. { the expression. }
  2228. { The following tokens (not strings) are recognized: }
  2229. { (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
  2230. {*********************************************************************}
  2231. { ENTRY: On entry the token should be any valid expression token. }
  2232. { EXIT: On Exit the token points to either COMMA or SEPARATOR }
  2233. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2234. { invalid tokens. }
  2235. {*********************************************************************}
  2236. var expr: string;
  2237. tempstr: string;
  2238. l : longint;
  2239. errorflag: boolean;
  2240. Begin
  2241. errorflag := FALSE;
  2242. expr := '';
  2243. tempstr := '';
  2244. Repeat
  2245. Case actasmtoken of
  2246. AS_LPAREN: Begin
  2247. Consume(AS_LPAREN);
  2248. expr := expr + '(';
  2249. end;
  2250. AS_RPAREN: Begin
  2251. Consume(AS_RPAREN);
  2252. expr := expr + ')';
  2253. end;
  2254. AS_SHL: Begin
  2255. Consume(AS_SHL);
  2256. expr := expr + '<';
  2257. end;
  2258. AS_SHR: Begin
  2259. Consume(AS_SHR);
  2260. expr := expr + '>';
  2261. end;
  2262. AS_SLASH: Begin
  2263. Consume(AS_SLASH);
  2264. expr := expr + '/';
  2265. end;
  2266. AS_MOD: Begin
  2267. Consume(AS_MOD);
  2268. expr := expr + '%';
  2269. end;
  2270. AS_STAR: Begin
  2271. Consume(AS_STAR);
  2272. expr := expr + '*';
  2273. end;
  2274. AS_PLUS: Begin
  2275. Consume(AS_PLUS);
  2276. expr := expr + '+';
  2277. end;
  2278. AS_MINUS: Begin
  2279. Consume(AS_MINUS);
  2280. expr := expr + '-';
  2281. end;
  2282. AS_AND: Begin
  2283. Consume(AS_AND);
  2284. expr := expr + '&';
  2285. end;
  2286. AS_NOT: Begin
  2287. Consume(AS_NOT);
  2288. expr := expr + '~';
  2289. end;
  2290. AS_XOR: Begin
  2291. Consume(AS_XOR);
  2292. expr := expr + '^';
  2293. end;
  2294. AS_OR: Begin
  2295. Consume(AS_OR);
  2296. expr := expr + '|';
  2297. end;
  2298. AS_ID: Begin
  2299. if NOT SearchIConstant(actasmpattern,l) then
  2300. Begin
  2301. Message1(assem_e_invalid_const_symbol,actasmpattern);
  2302. l := 0;
  2303. end;
  2304. str(l, tempstr);
  2305. expr := expr + tempstr;
  2306. Consume(AS_ID);
  2307. end;
  2308. AS_INTNUM: Begin
  2309. expr := expr + actasmpattern;
  2310. Consume(AS_INTNUM);
  2311. end;
  2312. AS_BINNUM: Begin
  2313. tempstr := BinaryToDec(actasmpattern);
  2314. if tempstr = '' then
  2315. Message(assem_f_error_converting_bin);
  2316. expr:=expr+tempstr;
  2317. Consume(AS_BINNUM);
  2318. end;
  2319. AS_HEXNUM: Begin
  2320. tempstr := HexToDec(actasmpattern);
  2321. if tempstr = '' then
  2322. Message(assem_f_error_converting_hex);
  2323. expr:=expr+tempstr;
  2324. Consume(AS_HEXNUM);
  2325. end;
  2326. AS_OCTALNUM: Begin
  2327. tempstr := OctalToDec(actasmpattern);
  2328. if tempstr = '' then
  2329. Message(assem_f_error_converting_octal);
  2330. expr:=expr+tempstr;
  2331. Consume(AS_OCTALNUM);
  2332. end;
  2333. { go to next term }
  2334. AS_COMMA: Begin
  2335. if not ErrorFlag then
  2336. BuildExpression := CalculateExpression(expr)
  2337. else
  2338. BuildExpression := 0;
  2339. Exit;
  2340. end;
  2341. { go to next symbol }
  2342. AS_SEPARATOR: Begin
  2343. if not ErrorFlag then
  2344. BuildExpression := CalculateExpression(expr)
  2345. else
  2346. BuildExpression := 0;
  2347. Exit;
  2348. end;
  2349. else
  2350. Begin
  2351. { only write error once. }
  2352. if not errorflag then
  2353. Message(assem_e_invalid_constant_expression);
  2354. { consume tokens until we find COMMA or SEPARATOR }
  2355. Consume(actasmtoken);
  2356. errorflag := TRUE;
  2357. End;
  2358. end;
  2359. Until false;
  2360. end;
  2361. Procedure BuildRealConstant(typ : tfloattype);
  2362. {*********************************************************************}
  2363. { PROCEDURE BuilRealConst }
  2364. { Description: This routine calculates a constant expression to }
  2365. { a given value. The return value is the value calculated from }
  2366. { the expression. }
  2367. { The following tokens (not strings) are recognized: }
  2368. { +/-,numbers and real numbers }
  2369. {*********************************************************************}
  2370. { ENTRY: On entry the token should be any valid expression token. }
  2371. { EXIT: On Exit the token points to either COMMA or SEPARATOR }
  2372. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2373. { invalid tokens. }
  2374. {*********************************************************************}
  2375. var expr: string;
  2376. tempstr: string;
  2377. r : extended;
  2378. code : word;
  2379. negativ : boolean;
  2380. errorflag: boolean;
  2381. Begin
  2382. errorflag := FALSE;
  2383. Repeat
  2384. negativ:=false;
  2385. expr := '';
  2386. tempstr := '';
  2387. if actasmtoken=AS_PLUS then Consume(AS_PLUS)
  2388. else if actasmtoken=AS_MINUS then
  2389. begin
  2390. negativ:=true;
  2391. consume(AS_MINUS);
  2392. end;
  2393. Case actasmtoken of
  2394. AS_INTNUM: Begin
  2395. expr := actasmpattern;
  2396. Consume(AS_INTNUM);
  2397. end;
  2398. AS_REALNUM: Begin
  2399. expr := actasmpattern;
  2400. { in ATT syntax you have 0d in front of the real }
  2401. { should this be forced ? yes i think so, as to }
  2402. { conform to gas as much as possible. }
  2403. if (expr[1]='0') and (upper(expr[2])='D') then
  2404. expr:=copy(expr,3,255);
  2405. Consume(AS_REALNUM);
  2406. end;
  2407. AS_BINNUM: Begin
  2408. { checking for real constants with this should use }
  2409. { real DECODING otherwise the compiler will crash! }
  2410. Message(assem_w_float_bin_ignored);
  2411. Consume(AS_BINNUM);
  2412. end;
  2413. AS_HEXNUM: Begin
  2414. { checking for real constants with this should use }
  2415. { real DECODING otherwise the compiler will crash! }
  2416. Message(assem_w_float_hex_ignored);
  2417. Consume(AS_HEXNUM);
  2418. end;
  2419. AS_OCTALNUM: Begin
  2420. { checking for real constants with this should use }
  2421. { real DECODING otherwise the compiler will crash! }
  2422. { xxxToDec using reals could be a solution, but the }
  2423. { problem is that these will crash the m68k compiler }
  2424. { when compiling -- because of lack of good fpu }
  2425. { support. }
  2426. Message(assem_w_float_octal_ignored);
  2427. Consume(AS_OCTALNUM);
  2428. end;
  2429. else
  2430. Begin
  2431. { only write error once. }
  2432. if not errorflag then
  2433. Message(assem_e_invalid_real_const);
  2434. { consume tokens until we find COMMA or SEPARATOR }
  2435. Consume(actasmtoken);
  2436. errorflag := TRUE;
  2437. End;
  2438. end;
  2439. { go to next term }
  2440. if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
  2441. Begin
  2442. if negativ then expr:='-'+expr;
  2443. val(expr,r,code);
  2444. if code<>0 then
  2445. Begin
  2446. r:=0;
  2447. Message(assem_e_invalid_real_const);
  2448. ConcatRealConstant(p,r,typ);
  2449. End
  2450. else
  2451. Begin
  2452. ConcatRealConstant(p,r,typ);
  2453. End;
  2454. end
  2455. else
  2456. Message(assem_e_invalid_real_const);
  2457. Until actasmtoken=AS_SEPARATOR;
  2458. end;
  2459. Procedure BuildScaling(Var instr: TInstruction);
  2460. {*********************************************************************}
  2461. { Takes care of parsing expression starting from the scaling value }
  2462. { up to and including possible field specifiers. }
  2463. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR }
  2464. { or AS_COMMA. On entry should point to the AS_COMMA token. }
  2465. {*********************************************************************}
  2466. var str:string;
  2467. l: longint;
  2468. code: integer;
  2469. Begin
  2470. Consume(AS_COMMA);
  2471. if (instr.operands[operandnum].ref.scalefactor <> 0)
  2472. and (instr.operands[operandnum].ref.scalefactor <> 1) then
  2473. Message(assem_f_internal_error_in_buildscale);
  2474. case actasmtoken of
  2475. AS_INTNUM: str := actasmpattern;
  2476. AS_HEXNUM: str := HexToDec(actasmpattern);
  2477. AS_BINNUM: str := BinaryToDec(actasmpattern);
  2478. AS_OCTALNUM: str := OctalToDec(actasmpattern);
  2479. else
  2480. Message(assem_e_syntax_error);
  2481. end;
  2482. val(str, l, code);
  2483. if code <> 0 then
  2484. Message(assem_e_invalid_scaling_factor);
  2485. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
  2486. begin
  2487. instr.operands[operandnum].ref.scalefactor := l;
  2488. end
  2489. else
  2490. Begin
  2491. Message(assem_e_invalid_scaling_value);
  2492. instr.operands[operandnum].ref.scalefactor := 0;
  2493. end;
  2494. if instr.operands[operandnum].ref.index = R_NO then
  2495. Begin
  2496. Message(assem_e_scaling_value_only_allowed_with_index);
  2497. instr.operands[operandnum].ref.scalefactor := 0;
  2498. end;
  2499. { Consume the scaling number }
  2500. Consume(actasmtoken);
  2501. if actasmtoken = AS_RPAREN then
  2502. Consume(AS_RPAREN)
  2503. else
  2504. Message(assem_e_invalid_scaling_value);
  2505. { // .Field.Field ... or separator/comma // }
  2506. if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
  2507. Begin
  2508. end
  2509. else
  2510. Message(assem_e_syntax_error);
  2511. end;
  2512. Function BuildRefExpression: longint;
  2513. {*********************************************************************}
  2514. { FUNCTION BuildExpression: longint }
  2515. { Description: This routine calculates a constant expression to }
  2516. { a given value. The return value is the value calculated from }
  2517. { the expression. }
  2518. { The following tokens (not strings) are recognized: }
  2519. { SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
  2520. {*********************************************************************}
  2521. { ENTRY: On entry the token should be any valid expression token. }
  2522. { EXIT: On Exit the token points to the LPAREN token. }
  2523. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2524. { invalid tokens. }
  2525. {*********************************************************************}
  2526. var tempstr: string;
  2527. expr: string;
  2528. l : longint;
  2529. errorflag : boolean;
  2530. Begin
  2531. errorflag := FALSE;
  2532. tempstr := '';
  2533. expr := '';
  2534. Repeat
  2535. Case actasmtoken of
  2536. AS_RPAREN: Begin
  2537. Message(assem_e_parenthesis_are_not_allowed);
  2538. Consume(AS_RPAREN);
  2539. end;
  2540. AS_SHL: Begin
  2541. Consume(AS_SHL);
  2542. expr := expr + '<';
  2543. end;
  2544. AS_SHR: Begin
  2545. Consume(AS_SHR);
  2546. expr := expr + '>';
  2547. end;
  2548. AS_SLASH: Begin
  2549. Consume(AS_SLASH);
  2550. expr := expr + '/';
  2551. end;
  2552. AS_MOD: Begin
  2553. Consume(AS_MOD);
  2554. expr := expr + '%';
  2555. end;
  2556. AS_STAR: Begin
  2557. Consume(AS_STAR);
  2558. expr := expr + '*';
  2559. end;
  2560. AS_PLUS: Begin
  2561. Consume(AS_PLUS);
  2562. expr := expr + '+';
  2563. end;
  2564. AS_MINUS: Begin
  2565. Consume(AS_MINUS);
  2566. expr := expr + '-';
  2567. end;
  2568. AS_AND: Begin
  2569. Consume(AS_AND);
  2570. expr := expr + '&';
  2571. end;
  2572. AS_NOT: Begin
  2573. Consume(AS_NOT);
  2574. expr := expr + '~';
  2575. end;
  2576. AS_XOR: Begin
  2577. Consume(AS_XOR);
  2578. expr := expr + '^';
  2579. end;
  2580. AS_OR: Begin
  2581. Consume(AS_OR);
  2582. expr := expr + '|';
  2583. end;
  2584. { End of reference }
  2585. AS_LPAREN: Begin
  2586. if not ErrorFlag then
  2587. BuildRefExpression := CalculateExpression(expr)
  2588. else
  2589. BuildRefExpression := 0;
  2590. { no longer in an expression }
  2591. exit;
  2592. end;
  2593. AS_ID:
  2594. Begin
  2595. if NOT SearchIConstant(actasmpattern,l) then
  2596. Begin
  2597. Message1(assem_e_invalid_const_symbol,actasmpattern);
  2598. l := 0;
  2599. end;
  2600. str(l, tempstr);
  2601. expr := expr + tempstr;
  2602. Consume(AS_ID);
  2603. end;
  2604. AS_INTNUM: Begin
  2605. expr := expr + actasmpattern;
  2606. Consume(AS_INTNUM);
  2607. end;
  2608. AS_BINNUM: Begin
  2609. tempstr := BinaryToDec(actasmpattern);
  2610. if tempstr = '' then
  2611. Message(assem_f_error_converting_bin);
  2612. expr:=expr+tempstr;
  2613. Consume(AS_BINNUM);
  2614. end;
  2615. AS_HEXNUM: Begin
  2616. tempstr := HexToDec(actasmpattern);
  2617. if tempstr = '' then
  2618. Message(assem_f_error_converting_hex);
  2619. expr:=expr+tempstr;
  2620. Consume(AS_HEXNUM);
  2621. end;
  2622. AS_OCTALNUM: Begin
  2623. tempstr := OctalToDec(actasmpattern);
  2624. if tempstr = '' then
  2625. Message(assem_f_error_converting_octal);
  2626. expr:=expr+tempstr;
  2627. Consume(AS_OCTALNUM);
  2628. end;
  2629. else
  2630. Begin
  2631. { write error only once. }
  2632. if not errorflag then
  2633. Message(assem_e_invalid_constant_expression);
  2634. BuildRefExpression := 0;
  2635. if actasmtoken in [AS_COMMA,AS_SEPARATOR] then exit;
  2636. { consume tokens until we find COMMA or SEPARATOR }
  2637. Consume(actasmtoken);
  2638. errorflag := TRUE;
  2639. end;
  2640. end;
  2641. Until false;
  2642. end;
  2643. Procedure BuildReference(var Instr: TInstruction);
  2644. {*********************************************************************}
  2645. { PROCEDURE BuildBracketExpression }
  2646. { Description: This routine builds up an expression after a LPAREN }
  2647. { token is encountered. }
  2648. { On entry actasmtoken should be equal to AS_LPAREN }
  2649. {*********************************************************************}
  2650. { EXIT CONDITION: On exit the routine should point to either the }
  2651. { AS_COMMA or AS_SEPARATOR token. }
  2652. {*********************************************************************}
  2653. var
  2654. l:longint;
  2655. code: integer;
  2656. str: string;
  2657. Begin
  2658. Consume(AS_LPAREN);
  2659. initAsmRef(instr);
  2660. Case actasmtoken of
  2661. { // (reg ... // }
  2662. AS_REGISTER: Begin
  2663. instr.operands[operandnum].ref.base :=
  2664. findregister(actasmpattern);
  2665. Consume(AS_REGISTER);
  2666. { can either be a register or a right parenthesis }
  2667. { // (reg) // }
  2668. if actasmtoken=AS_RPAREN then Begin
  2669. Consume(AS_RPAREN);
  2670. if not (actasmtoken in [AS_COMMA,
  2671. AS_SEPARATOR]) then
  2672. Begin
  2673. Message(assem_e_invalid_reference);
  2674. { error recovery ... }
  2675. while actasmtoken <> AS_SEPARATOR do
  2676. Consume(actasmtoken);
  2677. end;
  2678. exit;
  2679. end;
  2680. { // (reg,reg .. // }
  2681. { we need a comman here !! }
  2682. { oops.. }
  2683. Consume(AS_COMMA);
  2684. Case actasmtoken of
  2685. AS_REGISTER: Begin
  2686. instr.operands[operandnum].ref.index :=
  2687. findregister(actasmpattern);
  2688. Consume(AS_REGISTER);
  2689. { check for scaling ... }
  2690. case actasmtoken of
  2691. AS_RPAREN:
  2692. Begin
  2693. Consume(AS_RPAREN);
  2694. if not (actasmtoken in [AS_COMMA,
  2695. AS_SEPARATOR]) then
  2696. Begin
  2697. { error recovery ... }
  2698. Message(assem_e_invalid_reference);
  2699. while actasmtoken <> AS_SEPARATOR do
  2700. Consume(actasmtoken);
  2701. end;
  2702. exit;
  2703. end;
  2704. AS_COMMA:
  2705. Begin
  2706. BuildScaling(instr);
  2707. end;
  2708. else
  2709. Begin
  2710. Message(assem_e_invalid_reference_syntax);
  2711. while (actasmtoken <> AS_SEPARATOR) do
  2712. Consume(actasmtoken);
  2713. end;
  2714. end; { end case }
  2715. end;
  2716. else
  2717. Begin
  2718. Message(assem_e_invalid_reference_syntax);
  2719. while (actasmtoken <> AS_SEPARATOR) do
  2720. Consume(actasmtoken);
  2721. end;
  2722. end; {end case }
  2723. end;
  2724. { // (, ... // }
  2725. AS_COMMA: { can either be scaling, or index }
  2726. Begin
  2727. Consume(AS_COMMA);
  2728. case actasmtoken of
  2729. AS_REGISTER: Begin
  2730. instr.operands[operandnum].ref.index :=
  2731. findregister(actasmpattern);
  2732. Consume(AS_REGISTER);
  2733. { check for scaling ... }
  2734. case actasmtoken of
  2735. AS_RPAREN:
  2736. Begin
  2737. Consume(AS_RPAREN);
  2738. if not (actasmtoken in [AS_COMMA,
  2739. AS_SEPARATOR]) then
  2740. Begin
  2741. { error recovery ... }
  2742. Message(assem_e_invalid_reference);
  2743. while actasmtoken <> AS_SEPARATOR do
  2744. Consume(actasmtoken);
  2745. end;
  2746. exit;
  2747. end;
  2748. AS_COMMA:
  2749. Begin
  2750. BuildScaling(instr);
  2751. end;
  2752. else
  2753. Begin
  2754. Message(assem_e_invalid_reference_syntax);
  2755. while (actasmtoken <> AS_SEPARATOR) do
  2756. Consume(actasmtoken);
  2757. end;
  2758. end; {end case }
  2759. end;
  2760. AS_HEXNUM,AS_INTNUM, { we have to process the scaling }
  2761. AS_BINNUM,AS_OCTALNUM: { directly here... }
  2762. Begin
  2763. case actasmtoken of
  2764. AS_INTNUM: str :=
  2765. actasmpattern;
  2766. AS_HEXNUM: str :=
  2767. HexToDec(actasmpattern);
  2768. AS_BINNUM: str :=
  2769. BinaryToDec(actasmpattern);
  2770. AS_OCTALNUM: str :=
  2771. OctalToDec(actasmpattern);
  2772. else
  2773. Message(assem_e_syntax_error);
  2774. end; { end case }
  2775. val(str, l, code);
  2776. if code <> 0 then
  2777. Message(assem_e_invalid_scaling_factor);
  2778. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
  2779. begin
  2780. instr.operands[operandnum].
  2781. ref.scalefactor := l;
  2782. end
  2783. else
  2784. Begin
  2785. Message(assem_e_invalid_scaling_value);
  2786. instr.operands[operandnum].
  2787. ref.scalefactor := 0;
  2788. end;
  2789. Consume(actasmtoken);
  2790. if actasmtoken <> AS_RPAREN then
  2791. Begin
  2792. Message(assem_e_invalid_scaling_value);
  2793. while actasmtoken <> AS_SEPARATOR do
  2794. Consume(actasmtoken);
  2795. end
  2796. else
  2797. Begin
  2798. Consume(AS_RPAREN);
  2799. if not (actasmtoken in [AS_COMMA,
  2800. AS_SEPARATOR]) then
  2801. Begin
  2802. { error recovery ... }
  2803. Message(assem_e_invalid_reference);
  2804. while actasmtoken <> AS_SEPARATOR do
  2805. Consume(actasmtoken);
  2806. end;
  2807. exit;
  2808. end;
  2809. end;
  2810. else
  2811. Begin
  2812. Message(assem_e_invalid_reference_syntax);
  2813. while (actasmtoken <> AS_SEPARATOR) do
  2814. Consume(actasmtoken);
  2815. end;
  2816. end; { end case }
  2817. end;
  2818. else
  2819. Begin
  2820. Message(assem_e_invalid_reference_syntax);
  2821. while (actasmtoken <> AS_SEPARATOR) do
  2822. Consume(actasmtoken);
  2823. end;
  2824. end; { end case }
  2825. end;
  2826. Procedure BuildOperand(var instr: TInstruction);
  2827. {*********************************************************************}
  2828. { EXIT CONDITION: On exit the routine should point to either the }
  2829. { AS_COMMA or AS_SEPARATOR token. }
  2830. {*********************************************************************}
  2831. var
  2832. tempstr: string;
  2833. expr: string;
  2834. lab: Pasmlabel;
  2835. hl: plabel;
  2836. Begin
  2837. tempstr := '';
  2838. expr := '';
  2839. case actasmtoken of
  2840. { // Memory reference // }
  2841. AS_LPAREN:
  2842. Begin
  2843. initAsmRef(instr);
  2844. BuildReference(instr);
  2845. end;
  2846. { // Constant expression // }
  2847. AS_DOLLAR: Begin
  2848. Consume(AS_DOLLAR);
  2849. if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_CONSTANT]) then
  2850. Message(assem_e_invalid_operand_type);
  2851. { identifiers are handled by BuildExpression }
  2852. instr.operands[operandnum].operandtype := OPR_CONSTANT;
  2853. instr.operands[operandnum].val :=BuildExpression;
  2854. end;
  2855. { // Constant memory offset . // }
  2856. { // This must absolutely be followed by ( // }
  2857. AS_HEXNUM,AS_INTNUM,AS_MINUS,
  2858. AS_BINNUM,AS_OCTALNUM,AS_PLUS:
  2859. Begin
  2860. InitAsmRef(instr);
  2861. instr.operands[operandnum].ref.offset:=BuildRefExpression;
  2862. BuildReference(instr);
  2863. end;
  2864. { // A constant expression, or a Variable ref. // }
  2865. AS_ID: Begin
  2866. { // Local label. // }
  2867. if (actasmpattern[1] ='.') and (actasmpattern[2] = 'L') then
  2868. Begin
  2869. Begin
  2870. delete(actasmpattern,1,1);
  2871. delete(actasmpattern,1,1);
  2872. if actasmpattern = '' then
  2873. Message(assem_e_null_label_ref_not_allowed);
  2874. lab := labellist.search(actasmpattern);
  2875. { check if the label is already defined }
  2876. { if so, we then check if the plabel is }
  2877. { non-nil, if so we add it to instruction }
  2878. if assigned(lab) then
  2879. Begin
  2880. if assigned(lab^.lab) then
  2881. Begin
  2882. instr.operands[operandnum].operandtype := OPR_LABINSTR;
  2883. instr.operands[operandnum].hl := lab^.lab;
  2884. instr.labeled := TRUE;
  2885. end;
  2886. end
  2887. else
  2888. { the label does not exist, create it }
  2889. { emit the opcode, but set that the }
  2890. { label has not been emitted }
  2891. Begin
  2892. getlabel(hl);
  2893. labellist.insert(actasmpattern,hl,FALSE);
  2894. instr.operands[operandnum].operandtype := OPR_LABINSTR;
  2895. instr.operands[operandnum].hl := hl;
  2896. instr.labeled := TRUE;
  2897. end;
  2898. end;
  2899. Consume(AS_ID);
  2900. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  2901. Begin
  2902. Message(assem_e_syntax_error);
  2903. end;
  2904. end
  2905. { probably a variable or normal expression }
  2906. { or a procedure (such as in CALL ID) }
  2907. else
  2908. Begin
  2909. { check if this is a label, if so then }
  2910. { emit it as a label. }
  2911. if SearchLabel(actasmpattern,hl) then
  2912. Begin
  2913. instr.operands[operandnum].operandtype := OPR_LABINSTR;
  2914. instr.operands[operandnum].hl := hl;
  2915. instr.labeled := TRUE;
  2916. Consume(AS_ID);
  2917. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  2918. Message(assem_e_syntax_error);
  2919. end
  2920. else
  2921. { is it a normal variable ? }
  2922. Begin
  2923. initAsmRef(instr);
  2924. if not CreateVarInstr(instr,actasmpattern,operandnum) then
  2925. Begin
  2926. { look for special symbols ... }
  2927. if actasmpattern = '__RESULT' then
  2928. SetUpResult(instr,operandnum)
  2929. else
  2930. if actasmpattern = '__SELF' then
  2931. Begin
  2932. if assigned(procinfo._class) then
  2933. Begin
  2934. instr.operands[operandnum].operandtype := OPR_REFERENCE;
  2935. instr.operands[operandnum].ref.offset :=
  2936. procinfo.ESI_offset;
  2937. instr.operands[operandnum].ref.base :=
  2938. procinfo.framepointer;
  2939. end
  2940. else
  2941. Message(assem_e_cannot_use___SELF_outside_methode);
  2942. end
  2943. else
  2944. if actasmpattern = '__OLDEBP' then
  2945. Begin
  2946. if lexlevel>2 then
  2947. Begin
  2948. instr.operands[operandnum].operandtype := OPR_REFERENCE;
  2949. instr.operands[operandnum].ref.offset :=
  2950. procinfo.framepointer_offset;
  2951. instr.operands[operandnum].ref.base :=
  2952. procinfo.framepointer;
  2953. end
  2954. else
  2955. Message(assem_e_cannot_use___OLDEBP_outside_nested_procedure);
  2956. end { endif actasmpattern = '__OLDEBP' }
  2957. else
  2958. { check for direct symbolic names }
  2959. { only if compiling the system unit }
  2960. if (cs_compilesystem in aktswitches) then
  2961. begin
  2962. if not SearchDirectVar(instr,actasmpattern,operandnum) then
  2963. Begin
  2964. { not found, finally ... add it anyways ... }
  2965. Message1(assem_w_id_supposed_external,actasmpattern);
  2966. instr.operands[operandnum].ref.symbol := newpasstr(actasmpattern);
  2967. end;
  2968. end
  2969. else
  2970. Message1(assem_e_unknown_id,actasmpattern);
  2971. end;
  2972. expr := actasmpattern;
  2973. Consume(AS_ID);
  2974. case actasmtoken of
  2975. AS_LPAREN: { indexing }
  2976. BuildReference(instr);
  2977. AS_SEPARATOR,AS_COMMA: ;
  2978. else
  2979. Message(assem_e_syntax_error);
  2980. end; { end case }
  2981. end; { end if }
  2982. end; { end if }
  2983. end; { end this case }
  2984. { // Register, a variable reference or a constant reference // }
  2985. AS_REGISTER: Begin
  2986. { save the type of register used. }
  2987. tempstr := actasmpattern;
  2988. Consume(AS_REGISTER);
  2989. if actasmtoken = AS_COLON then
  2990. Begin
  2991. Consume(AS_COLON);
  2992. initAsmRef(instr);
  2993. instr.operands[operandnum].ref.segment := findsegment(tempstr);
  2994. { here we can have either an identifier }
  2995. { or a constant, where either can be }
  2996. { followed by a parenthesis... }
  2997. { // Constant memory offset . // }
  2998. { // This must absolutely be followed by ( // }
  2999. case actasmtoken of
  3000. AS_HEXNUM,AS_INTNUM,AS_MINUS,
  3001. AS_BINNUM,AS_OCTALNUM,AS_PLUS
  3002. : Begin
  3003. instr.operands[operandnum].
  3004. ref.offset:=BuildRefExpression;
  3005. BuildReference(instr);
  3006. end;
  3007. AS_LPAREN: BuildReference(instr);
  3008. { only a variable is allowed ... }
  3009. AS_ID: Begin
  3010. { is it a normal variable ? }
  3011. if not CreateVarInstr(instr,actasmpattern,operandnum)
  3012. then
  3013. begin
  3014. { check for direct symbolic names }
  3015. { only if compiling the system unit }
  3016. if (cs_compilesystem in aktswitches) then
  3017. begin
  3018. if not SearchDirectVar(instr,actasmpattern,operandnum) then
  3019. Message(assem_e_invalid_seg_override);
  3020. end
  3021. else
  3022. Message(assem_e_invalid_seg_override);
  3023. end;
  3024. Consume(actasmtoken);
  3025. case actasmtoken of
  3026. AS_SEPARATOR,AS_COMMA: ;
  3027. AS_LPAREN: BuildReference(instr);
  3028. else
  3029. Begin
  3030. Message(assem_e_invalid_seg_override);
  3031. Consume(actasmtoken);
  3032. end;
  3033. end; {end case }
  3034. end;
  3035. else
  3036. Begin
  3037. Message(assem_e_invalid_seg_override);
  3038. Consume(actasmtoken);
  3039. end;
  3040. end; { end case }
  3041. end
  3042. { // Simple register // }
  3043. else if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
  3044. Begin
  3045. if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_REGISTER]) then
  3046. Message(assem_e_invalid_operand_type);
  3047. instr.operands[operandnum].operandtype := OPR_REGISTER;
  3048. instr.operands[operandnum].reg := findregister(tempstr);
  3049. end
  3050. else
  3051. Message1(assem_e_syn_register,tempstr);
  3052. end;
  3053. AS_SEPARATOR, AS_COMMA: ;
  3054. else
  3055. Begin
  3056. Message(assem_e_syn_opcode_operand);
  3057. Consume(actasmtoken);
  3058. end;
  3059. end; { end case }
  3060. end;
  3061. Procedure BuildConstant(maxvalue: longint);
  3062. {*********************************************************************}
  3063. { PROCEDURE BuildConstant }
  3064. { Description: This routine takes care of parsing a DB,DD,or DW }
  3065. { line and adding those to the assembler node. Expressions, range- }
  3066. { checking are fullly taken care of. }
  3067. { maxvalue: $ff -> indicates that this is a DB node. }
  3068. { $ffff -> indicates that this is a DW node. }
  3069. { $ffffffff -> indicates that this is a DD node. }
  3070. {*********************************************************************}
  3071. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  3072. {*********************************************************************}
  3073. var
  3074. strlength: byte;
  3075. expr: string;
  3076. value : longint;
  3077. Begin
  3078. Repeat
  3079. Case actasmtoken of
  3080. AS_STRING: Begin
  3081. if maxvalue = $ff then
  3082. strlength := 1
  3083. else
  3084. Message(assem_e_string_not_allowed_as_const);
  3085. expr := actasmpattern;
  3086. if length(expr) > 1 then
  3087. Message(assem_e_string_not_allowed_as_const);
  3088. Consume(AS_STRING);
  3089. Case actasmtoken of
  3090. AS_COMMA: Consume(AS_COMMA);
  3091. AS_SEPARATOR: ;
  3092. else
  3093. Message(assem_e_invalid_string_expression);
  3094. end; { end case }
  3095. ConcatString(p,expr);
  3096. end;
  3097. AS_INTNUM,AS_BINNUM,
  3098. AS_OCTALNUM,AS_HEXNUM:
  3099. Begin
  3100. value:=BuildExpression;
  3101. ConcatConstant(p,value,maxvalue);
  3102. end;
  3103. AS_ID:
  3104. Begin
  3105. value:=BuildExpression;
  3106. if value > maxvalue then
  3107. Begin
  3108. Message(assem_e_expression_out_of_bounds);
  3109. { assuming a value of maxvalue }
  3110. value := maxvalue;
  3111. end;
  3112. ConcatConstant(p,value,maxvalue);
  3113. end;
  3114. { These terms can start an assembler expression }
  3115. AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: Begin
  3116. value := BuildExpression;
  3117. ConcatConstant(p,value,maxvalue);
  3118. end;
  3119. AS_COMMA: BEGIN
  3120. Consume(AS_COMMA);
  3121. END;
  3122. AS_SEPARATOR: ;
  3123. else
  3124. Begin
  3125. Message(assem_f_internal_error_in_buildconstant);
  3126. end;
  3127. end; { end case }
  3128. Until actasmtoken = AS_SEPARATOR;
  3129. end;
  3130. Procedure BuildStringConstant(asciiz: boolean);
  3131. {*********************************************************************}
  3132. { PROCEDURE BuildStringConstant }
  3133. { Description: Takes care of a ASCII, or ASCIIZ directive. }
  3134. { asciiz: boolean -> if true then string will be null terminated. }
  3135. {*********************************************************************}
  3136. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  3137. { On ENTRY: Token should point to AS_STRING }
  3138. {*********************************************************************}
  3139. var
  3140. expr: string;
  3141. errorflag : boolean;
  3142. Begin
  3143. errorflag := FALSE;
  3144. Repeat
  3145. Case actasmtoken of
  3146. AS_STRING: Begin
  3147. expr:=actasmpattern;
  3148. if asciiz then
  3149. expr:=expr+#0;
  3150. ConcatPasString(p,expr);
  3151. Consume(AS_STRING);
  3152. end;
  3153. AS_COMMA: BEGIN
  3154. Consume(AS_COMMA);
  3155. END;
  3156. AS_SEPARATOR: ;
  3157. else
  3158. Begin
  3159. Consume(actasmtoken);
  3160. if not errorflag then
  3161. Message(assem_e_invalid_string_expression);
  3162. errorflag := TRUE;
  3163. end;
  3164. end; { end case }
  3165. Until actasmtoken = AS_SEPARATOR;
  3166. end;
  3167. Procedure BuildOpCode;
  3168. {*********************************************************************}
  3169. { PROCEDURE BuildOpcode; }
  3170. { Description: Parses the intel opcode and operands, and writes it }
  3171. { in the TInstruction object. }
  3172. {*********************************************************************}
  3173. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  3174. { On ENTRY: Token should point to AS_OPCODE }
  3175. {*********************************************************************}
  3176. var asmtok: tasmop;
  3177. op: tasmop;
  3178. expr: string;
  3179. segreg: tregister;
  3180. Begin
  3181. expr := '';
  3182. asmtok := A_NONE; { assmume no prefix }
  3183. segreg := R_NO; { assume no segment override }
  3184. { // prefix seg opcode // }
  3185. { // prefix opcode // }
  3186. if findprefix(actasmpattern,asmtok) then
  3187. Begin
  3188. { standard opcode prefix }
  3189. if asmtok <> A_NONE then
  3190. instr.addprefix(asmtok);
  3191. Consume(AS_OPCODE);
  3192. end;
  3193. { // opcode // }
  3194. { allow for newline as in gas styled syntax }
  3195. { under DOS you get two AS_SEPARATOR !! }
  3196. while actasmtoken=AS_SEPARATOR do
  3197. Consume(AS_SEPARATOR);
  3198. if (actasmtoken <> AS_OPCODE) then
  3199. Begin
  3200. Message(assem_e_invalid_or_missing_opcode);
  3201. { error recovery }
  3202. While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  3203. Consume(actasmtoken);
  3204. exit;
  3205. end
  3206. else
  3207. Begin
  3208. op := findopcode(actasmpattern);
  3209. instr.addinstr(op);
  3210. { // Valid combination of prefix and instruction ? // }
  3211. if (asmtok <> A_NONE) and (NOT CheckPrefix(asmtok,op)) then
  3212. Message1(assem_e_invalid_prefix_and_opcode,actasmpattern);
  3213. Consume(AS_OPCODE);
  3214. { // Zero operand opcode ? // }
  3215. if actasmtoken = AS_SEPARATOR then
  3216. exit
  3217. else
  3218. operandnum := 1;
  3219. end;
  3220. While actasmtoken <> AS_SEPARATOR do
  3221. Begin
  3222. case actasmtoken of
  3223. { // Operand delimiter // }
  3224. AS_COMMA: Begin
  3225. if operandnum > MaxOperands then
  3226. Message(assem_e_too_many_operands)
  3227. else
  3228. Inc(operandnum);
  3229. Consume(AS_COMMA);
  3230. end;
  3231. { // End of asm operands for this opcode // }
  3232. AS_SEPARATOR: ;
  3233. else
  3234. BuildOperand(instr);
  3235. end; { end case }
  3236. end; { end while }
  3237. end;
  3238. Function Assemble: Ptree;
  3239. {*********************************************************************}
  3240. { PROCEDURE Assemble; }
  3241. { Description: Parses the att assembler syntax, parsing is done }
  3242. { according to GAs rules. }
  3243. {*********************************************************************}
  3244. Var
  3245. hl: plabel;
  3246. labelptr,nextlabel : pasmlabel;
  3247. commname : string;
  3248. store_p : paasmoutput;
  3249. Begin
  3250. Message(assem_d_start_att);
  3251. firsttoken := TRUE;
  3252. operandnum := 0;
  3253. if assigned(procinfo.retdef) and
  3254. (is_fpu(procinfo.retdef) or
  3255. ret_in_acc(procinfo.retdef)) then
  3256. procinfo.funcret_is_valid:=true;
  3257. { sets up all opcode and register tables in uppercase }
  3258. if not _asmsorted then
  3259. Begin
  3260. SetupTables;
  3261. _asmsorted := TRUE;
  3262. end;
  3263. p:=new(paasmoutput,init);
  3264. { save pointer code section }
  3265. store_p:=p;
  3266. { setup label linked list }
  3267. labellist.init;
  3268. c:={$ifdef NEWINPUT}current_scanner^.{$endif}asmgetchar;
  3269. actasmtoken:=gettoken;
  3270. while actasmtoken<>AS_END do
  3271. Begin
  3272. case actasmtoken of
  3273. AS_LLABEL: Begin
  3274. labelptr := labellist.search(actasmpattern);
  3275. if not assigned(labelptr) then
  3276. Begin
  3277. getlabel(hl);
  3278. labellist.insert(actasmpattern,hl,TRUE);
  3279. ConcatLabel(p,A_LABEL,hl);
  3280. end
  3281. else
  3282. { the label has already been inserted into the }
  3283. { label list, either as an instruction label (in}
  3284. { this case it has not been emitted), or as a }
  3285. { duplicate local symbol (in this case it has }
  3286. { already been emitted). }
  3287. Begin
  3288. if labelptr^.emitted then
  3289. Message1(assem_e_dup_local_sym,'.L'+labelptr^.name^)
  3290. else
  3291. Begin
  3292. if assigned(labelptr^.lab) then
  3293. ConcatLabel(p,A_LABEL,labelptr^.lab);
  3294. labelptr^.emitted := TRUE;
  3295. end;
  3296. end;
  3297. Consume(AS_LLABEL);
  3298. end;
  3299. AS_LABEL: Begin
  3300. { when looking for Pascal labels, these must }
  3301. { be in uppercase. }
  3302. if SearchLabel(upper(actasmpattern),hl) then
  3303. ConcatLabel(p,A_LABEL, hl)
  3304. else
  3305. Begin
  3306. if (cs_compilesystem in aktswitches) then
  3307. begin
  3308. Message1(assem_e_unknown_label_identifer,actasmpattern);
  3309. { once again we don't know what it represents }
  3310. { so we simply concatenate it }
  3311. ConcatLocal(p,actasmpattern);
  3312. end
  3313. else
  3314. Message1(assem_e_unknown_label_identifer,actasmpattern);
  3315. end;
  3316. Consume(AS_LABEL);
  3317. end;
  3318. AS_DW: Begin
  3319. Consume(AS_DW);
  3320. BuildConstant($ffff);
  3321. end;
  3322. AS_DATA: Begin
  3323. { -- this should only be allowed for system development -- }
  3324. { i think this should be fixed in the dos unit, and }
  3325. { not here. }
  3326. if (cs_compilesystem in aktswitches) then
  3327. p:=datasegment
  3328. else
  3329. Message(assem_e_switching_sections_not_allowed);
  3330. Consume(AS_DATA);
  3331. end;
  3332. AS_TEXT: Begin
  3333. { -- this should only be allowed for system development -- }
  3334. { i think this should be fixed in the dos unit, and }
  3335. { not here. }
  3336. if (cs_compilesystem in aktswitches) then
  3337. p:=store_p
  3338. else
  3339. Message(assem_e_switching_sections_not_allowed);
  3340. Consume(AS_TEXT);
  3341. end;
  3342. AS_DB: Begin
  3343. Consume(AS_DB);
  3344. BuildConstant($ff);
  3345. end;
  3346. AS_DD: Begin
  3347. Consume(AS_DD);
  3348. BuildConstant($ffffffff);
  3349. end;
  3350. AS_DQ: Begin
  3351. Consume(AS_DQ);
  3352. BuildRealConstant(s64bit);
  3353. end;
  3354. AS_SINGLE: Begin
  3355. Consume(AS_SINGLE);
  3356. BuildRealConstant(s32real);
  3357. end;
  3358. AS_DOUBLE: Begin
  3359. Consume(AS_DOUBLE);
  3360. BuildRealConstant(s64real);
  3361. end;
  3362. AS_EXTENDED: Begin
  3363. Consume(AS_EXTENDED);
  3364. BuildRealConstant(s80real);
  3365. end;
  3366. AS_GLOBAL:
  3367. Begin
  3368. { normal units should not be able to declare }
  3369. { direct label names like this... anyhow }
  3370. { procedural calls in asm blocks are }
  3371. { supposedely replaced automatically }
  3372. if (cs_compilesystem in aktswitches) then
  3373. begin
  3374. Consume(AS_GLOBAL);
  3375. if actasmtoken <> AS_ID then
  3376. Message(assem_e_invalid_global_def)
  3377. else
  3378. ConcatPublic(p,actasmpattern);
  3379. Consume(actasmtoken);
  3380. if actasmtoken <> AS_SEPARATOR then
  3381. Begin
  3382. Message(assem_e_line_separator_expected);
  3383. while actasmtoken <> AS_SEPARATOR do
  3384. Consume(actasmtoken);
  3385. end;
  3386. end
  3387. else
  3388. begin
  3389. Message(assem_w_globl_not_supported);
  3390. while actasmtoken <> AS_SEPARATOR do
  3391. Consume(actasmtoken);
  3392. end;
  3393. end;
  3394. AS_ALIGN: Begin
  3395. Message(assem_w_align_not_supported);
  3396. while actasmtoken <> AS_SEPARATOR do
  3397. Consume(actasmtoken);
  3398. end;
  3399. AS_ASCIIZ: Begin
  3400. Consume(AS_ASCIIZ);
  3401. BuildStringConstant(TRUE);
  3402. end;
  3403. AS_ASCII: Begin
  3404. Consume(AS_ASCII);
  3405. BuildStringConstant(FALSE);
  3406. end;
  3407. AS_LCOMM: Begin
  3408. { -- this should only be allowed for system development -- }
  3409. { -- otherwise may mess up future enhancements we might -- }
  3410. { -- add. -- }
  3411. if (cs_compilesystem in aktswitches) then
  3412. begin
  3413. Consume(AS_LCOMM);
  3414. if actasmtoken <> AS_ID then
  3415. begin
  3416. Message(assem_e_invalid_lcomm_def);
  3417. { error recovery }
  3418. while actasmtoken <> AS_SEPARATOR do
  3419. Consume(actasmtoken);
  3420. end
  3421. else
  3422. begin
  3423. commname:=actasmpattern;
  3424. Consume(AS_COMMA);
  3425. ConcatLocalBss(actasmpattern,BuildExpression);
  3426. if actasmtoken <> AS_SEPARATOR then
  3427. Begin
  3428. Message(assem_e_line_separator_expected);
  3429. while actasmtoken <> AS_SEPARATOR do
  3430. Consume(actasmtoken);
  3431. end;
  3432. end;
  3433. end
  3434. else
  3435. begin
  3436. Message(assem_w_lcomm_not_supported);
  3437. while actasmtoken <> AS_SEPARATOR do
  3438. Consume(actasmtoken);
  3439. end;
  3440. end;
  3441. AS_COMM: Begin
  3442. { -- this should only be allowed for system development -- }
  3443. { -- otherwise may mess up future enhancements we might -- }
  3444. { -- add. -- }
  3445. if (cs_compilesystem in aktswitches) then
  3446. begin
  3447. Consume(AS_COMM);
  3448. if actasmtoken <> AS_ID then
  3449. begin
  3450. Message(assem_e_invalid_comm_def);
  3451. { error recovery }
  3452. while actasmtoken <> AS_SEPARATOR do
  3453. Consume(actasmtoken);
  3454. end
  3455. else
  3456. begin
  3457. commname:=actasmpattern;
  3458. Consume(AS_COMMA);
  3459. ConcatGlobalBss(actasmpattern,BuildExpression);
  3460. if actasmtoken <> AS_SEPARATOR then
  3461. Begin
  3462. Message(assem_e_line_separator_expected);
  3463. while actasmtoken <> AS_SEPARATOR do
  3464. Consume(actasmtoken);
  3465. end;
  3466. end;
  3467. end
  3468. else
  3469. begin
  3470. Message(assem_w_comm_not_supported);
  3471. while actasmtoken <> AS_SEPARATOR do
  3472. Consume(actasmtoken);
  3473. end;
  3474. end;
  3475. AS_OPCODE: Begin
  3476. instr.init;
  3477. BuildOpcode;
  3478. instr.numops := operandnum;
  3479. if instr.labeled then
  3480. ConcatLabeledInstr(instr)
  3481. else
  3482. ConcatOpCode(instr);
  3483. end;
  3484. AS_SEPARATOR:Begin
  3485. Consume(AS_SEPARATOR);
  3486. { let us go back to the first operand }
  3487. operandnum := 0;
  3488. end;
  3489. AS_END: ; { end assembly block }
  3490. else
  3491. Begin
  3492. Message(assem_e_assemble_node_syntax_error);
  3493. { error recovery }
  3494. Consume(actasmtoken);
  3495. end;
  3496. end; { end case }
  3497. end; { end while }
  3498. { check if there were undefined symbols. }
  3499. { if so, then list each of those undefined }
  3500. { labels. }
  3501. if assigned(labellist.First) then
  3502. Begin
  3503. labelptr := labellist.First;
  3504. While labelptr <> nil do
  3505. Begin
  3506. nextlabel:=labelptr^.next;
  3507. if not labelptr^.emitted then
  3508. Message1(assem_e_local_sym_not_found_in_asm_statement,'.L'+labelptr^.name^);
  3509. labelptr:=nextlabel;
  3510. end;
  3511. end;
  3512. if p<>store_p then
  3513. begin
  3514. Message(assem_e_assembler_code_not_returned_to_text);
  3515. p:=store_p;
  3516. end;
  3517. assemble := genasmnode(p);
  3518. labellist.done;
  3519. Message(assem_d_finish_att);
  3520. end;
  3521. var
  3522. old_exit: pointer;
  3523. procedure ra386att_exit;{$ifndef FPC}far;{$endif}
  3524. begin
  3525. if assigned(iasmops) then
  3526. dispose(iasmops);
  3527. exitproc:=old_exit;
  3528. end;
  3529. Begin
  3530. line:=''; { Initialization of line variable.
  3531. No 255 char coonst string in version 0.9.1 MVC}
  3532. old_exit := exitproc;
  3533. exitproc := @ra386att_exit;
  3534. end.
  3535. {
  3536. $Log$
  3537. Revision 1.4 1998-07-08 15:06:41 daniel
  3538. + $N+,E+ added for TP.
  3539. Revision 1.3 1998/07/07 11:20:07 peter
  3540. + NEWINPUT for a better inputfile and scanner object
  3541. Revision 1.2 1998/06/24 14:06:36 peter
  3542. * fixed the name changes
  3543. Revision 1.1 1998/06/23 14:00:17 peter
  3544. * renamed RA* units
  3545. Revision 1.13 1998/06/16 08:56:29 peter
  3546. + targetcpu
  3547. * cleaner pmodules for newppu
  3548. Revision 1.12 1998/06/12 10:32:35 pierre
  3549. * column problem hopefully solved
  3550. + C vars declaration changed
  3551. Revision 1.11 1998/05/31 14:13:35 peter
  3552. * fixed call bugs with assembler readers
  3553. + OPR_SYMBOL to hold a symbol in the asm parser
  3554. * fixed staticsymtable vars which were acessed through %ebp instead of
  3555. name
  3556. Revision 1.10 1998/05/30 14:31:08 peter
  3557. + $ASMMODE
  3558. Revision 1.9 1998/05/29 09:58:16 pierre
  3559. * OPR_REGISTER for 1 arg was missing in ratti386.pas
  3560. (probably a merging problem)
  3561. * errors at start of line were lost
  3562. Revision 1.8 1998/05/28 16:34:36 carl
  3563. * call bugfix
  3564. * operand with regs bugfix (manual patch in both cases)
  3565. Revision 1.7 1998/05/23 01:21:27 peter
  3566. + aktasmmode, aktoptprocessor, aktoutputformat
  3567. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  3568. + $LIBNAME to set the library name where the unit will be put in
  3569. * splitted cgi386 a bit (codeseg to large for bp7)
  3570. * nasm, tasm works again. nasm moved to ag386nsm.pas
  3571. Revision 1.6 1998/05/20 09:42:37 pierre
  3572. + UseTokenInfo now default
  3573. * unit in interface uses and implementation uses gives error now
  3574. * only one error for unknown symbol (uses lastsymknown boolean)
  3575. the problem came from the label code !
  3576. + first inlined procedures and function work
  3577. (warning there might be allowed cases were the result is still wrong !!)
  3578. * UseBrower updated gives a global list of all position of all used symbols
  3579. with switch -gb
  3580. Revision 1.5 1998/04/29 13:52:23 peter
  3581. * small optimize fix
  3582. Revision 1.4 1998/04/29 10:34:04 pierre
  3583. + added some code for ansistring (not complete nor working yet)
  3584. * corrected operator overloading
  3585. * corrected nasm output
  3586. + started inline procedures
  3587. + added starstarn : use ** for exponentiation (^ gave problems)
  3588. + started UseTokenInfo cond to get accurate positions
  3589. Revision 1.3 1998/04/08 16:58:07 pierre
  3590. * several bugfixes
  3591. ADD ADC and AND are also sign extended
  3592. nasm output OK (program still crashes at end
  3593. and creates wrong assembler files !!)
  3594. procsym types sym in tdef removed !!
  3595. }