ra386att.pas 156 KB

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