ra386att.pas 159 KB

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