ra386att.pas 145 KB

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