ra386att.pas 143 KB

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