ra386att.pas 154 KB

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