ra386att.pas 148 KB

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