ratti386.pas 149 KB

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