ratti386.pas 149 KB

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