ratti386.pas 150 KB

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