ra386att.pas 156 KB

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