ra386att.pas 144 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889
  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. Function CheckAndSetOpsize(var op : toperand;size : topsize) : boolean;
  997. Begin
  998. CheckAndSetOpsize:=true;
  999. { operandtype for constant get a default value for size }
  1000. if (op.operandtype<>OPR_CONSTANT) and (op.size<>S_NO) and (op.size<>size) then
  1001. begin
  1002. CheckAndSetOpsize:=false;
  1003. if (cs_compilesystem in aktmoduleswitches) or
  1004. not (cs_check_range in aktlocalswitches) then
  1005. Message(assem_w_size_suffix_and_dest_dont_match)
  1006. else
  1007. Message(assem_e_size_suffix_and_dest_dont_match);
  1008. end;
  1009. op.size:=size;
  1010. End;
  1011. Procedure ConcatOpCode(var instr: TInstruction);
  1012. {*********************************************************************}
  1013. { First Pass: }
  1014. { - If this is a three operand opcode: }
  1015. { imul,shld,and shrd -> check them manually. }
  1016. {*********************************************************************}
  1017. var
  1018. fits : boolean;
  1019. i: longint;
  1020. opsize: topsize;
  1021. optyp1, optyp2, optyp3: longint;
  1022. instruc: tasmop;
  1023. href : treference;
  1024. Begin
  1025. fits := FALSE;
  1026. for i:=1 to instr.numops do
  1027. Begin
  1028. case instr.operands[i].operandtype of
  1029. OPR_REGISTER: instr.operands[i].size :=
  1030. reg_2_size[instr.operands[i].reg];
  1031. end; { end case }
  1032. end; { endif }
  1033. { setup specific instructions for first pass }
  1034. instruc := instr.getinstruction;
  1035. Case instruc Of
  1036. A_LEA,A_LDS,A_LSS,A_LES,A_LFS,A_LGS:
  1037. Begin
  1038. if instr.operands[2].size <> S_L then
  1039. Begin
  1040. Message(assem_e_16bit_base_in_32bit_segment);
  1041. exit;
  1042. end; { endif }
  1043. end;
  1044. End;
  1045. With instr do
  1046. Begin
  1047. for i:=1 to numops do
  1048. Begin
  1049. With operands[i] do
  1050. Begin
  1051. { check for 16-bit bases/indexes and emit an error. }
  1052. { we cannot only emit a warning since gas does not }
  1053. { accept 16-bit indexes and bases. }
  1054. if (operandtype = OPR_REFERENCE) and
  1055. ((ref.base <> R_NO) or
  1056. (ref.index <> R_NO)) then
  1057. Begin
  1058. { index or base defined. }
  1059. if (ref.base <> R_NO) then
  1060. Begin
  1061. if not (ref.base in
  1062. [R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESI,R_EDI,R_ESP]) then
  1063. Message(assem_e_16bit_base_in_32bit_segment);
  1064. end;
  1065. { index or base defined. }
  1066. if (ref.index <> R_NO) then
  1067. Begin
  1068. if not (ref.index in
  1069. [R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESI,R_EDI,R_ESP]) then
  1070. Message(assem_e_16bit_index_in_32bit_segment);
  1071. end;
  1072. end;
  1073. { Check for constants without bases/indexes in memory }
  1074. { references. }
  1075. { Update: allow constant references under Go32v2, to }
  1076. { access data in the bios data segmement (JM) }
  1077. if (target_info.target<>target_i386_Go32v2) and
  1078. ((operandtype = OPR_REFERENCE) and
  1079. (ref.base = R_NO) and
  1080. (ref.index = R_NO) and
  1081. (ref.symbol = nil) and
  1082. (ref.offset <> 0)) then
  1083. Begin
  1084. ref.isintvalue := TRUE;
  1085. Message(assem_e_const_ref_not_allowed);
  1086. end;
  1087. opinfo := findtype(operands[i]);
  1088. end; { end with }
  1089. end; {endfor}
  1090. { TAKE CARE OF SPECIAL OPCODES, TAKE CARE OF THEM INDIVUALLY. }
  1091. { ALL THE REST ARE TAKEN CARE BY OPCODE TABLE AND THIRD PASS. }
  1092. { is this right for ratti386 ? (PM) }
  1093. { almost... here we check for the size of registers and references }
  1094. { to determine the correct gas opcode to use, because if the token }
  1095. { is A_MOVSX or A_MOVZX then that means that the person forgot to }
  1096. { specify the size.. }
  1097. { if memory size is not specified, will of course give out an error}
  1098. Case instruc Of
  1099. A_MOVSX:
  1100. Begin
  1101. if numops = 2 then
  1102. begin
  1103. if stropsize = S_BL then
  1104. begin
  1105. CheckAndSetOpsize(operands[1],S_B);
  1106. stropsize := S_NO;
  1107. CheckAndSetOpsize(operands[2],S_L);
  1108. addinstr(A_MOVSBL)
  1109. end
  1110. else
  1111. if stropsize = S_WL then
  1112. begin
  1113. CheckAndSetOpsize(operands[1],S_W);
  1114. stropsize := S_NO;
  1115. CheckAndSetOpsize(operands[2],S_L);
  1116. addinstr(A_MOVSWL)
  1117. end
  1118. else
  1119. if stropsize = S_BW then
  1120. begin
  1121. CheckAndSetOpsize(operands[1],S_B);
  1122. stropsize := S_NO;
  1123. CheckAndSetOpsize(operands[2],S_W);
  1124. addinstr(A_MOVSBW)
  1125. end
  1126. else
  1127. if (operands[1].size = S_B) and
  1128. (operands[2].size = S_W) then
  1129. addinstr(A_MOVSBW)
  1130. else
  1131. if (operands[1].size = S_B) and
  1132. (operands[2].size = S_L) then
  1133. addinstr(A_MOVSBL)
  1134. else
  1135. if (operands[1].size = S_W) and
  1136. (operands[2].size = S_L) then
  1137. addinstr(A_MOVSWL)
  1138. else
  1139. begin
  1140. Message(assem_e_invalid_size_movzx);
  1141. exit;
  1142. end;
  1143. instruc := getinstruction; { reload instruction }
  1144. end
  1145. else
  1146. begin
  1147. Message(assem_e_too_many_operands);
  1148. exit;
  1149. end;
  1150. end;
  1151. A_MOVZX:
  1152. Begin
  1153. if numops = 2 then
  1154. Begin
  1155. if stropsize = S_BW then
  1156. begin
  1157. CheckAndSetOpsize(operands[1],S_B);
  1158. stropsize := S_NO;
  1159. CheckAndSetOpsize(operands[2],S_W);
  1160. addinstr(A_MOVZB)
  1161. end
  1162. else
  1163. if stropsize = S_BL then
  1164. begin
  1165. CheckAndSetOpsize(operands[1],S_B);
  1166. stropsize := S_NO;
  1167. CheckAndSetOpsize(operands[2],S_L);
  1168. addinstr(A_MOVZB)
  1169. end
  1170. else
  1171. if stropsize = S_WL then
  1172. begin
  1173. CheckAndSetOpsize(operands[1],S_W);
  1174. stropsize := S_NO;
  1175. CheckAndSetOpsize(operands[2],S_L);
  1176. addinstr(A_MOVZWL)
  1177. end
  1178. else
  1179. { change the instruction to conform to GAS }
  1180. if (operands[1].size = S_B) and
  1181. (operands[2].size in [S_W,S_L]) then
  1182. addinstr(A_MOVZB)
  1183. else
  1184. if (operands[1].size = S_W) and
  1185. (operands[2].size = S_L) then
  1186. addinstr(A_MOVZWL)
  1187. else
  1188. begin
  1189. Message(assem_e_invalid_size_movzx);
  1190. exit;
  1191. end;
  1192. instruc := getinstruction; { reload instruction }
  1193. end
  1194. else
  1195. Begin
  1196. Message(assem_e_too_many_operands);
  1197. exit;
  1198. end;
  1199. end;
  1200. A_FWAIT: FWaitWarning;
  1201. A_BT,A_BTC,A_BTR,A_BTS:
  1202. Begin
  1203. if numops = 2 then
  1204. Begin
  1205. if (operands[1].operandtype = OPR_CONSTANT)
  1206. and (operands[1].val <= $ff) then
  1207. Begin
  1208. operands[1].opinfo := ao_imm8;
  1209. { no operand size if using constant. }
  1210. operands[1].size := S_NO;
  1211. fits := TRUE;
  1212. end
  1213. end
  1214. else
  1215. Begin
  1216. Message(assem_e_invalid_opcode_and_operand);
  1217. exit;
  1218. end;
  1219. end;
  1220. A_ENTER:
  1221. Begin
  1222. if numops =2 then
  1223. Begin
  1224. if (operands[1].operandtype = OPR_CONSTANT) and
  1225. (operands[1].val <= $ffff) then
  1226. Begin
  1227. operands[1].opinfo := ao_imm16;
  1228. end { endif }
  1229. end { endif }
  1230. else
  1231. Begin
  1232. Message(assem_e_invalid_opcode_and_operand);
  1233. exit;
  1234. end
  1235. end;
  1236. { Handle special opcodes for the opcode }
  1237. { table. Set them up correctly. }
  1238. A_INS,A_IN:
  1239. Begin
  1240. if numops =2 then
  1241. Begin
  1242. if (operands[1].operandtype = OPR_REGISTER) and
  1243. (operands[1].reg = R_DX) then
  1244. Begin
  1245. operands[1].opinfo := ao_inoutportreg;
  1246. if (operands[2].operandtype = OPR_REGISTER) and
  1247. (operands[2].reg in [R_EAX,R_AX,R_AL]) and
  1248. (instruc = A_IN) then
  1249. Begin
  1250. operands[2].opinfo := ao_acc;
  1251. case operands[2].reg of
  1252. R_EAX: operands[2].size := S_L;
  1253. R_AX: operands[2].size := S_W;
  1254. R_AL: operands[2].size := S_B;
  1255. end;
  1256. end
  1257. end
  1258. else
  1259. if (operands[1].operandtype = OPR_CONSTANT) and
  1260. (operands[1].val <= $ff) And
  1261. (instruc = A_IN) then
  1262. Begin
  1263. operands[1].opinfo := ao_imm8;
  1264. operands[1].size := S_B;
  1265. if (operands[2].operandtype = OPR_REGISTER) and
  1266. (operands[2].reg in [R_EAX,R_AX,R_AL]) and
  1267. (instruc = A_IN) then
  1268. Begin
  1269. operands[2].opinfo := ao_acc;
  1270. end
  1271. end;
  1272. end
  1273. else
  1274. Begin
  1275. Message(assem_e_invalid_opcode_and_operand);
  1276. exit;
  1277. end;
  1278. end;
  1279. A_OUTS,A_OUT:
  1280. Begin
  1281. if numops =2 then
  1282. Begin
  1283. if (operands[2].operandtype = OPR_REGISTER) and
  1284. (operands[2].reg = R_DX) then
  1285. Begin
  1286. operands[2].opinfo := ao_inoutportreg;
  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. else
  1296. if (operands[2].operandtype = OPR_CONSTANT) and
  1297. (operands[2].val <= $ff) and
  1298. (instruc = A_OUT) then
  1299. Begin
  1300. operands[2].opinfo := ao_imm8;
  1301. operands[2].size := S_B;
  1302. if (operands[1].operandtype = OPR_REGISTER) and
  1303. (operands[1].reg in [R_EAX,R_AX,R_AL]) and
  1304. (instruc = A_OUT) then
  1305. Begin
  1306. operands[1].opinfo := ao_acc;
  1307. fits := TRUE;
  1308. end
  1309. end;
  1310. end
  1311. else
  1312. Begin
  1313. Message(assem_e_invalid_opcode_and_operand);
  1314. exit;
  1315. end;
  1316. end;
  1317. A_RCL,A_RCR,A_ROL,A_ROR,A_SAL,A_SAR,A_SHL,A_SHR:
  1318. Begin
  1319. if numops =2 then
  1320. Begin
  1321. if (operands[1].operandtype = OPR_REGISTER) and
  1322. (operands[1].reg = R_CL) then
  1323. Begin
  1324. operands[1].opinfo := ao_shiftcount
  1325. end
  1326. else
  1327. if (operands[1].operandtype = OPR_CONSTANT) and
  1328. (operands[1].val <= $ff) then
  1329. Begin
  1330. operands[1].opinfo := ao_imm8;
  1331. operands[1].size := S_B;
  1332. end;
  1333. end
  1334. else { if numops = 2 }
  1335. Begin
  1336. Message(assem_e_invalid_opcode_and_operand);
  1337. exit;
  1338. end;
  1339. end;
  1340. { this did not work (PM) }
  1341. A_DIV, A_IDIV:
  1342. Begin
  1343. if (operands[2].operandtype = OPR_REGISTER) and
  1344. (operands[2].reg in [R_AL,R_AX,R_EAX]) then
  1345. operands[2].opinfo := ao_acc;
  1346. end;
  1347. A_FNSTSW, A_FSTSW:
  1348. Begin
  1349. { %ax can be omitted in ATT syntax }
  1350. if numops = 0 then
  1351. Begin
  1352. numops:=1;
  1353. operands[1].operandtype:=OPR_REGISTER;
  1354. operands[1].reg:=R_AX;
  1355. operands[1].opinfo := ao_acc;
  1356. end
  1357. else
  1358. if numops = 1 then
  1359. Begin
  1360. if (operands[1].operandtype = OPR_REGISTER) and
  1361. (operands[1].reg = R_AX) then
  1362. operands[1].opinfo := ao_acc;
  1363. end
  1364. else
  1365. Begin
  1366. Message(assem_e_invalid_opcode_and_operand);
  1367. exit;
  1368. end;
  1369. end;
  1370. A_SHLD,A_SHRD:
  1371. { these instruction are fully parsed individually on pass three }
  1372. { so we just do a summary checking here. }
  1373. Begin
  1374. if numops = 3 then
  1375. Begin
  1376. if (operands[1].operandtype = OPR_CONSTANT) and
  1377. (operands[1].val <= $ff) then
  1378. Begin
  1379. operands[1].opinfo := ao_imm8;
  1380. operands[1].size := S_B;
  1381. end;
  1382. end
  1383. else
  1384. Begin
  1385. Message(assem_e_invalid_opcode_and_operand);
  1386. exit;
  1387. end;
  1388. end;
  1389. A_INT:
  1390. Begin
  1391. if numops = 1 then
  1392. Begin
  1393. if (operands[1].operandtype = OPR_CONSTANT) and
  1394. (operands[1].val <= $ff) then
  1395. operands[1].opinfo := ao_imm8;
  1396. end
  1397. end;
  1398. A_RET:
  1399. Begin
  1400. if numops =1 then
  1401. Begin
  1402. if (operands[1].operandtype = OPR_CONSTANT) and
  1403. (operands[1].val <= $ffff) then
  1404. operands[1].opinfo := ao_imm16;
  1405. end
  1406. end;
  1407. { all string instructions have default memory }
  1408. { location which are ignored. Take care of }
  1409. { those. }
  1410. { Here could be added the code for segment }
  1411. { overrides. }
  1412. A_SCAS,A_CMPS,A_STOS,A_LODS:
  1413. Begin
  1414. if numops =1 then
  1415. Begin
  1416. if (operands[1].operandtype = OPR_REFERENCE) and
  1417. (assigned(operands[1].ref.symbol)) then
  1418. Freemem(operands[1].ref.symbol,length(operands[1].ref.symbol^)+1);
  1419. operands[1].operandtype := OPR_NONE;
  1420. numops := 0;
  1421. end;
  1422. end;
  1423. A_XLAT:
  1424. Begin
  1425. { handle special TP syntax case for XLAT }
  1426. { here we accept XLAT, XLATB and XLAT m8 }
  1427. if (numops = 1) or (numops = 0) then
  1428. Begin
  1429. if (operands[1].operandtype = OPR_REFERENCE) and
  1430. (assigned(operands[1].ref.symbol)) then
  1431. Freemem(operands[1].ref.symbol,length(operands[1].ref.symbol^)+1);
  1432. operands[1].operandtype := OPR_NONE;
  1433. numops := 0;
  1434. { always a byte for XLAT }
  1435. instr.stropsize := S_B;
  1436. end;
  1437. end;
  1438. { ------------------------------------------------------------------- }
  1439. { ------------------------- SIZE CHECK ------------------------------ }
  1440. { ------------- presently done only for most used opcodes ---------- }
  1441. { Checks if the suffix concords with the destination size , if }
  1442. { not gives out an error. (This check is stricter then gas but is }
  1443. { REQUIRED for intasmi3) }
  1444. A_MOV,A_ADD,A_SUB,A_ADC,A_SBB,A_CMP,A_AND,A_OR,A_TEST,A_XOR:
  1445. begin
  1446. if (instr.stropsize <> S_NO) then
  1447. Begin
  1448. if not CheckAndSetOpsize(operands[1],instr.stropsize) or
  1449. not CheckAndSetOpsize(operands[2],instr.stropsize) then
  1450. End;
  1451. end;
  1452. A_DEC,A_INC,A_NOT,A_NEG:
  1453. begin
  1454. if (instr.stropsize <> S_NO) and
  1455. (instr.operands[1].size <> S_NO) then
  1456. if (instr.stropsize <> instr.operands[1].size) then
  1457. begin
  1458. Message(assem_e_size_suffix_and_dest_reg_dont_match);
  1459. exit;
  1460. end;
  1461. end;
  1462. A_PUSH:
  1463. Begin
  1464. if (instr.operands[1].operandtype = OPR_CONSTANT) and
  1465. (instr.stropsize = S_NO) then
  1466. Message(assem_e_size_suffix_and_dest_reg_dont_match);
  1467. end;
  1468. End; { case }
  1469. {we have to start a new case because A_INS etc are already handled before
  1470. as well... (JM)}
  1471. Case instruc of
  1472. A_INS,A_MOVS,A_OUTS:
  1473. Begin
  1474. if numops =2 then
  1475. Begin
  1476. if (operands[2].operandtype = OPR_REFERENCE) and
  1477. (assigned(operands[2].ref.symbol)) then
  1478. Freemem(operands[2].ref.symbol,length(operands[2].ref.symbol^)+1);
  1479. if (operands[1].operandtype = OPR_REFERENCE) and
  1480. (assigned(operands[1].ref.symbol)) then
  1481. Freemem(operands[1].ref.symbol,length(operands[2].ref.symbol^)+1);
  1482. operands[2].operandtype := OPR_NONE;
  1483. operands[1].operandtype := OPR_NONE;
  1484. numops := 0;
  1485. end;
  1486. end;
  1487. { handle parameter for segment overrides }
  1488. end; { case }
  1489. { ------------------------------------------------------------------- }
  1490. { copy them to local variables }
  1491. { for faster access }
  1492. optyp1:=operands[1].opinfo;
  1493. optyp2:=operands[2].opinfo;
  1494. optyp3:=operands[3].opinfo;
  1495. end; { end with }
  1496. { after reading the operands }
  1497. { search the instruction }
  1498. { setup startvalue from cache }
  1499. if itcache^[instruc]<>-1 then
  1500. i:=itcache^[instruc]
  1501. else
  1502. i:=0;
  1503. { I think this is too dangerous for me therefore i decided that for }
  1504. { the att version only if the processor > i386 or we are compiling }
  1505. { the system unit then this will be allowed... }
  1506. if (instruc > lastop_ittable) then
  1507. begin
  1508. Message1(assem_w_opcode_not_in_table,upper(att_op2str[instruc]));
  1509. fits:=true;
  1510. end
  1511. else while not(fits) do
  1512. begin
  1513. { set the instruction cache, if the instruction }
  1514. { occurs the first time }
  1515. if (it[i].i=instruc) and (itcache^[instruc]=-1) then
  1516. itcache^[instruc]:=i;
  1517. if (it[i].i=instruc) and (instr.numops=it[i].ops) then
  1518. begin
  1519. { first fit }
  1520. case instr.numops of
  1521. 0 : begin
  1522. fits:=true;
  1523. break;
  1524. end;
  1525. 1 :
  1526. Begin
  1527. if (optyp1 and it[i].o1)<>0 then
  1528. Begin
  1529. fits:=true;
  1530. break;
  1531. end;
  1532. { I consider sign-extended 8bit value to }
  1533. { be equal to immediate 8bit therefore }
  1534. { convert... }
  1535. if (optyp1 = ao_imm8) then
  1536. Begin
  1537. { check if this is a simple sign extend. }
  1538. if (it[i].o1<>ao_imm8s) then
  1539. Begin
  1540. fits:=true;
  1541. break;
  1542. end;
  1543. end;
  1544. end;
  1545. 2 : if ((optyp1 and it[i].o1)<>0) and
  1546. ((optyp2 and it[i].o2)<>0) then
  1547. Begin
  1548. fits:=true;
  1549. break;
  1550. end
  1551. { if the operands can be swaped }
  1552. { then swap them }
  1553. else if ((it[i].m and af_d)<>0) and
  1554. ((optyp1 and it[i].o2)<>0) and
  1555. ((optyp2 and it[i].o1)<>0) then
  1556. begin
  1557. fits:=true;
  1558. break;
  1559. end;
  1560. 3 : if ((optyp1 and it[i].o1)<>0) and
  1561. ((optyp2 and it[i].o2)<>0) and
  1562. ((optyp3 and it[i].o3)<>0) then
  1563. Begin
  1564. fits:=true;
  1565. break;
  1566. end;
  1567. end; { end case }
  1568. end; { endif }
  1569. if it[i].i=A_NONE then
  1570. begin
  1571. { NO MATCH! }
  1572. Message(assem_e_invalid_opcode_and_operand);
  1573. exit;
  1574. end;
  1575. inc(i);
  1576. end; { end while }
  1577. { We add the opcode to the opcode linked list }
  1578. if fits then
  1579. Begin
  1580. if instr.getprefix <> A_NONE then
  1581. Begin
  1582. p^.concat(new(pai386,op_none(instr.getprefix,S_NO)));
  1583. end;
  1584. { change from AT&T styled floating point to }
  1585. { intel styled floating point with valid size }
  1586. { we use these instructions so it does not }
  1587. { mess up intasmi3 }
  1588. if (instruc >= A_FILDQ) and (instruc <= A_FIDIVRS) then
  1589. Begin
  1590. instr.stropsize := _fpusizes[instruc];
  1591. instr.addinstr(_fpuopcodes[instruc]);
  1592. instruc := instr.getinstruction;
  1593. end;
  1594. case instr.numops of
  1595. 0:
  1596. if instr.stropsize <> S_NO then
  1597. { is this a string operation opcode or xlat then check }
  1598. { the size of the operation. }
  1599. p^.concat(new(pai386,op_none(instruc,instr.stropsize)))
  1600. else
  1601. p^.concat(new(pai386,op_none(instruc,S_NO)));
  1602. 1: Begin
  1603. case instr.operands[1].operandtype of
  1604. { GAS requires that the size be set in the case of a push }
  1605. { constant value, }
  1606. OPR_CONSTANT:
  1607. Begin
  1608. if instruc = A_PUSH then
  1609. Begin
  1610. if instr.stropsize <> S_NO then
  1611. p^.concat(new(pai386,op_const(instruc,
  1612. instr.stropsize, instr.operands[1].val)))
  1613. else
  1614. Message(assem_e_invalid_opcode_and_operand);
  1615. end
  1616. else
  1617. p^.concat(new(pai386,op_const(instruc,
  1618. S_NO, instr.operands[1].val)));
  1619. end;
  1620. OPR_REGISTER:
  1621. Begin
  1622. if (instr.stropsize<>S_NO) then
  1623. opsize:=instr.stropsize
  1624. else
  1625. opsize:=instr.operands[1].size;
  1626. p^.concat(new(pai386,op_reg(instruc,opsize,instr.operands[1].reg)));
  1627. End;
  1628. OPR_SYMBOL:
  1629. Begin
  1630. p^.concat(new(pai386,op_csymbol(instruc,
  1631. instr.stropsize, newcsymbol(instr.operands[1].symbol^,0))));
  1632. End;
  1633. OPR_REFERENCE:
  1634. { now first check suffix ... }
  1635. if instr.stropsize <> S_NO then
  1636. Begin
  1637. p^.concat(new(pai386,op_ref(instruc,
  1638. instr.stropsize,newreference(instr.operands[1].ref))));
  1639. end
  1640. { no suffix... therefore resort using intel styled checking .. }
  1641. else if (instr.operands[1].size <> S_NO) and
  1642. Not ((instruc = A_CALL) or (instruc = A_JMP)) then
  1643. Begin
  1644. p^.concat(new(pai386,op_ref(instruc,
  1645. instr.operands[1].size,newreference(instr.operands[1].ref))));
  1646. end
  1647. else
  1648. Begin
  1649. { special jmp and call case with }
  1650. { symbolic references. }
  1651. Case instruc of
  1652. A_CALL,A_JMP,A_FNSTCW,A_FSTCW,A_FLDCW,A_FNSTSW,
  1653. A_FSTSW,A_FLDENV,A_FSTENV,A_FNSAVE,A_FSAVE:
  1654. Begin
  1655. p^.concat(new(pai386,op_ref(instruc,
  1656. S_NO,newreference(instr.operands[1].ref))));
  1657. end
  1658. else
  1659. Message(assem_e_invalid_opcode_and_operand);
  1660. End
  1661. end;
  1662. { This either crashed the compiler or the symbol would always be nil! }
  1663. { The problem is here is I didn't see any way of adding the labeled }
  1664. { symbol in the internal list, since i think from what i see in aasm }
  1665. { that these will automatically be declared as external ?? }
  1666. { note: has to be changed to a case if ever activated again to avoid }
  1667. { range problems (JM) }
  1668. { if (instruc in [A_JO,A_JNO,A_JB,A_JC,A_JNAE,
  1669. A_JNB,A_JNC,A_JAE,A_JE,A_JZ,A_JNE,A_JNZ,A_JBE,A_JNA,A_JNBE,
  1670. A_JA,A_JS,A_JNS,A_JP,A_JPE,A_JNP,A_JPO,A_JL,A_JNGE,A_JNL,A_JGE,
  1671. A_JLE,A_JNG,A_JNLE,A_JG,A_JCXZ,A_JECXZ,A_LOOP,A_LOOPZ,A_LOOPE,
  1672. A_LOOPNZ,A_LOOPNE,A_JMP,A_CALL]) then
  1673. Begin
  1674. if assigned(instr.operands[1].ref.symbol) then
  1675. p^.concat(new(pai386,op_csymbol(instruc,
  1676. S_NO,newcsymbol(instr.operands[1].ref.symbol^,instr.operands[1].ref.offset))))
  1677. else
  1678. Message(assem_e_invalid_opcode_and_operand);
  1679. end
  1680. else
  1681. else
  1682. Message(assem_e_invalid_opcode_and_operand);
  1683. end;}
  1684. OPR_NONE: Begin
  1685. Message(assem_f_internal_error_in_concatopcode);
  1686. end;
  1687. else
  1688. Begin
  1689. Message(assem_f_internal_error_in_concatopcode);
  1690. end;
  1691. end;
  1692. end;
  1693. 2:
  1694. Begin
  1695. Case instruc Of
  1696. A_MOVSX,A_MOVZX,A_MOVSB,A_MOVSBL,A_MOVSBW,A_MOVSWL,
  1697. A_MOVZB,A_MOVZWL:
  1698. { movzx and movsx }
  1699. HandleExtend(instr);
  1700. else
  1701. { other instructions }
  1702. Begin
  1703. With instr do
  1704. Begin
  1705. { source }
  1706. opsize := operands[1].size;
  1707. case operands[1].operandtype of
  1708. { reg,reg }
  1709. { reg,ref }
  1710. { const,reg -- IN/OUT }
  1711. OPR_REGISTER:
  1712. Begin
  1713. case operands[2].operandtype of
  1714. OPR_REGISTER:
  1715. { correction: according to the DJGPP FAQ, gas }
  1716. { doesn't even check correctly the size of }
  1717. { operands, therefore let us specify a size! }
  1718. { as in the GAS docs... destination tells us }
  1719. { the size! This might give out invalid output }
  1720. { in some very rare cases (because the size }
  1721. { checking is still not perfect). }
  1722. if (opsize = operands[2].size) then
  1723. begin
  1724. p^.concat(new(pai386,op_reg_reg(instruc,
  1725. opsize,operands[1].reg,operands[2].reg)));
  1726. end
  1727. else
  1728. Case instruc of
  1729. A_IN:
  1730. p^.concat(new(pai386,op_reg_reg(instruc,
  1731. operands[2].size,operands[1].reg,operands[2].reg)));
  1732. A_OUT:
  1733. p^.concat(new(pai386,op_reg_reg(instruc,
  1734. operands[1].size,operands[1].reg,operands[2].reg)));
  1735. { these do not require any size specification. }
  1736. A_SAL,A_SAR,A_SHL,A_SHR,A_ROL,A_ROR,A_RCR,
  1737. A_RCL:
  1738. { outs and ins are already taken care by }
  1739. { the first pass. }
  1740. p^.concat(new(pai386,op_reg_reg(instruc,
  1741. S_NO,operands[1].reg,operands[2].reg)))
  1742. else
  1743. if stropsize <> S_NO then
  1744. Begin
  1745. p^.concat(new(pai386,op_reg_reg(instruc,
  1746. stropsize,operands[1].reg,operands[2].reg)))
  1747. end
  1748. else
  1749. Begin
  1750. Message(assem_e_invalid_opcode_and_operand);
  1751. end;
  1752. end; {case instruc of}
  1753. OPR_REFERENCE:
  1754. { variable name. }
  1755. { here we must check the instruction type }
  1756. { before deciding if to use and compare }
  1757. { any sizes. }
  1758. if assigned(operands[2].ref.symbol) then
  1759. Begin
  1760. if stropsize <> S_NO then
  1761. Begin
  1762. p^.concat(new(pai386,op_reg_ref(instruc,
  1763. stropsize,operands[1].reg,newreference(operands[2].ref))))
  1764. end
  1765. else
  1766. if (opsize = operands[2].size) Then
  1767. p^.concat(new(pai386,op_reg_ref(instruc,
  1768. opsize,operands[1].reg,newreference(operands[2].ref))))
  1769. else
  1770. Case instruc of
  1771. A_RCL,A_RCR,A_ROL,A_ROR,A_SAL,A_SAR,
  1772. A_SHR,A_SHL:
  1773. p^.concat(new(pai386,op_reg_ref(instruc,
  1774. opsize,operands[1].reg,newreference(operands[2].ref))))
  1775. else
  1776. Message(assem_e_invalid_size_in_ref);
  1777. end
  1778. end
  1779. else
  1780. Begin
  1781. { register reference }
  1782. if stropsize <> S_NO then
  1783. Begin
  1784. p^.concat(new(pai386,op_reg_ref(instruc,
  1785. stropsize,operands[1].reg,newreference(operands[2].ref))))
  1786. end
  1787. else
  1788. if (opsize = operands[2].size) or
  1789. (operands[2].size = S_NO) then
  1790. p^.concat(new(pai386,op_reg_ref(instruc,
  1791. opsize,operands[1].reg,newreference(operands[2].ref))))
  1792. else
  1793. Message(assem_e_invalid_size_in_ref);
  1794. end;
  1795. OPR_CONSTANT: { OUT }
  1796. begin
  1797. { determine first with suffix }
  1798. if instruc = A_OUT then
  1799. begin
  1800. if instr.stropsize <> S_NO then
  1801. p^.concat(new(pai386,op_reg_const(instruc,stropsize,
  1802. instr.operands[1].reg, instr.operands[2].val)))
  1803. else
  1804. p^.concat(new(pai386,op_reg_const(instruc,S_NO,
  1805. instr.operands[1].reg, instr.operands[2].val)));
  1806. end
  1807. else
  1808. Message(assem_e_invalid_opcode);
  1809. end;
  1810. else { else case }
  1811. Begin
  1812. Message(assem_f_internal_error_in_concatopcode);
  1813. end;
  1814. end; { end inner case }
  1815. end;
  1816. { const,reg }
  1817. { const,const }
  1818. { const,ref }
  1819. OPR_CONSTANT:
  1820. case instr.operands[2].operandtype of
  1821. { constant, constant does not have a specific size. }
  1822. OPR_CONSTANT:
  1823. p^.concat(new(pai386,op_const_const(instruc,
  1824. S_NO,operands[1].val,operands[2].val)));
  1825. OPR_REFERENCE:
  1826. Begin
  1827. { check for suffix first ... }
  1828. if (instr.stropsize <> S_NO) then
  1829. Begin
  1830. p^.concat(new(pai386,op_const_ref(instruc,
  1831. stropsize,operands[1].val,
  1832. newreference(operands[2].ref))))
  1833. end
  1834. else
  1835. { resort to intel styled checking ... }
  1836. if (operands[1].val <= $ff) and
  1837. (operands[2].size in [S_B,S_W,S_L]) then
  1838. p^.concat(new(pai386,op_const_ref(instruc,
  1839. operands[2].size,operands[1].val,
  1840. newreference(operands[2].ref))))
  1841. else
  1842. if (operands[1].val <= $ffff) and
  1843. (operands[2].size in [S_W,S_L]) then
  1844. p^.concat(new(pai386,op_const_ref(instruc,
  1845. operands[2].size,operands[1].val,
  1846. newreference(operands[2].ref))))
  1847. else
  1848. if (operands[1].val <= $7fffffff) and
  1849. (operands[2].size in [S_L]) then
  1850. p^.concat(new(pai386,op_const_ref(instruc,
  1851. operands[2].size,operands[1].val,
  1852. newreference(operands[2].ref))))
  1853. else
  1854. Message(assem_e_invalid_size_in_ref);
  1855. end;
  1856. OPR_REGISTER:
  1857. Begin
  1858. { size of opcode determined by register }
  1859. if (operands[1].val <= $ff) and
  1860. (operands[2].size in [S_B,S_W,S_L]) then
  1861. p^.concat(new(pai386,op_const_reg(instruc,
  1862. operands[2].size,operands[1].val,
  1863. operands[2].reg)))
  1864. else
  1865. if (operands[1].val <= $ffff) and
  1866. (operands[2].size in [S_W,S_L]) then
  1867. p^.concat(new(pai386,op_const_reg(instruc,
  1868. operands[2].size,operands[1].val,
  1869. operands[2].reg)))
  1870. else
  1871. if (operands[1].val <= $7fffffff) and
  1872. (operands[2].size in [S_L]) then
  1873. p^.concat(new(pai386,op_const_reg(instruc,
  1874. operands[2].size,operands[1].val,
  1875. operands[2].reg)))
  1876. else
  1877. Message(assem_e_invalid_opcode_size);
  1878. end;
  1879. else
  1880. Begin
  1881. Message(assem_f_internal_error_in_concatopcode);
  1882. end;
  1883. end; { end case }
  1884. { sym,reg }
  1885. OPR_SYMBOL:
  1886. case instr.operands[2].operandtype of
  1887. OPR_REGISTER:
  1888. Begin
  1889. Case instruc of
  1890. A_LDS,A_LES,A_LFS,A_LGS,A_LSS:
  1891. opsize:=S_NO
  1892. else
  1893. if stropsize<>S_NO then
  1894. opsize:=stropsize
  1895. else
  1896. if (opsize<>operands[2].size) then
  1897. Message(assem_e_invalid_opcode_and_operand);
  1898. { create an temporary reference }
  1899. End; {case}
  1900. reset_reference(href);
  1901. href.symbol:=stringdup(instr.operands[1].symbol^);
  1902. p^.concat(new(pai386,op_ref_reg(instruc,opsize,
  1903. newreference(href),operands[2].reg)));
  1904. clear_reference(href);
  1905. end;
  1906. else
  1907. Begin
  1908. Message(assem_f_internal_error_in_concatopcode);
  1909. end;
  1910. end; { end inner case }
  1911. { ref,reg }
  1912. { ref,ref }
  1913. OPR_REFERENCE:
  1914. case instr.operands[2].operandtype of
  1915. OPR_REGISTER:
  1916. if assigned(operands[1].ref.symbol) then
  1917. { global variable }
  1918. Begin
  1919. Case instruc Of
  1920. A_LDS,A_LES,A_LFS,A_LGS,A_LSS:
  1921. opsize:=S_NO
  1922. else
  1923. if stropsize<>S_NO then
  1924. opsize:=stropsize
  1925. else
  1926. if (opsize<>operands[2].size) then
  1927. Message(assem_e_invalid_opcode_and_operand);
  1928. end; { case }
  1929. p^.concat(new(pai386,op_ref_reg(instruc,
  1930. opsize,newreference(operands[1].ref),operands[2].reg)));
  1931. end
  1932. else
  1933. Begin
  1934. { register reference }
  1935. { possiblities:1) local variable which }
  1936. { has been replaced by bp and offset }
  1937. { in this case size should be valid }
  1938. { 2) Indirect register }
  1939. { adressing, 2nd operand determines }
  1940. { size. }
  1941. if (stropsize <> S_NO) then
  1942. Begin
  1943. p^.concat(new(pai386,op_ref_reg(instruc,
  1944. stropsize,newreference(operands[1].ref),
  1945. operands[2].reg)))
  1946. end
  1947. else
  1948. if (opsize = operands[2].size) or
  1949. (opsize = S_NO) then
  1950. Begin
  1951. p^.concat(new(pai386,op_ref_reg(instruc,
  1952. operands[2].size,newreference(operands[1].ref),
  1953. operands[2].reg)));
  1954. end
  1955. else
  1956. Message(assem_e_invalid_size_in_ref);
  1957. end;
  1958. OPR_REFERENCE: { special opcodes }
  1959. p^.concat(new(pai386,op_ref_ref(instruc,
  1960. opsize,newreference(operands[1].ref),
  1961. newreference(operands[2].ref))));
  1962. else
  1963. Begin
  1964. Message(assem_f_internal_error_in_concatopcode);
  1965. end;
  1966. end; { end inner case }
  1967. end; { end case }
  1968. end; { end with }
  1969. end; {end else of case instruc of movsx ... }
  1970. end; { end case movsx ...}
  1971. end;
  1972. 3: Begin
  1973. { only imul, shld and shrd }
  1974. { middle must be a register }
  1975. if (instruc = A_SHLD) Or (instruc = A_SHRD) and
  1976. (instr.operands[2].operandtype = OPR_REGISTER) then
  1977. Begin
  1978. case instr.operands[2].size of
  1979. S_W: if instr.operands[1].operandtype = OPR_CONSTANT then
  1980. Begin
  1981. if instr.operands[1].val <= $ff then
  1982. Begin
  1983. if instr.operands[3].size in [S_W] then
  1984. Begin
  1985. case instr.operands[3].operandtype of
  1986. OPR_REFERENCE: { MISSING !!!! } ;
  1987. OPR_REGISTER: p^.concat(new(pai386,
  1988. op_const_reg_reg(instruc, S_W,
  1989. instr.operands[1].val, instr.operands[2].reg,
  1990. instr.operands[3].reg)));
  1991. else
  1992. Message(assem_e_invalid_opcode_and_operand);
  1993. end;
  1994. end
  1995. else
  1996. Message(assem_e_invalid_opcode_and_operand);
  1997. end;
  1998. end
  1999. else
  2000. Message(assem_e_invalid_opcode_and_operand);
  2001. S_L: if instr.operands[1].operandtype = OPR_CONSTANT then
  2002. Begin
  2003. if instr.operands[1].val <= $ff then
  2004. Begin
  2005. if instr.operands[3].size in [S_L] then
  2006. Begin
  2007. case instr.operands[3].operandtype of
  2008. OPR_REFERENCE: { MISSING !!!! } ;
  2009. OPR_REGISTER: p^.concat(new(pai386,
  2010. op_const_reg_reg(instruc, S_L,
  2011. instr.operands[1].val, instr.operands[2].reg,
  2012. instr.operands[3].reg)));
  2013. else
  2014. Message(assem_e_invalid_opcode_and_operand);
  2015. end;
  2016. end
  2017. else
  2018. Message(assem_e_invalid_opcode_and_operand);
  2019. end;
  2020. end
  2021. else
  2022. Message(assem_e_invalid_opcode_and_operand);
  2023. else
  2024. Message(assem_e_invalid_opcode_and_operand);
  2025. end; { end case }
  2026. end
  2027. else
  2028. if (instruc = A_IMUL) and (instr.operands[3].operandtype
  2029. = OPR_REGISTER) then
  2030. Begin
  2031. case instr.operands[3].size of
  2032. S_W: if instr.operands[1].operandtype = OPR_CONSTANT then
  2033. Begin
  2034. if instr.operands[1].val <= $ffff then
  2035. Begin
  2036. if instr.operands[2].size in [S_W] then
  2037. Begin
  2038. case instr.operands[2].operandtype of
  2039. OPR_REFERENCE: { MISSING !!!! } ;
  2040. OPR_REGISTER: p^.concat(new(pai386,
  2041. op_const_reg_reg(instruc, S_W,
  2042. instr.operands[1].val, instr.operands[2].reg,
  2043. instr.operands[3].reg)));
  2044. else
  2045. Message(assem_e_invalid_opcode_and_operand);
  2046. end; { end case }
  2047. end
  2048. else
  2049. Message(assem_e_invalid_opcode_and_operand);
  2050. end;
  2051. end
  2052. else
  2053. Message(assem_e_invalid_opcode_and_operand);
  2054. S_L: if instr.operands[1].operandtype = OPR_CONSTANT then
  2055. Begin
  2056. if instr.operands[1].val <= $7fffffff then
  2057. Begin
  2058. if instr.operands[2].size in [S_L] then
  2059. Begin
  2060. case instr.operands[2].operandtype of
  2061. OPR_REFERENCE: { MISSING !!!! } ;
  2062. OPR_REGISTER: p^.concat(new(pai386,
  2063. op_const_reg_reg(instruc, S_L,
  2064. instr.operands[1].val, instr.operands[2].reg,
  2065. instr.operands[3].reg)));
  2066. else
  2067. Message(assem_e_invalid_opcode_and_operand);
  2068. end; { end case }
  2069. end
  2070. else
  2071. Message(assem_e_invalid_opcode_and_operand);
  2072. end;
  2073. end
  2074. else
  2075. Message(assem_e_invalid_opcode_and_operand);
  2076. else
  2077. Message(assem_e_invalid_middle_sized_operand);
  2078. end; { end case }
  2079. end { endif }
  2080. else
  2081. Message(assem_e_invalid_three_operand_opcode);
  2082. end;
  2083. end; { end case }
  2084. end;
  2085. end;
  2086. Procedure ConcatLabeledInstr(var instr: TInstruction);
  2087. Var instruct : tasmop;
  2088. i : longint;
  2089. Begin
  2090. instruct:=instr.getinstruction;
  2091. Case instruct Of
  2092. A_JO,A_JNO,A_JB,A_JC,A_JNAE,
  2093. A_JNB,A_JNC,A_JAE,A_JE,A_JZ,A_JNE,A_JNZ,A_JBE,A_JNA,A_JNBE,
  2094. A_JA,A_JS,A_JNS,A_JP,A_JPE,A_JNP,A_JPO,A_JL,A_JNGE,A_JNL,A_JGE,
  2095. A_JLE,A_JNG,A_JNLE,A_JG,A_JCXZ,A_JECXZ,A_LOOP,A_LOOPZ,A_LOOPE,
  2096. A_LOOPNZ,A_LOOPNE,A_JMP,A_CALL:
  2097. Begin
  2098. if (instr.numops <> 1) then
  2099. Message(assem_e_invalid_labeled_opcode)
  2100. else if instr.operands[1].operandtype <> OPR_LABINSTR then
  2101. Message(assem_e_invalid_labeled_opcode)
  2102. else if assigned(instr.operands[1].hl) then
  2103. ConcatLabel(p,instruct, instr.operands[1].hl)
  2104. else
  2105. Begin
  2106. Message(assem_f_internal_error_in_concatlabeledinstr);
  2107. end;
  2108. end;
  2109. A_MOV: { move from/to rel8 };
  2110. else
  2111. if (cs_compilesystem in aktmoduleswitches) then
  2112. begin
  2113. for i:=1 to instr.numops do
  2114. if instr.operands[i].operandtype=OPR_LABINSTR then
  2115. begin
  2116. instr.operands[i].operandtype:=OPR_REFERENCE;
  2117. instr.operands[i].ref.symbol:=newpasstr(lab2str(instr.operands[i].hl) );
  2118. instr.operands[i].opinfo:=ao_mem;
  2119. instr.operands[i].ref.base:=R_NO;
  2120. instr.operands[i].ref.index:=R_NO;
  2121. instr.operands[i].ref.segment:=R_DEFAULT_SEG;
  2122. instr.operands[i].ref.offset:=0;
  2123. end;
  2124. { handle now as an ordinary opcode }
  2125. concatopcode(instr);
  2126. end
  2127. else
  2128. Message1(assem_e_invalid_operand,'');
  2129. end; { case }
  2130. end;
  2131. {---------------------------------------------------------------------}
  2132. { Routines for the parsing }
  2133. {---------------------------------------------------------------------}
  2134. procedure consume(t : tinteltoken);
  2135. begin
  2136. if t<>actasmtoken then
  2137. Message(assem_e_syntax_error);
  2138. actasmtoken:=gettoken;
  2139. { set the previous id flag }
  2140. previous_was_id:=(actasmtoken=AS_ID);
  2141. { if the token must be ignored, then }
  2142. { get another token to parse. }
  2143. if actasmtoken = AS_NONE then
  2144. actasmtoken := gettoken;
  2145. end;
  2146. function findregister(const s : string): tregister;
  2147. {*********************************************************************}
  2148. { FUNCTION findregister(s: string):tasmop; }
  2149. { Description: Determines if the s string is a valid register, }
  2150. { if so returns correct tregister token, or R_NO if not found. }
  2151. {*********************************************************************}
  2152. var
  2153. i: tregister;
  2154. begin
  2155. findregister := R_NO;
  2156. for i:=firstreg to lastreg do
  2157. if s = iasmregs[i] then
  2158. Begin
  2159. findregister := i;
  2160. exit;
  2161. end;
  2162. end;
  2163. function findprefix(const s: string; var token: tasmop): boolean;
  2164. var i: byte;
  2165. Begin
  2166. findprefix := FALSE;
  2167. for i:=0 to _count_asmprefixes do
  2168. Begin
  2169. if s = _asmprefixes[i] then
  2170. begin
  2171. token := _prefixtokens[i];
  2172. findprefix := TRUE;
  2173. exit;
  2174. end;
  2175. end;
  2176. end;
  2177. function findsegment(const s:string): tregister;
  2178. {*********************************************************************}
  2179. { FUNCTION findsegment(s: string):tasmop; }
  2180. { Description: Determines if the s string is a valid segment register}
  2181. { if so returns correct tregister token, or R_NO if not found. }
  2182. {*********************************************************************}
  2183. var
  2184. i: tregister;
  2185. Begin
  2186. findsegment := R_DEFAULT_SEG;
  2187. for i:=firstsreg to lastsreg do
  2188. if s = iasmregs[i] then
  2189. Begin
  2190. findsegment := i;
  2191. exit;
  2192. end;
  2193. end;
  2194. function findopcode(const s: string): tasmop;
  2195. {*********************************************************************}
  2196. { FUNCTION findopcode(s: string): tasmop; }
  2197. { Description: Determines if the s string is a valid opcode }
  2198. { if so returns correct tasmop token. }
  2199. {*********************************************************************}
  2200. var
  2201. i: tasmop;
  2202. j: byte;
  2203. hs: topsize;
  2204. hid: string;
  2205. Begin
  2206. findopcode := A_NONE;
  2207. { first search for extended opcodes }
  2208. { now, in this case, we must use the suffix }
  2209. { to determine the size of the instruction }
  2210. for j:=0 to _count_asmspecialops do
  2211. Begin
  2212. if s = _specialops[j] then
  2213. Begin
  2214. findopcode := _specialopstokens[j];
  2215. { set the size }
  2216. case s[length(s)] of
  2217. 'B': instr.stropsize := S_B;
  2218. 'L': instr.stropsize := S_L;
  2219. 'W': instr.stropsize := S_W;
  2220. end;
  2221. exit;
  2222. end;
  2223. end;
  2224. for i:=firstop to lastop do
  2225. Begin
  2226. if s=iasmops^[i] then
  2227. begin
  2228. findopcode := i;
  2229. instr.stropsize := S_NO;
  2230. exit;
  2231. end;
  2232. end;
  2233. { not found yet ... }
  2234. { search for all possible suffixes }
  2235. for hs:=S_WL downto S_B do
  2236. if copy(s,length(s)-length(att_opsize2str[hs])+1,
  2237. length(att_opsize2str[hs]))=upper(att_opsize2str[hs]) then
  2238. begin
  2239. hid:=copy(s,1,length(s)-length(att_opsize2str[hs]));
  2240. for i:=firstop to lastop do
  2241. if (length(hid) > 0) and (hid=iasmops^[i]) then
  2242. begin
  2243. findopcode := i;
  2244. instr.stropsize := hs;
  2245. exit;
  2246. end;
  2247. end;
  2248. end;
  2249. Function CheckPrefix(prefix: tasmop; opcode:tasmop): Boolean;
  2250. { Checks if the prefix is valid with the following instruction }
  2251. { return false if not, otherwise true }
  2252. Begin
  2253. CheckPrefix := TRUE;
  2254. Case prefix of
  2255. A_REP,A_REPNE,A_REPE:
  2256. Case opcode Of
  2257. A_SCAS,A_INS,A_OUTS,A_MOVS,
  2258. A_CMPS,A_LODS,A_STOS:;
  2259. Else
  2260. Begin
  2261. CheckPrefix := FALSE;
  2262. exit;
  2263. end;
  2264. End;
  2265. A_LOCK:
  2266. Case opcode Of
  2267. A_BT,A_BTS,A_BTR,A_BTC,A_XCHG,A_ADD,A_OR,
  2268. A_ADC,A_SBB,A_AND,A_SUB,A_XOR,A_NOT,A_NEG,A_INC,A_DEC:;
  2269. Else
  2270. Begin
  2271. CheckPrefix := FALSE;
  2272. Exit;
  2273. end;
  2274. End;
  2275. A_NONE: exit; { no prefix here }
  2276. else
  2277. CheckPrefix := FALSE;
  2278. end; { end case }
  2279. end;
  2280. Procedure InitAsmRef(var instr: TInstruction);
  2281. {*********************************************************************}
  2282. { Description: This routine first check if the instruction is of }
  2283. { type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
  2284. { If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
  2285. { the operand type to OPR_REFERENCE, as well as setting up the ref }
  2286. { to point to the default segment. }
  2287. {*********************************************************************}
  2288. Begin
  2289. With instr do
  2290. Begin
  2291. case operands[operandnum].operandtype of
  2292. OPR_REFERENCE: exit;
  2293. OPR_NONE: ;
  2294. else
  2295. Message(assem_e_invalid_operand_type);
  2296. end;
  2297. operands[operandnum].operandtype := OPR_REFERENCE;
  2298. operands[operandnum].ref.segment := R_DEFAULT_SEG;
  2299. end;
  2300. end;
  2301. Function CheckOverride(segreg: tregister; var instr: TInstruction): Boolean;
  2302. { Check if the override is valid, and if so then }
  2303. { update the instr variable accordingly. }
  2304. Begin
  2305. CheckOverride := FALSE;
  2306. Case instr.getinstruction of
  2307. A_MOVS,A_XLAT,A_CMPS:
  2308. Begin
  2309. CheckOverride := TRUE;
  2310. Message(assem_e_segment_override_not_supported);
  2311. end
  2312. end
  2313. end;
  2314. Procedure GetRecordOffsetSize(const expr: string;var offset:longint;var size:longint);
  2315. {*********************************************************************}
  2316. { PROCEDURE GetRecordOffsetSize }
  2317. { Description: This routine builds up a record offset after a AS_DOT }
  2318. { token is encountered. }
  2319. { On entry actasmtoken should be equal to AS_DOT }
  2320. {*********************************************************************}
  2321. { EXIT CONDITION: On exit the routine should point to either the }
  2322. { ERROR RECOVER: read until AS_COMMA or AS_SEPARATOR token. }
  2323. { Warning: This is called recursively. }
  2324. {*********************************************************************}
  2325. var
  2326. toffset,tsize : longint;
  2327. Begin
  2328. offset:=0;
  2329. size:=0;
  2330. Consume(AS_DOT);
  2331. if actasmtoken = AS_ID then
  2332. Begin
  2333. if not GetTypeOffsetSize(expr,actasmpattern,toffset,tsize) and
  2334. not GetVarOffsetSize(expr,actasmpattern,toffset,tsize) then
  2335. begin
  2336. Message(assem_e_syntax_error);
  2337. toffset:=0;
  2338. tsize:=0;
  2339. end;
  2340. inc(offset,toffset);
  2341. size:=tsize;
  2342. Consume(AS_ID);
  2343. if actasmtoken=AS_DOT then
  2344. begin
  2345. GetRecordOffsetSize(expr,toffset,tsize);
  2346. inc(offset,toffset);
  2347. size:=tsize;
  2348. end;
  2349. end
  2350. else
  2351. Begin
  2352. Message(assem_e_syntax_error);
  2353. repeat
  2354. consume(actasmtoken)
  2355. until (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA);
  2356. end;
  2357. end;
  2358. Function BuildConstExpression(allowref,betweenbracket:boolean): longint;
  2359. {*********************************************************************}
  2360. { FUNCTION BuildConstExpression: longint }
  2361. { Description: This routine calculates a constant expression to }
  2362. { a given value. The return value is the value calculated from }
  2363. { the expression. }
  2364. { The following tokens (not strings) are recognized: }
  2365. { (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
  2366. {*********************************************************************}
  2367. { ENTRY: On entry the token should be any valid expression token. }
  2368. { EXIT: On Exit the token points to any token after the closing }
  2369. { RBRACKET }
  2370. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2371. { invalid tokens. }
  2372. {*********************************************************************}
  2373. var
  2374. tempstr,expr : string;
  2375. parenlevel,l,k : longint;
  2376. errorflag : boolean;
  2377. prevtoken : tinteltoken;
  2378. Begin
  2379. errorflag := FALSE;
  2380. tempstr := '';
  2381. expr := '';
  2382. inexpression := TRUE;
  2383. prevtoken := AS_NONE;
  2384. parenlevel := 0;
  2385. Repeat
  2386. if actasmtoken<>AS_LPAREN then
  2387. prevtoken:=actasmtoken;
  2388. Case actasmtoken of
  2389. AS_LPAREN:
  2390. Begin
  2391. { Exit if ref? }
  2392. if allowref and (prevtoken in [AS_INTNUM,AS_BINNUM,AS_OCTALNUM,AS_ID,AS_HEXNUM]) then
  2393. break;
  2394. Consume(AS_LPAREN);
  2395. expr := expr + '(';
  2396. inc(parenlevel);
  2397. end;
  2398. AS_RPAREN:
  2399. Begin
  2400. { end of ref ? }
  2401. if (parenlevel=0) and betweenbracket then
  2402. break;
  2403. Consume(AS_RPAREN);
  2404. expr := expr + ')';
  2405. dec(parenlevel);
  2406. end;
  2407. AS_SHL:
  2408. Begin
  2409. Consume(AS_SHL);
  2410. expr := expr + '<';
  2411. end;
  2412. AS_SHR:
  2413. Begin
  2414. Consume(AS_SHR);
  2415. expr := expr + '>';
  2416. end;
  2417. AS_SLASH:
  2418. Begin
  2419. Consume(AS_SLASH);
  2420. expr := expr + '/';
  2421. end;
  2422. AS_MOD:
  2423. Begin
  2424. Consume(AS_MOD);
  2425. expr := expr + '%';
  2426. end;
  2427. AS_STAR:
  2428. Begin
  2429. Consume(AS_STAR);
  2430. expr := expr + '*';
  2431. end;
  2432. AS_PLUS:
  2433. Begin
  2434. Consume(AS_PLUS);
  2435. expr := expr + '+';
  2436. end;
  2437. AS_MINUS:
  2438. Begin
  2439. Consume(AS_MINUS);
  2440. expr := expr + '-';
  2441. end;
  2442. AS_AND:
  2443. Begin
  2444. Consume(AS_AND);
  2445. expr := expr + '&';
  2446. end;
  2447. AS_NOT:
  2448. Begin
  2449. Consume(AS_NOT);
  2450. expr := expr + '~';
  2451. end;
  2452. AS_XOR:
  2453. Begin
  2454. Consume(AS_XOR);
  2455. expr := expr + '^';
  2456. end;
  2457. AS_OR:
  2458. Begin
  2459. Consume(AS_OR);
  2460. expr := expr + '|';
  2461. end;
  2462. AS_INTNUM:
  2463. Begin
  2464. expr := expr + actasmpattern;
  2465. Consume(AS_INTNUM);
  2466. end;
  2467. AS_BINNUM:
  2468. Begin
  2469. expr:=expr+BinaryToDec(actasmpattern);
  2470. Consume(AS_BINNUM);
  2471. end;
  2472. AS_HEXNUM:
  2473. Begin
  2474. expr:=expr+HexToDec(actasmpattern);
  2475. Consume(AS_HEXNUM);
  2476. end;
  2477. AS_OCTALNUM:
  2478. Begin
  2479. expr:=expr+OctalToDec(actasmpattern);
  2480. Consume(AS_OCTALNUM);
  2481. end;
  2482. AS_ID:
  2483. Begin
  2484. tempstr:=actasmpattern;
  2485. consume(AS_ID);
  2486. if actasmtoken=AS_DOT then
  2487. begin
  2488. GetRecordOffsetSize(tempstr,l,k);
  2489. str(l, tempstr);
  2490. expr := expr + tempstr;
  2491. end
  2492. else
  2493. begin
  2494. if SearchIConstant(tempstr,l) then
  2495. begin
  2496. str(l, tempstr);
  2497. expr := expr + tempstr;
  2498. end
  2499. else
  2500. Message1(assem_e_invalid_const_symbol,tempstr);
  2501. end;
  2502. end;
  2503. AS_SEPARATOR,
  2504. AS_COMMA:
  2505. Begin
  2506. break;
  2507. end;
  2508. else
  2509. Begin
  2510. { write error only once. }
  2511. if not errorflag then
  2512. Message(assem_e_invalid_constant_expression);
  2513. BuildConstExpression := 0;
  2514. if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
  2515. exit;
  2516. { consume tokens until we find COMMA or SEPARATOR }
  2517. Consume(actasmtoken);
  2518. errorflag := TRUE;
  2519. end;
  2520. end;
  2521. Until false;
  2522. { calculate expression }
  2523. if not ErrorFlag then
  2524. BuildConstExpression := CalculateExpression(expr)
  2525. else
  2526. BuildConstExpression := 0;
  2527. { no longer in an expression }
  2528. inexpression := FALSE;
  2529. end;
  2530. Procedure BuildRealConstant(typ : tfloattype);
  2531. {*********************************************************************}
  2532. { PROCEDURE BuilRealConst }
  2533. { Description: This routine calculates a constant expression to }
  2534. { a given value. The return value is the value calculated from }
  2535. { the expression. }
  2536. { The following tokens (not strings) are recognized: }
  2537. { +/-,numbers and real numbers }
  2538. {*********************************************************************}
  2539. { ENTRY: On entry the token should be any valid expression token. }
  2540. { EXIT: On Exit the token points to either COMMA or SEPARATOR }
  2541. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2542. { invalid tokens. }
  2543. {*********************************************************************}
  2544. var expr: string;
  2545. tempstr: string;
  2546. r : bestreal;
  2547. code : word;
  2548. negativ : boolean;
  2549. errorflag: boolean;
  2550. Begin
  2551. errorflag := FALSE;
  2552. Repeat
  2553. negativ:=false;
  2554. expr := '';
  2555. tempstr := '';
  2556. if actasmtoken=AS_PLUS then Consume(AS_PLUS)
  2557. else if actasmtoken=AS_MINUS then
  2558. begin
  2559. negativ:=true;
  2560. consume(AS_MINUS);
  2561. end;
  2562. Case actasmtoken of
  2563. AS_INTNUM: Begin
  2564. expr := actasmpattern;
  2565. Consume(AS_INTNUM);
  2566. end;
  2567. AS_REALNUM: Begin
  2568. expr := actasmpattern;
  2569. { in ATT syntax you have 0d in front of the real }
  2570. { should this be forced ? yes i think so, as to }
  2571. { conform to gas as much as possible. }
  2572. if (expr[1]='0') and (upper(expr[2])='D') then
  2573. expr:=copy(expr,3,255);
  2574. Consume(AS_REALNUM);
  2575. end;
  2576. AS_BINNUM: Begin
  2577. { checking for real constants with this should use }
  2578. { real DECODING otherwise the compiler will crash! }
  2579. Message(assem_w_float_bin_ignored);
  2580. Consume(AS_BINNUM);
  2581. end;
  2582. AS_HEXNUM: Begin
  2583. { checking for real constants with this should use }
  2584. { real DECODING otherwise the compiler will crash! }
  2585. Message(assem_w_float_hex_ignored);
  2586. Consume(AS_HEXNUM);
  2587. end;
  2588. AS_OCTALNUM: Begin
  2589. { checking for real constants with this should use }
  2590. { real DECODING otherwise the compiler will crash! }
  2591. { xxxToDec using reals could be a solution, but the }
  2592. { problem is that these will crash the m68k compiler }
  2593. { when compiling -- because of lack of good fpu }
  2594. { support. }
  2595. Message(assem_w_float_octal_ignored);
  2596. Consume(AS_OCTALNUM);
  2597. end;
  2598. else
  2599. Begin
  2600. { only write error once. }
  2601. if not errorflag then
  2602. Message(assem_e_invalid_real_const);
  2603. { consume tokens until we find COMMA or SEPARATOR }
  2604. Consume(actasmtoken);
  2605. errorflag := TRUE;
  2606. End;
  2607. end;
  2608. { go to next term }
  2609. if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
  2610. Begin
  2611. if negativ then expr:='-'+expr;
  2612. val(expr,r,code);
  2613. if code<>0 then
  2614. Begin
  2615. r:=0;
  2616. Message(assem_e_invalid_real_const);
  2617. ConcatRealConstant(p,r,typ);
  2618. End
  2619. else
  2620. Begin
  2621. ConcatRealConstant(p,r,typ);
  2622. End;
  2623. end
  2624. else
  2625. Message(assem_e_invalid_real_const);
  2626. Until actasmtoken=AS_SEPARATOR;
  2627. end;
  2628. Procedure BuildReference(var Instr: TInstruction);
  2629. {*********************************************************************}
  2630. { PROCEDURE BuildReference }
  2631. { Description: This routine builds up an expression after a LPAREN }
  2632. { token is encountered. }
  2633. { On entry actasmtoken should be equal to AS_LPAREN }
  2634. {*********************************************************************}
  2635. { EXIT CONDITION: On exit the routine should point to either the }
  2636. { AS_COMMA or AS_SEPARATOR token. }
  2637. {*********************************************************************}
  2638. procedure Consume_RParen;
  2639. begin
  2640. if actasmtoken <> AS_RPAREN then
  2641. Begin
  2642. Message(assem_e_invalid_reference);
  2643. while actasmtoken <> AS_SEPARATOR do
  2644. Consume(actasmtoken);
  2645. end
  2646. else
  2647. begin
  2648. Consume(AS_RPAREN);
  2649. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  2650. Begin
  2651. Message(assem_e_invalid_reference);
  2652. { error recovery ... }
  2653. while actasmtoken <> AS_SEPARATOR do
  2654. Consume(actasmtoken);
  2655. end;
  2656. end;
  2657. end;
  2658. var
  2659. l:longint;
  2660. Begin
  2661. Consume(AS_LPAREN);
  2662. initAsmRef(instr);
  2663. Case actasmtoken of
  2664. AS_HEXNUM,
  2665. AS_INTNUM,
  2666. AS_BINNUM,
  2667. AS_OCTALNUM,
  2668. AS_MINUS,
  2669. AS_PLUS: { absolute offset, such as fs:(0x046c) }
  2670. Begin
  2671. { offset(offset) is invalid }
  2672. If Instr.Operands[OperandNum].Ref.Offset <> 0 Then
  2673. Begin
  2674. Message(assem_e_invalid_reference);
  2675. while actasmtoken <> AS_SEPARATOR do
  2676. Consume(actasmtoken);
  2677. End
  2678. Else
  2679. Begin
  2680. Instr.Operands[OperandNum].Ref.Offset := BuildConstExpression(false,true);
  2681. Consume_RParen;
  2682. end;
  2683. exit;
  2684. End;
  2685. AS_REGISTER: { (reg ... }
  2686. Begin
  2687. { Check if there is already a base (mostly ebp,esp) than this is
  2688. not allowed,becuase it will give crashing code }
  2689. if instr.operands[operandnum].ref.base<>R_NO then
  2690. Message(assem_e_cannot_index_relative_var);
  2691. instr.operands[operandnum].ref.base := findregister(actasmpattern);
  2692. Consume(AS_REGISTER);
  2693. { can either be a register or a right parenthesis }
  2694. { (reg) }
  2695. if actasmtoken=AS_RPAREN then
  2696. Begin
  2697. Consume_RParen;
  2698. exit;
  2699. end;
  2700. { (reg,reg .. }
  2701. Consume(AS_COMMA);
  2702. if actasmtoken=AS_REGISTER then
  2703. Begin
  2704. instr.operands[operandnum].ref.index := findregister(actasmpattern);
  2705. Consume(AS_REGISTER);
  2706. { check for scaling ... }
  2707. case actasmtoken of
  2708. AS_RPAREN:
  2709. Begin
  2710. Consume_RParen;
  2711. exit;
  2712. end;
  2713. AS_COMMA:
  2714. Begin
  2715. Consume(AS_COMMA);
  2716. { we have to process the scaling }
  2717. l:=BuildConstExpression(false,true);
  2718. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  2719. instr.operands[operandnum].ref.scalefactor := l
  2720. else
  2721. Begin
  2722. Message(assem_e_invalid_scaling_value);
  2723. instr.operands[operandnum].ref.scalefactor := 0;
  2724. end;
  2725. Consume_RParen;
  2726. end;
  2727. else
  2728. Begin
  2729. Message(assem_e_invalid_reference_syntax);
  2730. while (actasmtoken <> AS_SEPARATOR) do
  2731. Consume(actasmtoken);
  2732. end;
  2733. end; { end case }
  2734. end
  2735. else
  2736. Begin
  2737. Message(assem_e_invalid_reference_syntax);
  2738. while (actasmtoken <> AS_SEPARATOR) do
  2739. Consume(actasmtoken);
  2740. end;
  2741. end; {end case }
  2742. AS_COMMA: { (, ... can either be scaling, or index }
  2743. Begin
  2744. Consume(AS_COMMA);
  2745. { Index }
  2746. if (actasmtoken=AS_REGISTER) then
  2747. Begin
  2748. instr.operands[operandnum].ref.index := findregister(actasmpattern);
  2749. Consume(AS_REGISTER);
  2750. { check for scaling ... }
  2751. case actasmtoken of
  2752. AS_RPAREN:
  2753. Begin
  2754. Consume_RParen;
  2755. exit;
  2756. end;
  2757. AS_COMMA:
  2758. Begin
  2759. Consume(AS_COMMA);
  2760. { we have to process the scaling }
  2761. l:=BuildConstExpression(false,true);
  2762. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  2763. instr.operands[operandnum].ref.scalefactor := l
  2764. else
  2765. Begin
  2766. Message(assem_e_invalid_scaling_value);
  2767. instr.operands[operandnum].ref.scalefactor := 0;
  2768. end;
  2769. Consume_RParen;
  2770. end;
  2771. else
  2772. Begin
  2773. Message(assem_e_invalid_reference_syntax);
  2774. while (actasmtoken <> AS_SEPARATOR) do
  2775. Consume(actasmtoken);
  2776. end;
  2777. end; {end case }
  2778. end
  2779. { Scaling }
  2780. else
  2781. Begin
  2782. l:=BuildConstExpression(false,true);
  2783. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  2784. instr.operands[operandnum].ref.scalefactor := l
  2785. else
  2786. Begin
  2787. Message(assem_e_invalid_scaling_value);
  2788. instr.operands[operandnum].ref.scalefactor := 0;
  2789. end;
  2790. Consume_RParen;
  2791. exit;
  2792. end;
  2793. end;
  2794. else
  2795. Begin
  2796. Message(assem_e_invalid_reference_syntax);
  2797. while (actasmtoken <> AS_SEPARATOR) do
  2798. Consume(actasmtoken);
  2799. end;
  2800. end; { end case }
  2801. end;
  2802. Procedure BuildOperand(var instr: TInstruction);
  2803. {*********************************************************************}
  2804. { EXIT CONDITION: On exit the routine should point to either the }
  2805. { AS_COMMA or AS_SEPARATOR token. }
  2806. {*********************************************************************}
  2807. var
  2808. tempstr: string;
  2809. expr: string;
  2810. lab: Pasmlabel;
  2811. hl: plabel;
  2812. tsize,l,
  2813. toffset : longint;
  2814. Begin
  2815. tempstr := '';
  2816. expr := '';
  2817. case actasmtoken of
  2818. AS_LPAREN: { Memory reference or constant expression }
  2819. Begin
  2820. initAsmRef(instr);
  2821. BuildReference(instr);
  2822. end;
  2823. AS_DOLLAR: { Constant expression }
  2824. Begin
  2825. Consume(AS_DOLLAR);
  2826. if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_CONSTANT]) then
  2827. Message(assem_e_invalid_operand_type);
  2828. { identifiers are handled by BuildExpression }
  2829. instr.operands[operandnum].operandtype := OPR_CONSTANT;
  2830. instr.operands[operandnum].val :=BuildConstExpression(False,False);
  2831. end;
  2832. AS_HEXNUM,AS_INTNUM,AS_MINUS,
  2833. AS_BINNUM,AS_OCTALNUM,AS_PLUS:
  2834. Begin
  2835. { Constant memory offset }
  2836. { This must absolutely be followed by ( }
  2837. InitAsmRef(instr);
  2838. instr.operands[operandnum].ref.offset:=BuildConstExpression(True,False);
  2839. if actasmtoken<>AS_LPAREN then
  2840. Message(assem_e_invalid_reference_syntax)
  2841. else
  2842. BuildReference(instr);
  2843. end;
  2844. AS_STAR: { Call from memory address }
  2845. Begin
  2846. Consume(AS_STAR);
  2847. InitAsmRef(instr);
  2848. if not CreateVarInstr(instr,actasmpattern,operandnum) then
  2849. Message(assem_e_syn_opcode_operand);
  2850. end;
  2851. AS_ID: { A constant expression, or a Variable ref. }
  2852. Begin
  2853. { Local label ? }
  2854. if (actasmpattern[1] ='.') and (actasmpattern[2] = 'L') then
  2855. Begin
  2856. delete(actasmpattern,1,2);
  2857. if actasmpattern = '' then
  2858. Message(assem_e_null_label_ref_not_allowed);
  2859. lab := labellist.search(actasmpattern);
  2860. { check if the label is already defined }
  2861. { if so, we then check if the plabel is }
  2862. { non-nil, if so we add it to instruction }
  2863. if assigned(lab) then
  2864. Begin
  2865. if assigned(lab^.lab) then
  2866. Begin
  2867. instr.operands[operandnum].operandtype := OPR_LABINSTR;
  2868. instr.operands[operandnum].hl := lab^.lab;
  2869. instr.labeled := TRUE;
  2870. end;
  2871. end
  2872. else
  2873. Begin
  2874. { the label does not exist, create it }
  2875. { emit the opcode, but set that the }
  2876. { label has not been emitted }
  2877. getlabel(hl);
  2878. labellist.insert(actasmpattern,hl,FALSE);
  2879. instr.operands[operandnum].operandtype := OPR_LABINSTR;
  2880. instr.operands[operandnum].hl := hl;
  2881. instr.labeled := TRUE;
  2882. end;
  2883. Consume(AS_ID);
  2884. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  2885. Begin
  2886. Message(assem_e_syntax_error);
  2887. end;
  2888. end
  2889. else
  2890. { probably a variable or normal expression }
  2891. { or a procedure (such as in CALL ID) }
  2892. Begin
  2893. { check if this is a label, if so then }
  2894. { emit it as a label. }
  2895. if SearchLabel(actasmpattern,hl) then
  2896. Begin
  2897. instr.operands[operandnum].operandtype := OPR_LABINSTR;
  2898. instr.operands[operandnum].hl := hl;
  2899. instr.labeled := TRUE;
  2900. Consume(AS_ID);
  2901. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  2902. Message(assem_e_syntax_error);
  2903. end
  2904. else
  2905. { is it a normal variable ? }
  2906. Begin
  2907. { context for scanner }
  2908. initAsmRef(instr);
  2909. if not CreateVarInstr(instr,actasmpattern,operandnum) then
  2910. Begin
  2911. { look for special symbols ... }
  2912. if actasmpattern = '__RESULT' then
  2913. SetUpResult(instr,operandnum)
  2914. else
  2915. if actasmpattern = '__SELF' then
  2916. Begin
  2917. if assigned(procinfo._class) then
  2918. Begin
  2919. instr.operands[operandnum].operandtype := OPR_REFERENCE;
  2920. instr.operands[operandnum].ref.offset := procinfo.ESI_offset;
  2921. instr.operands[operandnum].ref.base := procinfo.framepointer;
  2922. end
  2923. else
  2924. Message(assem_e_cannot_use___SELF_outside_methode);
  2925. end
  2926. else
  2927. if actasmpattern = '__OLDEBP' then
  2928. Begin
  2929. if lexlevel>normal_function_level then
  2930. Begin
  2931. instr.operands[operandnum].operandtype := OPR_REFERENCE;
  2932. instr.operands[operandnum].ref.offset := procinfo.framepointer_offset;
  2933. instr.operands[operandnum].ref.base := procinfo.framepointer;
  2934. end
  2935. else
  2936. Message(assem_e_cannot_use___OLDEBP_outside_nested_procedure);
  2937. end
  2938. else
  2939. { check for direct symbolic names }
  2940. { only if compiling the system unit }
  2941. if (cs_compilesystem in aktmoduleswitches) then
  2942. begin
  2943. if not SearchDirectVar(instr,actasmpattern,operandnum) then
  2944. Begin
  2945. { not found, finally ... add it anyways ... }
  2946. Message1(assem_w_id_supposed_external,actasmpattern);
  2947. instr.operands[operandnum].ref.symbol := newpasstr(actasmpattern);
  2948. end;
  2949. end
  2950. else
  2951. Message1(assem_e_unknown_id,actasmpattern);
  2952. end;
  2953. { constant expression? }
  2954. if (instr.operands[operandnum].operandtype=OPR_CONSTANT) then
  2955. begin
  2956. l:=BuildConstExpression(true,false);
  2957. { indexing? }
  2958. if actasmtoken=AS_LPAREN then
  2959. begin
  2960. instr.operands[operandnum].operandtype:=OPR_REFERENCE;
  2961. reset_reference(Instr.Operands[OperandNum].Ref);
  2962. Instr.Operands[OperandNum].Ref.Offset:=l;
  2963. BuildReference(instr);
  2964. end
  2965. else
  2966. Instr.Operands[OperandNum].Val:=l;
  2967. end
  2968. else
  2969. begin
  2970. expr := actasmpattern;
  2971. Consume(AS_ID);
  2972. if actasmtoken=AS_DOT then
  2973. begin
  2974. GetRecordOffsetSize(expr,toffset,tsize);
  2975. inc(instr.operands[operandnum].ref.offset,toffset);
  2976. SetOperandSize(instr,operandnum,tsize);
  2977. end;
  2978. if actasmtoken=AS_LPAREN then
  2979. BuildReference(instr);
  2980. end;
  2981. end; { end if }
  2982. end; { end if }
  2983. end;
  2984. AS_REGISTER: { Register, a variable reference or a constant reference }
  2985. Begin
  2986. { save the type of register used. }
  2987. tempstr := actasmpattern;
  2988. Consume(AS_REGISTER);
  2989. if actasmtoken = AS_COLON then
  2990. Begin
  2991. Consume(AS_COLON);
  2992. initAsmRef(instr);
  2993. instr.operands[operandnum].ref.segment := findsegment(tempstr);
  2994. { here we can have either an identifier }
  2995. { or a constant, where either can be }
  2996. { followed by a parenthesis... }
  2997. { Constant memory offset . }
  2998. { This must absolutely be followed by ( }
  2999. case actasmtoken of
  3000. AS_HEXNUM,AS_INTNUM,AS_MINUS,
  3001. AS_BINNUM,AS_OCTALNUM,AS_PLUS:
  3002. Begin
  3003. instr.operands[operandnum].ref.offset:=BuildConstExpression(True,False);
  3004. if actasmtoken<>AS_LPAREN then
  3005. Message(assem_e_invalid_reference_syntax)
  3006. else
  3007. BuildReference(instr);
  3008. end;
  3009. AS_LPAREN:
  3010. BuildReference(instr);
  3011. AS_ID: { only a variable is allowed ... }
  3012. Begin
  3013. { is it a normal variable ? }
  3014. if not CreateVarInstr(instr,actasmpattern,operandnum) then
  3015. begin
  3016. { check for direct symbolic names }
  3017. { only if compiling the system unit }
  3018. if (cs_compilesystem in aktmoduleswitches) then
  3019. begin
  3020. if not SearchDirectVar(instr,actasmpattern,operandnum) then
  3021. Message(assem_e_invalid_seg_override);
  3022. end
  3023. else
  3024. Message(assem_e_invalid_seg_override);
  3025. end;
  3026. Consume(actasmtoken);
  3027. case actasmtoken of
  3028. AS_SEPARATOR,
  3029. AS_COMMA: ;
  3030. AS_LPAREN: BuildReference(instr);
  3031. else
  3032. Begin
  3033. Message(assem_e_invalid_seg_override);
  3034. Consume(actasmtoken);
  3035. end;
  3036. end; {end case }
  3037. end;
  3038. else
  3039. Begin
  3040. Message(assem_e_invalid_seg_override);
  3041. Consume(actasmtoken);
  3042. end;
  3043. end; { end case }
  3044. end
  3045. { Simple register }
  3046. else if (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  3047. Begin
  3048. if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_REGISTER]) then
  3049. Message(assem_e_invalid_operand_type);
  3050. instr.operands[operandnum].operandtype := OPR_REGISTER;
  3051. instr.operands[operandnum].reg := findregister(tempstr);
  3052. end
  3053. else
  3054. Message1(assem_e_syn_register,tempstr);
  3055. end;
  3056. AS_SEPARATOR,
  3057. AS_COMMA: ;
  3058. else
  3059. Begin
  3060. Message(assem_e_syn_opcode_operand);
  3061. Consume(actasmtoken);
  3062. end;
  3063. end; { end case }
  3064. end;
  3065. Procedure BuildConstant(maxvalue: longint);
  3066. {*********************************************************************}
  3067. { PROCEDURE BuildConstant }
  3068. { Description: This routine takes care of parsing a DB,DD,or DW }
  3069. { line and adding those to the assembler node. Expressions, range- }
  3070. { checking are fullly taken care of. }
  3071. { maxvalue: $ff -> indicates that this is a DB node. }
  3072. { $ffff -> indicates that this is a DW node. }
  3073. { $ffffffff -> indicates that this is a DD node. }
  3074. {*********************************************************************}
  3075. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  3076. {*********************************************************************}
  3077. var
  3078. strlength: byte;
  3079. expr: string;
  3080. value : longint;
  3081. Begin
  3082. Repeat
  3083. Case actasmtoken of
  3084. AS_STRING:
  3085. Begin
  3086. if maxvalue = $ff then
  3087. strlength := 1
  3088. else
  3089. Message(assem_e_string_not_allowed_as_const);
  3090. expr := actasmpattern;
  3091. if length(expr) > 1 then
  3092. Message(assem_e_string_not_allowed_as_const);
  3093. Consume(AS_STRING);
  3094. Case actasmtoken of
  3095. AS_COMMA: Consume(AS_COMMA);
  3096. AS_SEPARATOR: ;
  3097. else
  3098. Message(assem_e_invalid_string_expression);
  3099. end; { end case }
  3100. ConcatString(p,expr);
  3101. end;
  3102. AS_INTNUM,
  3103. AS_BINNUM,
  3104. AS_OCTALNUM,
  3105. AS_HEXNUM,
  3106. AS_PLUS,
  3107. AS_MINUS,
  3108. AS_LPAREN,
  3109. AS_NOT:
  3110. Begin
  3111. value:=BuildConstExpression(false,false);
  3112. ConcatConstant(p,value,maxvalue);
  3113. end;
  3114. AS_COMMA:
  3115. Begin
  3116. Consume(AS_COMMA);
  3117. end;
  3118. AS_SEPARATOR:
  3119. begin
  3120. break;
  3121. end;
  3122. else
  3123. Begin
  3124. Message(assem_f_internal_error_in_buildconstant);
  3125. end;
  3126. end; { end case }
  3127. Until false;
  3128. end;
  3129. Procedure BuildStringConstant(asciiz: boolean);
  3130. {*********************************************************************}
  3131. { PROCEDURE BuildStringConstant }
  3132. { Description: Takes care of a ASCII, or ASCIIZ directive. }
  3133. { asciiz: boolean -> if true then string will be null terminated. }
  3134. {*********************************************************************}
  3135. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  3136. { On ENTRY: Token should point to AS_STRING }
  3137. {*********************************************************************}
  3138. var
  3139. expr: string;
  3140. errorflag : boolean;
  3141. Begin
  3142. errorflag := FALSE;
  3143. Repeat
  3144. Case actasmtoken of
  3145. AS_STRING:
  3146. Begin
  3147. expr:=actasmpattern;
  3148. if asciiz then
  3149. expr:=expr+#0;
  3150. ConcatPasString(p,expr);
  3151. Consume(AS_STRING);
  3152. end;
  3153. AS_COMMA:
  3154. begin
  3155. Consume(AS_COMMA);
  3156. end;
  3157. AS_SEPARATOR:
  3158. begin
  3159. break;
  3160. end;
  3161. else
  3162. Begin
  3163. Consume(actasmtoken);
  3164. if not errorflag then
  3165. Message(assem_e_invalid_string_expression);
  3166. errorflag := TRUE;
  3167. end;
  3168. end;
  3169. Until false;
  3170. end;
  3171. Procedure BuildOpCode;
  3172. {*********************************************************************}
  3173. { PROCEDURE BuildOpcode; }
  3174. { Description: Parses the intel opcode and operands, and writes it }
  3175. { in the TInstruction object. }
  3176. {*********************************************************************}
  3177. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  3178. { On ENTRY: Token should point to AS_OPCODE }
  3179. {*********************************************************************}
  3180. var
  3181. asmtok: tasmop;
  3182. op: tasmop;
  3183. expr: string;
  3184. segreg: tregister;
  3185. Begin
  3186. expr := '';
  3187. asmtok := A_NONE; { assmume no prefix }
  3188. segreg := R_NO; { assume no segment override }
  3189. { prefix seg opcode }
  3190. { prefix opcode }
  3191. if findprefix(actasmpattern,asmtok) then
  3192. Begin
  3193. { standard opcode prefix }
  3194. if asmtok <> A_NONE then
  3195. instr.addprefix(asmtok);
  3196. Consume(AS_OPCODE);
  3197. end;
  3198. { allow for newline as in gas styled syntax }
  3199. { under DOS you get two AS_SEPARATOR !! }
  3200. while actasmtoken=AS_SEPARATOR do
  3201. Consume(AS_SEPARATOR);
  3202. if (actasmtoken <> AS_OPCODE) then
  3203. Begin
  3204. Message(assem_e_invalid_or_missing_opcode);
  3205. { error recovery }
  3206. While not (actasmtoken in [AS_SEPARATOR,AS_COMMA,AS_END]) do
  3207. Consume(actasmtoken);
  3208. exit;
  3209. end
  3210. else
  3211. Begin
  3212. op := findopcode(actasmpattern);
  3213. instr.addinstr(op);
  3214. { Valid combination of prefix and instruction ? }
  3215. if (asmtok <> A_NONE) and (NOT CheckPrefix(asmtok,op)) then
  3216. Message1(assem_e_invalid_prefix_and_opcode,actasmpattern);
  3217. Consume(AS_OPCODE);
  3218. { Zero operand opcode ? }
  3219. if actasmtoken in [AS_SEPARATOR,AS_END] then
  3220. exit
  3221. else
  3222. operandnum := 1;
  3223. end;
  3224. repeat
  3225. case actasmtoken of
  3226. AS_COMMA: { Operand delimiter }
  3227. Begin
  3228. if operandnum > MaxOperands then
  3229. Message(assem_e_too_many_operands)
  3230. else
  3231. Inc(operandnum);
  3232. Consume(AS_COMMA);
  3233. end;
  3234. AS_SEPARATOR,
  3235. AS_END : { End of asm operands for this opcode }
  3236. begin
  3237. break;
  3238. end;
  3239. else
  3240. BuildOperand(instr);
  3241. end; { end case }
  3242. until false;
  3243. end;
  3244. Function Assemble: Ptree;
  3245. {*********************************************************************}
  3246. { PROCEDURE Assemble; }
  3247. { Description: Parses the att assembler syntax, parsing is done }
  3248. { according to GAs rules. }
  3249. {*********************************************************************}
  3250. Var
  3251. hl: plabel;
  3252. labelptr,nextlabel : pasmlabel;
  3253. commname : string;
  3254. store_p : paasmoutput;
  3255. Begin
  3256. Message(assem_d_start_att);
  3257. firsttoken := TRUE;
  3258. operandnum := 0;
  3259. previous_was_id := FALSE;
  3260. if assigned(procinfo.retdef) and
  3261. (is_fpu(procinfo.retdef) or
  3262. ret_in_acc(procinfo.retdef)) then
  3263. procinfo.funcret_is_valid:=true;
  3264. { sets up all opcode and register tables in uppercase }
  3265. if not _asmsorted then
  3266. Begin
  3267. SetupTables;
  3268. _asmsorted := TRUE;
  3269. end;
  3270. p:=new(paasmoutput,init);
  3271. { save pointer code section }
  3272. store_p:=p;
  3273. { setup label linked list }
  3274. labellist.init;
  3275. c:=current_scanner^.asmgetchar;
  3276. actasmtoken:=gettoken;
  3277. repeat
  3278. case actasmtoken of
  3279. AS_LLABEL:
  3280. Begin
  3281. labelptr := labellist.search(actasmpattern);
  3282. if not assigned(labelptr) then
  3283. Begin
  3284. getlabel(hl);
  3285. labellist.insert(actasmpattern,hl,TRUE);
  3286. ConcatLabel(p,A_LABEL,hl);
  3287. end
  3288. else
  3289. Begin
  3290. { the label has already been inserted into the }
  3291. { label list, either as an instruction label (in}
  3292. { this case it has not been emitted), or as a }
  3293. { duplicate local symbol (in this case it has }
  3294. { already been emitted). }
  3295. if labelptr^.emitted then
  3296. Message1(assem_e_dup_local_sym,'.L'+labelptr^.name^)
  3297. else
  3298. Begin
  3299. if assigned(labelptr^.lab) then
  3300. ConcatLabel(p,A_LABEL,labelptr^.lab);
  3301. labelptr^.emitted := TRUE;
  3302. end;
  3303. end;
  3304. Consume(AS_LLABEL);
  3305. end;
  3306. AS_LABEL:
  3307. Begin
  3308. { when looking for Pascal labels, these must }
  3309. { be in uppercase. }
  3310. if SearchLabel(upper(actasmpattern),hl) then
  3311. ConcatLabel(p,A_LABEL, hl)
  3312. else
  3313. Begin
  3314. if (cs_compilesystem in aktmoduleswitches) then
  3315. begin
  3316. Message1(assem_e_unknown_label_identifer,actasmpattern);
  3317. { once again we don't know what it represents }
  3318. { so we simply concatenate it }
  3319. ConcatLocal(p,actasmpattern);
  3320. end
  3321. else
  3322. Message1(assem_e_unknown_label_identifer,actasmpattern);
  3323. end;
  3324. Consume(AS_LABEL);
  3325. end;
  3326. AS_DW:
  3327. Begin
  3328. Consume(AS_DW);
  3329. BuildConstant($ffff);
  3330. end;
  3331. AS_DATA:
  3332. Begin
  3333. { -- this should only be allowed for system development -- }
  3334. { i think this should be fixed in the dos unit, and }
  3335. { not here. }
  3336. if (cs_compilesystem in aktmoduleswitches) then
  3337. p:=datasegment
  3338. else
  3339. Message(assem_e_switching_sections_not_allowed);
  3340. Consume(AS_DATA);
  3341. end;
  3342. AS_TEXT:
  3343. Begin
  3344. { -- this should only be allowed for system development -- }
  3345. { i think this should be fixed in the dos unit, and }
  3346. { not here. }
  3347. if (cs_compilesystem in aktmoduleswitches) then
  3348. p:=store_p
  3349. else
  3350. Message(assem_e_switching_sections_not_allowed);
  3351. Consume(AS_TEXT);
  3352. end;
  3353. AS_DB:
  3354. Begin
  3355. Consume(AS_DB);
  3356. BuildConstant($ff);
  3357. end;
  3358. AS_DD:
  3359. Begin
  3360. Consume(AS_DD);
  3361. BuildConstant($ffffffff);
  3362. end;
  3363. AS_DQ:
  3364. Begin
  3365. Consume(AS_DQ);
  3366. BuildRealConstant(s64bit);
  3367. end;
  3368. AS_SINGLE:
  3369. Begin
  3370. Consume(AS_SINGLE);
  3371. BuildRealConstant(s32real);
  3372. end;
  3373. AS_DOUBLE:
  3374. Begin
  3375. Consume(AS_DOUBLE);
  3376. BuildRealConstant(s64real);
  3377. end;
  3378. AS_EXTENDED:
  3379. Begin
  3380. Consume(AS_EXTENDED);
  3381. BuildRealConstant(s80real);
  3382. end;
  3383. AS_GLOBAL:
  3384. Begin
  3385. { normal units should not be able to declare }
  3386. { direct label names like this... anyhow }
  3387. { procedural calls in asm blocks are }
  3388. { supposedely replaced automatically }
  3389. if (cs_compilesystem in aktmoduleswitches) then
  3390. begin
  3391. Consume(AS_GLOBAL);
  3392. if actasmtoken <> AS_ID then
  3393. Message(assem_e_invalid_global_def)
  3394. else
  3395. ConcatPublic(p,actasmpattern);
  3396. Consume(actasmtoken);
  3397. if actasmtoken <> AS_SEPARATOR then
  3398. Begin
  3399. Message(assem_e_line_separator_expected);
  3400. while actasmtoken <> AS_SEPARATOR do
  3401. Consume(actasmtoken);
  3402. end;
  3403. end
  3404. else
  3405. begin
  3406. Message(assem_w_globl_not_supported);
  3407. while actasmtoken <> AS_SEPARATOR do
  3408. Consume(actasmtoken);
  3409. end;
  3410. end;
  3411. AS_ALIGN:
  3412. Begin
  3413. Message(assem_w_align_not_supported);
  3414. while actasmtoken <> AS_SEPARATOR do
  3415. Consume(actasmtoken);
  3416. end;
  3417. AS_ASCIIZ:
  3418. Begin
  3419. Consume(AS_ASCIIZ);
  3420. BuildStringConstant(TRUE);
  3421. end;
  3422. AS_ASCII:
  3423. Begin
  3424. Consume(AS_ASCII);
  3425. BuildStringConstant(FALSE);
  3426. end;
  3427. AS_LCOMM:
  3428. Begin
  3429. { -- this should only be allowed for system development -- }
  3430. { -- otherwise may mess up future enhancements we might -- }
  3431. { -- add. -- }
  3432. if (cs_compilesystem in aktmoduleswitches) then
  3433. begin
  3434. Consume(AS_LCOMM);
  3435. if actasmtoken <> AS_ID then
  3436. begin
  3437. Message(assem_e_invalid_lcomm_def);
  3438. { error recovery }
  3439. while actasmtoken <> AS_SEPARATOR do
  3440. Consume(actasmtoken);
  3441. end
  3442. else
  3443. begin
  3444. commname:=actasmpattern;
  3445. Consume(AS_COMMA);
  3446. ConcatLocalBss(actasmpattern,BuildConstExpression(false,false));
  3447. if actasmtoken <> AS_SEPARATOR then
  3448. Begin
  3449. Message(assem_e_line_separator_expected);
  3450. while actasmtoken <> AS_SEPARATOR do
  3451. Consume(actasmtoken);
  3452. end;
  3453. end;
  3454. end
  3455. else
  3456. begin
  3457. Message(assem_w_lcomm_not_supported);
  3458. while actasmtoken <> AS_SEPARATOR do
  3459. Consume(actasmtoken);
  3460. end;
  3461. end;
  3462. AS_COMM:
  3463. Begin
  3464. { -- this should only be allowed for system development -- }
  3465. { -- otherwise may mess up future enhancements we might -- }
  3466. { -- add. -- }
  3467. if (cs_compilesystem in aktmoduleswitches) then
  3468. begin
  3469. Consume(AS_COMM);
  3470. if actasmtoken <> AS_ID then
  3471. begin
  3472. Message(assem_e_invalid_comm_def);
  3473. { error recovery }
  3474. while actasmtoken <> AS_SEPARATOR do
  3475. Consume(actasmtoken);
  3476. end
  3477. else
  3478. begin
  3479. commname:=actasmpattern;
  3480. Consume(AS_COMMA);
  3481. ConcatGlobalBss(actasmpattern,BuildConstExpression(false,false));
  3482. if actasmtoken <> AS_SEPARATOR then
  3483. Begin
  3484. Message(assem_e_line_separator_expected);
  3485. while actasmtoken <> AS_SEPARATOR do
  3486. Consume(actasmtoken);
  3487. end;
  3488. end;
  3489. end
  3490. else
  3491. begin
  3492. Message(assem_w_comm_not_supported);
  3493. while actasmtoken <> AS_SEPARATOR do
  3494. Consume(actasmtoken);
  3495. end;
  3496. end;
  3497. AS_OPCODE:
  3498. Begin
  3499. instr.init;
  3500. BuildOpcode;
  3501. instr.numops := operandnum;
  3502. if instr.labeled then
  3503. ConcatLabeledInstr(instr)
  3504. else
  3505. ConcatOpCode(instr);
  3506. instr.done;
  3507. end;
  3508. AS_SEPARATOR:
  3509. Begin
  3510. Consume(AS_SEPARATOR);
  3511. { let us go back to the first operand }
  3512. operandnum := 0;
  3513. end;
  3514. AS_END:
  3515. begin
  3516. break; { end assembly block }
  3517. end;
  3518. else
  3519. Begin
  3520. Message(assem_e_assemble_node_syntax_error);
  3521. { error recovery }
  3522. Consume(actasmtoken);
  3523. end;
  3524. end; { end case }
  3525. until false;
  3526. { check if there were undefined symbols. }
  3527. { if so, then list each of those undefined }
  3528. { labels. }
  3529. if assigned(labellist.First) then
  3530. Begin
  3531. labelptr := labellist.First;
  3532. While labelptr <> nil do
  3533. Begin
  3534. nextlabel:=labelptr^.next;
  3535. if not labelptr^.emitted then
  3536. Message1(assem_e_local_sym_not_found_in_asm_statement,'.L'+labelptr^.name^);
  3537. labelptr:=nextlabel;
  3538. end;
  3539. end;
  3540. if p<>store_p then
  3541. begin
  3542. Message(assem_e_assembler_code_not_returned_to_text);
  3543. p:=store_p;
  3544. end;
  3545. assemble := genasmnode(p);
  3546. labellist.done;
  3547. Message(assem_d_finish_att);
  3548. end;
  3549. var
  3550. old_exit: pointer;
  3551. procedure ra386att_exit;{$ifndef FPC}far;{$endif}
  3552. begin
  3553. if assigned(iasmops) then
  3554. dispose(iasmops);
  3555. exitproc:=old_exit;
  3556. end;
  3557. Begin
  3558. old_exit := exitproc;
  3559. exitproc := @ra386att_exit;
  3560. end.
  3561. {
  3562. $Log$
  3563. Revision 1.30 1999-01-28 14:12:59 pierre
  3564. * bug0175 solved give error on $R+ and warning otherwise
  3565. Revision 1.29 1999/01/10 15:37:54 peter
  3566. * moved some tables from ra386*.pas -> i386.pas
  3567. + start of coff writer
  3568. * renamed asmutils unit to rautils
  3569. Revision 1.28 1998/12/28 15:47:09 peter
  3570. * general constant solution. Constant expressions are now almost
  3571. everywhere allowed and correctly parsed
  3572. Revision 1.27 1998/12/23 22:55:56 peter
  3573. + rec.field(%esi) support
  3574. + [esi+rec.field] support
  3575. Revision 1.26 1998/12/11 00:03:42 peter
  3576. + globtype,tokens,version unit splitted from globals
  3577. Revision 1.25 1998/12/09 13:23:40 jonas
  3578. * replaced two "in [A_...]" constructs I had missed before
  3579. * for shrd/shld: "if operands[1].operandtype = OPR_CONSTANT" instead of
  3580. "if operands[3].operandtype ..."
  3581. Revision 1.24 1998/12/08 23:03:48 jonas
  3582. * allow constant offsets for go32v2 in assembler blocks
  3583. Revision 1.23 1998/12/02 16:23:33 jonas
  3584. * changed "if longintvar in set" to case or "if () or () .." statements
  3585. * tree.pas: changed inlinenumber (and associated constructor/vars) to a byte
  3586. Revision 1.22 1998/11/29 12:47:21 peter
  3587. * fixes for 'asm sti end;'
  3588. Revision 1.21 1998/11/16 15:38:54 peter
  3589. * fixed instruct not in table msg
  3590. Revision 1.20 1998/11/13 15:40:27 pierre
  3591. + added -Se in Makefile cvstest target
  3592. + lexlevel cleanup
  3593. normal_function_level main_program_level and unit_init_level defined
  3594. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  3595. (test added in code !)
  3596. * -Un option was wrong
  3597. * _FAIL and _SELF only keyword inside
  3598. constructors and methods respectively
  3599. Revision 1.19 1998/11/13 10:12:16 peter
  3600. * constant fixes
  3601. Revision 1.18 1998/11/05 23:48:26 peter
  3602. * recordtype.field support in constant expressions
  3603. * fixed imul for oa_imm8 which was not allowed
  3604. * fixed reading of local typed constants
  3605. * fixed comment reading which is not any longer a separator
  3606. Revision 1.17 1998/10/28 21:34:39 peter
  3607. * fixed some opsize
  3608. Revision 1.16 1998/10/28 00:08:48 peter
  3609. + leal procsym,eax is now allowed
  3610. + constants are now handled also when starting an expression
  3611. + call *pointer is now allowed
  3612. Revision 1.15 1998/10/13 16:50:16 pierre
  3613. * undid some changes of Peter that made the compiler wrong
  3614. for m68k (I had to reinsert some ifdefs)
  3615. * removed several memory leaks under m68k
  3616. * removed the meory leaks for assembler readers
  3617. * cross compiling shoud work again better
  3618. ( crosscompiling sysamiga works
  3619. but as68k still complain about some code !)
  3620. Revision 1.14 1998/10/07 04:28:52 carl
  3621. * bugfix of in/out with gas (ins/outs still left though)
  3622. * bugfix of wrong error output with concatlabel
  3623. * gettoken always returns something valid now
  3624. Revision 1.13 1998/09/24 17:52:31 carl
  3625. * bugfix from fix branch
  3626. Revision 1.12.2.1 1998/09/24 17:47:16 carl
  3627. * bugfix with objects/records access
  3628. Revision 1.12 1998/09/03 17:08:46 pierre
  3629. * better lines for stabs
  3630. (no scroll back to if before else part
  3631. no return to case line at jump outside case)
  3632. + source lines also if not in order
  3633. Revision 1.11 1998/09/02 15:16:44 carl
  3634. * indirect register refs with movsx/movzx fixed
  3635. Revision 1.10 1998/09/02 01:24:09 carl
  3636. * bugfix of PUSH opcode with constants
  3637. Revision 1.9 1998/08/21 08:45:49 pierre
  3638. * better line info for asm statements
  3639. Revision 1.8 1998/08/19 16:07:54 jonas
  3640. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  3641. Revision 1.7 1998/08/10 23:57:23 peter
  3642. * use bestreal instead of extended
  3643. Revision 1.6 1998/08/10 14:50:21 peter
  3644. + localswitches, moduleswitches, globalswitches splitting
  3645. Revision 1.5 1998/07/14 14:46:58 peter
  3646. * released NEWINPUT
  3647. Revision 1.4 1998/07/08 15:06:41 daniel
  3648. + $N+,E+ added for TP.
  3649. Revision 1.3 1998/07/07 11:20:07 peter
  3650. + NEWINPUT for a better inputfile and scanner object
  3651. Revision 1.2 1998/06/24 14:06:36 peter
  3652. * fixed the name changes
  3653. Revision 1.1 1998/06/23 14:00:17 peter
  3654. * renamed RA* units
  3655. Revision 1.13 1998/06/16 08:56:29 peter
  3656. + targetcpu
  3657. * cleaner pmodules for newppu
  3658. Revision 1.12 1998/06/12 10:32:35 pierre
  3659. * column problem hopefully solved
  3660. + C vars declaration changed
  3661. Revision 1.11 1998/05/31 14:13:35 peter
  3662. * fixed call bugs with assembler readers
  3663. + OPR_SYMBOL to hold a symbol in the asm parser
  3664. * fixed staticsymtable vars which were acessed through %ebp instead of
  3665. name
  3666. Revision 1.10 1998/05/30 14:31:08 peter
  3667. + $ASMMODE
  3668. Revision 1.9 1998/05/29 09:58:16 pierre
  3669. * OPR_REGISTER for 1 arg was missing in ratti386.pas
  3670. (probably a merging problem)
  3671. * errors at start of line were lost
  3672. Revision 1.8 1998/05/28 16:34:36 carl
  3673. * call bugfix
  3674. * operand with regs bugfix (manual patch in both cases)
  3675. Revision 1.7 1998/05/23 01:21:27 peter
  3676. + aktasmmode, aktoptprocessor, aktoutputformat
  3677. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  3678. + $LIBNAME to set the library name where the unit will be put in
  3679. * splitted cgi386 a bit (codeseg to large for bp7)
  3680. * nasm, tasm works again. nasm moved to ag386nsm.pas
  3681. Revision 1.6 1998/05/20 09:42:37 pierre
  3682. + UseTokenInfo now default
  3683. * unit in interface uses and implementation uses gives error now
  3684. * only one error for unknown symbol (uses lastsymknown boolean)
  3685. the problem came from the label code !
  3686. + first inlined procedures and function work
  3687. (warning there might be allowed cases were the result is still wrong !!)
  3688. * UseBrower updated gives a global list of all position of all used symbols
  3689. with switch -gb
  3690. Revision 1.5 1998/04/29 13:52:23 peter
  3691. * small optimize fix
  3692. Revision 1.4 1998/04/29 10:34:04 pierre
  3693. + added some code for ansistring (not complete nor working yet)
  3694. * corrected operator overloading
  3695. * corrected nasm output
  3696. + started inline procedures
  3697. + added starstarn : use ** for exponentiation (^ gave problems)
  3698. + started UseTokenInfo cond to get accurate positions
  3699. Revision 1.3 1998/04/08 16:58:07 pierre
  3700. * several bugfixes
  3701. ADD ADC and AND are also sign extended
  3702. nasm output OK (program still crashes at end
  3703. and creates wrong assembler files !!)
  3704. procsym types sym in tdef removed !!
  3705. }