cg68k.pas 235 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480
  1. {
  2. $Id$
  3. Copyright (c) 1993,98 by Florian Klaempfl, Carl Eric Codere
  4. This unit generates 68000 (or better) assembler from the parse tree
  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. {$ifdef tp}
  18. {$E+,F+,N+,D+,L+,Y+}
  19. {$endif}
  20. {---------------------------------------------------------------------------}
  21. { LEFT TO DO IN CG68k AND CG68k2 }
  22. {---------------------------------------------------------------------------}
  23. { o Test and correct problems with extended support. }
  24. { o Optimize secondmoddiv when doing a constant modulo. }
  25. { o Add emulation support for Cardinal under MC68000. }
  26. {---------------------------------------------------------------------------}
  27. unit cg68k;
  28. {***************************************************************************}
  29. interface
  30. {***************************************************************************}
  31. uses objects,verbose,cobjects,systems,globals,tree,
  32. symtable,types,strings,pass_1,hcodegen,temp_gen,
  33. aasm,m68k,tgen68k,files,cga68k,cg68k2,link
  34. {$ifdef GDB}
  35. ,gdb
  36. {$endif}
  37. ;
  38. { produces assembler for the expression in variable p }
  39. { and produces an assembler node at the end }
  40. procedure generatecode(var p : ptree);
  41. { produces the actual code }
  42. function do_secondpass(var p : ptree) : boolean;
  43. procedure secondpass(var p : ptree);
  44. {$ifdef test_dest_loc}
  45. const { used to avoid temporary assignments }
  46. dest_loc_known : boolean = false;
  47. in_dest_loc : boolean = false;
  48. dest_loc_tree : ptree = nil;
  49. var dest_loc : tlocation;
  50. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  51. {$endif test_dest_loc}
  52. {***************************************************************************}
  53. implementation
  54. {***************************************************************************}
  55. uses
  56. scanner;
  57. const
  58. never_copy_const_param : boolean = false;
  59. bytes2Sxx:array[1..4] of Topsize=(S_B,S_W,S_NO,S_L);
  60. { used to avoid temporary assignments }
  61. dest_loc_known : boolean = false;
  62. in_dest_loc : boolean = false;
  63. dest_loc_tree : ptree = nil;
  64. var
  65. { this is for open arrays and strings }
  66. { but be careful, this data is in the }
  67. { generated code destroyed quick, and also }
  68. { the next call of secondload destroys this }
  69. { data }
  70. { So be careful using the informations }
  71. { provided by this variables }
  72. highframepointer : tregister;
  73. highoffset : longint;
  74. dest_loc : tlocation;
  75. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  76. begin
  77. if (dest_loc.loc=LOC_CREGISTER) or (dest_loc.loc=LOC_REGISTER) then
  78. begin
  79. emit_reg_reg(A_MOVE,s,reg,dest_loc.register);
  80. p^.location:=dest_loc;
  81. in_dest_loc:=true;
  82. end
  83. else
  84. if (dest_loc.loc=LOC_REFERENCE) or (dest_loc.loc=LOC_MEM) then
  85. begin
  86. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,s,reg,newreference(dest_loc.reference))));
  87. p^.location:=dest_loc;
  88. in_dest_loc:=true;
  89. end
  90. else
  91. internalerror(20080);
  92. end;
  93. procedure error(const t : tmsgconst);
  94. begin
  95. if not(codegenerror) then
  96. verbose.Message(t);
  97. codegenerror:=true;
  98. end;
  99. type
  100. secondpassproc = procedure(var p : ptree);
  101. procedure seconderror(var p : ptree);
  102. begin
  103. p^.error:=true;
  104. codegenerror:=true;
  105. end;
  106. procedure secondstatement(var p : ptree);
  107. var
  108. hp : ptree;
  109. begin
  110. hp:=p;
  111. while assigned(hp) do
  112. begin
  113. { assignments could be distance optimized }
  114. if assigned(hp^.right) then
  115. begin
  116. cleartempgen;
  117. secondpass(hp^.right);
  118. end;
  119. hp:=hp^.left;
  120. end;
  121. end;
  122. procedure secondload(var p : ptree);
  123. var
  124. hregister : tregister;
  125. i : longint;
  126. symtabletype: tsymtabletype;
  127. hp : preference;
  128. begin
  129. simple_loadn:=true;
  130. reset_reference(p^.location.reference);
  131. case p^.symtableentry^.typ of
  132. { this is only for toasm and toaddr }
  133. absolutesym :
  134. begin
  135. stringdispose(p^.location.reference.symbol);
  136. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  137. if p^.symtableentry^.owner^.symtabletype=unitsymtable then
  138. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  139. end;
  140. varsym :
  141. begin
  142. hregister:=R_NO;
  143. symtabletype:=p^.symtable^.symtabletype;
  144. { in case it is a register variable: }
  145. { we simply set the location to the }
  146. { correct register. }
  147. if pvarsym(p^.symtableentry)^.reg<>R_NO then
  148. begin
  149. p^.location.loc:=LOC_CREGISTER;
  150. p^.location.register:=pvarsym(p^.symtableentry)^.reg;
  151. unused:=unused-[pvarsym(p^.symtableentry)^.reg];
  152. end
  153. else
  154. begin
  155. { --------------------- LOCAL AND TEMP VARIABLES ------------- }
  156. if (symtabletype=parasymtable) or (symtabletype=localsymtable) then
  157. begin
  158. p^.location.reference.base:=procinfo.framepointer;
  159. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  160. if (symtabletype=localsymtable) then
  161. p^.location.reference.offset:=-p^.location.reference.offset;
  162. if (symtabletype=parasymtable) then
  163. inc(p^.location.reference.offset,p^.symtable^.call_offset);
  164. if (lexlevel>(p^.symtable^.symtablelevel)) then
  165. begin
  166. hregister:=getaddressreg;
  167. { make a reference }
  168. new(hp);
  169. reset_reference(hp^);
  170. hp^.offset:=procinfo.framepointer_offset;
  171. hp^.base:=procinfo.framepointer;
  172. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  173. simple_loadn:=false;
  174. i:=lexlevel-1;
  175. while i>(p^.symtable^.symtablelevel) do
  176. begin
  177. { make a reference }
  178. new(hp);
  179. reset_reference(hp^);
  180. hp^.offset:=8;
  181. hp^.base:=hregister;
  182. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  183. dec(i);
  184. end;
  185. p^.location.reference.base:=hregister;
  186. end;
  187. end
  188. { --------------------- END OF LOCAL AND TEMP VARS ---------------- }
  189. else
  190. case symtabletype of
  191. unitsymtable,globalsymtable,
  192. staticsymtable : begin
  193. stringdispose(p^.location.reference.symbol);
  194. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  195. if symtabletype=unitsymtable then
  196. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  197. end;
  198. objectsymtable : begin
  199. if (pvarsym(p^.symtableentry)^.properties and sp_static)<>0 then
  200. begin
  201. stringdispose(p^.location.reference.symbol);
  202. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  203. if p^.symtable^.defowner^.owner^.symtabletype=unitsymtable then
  204. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  205. end
  206. else
  207. begin
  208. p^.location.reference.base:=R_A5;
  209. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  210. end;
  211. end;
  212. withsymtable : begin
  213. hregister:=getaddressreg;
  214. p^.location.reference.base:=hregister;
  215. { make a reference }
  216. new(hp);
  217. reset_reference(hp^);
  218. hp^.offset:=p^.symtable^.datasize;
  219. hp^.base:=procinfo.framepointer;
  220. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  221. p^.location.reference.offset:=
  222. pvarsym(p^.symtableentry)^.address;
  223. end;
  224. end;
  225. { in case call by reference, then calculate: }
  226. if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
  227. ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
  228. dont_copy_const_param(pvarsym(p^.symtableentry)^.definition)) then
  229. begin
  230. simple_loadn:=false;
  231. if hregister=R_NO then
  232. hregister:=getaddressreg;
  233. { ADDED FOR OPEN ARRAY SUPPORT. }
  234. if (p^.location.reference.base=procinfo.framepointer) then
  235. begin
  236. highframepointer:=p^.location.reference.base;
  237. highoffset:=p^.location.reference.offset;
  238. end
  239. else
  240. begin
  241. highframepointer:=R_A1;
  242. highoffset:=p^.location.reference.offset;
  243. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  244. p^.location.reference.base,R_A1)));
  245. end;
  246. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),
  247. hregister)));
  248. { END ADDITION }
  249. clear_reference(p^.location.reference);
  250. p^.location.reference.base:=hregister;
  251. end;
  252. { should be dereferenced later (FK)
  253. if (pvarsym(p^.symtableentry)^.definition^.deftype=objectdef) and
  254. ((pobjectdef(pvarsym(p^.symtableentry)^.definition)^.options and oois_class)<>0) then
  255. begin
  256. simple_loadn:=false;
  257. if hregister=R_NO then
  258. hregister:=getaddressreg;
  259. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),
  260. hregister)));
  261. clear_reference(p^.location.reference);
  262. p^.location.reference.base:=hregister;
  263. end;
  264. }
  265. end;
  266. end;
  267. procsym:
  268. begin
  269. {!!!!! Be aware, work on virtual methods too }
  270. stringdispose(p^.location.reference.symbol);
  271. p^.location.reference.symbol:=
  272. stringdup(pprocsym(p^.symtableentry)^.definition^.mangledname);
  273. if p^.symtable^.symtabletype=unitsymtable then
  274. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  275. end;
  276. typedconstsym :
  277. begin
  278. stringdispose(p^.location.reference.symbol);
  279. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  280. if p^.symtable^.symtabletype=unitsymtable then
  281. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  282. end;
  283. else internalerror(4);
  284. end;
  285. end;
  286. { D0 and D1 used as temp (ok) }
  287. procedure secondmoddiv(var p : ptree);
  288. var
  289. hreg1 : tregister;
  290. power : longint;
  291. hl : plabel;
  292. reg: tregister;
  293. pushed: boolean;
  294. begin
  295. secondpass(p^.left);
  296. set_location(p^.location,p^.left^.location);
  297. pushed:=maybe_push(p^.right^.registers32,p);
  298. secondpass(p^.right);
  299. if pushed then restore(p);
  300. { put numerator in register }
  301. if p^.left^.location.loc<>LOC_REGISTER then
  302. begin
  303. if p^.left^.location.loc=LOC_CREGISTER then
  304. begin
  305. hreg1:=getregister32;
  306. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,hreg1);
  307. end
  308. else
  309. begin
  310. del_reference(p^.left^.location.reference);
  311. hreg1:=getregister32;
  312. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.left^.location.reference),
  313. hreg1)));
  314. end;
  315. p^.left^.location.loc:=LOC_REGISTER;
  316. p^.left^.location.register:=hreg1;
  317. end
  318. else hreg1:=p^.left^.location.register;
  319. if (p^.treetype=divn) and (p^.right^.treetype=ordconstn) and
  320. ispowerof2(p^.right^.value,power) then
  321. begin
  322. exprasmlist^.concat(new(pai68k, op_reg(A_TST, S_L, hreg1)));
  323. getlabel(hl);
  324. emitl(A_BPL,hl);
  325. if (power = 1) then
  326. exprasmlist^.concat(new(pai68k, op_const_reg(A_ADDQ, S_L,1, hreg1)));
  327. if (p^.right^.value-1) < 9 then
  328. exprasmlist^.concat(new(pai68k, op_const_reg(A_ADDQ, S_L,p^.right^.value-1, hreg1)))
  329. else
  330. exprasmlist^.concat(new(pai68k, op_const_reg(A_ADD, S_L,p^.right^.value-1, hreg1)));
  331. emitl(A_LABEL, hl);
  332. if (power > 0) and (power < 9) then
  333. exprasmlist^.concat(new(pai68k, op_const_reg(A_ASR, S_L,power, hreg1)))
  334. else
  335. begin
  336. exprasmlist^.concat(new(pai68k, op_const_reg(A_MOVE,S_L,power, R_D0)));
  337. exprasmlist^.concat(new(pai68k, op_reg_reg(A_ASR,S_L,R_D0, hreg1)));
  338. end;
  339. end
  340. else
  341. begin
  342. { bring denominator to D1 }
  343. { D1 is always free, it's }
  344. { only used for temporary }
  345. { purposes }
  346. if (p^.right^.location.loc<>LOC_REGISTER) and
  347. (p^.right^.location.loc<>LOC_CREGISTER) then
  348. begin
  349. del_reference(p^.right^.location.reference);
  350. p^.left^.location.loc:=LOC_REGISTER;
  351. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.right^.location.reference),R_D1)));
  352. end
  353. else
  354. begin
  355. ungetregister32(p^.right^.location.register);
  356. emit_reg_reg(A_MOVE,S_L,p^.right^.location.register,R_D1);
  357. end;
  358. { on entering this section D1 should contain the divisor }
  359. if (aktoptprocessor
  360. = MC68020) then
  361. begin
  362. if (p^.treetype = modn) then
  363. Begin
  364. reg := getregister32;
  365. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_L,reg)));
  366. getlabel(hl);
  367. { here what we do is prepare the high register with the }
  368. { correct sign. i.e we clear it, check if the low dword reg }
  369. { which will participate in the division is signed, if so we}
  370. { we extend the sign to the high doword register by inverting }
  371. { all the bits. }
  372. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_L,hreg1)));
  373. emitl(A_BPL,hl);
  374. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,reg)));
  375. emitl(A_LABEL,hl);
  376. { reg:hreg1 / d1 }
  377. exprasmlist^.concat(new(pai68k,op_reg_reg_reg(A_DIVSL,S_L,R_D1,reg,hreg1)));
  378. { hreg1 already contains quotient }
  379. { looking for remainder }
  380. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,reg,hreg1)));
  381. ungetregister32(reg);
  382. end
  383. else
  384. { simple division... }
  385. Begin
  386. { reg:hreg1 / d1 }
  387. exprasmlist^.concat(new(pai68k,op_reg_reg(A_DIVS,S_L,R_D1,hreg1)));
  388. end;
  389. end
  390. else { MC68000 operations }
  391. begin
  392. { put numerator in d0 }
  393. emit_reg_reg(A_MOVE,S_L,hreg1,R_D0);
  394. { operation to perform on entry to both }
  395. { routines... d0/d1 }
  396. { return result in d0 }
  397. if p^.treetype = divn then
  398. emitcall('LONGDIV',true)
  399. else
  400. emitcall('LONGMOD',true);
  401. emit_reg_reg(A_MOVE,S_L,R_D0,hreg1);
  402. end; { endif }
  403. end;
  404. { this registers are always used when div/mod are present }
  405. usedinproc:=usedinproc or ($800 shr word(R_D1));
  406. usedinproc:=usedinproc or ($800 shr word(R_D0));
  407. p^.location.loc:=LOC_REGISTER;
  408. p^.location.register:=hreg1;
  409. end;
  410. { D6 used as scratch (ok) }
  411. procedure secondshlshr(var p : ptree);
  412. var
  413. hregister1,hregister2,hregister3 : tregister;
  414. op : tasmop;
  415. pushed : boolean;
  416. begin
  417. secondpass(p^.left);
  418. pushed:=maybe_push(p^.right^.registers32,p);
  419. secondpass(p^.right);
  420. if pushed then restore(p);
  421. { load left operators in a register }
  422. if p^.left^.location.loc<>LOC_REGISTER then
  423. begin
  424. if p^.left^.location.loc=LOC_CREGISTER then
  425. begin
  426. hregister1:=getregister32;
  427. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,
  428. hregister1);
  429. end
  430. else
  431. begin
  432. del_reference(p^.left^.location.reference);
  433. hregister1:=getregister32;
  434. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.left^.location.reference),
  435. hregister1)));
  436. end;
  437. end
  438. else hregister1:=p^.left^.location.register;
  439. { determine operator }
  440. if p^.treetype=shln then
  441. op:=A_LSL
  442. else
  443. op:=A_LSR;
  444. { shifting by a constant directly decode: }
  445. if (p^.right^.treetype=ordconstn) then
  446. begin
  447. if (p^.right^.location.reference.offset and 31 > 0) and (p^.right^.location.reference.offset and 31 < 9) then
  448. exprasmlist^.concat(new(pai68k,op_const_reg(op,S_L,p^.right^.location.reference.offset and 31,
  449. hregister1)))
  450. else
  451. begin
  452. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,p^.right^.location.reference.offset and 31,
  453. R_D6)));
  454. exprasmlist^.concat(new(pai68k,op_reg_reg(op,S_L,R_D6,hregister1)));
  455. end;
  456. p^.location.loc:=LOC_REGISTER;
  457. p^.location.register:=hregister1;
  458. end
  459. else
  460. begin
  461. { load right operators in a register }
  462. if p^.right^.location.loc<>LOC_REGISTER then
  463. begin
  464. if p^.right^.location.loc=LOC_CREGISTER then
  465. begin
  466. hregister2:=getregister32;
  467. emit_reg_reg(A_MOVE,S_L,p^.right^.location.register,
  468. hregister2);
  469. end
  470. else
  471. begin
  472. del_reference(p^.right^.location.reference);
  473. hregister2:=getregister32;
  474. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.right^.location.reference),
  475. hregister2)));
  476. end;
  477. end
  478. else hregister2:=p^.right^.location.register;
  479. emit_reg_reg(op,S_L,hregister2,hregister1);
  480. p^.location.register:=hregister1;
  481. end;
  482. { this register is always used when shl/shr are present }
  483. usedinproc:=usedinproc or ($800 shr byte(R_D6));
  484. end;
  485. procedure secondrealconst(var p : ptree);
  486. var
  487. hp1 : pai;
  488. lastlabel : plabel;
  489. found : boolean;
  490. begin
  491. clear_reference(p^.location.reference);
  492. lastlabel:=nil;
  493. found:=false;
  494. { const already used ? }
  495. if p^.labnumber=-1 then
  496. begin
  497. { tries to found an old entry }
  498. hp1:=pai(consts^.first);
  499. while assigned(hp1) do
  500. begin
  501. if hp1^.typ=ait_label then
  502. lastlabel:=pai_label(hp1)^.l
  503. else
  504. begin
  505. if (hp1^.typ=p^.realtyp) and (lastlabel<>nil) then
  506. begin
  507. { Florian this caused a internalerror(10)=> no free reg !! }
  508. {if ((p^.realtyp=ait_real_64bit) and (pai_double(hp1)^.value=p^.valued)) or
  509. ((p^.realtyp=ait_real_80bit) and (pai_extended(hp1)^.value=p^.valued)) or
  510. ((p^.realtyp=ait_real_32bit) and (pai_single(hp1)^.value=p^.valued)) then }
  511. if ((p^.realtyp=ait_real_64bit) and (pai_double(hp1)^.value=p^.valued)) then
  512. found:=true;
  513. if ((p^.realtyp=ait_real_32bit) and (pai_single(hp1)^.value=p^.valued)) then
  514. found:=true;
  515. if ((p^.realtyp=ait_real_extended) and (pai_extended(hp1)^.value=p^.valued)) then
  516. found:=true;
  517. if found then
  518. begin
  519. { found! }
  520. p^.labnumber:=lastlabel^.nb;
  521. break;
  522. end;
  523. end;
  524. lastlabel:=nil;
  525. end;
  526. hp1:=pai(hp1^.next);
  527. end;
  528. { :-(, we must generate a new entry }
  529. if p^.labnumber=-1 then
  530. begin
  531. getlabel(lastlabel);
  532. p^.labnumber:=lastlabel^.nb;
  533. case p^.realtyp of
  534. ait_real_64bit : consts^.insert(new(pai_double,init(p^.valued)));
  535. ait_real_32bit : consts^.insert(new(pai_single,init(p^.valued)));
  536. ait_real_extended : consts^.insert(new(pai_extended,init(p^.valued)));
  537. else
  538. internalerror(10120);
  539. end;
  540. consts^.insert(new(pai_label,init(lastlabel)));
  541. end;
  542. end;
  543. stringdispose(p^.location.reference.symbol);
  544. p^.location.reference.symbol:=stringdup(lab2str(lastlabel));
  545. end;
  546. procedure secondfixconst(var p : ptree);
  547. begin
  548. { an fix comma const. behaves as a memory reference }
  549. p^.location.loc:=LOC_MEM;
  550. p^.location.reference.isintvalue:=true;
  551. p^.location.reference.offset:=p^.valuef;
  552. end;
  553. procedure secondordconst(var p : ptree);
  554. begin
  555. { an integer const. behaves as a memory reference }
  556. p^.location.loc:=LOC_MEM;
  557. p^.location.reference.isintvalue:=true;
  558. p^.location.reference.offset:=p^.value;
  559. end;
  560. procedure secondniln(var p : ptree);
  561. begin
  562. p^.location.loc:=LOC_MEM;
  563. p^.location.reference.isintvalue:=true;
  564. p^.location.reference.offset:=0;
  565. end;
  566. procedure secondstringconst(var p : ptree);
  567. var
  568. hp1 : pai;
  569. lastlabel : plabel;
  570. pc : pchar;
  571. same_string : boolean;
  572. i : word;
  573. begin
  574. clear_reference(p^.location.reference);
  575. lastlabel:=nil;
  576. { const already used ? }
  577. if p^.labstrnumber=-1 then
  578. begin
  579. { tries to found an old entry }
  580. hp1:=pai(consts^.first);
  581. while assigned(hp1) do
  582. begin
  583. if hp1^.typ=ait_label then
  584. lastlabel:=pai_label(hp1)^.l
  585. else
  586. begin
  587. if (hp1^.typ=ait_string) and (lastlabel<>nil) and
  588. (pai_string(hp1)^.len=length(p^.values^)+2) then
  589. begin
  590. same_string:=true;
  591. for i:=1 to length(p^.values^) do
  592. if pai_string(hp1)^.str[i]<>p^.values^[i] then
  593. begin
  594. same_string:=false;
  595. break;
  596. end;
  597. if same_string then
  598. begin
  599. { found! }
  600. p^.labstrnumber:=lastlabel^.nb;
  601. break;
  602. end;
  603. end;
  604. lastlabel:=nil;
  605. end;
  606. hp1:=pai(hp1^.next);
  607. end;
  608. { :-(, we must generate a new entry }
  609. if p^.labstrnumber=-1 then
  610. begin
  611. getlabel(lastlabel);
  612. p^.labstrnumber:=lastlabel^.nb;
  613. getmem(pc,length(p^.values^)+3);
  614. move(p^.values^,pc^,length(p^.values^)+1);
  615. pc[length(p^.values^)+1]:=#0;
  616. { we still will have a problem if there is a #0 inside the pchar }
  617. consts^.insert(new(pai_string,init_pchar(pc)));
  618. { to overcome this problem we set the length explicitly }
  619. { with the ending null char }
  620. pai_string(consts^.first)^.len:=length(p^.values^)+2;
  621. consts^.insert(new(pai_label,init(lastlabel)));
  622. end;
  623. end;
  624. stringdispose(p^.location.reference.symbol);
  625. p^.location.reference.symbol:=stringdup(lab2str(lastlabel));
  626. p^.location.loc := LOC_MEM;
  627. end;
  628. procedure secondumminus(var p : ptree);
  629. begin
  630. secondpass(p^.left);
  631. p^.location.loc:=LOC_REGISTER;
  632. case p^.left^.location.loc of
  633. LOC_REGISTER : begin
  634. p^.location.register:=p^.left^.location.register;
  635. exprasmlist^.concat(new(pai68k,op_reg(A_NEG,S_L,p^.location.register)));
  636. end;
  637. LOC_CREGISTER : begin
  638. p^.location.register:=getregister32;
  639. emit_reg_reg(A_MOVE,S_L,p^.location.register,
  640. p^.location.register);
  641. exprasmlist^.concat(new(pai68k,op_reg(A_NEG,S_L,p^.location.register)));
  642. end;
  643. LOC_REFERENCE,LOC_MEM :
  644. begin
  645. del_reference(p^.left^.location.reference);
  646. { change sign of a floating point }
  647. { in the case of emulation, get }
  648. { a free register, and change sign }
  649. { manually. }
  650. { otherwise simply load into an FPU}
  651. { register. }
  652. if (p^.left^.resulttype^.deftype=floatdef) and
  653. (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  654. begin
  655. { move to FPU }
  656. floatload(pfloatdef(p^.left^.resulttype)^.typ,
  657. p^.left^.location.reference,p^.location);
  658. if (cs_fp_emulation) in aktswitches then
  659. { if in emulation mode change sign manually }
  660. exprasmlist^.concat(new(pai68k,op_const_reg(A_BCHG,S_L,31,
  661. p^.location.fpureg)))
  662. else
  663. exprasmlist^.concat(new(pai68k,op_reg(A_FNEG,S_FX,
  664. p^.location.fpureg)));
  665. end
  666. else
  667. begin
  668. p^.location.register:=getregister32;
  669. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  670. newreference(p^.left^.location.reference),
  671. p^.location.register)));
  672. exprasmlist^.concat(new(pai68k,op_reg(A_NEG,S_L,p^.location.register)));
  673. end;
  674. end;
  675. LOC_FPU : begin
  676. p^.location.loc:=LOC_FPU;
  677. p^.location.fpureg := p^.left^.location.fpureg;
  678. if (cs_fp_emulation) in aktswitches then
  679. exprasmlist^.concat(new(pai68k,op_const_reg(A_BCHG,S_L,31,p^.location.fpureg)))
  680. else
  681. exprasmlist^.concat(new(pai68k,op_reg(A_FNEG,S_FX,p^.location.fpureg)));
  682. end;
  683. end;
  684. { emitoverflowcheck;}
  685. end;
  686. { use of A6 is required only temp (ok) }
  687. procedure secondaddr(var p : ptree);
  688. begin
  689. secondpass(p^.left);
  690. p^.location.loc:=LOC_REGISTER;
  691. p^.location.register:=getregister32;
  692. {@ on a procvar means returning an address to the procedure that
  693. is stored in it.}
  694. { yes but p^.left^.symtableentry can be nil
  695. for example on @self !! }
  696. { symtableentry can be also invalid, if left is no tree node }
  697. if (p^.left^.treetype=loadn) and
  698. assigned(p^.left^.symtableentry) and
  699. (p^.left^.symtableentry^.typ=varsym) and
  700. (Pvarsym(p^.left^.symtableentry)^.definition^.deftype=
  701. procvardef) then
  702. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  703. newreference(p^.left^.location.reference),
  704. p^.location.register)))
  705. else
  706. begin
  707. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  708. newreference(p^.left^.location.reference),R_A0)));
  709. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  710. R_A0,p^.location.register)));
  711. end;
  712. { for use of other segments }
  713. { if p^.left^.location.reference.segment<>R_DEFAULT_SEG then
  714. p^.location.segment:=p^.left^.location.reference.segment;
  715. }
  716. del_reference(p^.left^.location.reference);
  717. end;
  718. { register a6 used as scratch }
  719. procedure seconddoubleaddr(var p : ptree);
  720. begin
  721. secondpass(p^.left);
  722. p^.location.loc:=LOC_REGISTER;
  723. del_reference(p^.left^.location.reference);
  724. p^.location.register:=getregister32;
  725. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  726. newreference(p^.left^.location.reference),R_A0)));
  727. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  728. R_A0,p^.location.register)));
  729. end;
  730. procedure secondnot(var p : ptree);
  731. const
  732. flagsinvers : array[F_E..F_BE] of tresflags =
  733. (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
  734. F_A,F_AE,F_B,F_BE);
  735. var
  736. hl : plabel;
  737. begin
  738. if (p^.resulttype^.deftype=orddef) and
  739. (porddef(p^.resulttype)^.typ=bool8bit) then
  740. begin
  741. case p^.location.loc of
  742. LOC_JUMP : begin
  743. hl:=truelabel;
  744. truelabel:=falselabel;
  745. falselabel:=hl;
  746. secondpass(p^.left);
  747. maketojumpbool(p^.left);
  748. hl:=truelabel;
  749. truelabel:=falselabel;
  750. falselabel:=hl;
  751. end;
  752. LOC_FLAGS : begin
  753. secondpass(p^.left);
  754. p^.location.resflags:=flagsinvers[p^.left^.location.resflags];
  755. end;
  756. LOC_REGISTER : begin
  757. secondpass(p^.left);
  758. p^.location.register:=p^.left^.location.register;
  759. exprasmlist^.concat(new(pai68k,op_const_reg(A_EOR,S_B,1,p^.location.register)));
  760. end;
  761. LOC_CREGISTER : begin
  762. secondpass(p^.left);
  763. p^.location.loc:=LOC_REGISTER;
  764. p^.location.register:=getregister32;
  765. emit_reg_reg(A_MOVE,S_B,p^.left^.location.register,
  766. p^.location.register);
  767. exprasmlist^.concat(new(pai68k,op_const_reg(A_EOR,S_B,1,p^.location.register)));
  768. end;
  769. LOC_REFERENCE,LOC_MEM : begin
  770. secondpass(p^.left);
  771. del_reference(p^.left^.location.reference);
  772. p^.location.loc:=LOC_REGISTER;
  773. p^.location.register:=getregister32;
  774. if p^.left^.location.loc=LOC_CREGISTER then
  775. emit_reg_reg(A_MOVE,S_B,p^.left^.location.register,
  776. p^.location.register)
  777. else
  778. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,
  779. newreference(p^.left^.location.reference),
  780. p^.location.register)));
  781. exprasmlist^.concat(new(pai68k,op_const_reg(A_EOR,S_B,1,p^.location.register)));
  782. end;
  783. end;
  784. end
  785. else
  786. begin
  787. secondpass(p^.left);
  788. p^.location.loc:=LOC_REGISTER;
  789. case p^.left^.location.loc of
  790. LOC_REGISTER : begin
  791. p^.location.register:=p^.left^.location.register;
  792. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.location.register)));
  793. end;
  794. LOC_CREGISTER : begin
  795. p^.location.register:=getregister32;
  796. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,
  797. p^.location.register);
  798. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.location.register)));
  799. end;
  800. LOC_REFERENCE,LOC_MEM :
  801. begin
  802. del_reference(p^.left^.location.reference);
  803. p^.location.register:=getregister32;
  804. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  805. newreference(p^.left^.location.reference),
  806. p^.location.register)));
  807. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.location.register)));
  808. end;
  809. end;
  810. {if p^.left^.location.loc=loc_register then
  811. p^.location.register:=p^.left^.location.register
  812. else
  813. begin
  814. del_locref(p^.left^.location);
  815. p^.location.register:=getregister32;
  816. exprasmlist^.concat(new(pai68k,op_loc_reg(A_MOV,S_L,
  817. p^.left^.location,
  818. p^.location.register)));
  819. end;
  820. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.location.register)));}
  821. end;
  822. end;
  823. procedure secondnothing(var p : ptree);
  824. begin
  825. end;
  826. procedure secondassignment(var p : ptree);
  827. var
  828. opsize : topsize;
  829. withresult : boolean;
  830. otlabel,hlabel,oflabel : plabel;
  831. hregister : tregister;
  832. loc : tloc;
  833. begin
  834. otlabel:=truelabel;
  835. oflabel:=falselabel;
  836. getlabel(truelabel);
  837. getlabel(falselabel);
  838. withresult:=false;
  839. { calculate left sides }
  840. secondpass(p^.left);
  841. case p^.left^.location.loc of
  842. LOC_REFERENCE : begin
  843. { in case left operator uses too many registers }
  844. { but to few are free then LEA }
  845. if (p^.left^.location.reference.base<>R_NO) and
  846. (p^.left^.location.reference.index<>R_NO) and
  847. (usablereg32<p^.right^.registers32) then
  848. begin
  849. del_reference(p^.left^.location.reference);
  850. hregister:=getaddressreg;
  851. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(
  852. p^.left^.location.reference),
  853. hregister)));
  854. clear_reference(p^.left^.location.reference);
  855. p^.left^.location.reference.base:=hregister;
  856. p^.left^.location.reference.index:=R_NO;
  857. end;
  858. loc:=LOC_REFERENCE;
  859. end;
  860. LOC_CREGISTER : loc:=LOC_CREGISTER;
  861. else
  862. begin
  863. Message(cg_e_illegal_expression);
  864. exit;
  865. end;
  866. end;
  867. { lets try to optimize this (PM) }
  868. { define a dest_loc that is the location }
  869. { and a ptree to verify that it is the right }
  870. { place to insert it }
  871. {$ifdef test_dest_loc}
  872. if (aktexprlevel<4) then
  873. begin
  874. dest_loc_known:=true;
  875. dest_loc:=p^.left^.location;
  876. dest_loc_tree:=p^.right;
  877. end;
  878. {$endif test_dest_loc}
  879. if (p^.right^.treetype=realconstn) then
  880. begin
  881. if p^.left^.resulttype^.deftype=floatdef then
  882. begin
  883. case pfloatdef(p^.left^.resulttype)^.typ of
  884. s32real : p^.right^.realtyp:=ait_real_32bit;
  885. s64real : p^.right^.realtyp:=ait_real_64bit;
  886. s80real : p^.right^.realtyp:=ait_real_extended;
  887. { what about f32bit and s64bit }
  888. end;
  889. end;
  890. end;
  891. secondpass(p^.right);
  892. {$ifdef test_dest_loc}
  893. dest_loc_known:=false;
  894. if in_dest_loc then
  895. begin
  896. truelabel:=otlabel;
  897. falselabel:=oflabel;
  898. in_dest_loc:=false;
  899. exit;
  900. end;
  901. {$endif test_dest_loc}
  902. if p^.left^.resulttype^.deftype=stringdef then
  903. begin
  904. { we do not need destination anymore }
  905. del_reference(p^.left^.location.reference);
  906. { only source if withresult is set }
  907. if not(withresult) then
  908. del_reference(p^.right^.location.reference);
  909. loadstring(p);
  910. ungetiftemp(p^.right^.location.reference);
  911. end
  912. else case p^.right^.location.loc of
  913. LOC_REFERENCE,
  914. LOC_MEM : begin
  915. { handle ordinal constants trimmed }
  916. if (p^.right^.treetype in [ordconstn,fixconstn]) or
  917. (loc=LOC_CREGISTER) then
  918. begin
  919. case p^.left^.resulttype^.size of
  920. 1 : opsize:=S_B;
  921. 2 : opsize:=S_W;
  922. 4 : opsize:=S_L;
  923. end;
  924. if loc=LOC_CREGISTER then
  925. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  926. newreference(p^.right^.location.reference),
  927. p^.left^.location.register)))
  928. else
  929. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,opsize,
  930. p^.right^.location.reference.offset,
  931. newreference(p^.left^.location.reference))));
  932. {exprasmlist^.concat(new(pai68k,op_const_loc(A_MOV,opsize,
  933. p^.right^.location.reference.offset,
  934. p^.left^.location)));}
  935. end
  936. else
  937. begin
  938. concatcopy(p^.right^.location.reference,
  939. p^.left^.location.reference,p^.left^.resulttype^.size,
  940. withresult);
  941. ungetiftemp(p^.right^.location.reference);
  942. end;
  943. end;
  944. LOC_REGISTER,
  945. LOC_CREGISTER : begin
  946. case p^.right^.resulttype^.size of
  947. 1 : opsize:=S_B;
  948. 2 : opsize:=S_W;
  949. 4 : opsize:=S_L;
  950. end;
  951. { simplified with op_reg_loc }
  952. if loc=LOC_CREGISTER then
  953. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,opsize,
  954. p^.right^.location.register,
  955. p^.left^.location.register)))
  956. else
  957. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,opsize,
  958. p^.right^.location.register,
  959. newreference(p^.left^.location.reference))));
  960. {exprasmlist^.concat(new(pai68k,op_reg_loc(A_MOV,opsize,
  961. p^.right^.location.register,
  962. p^.left^.location))); }
  963. end;
  964. LOC_FPU : begin
  965. if loc<>LOC_REFERENCE then
  966. internalerror(10010)
  967. else
  968. floatstore(pfloatdef(p^.left^.resulttype)^.typ,
  969. p^.right^.location,p^.left^.location.reference);
  970. end;
  971. LOC_JUMP : begin
  972. getlabel(hlabel);
  973. emitl(A_LABEL,truelabel);
  974. if loc=LOC_CREGISTER then
  975. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,
  976. 1,p^.left^.location.register)))
  977. else
  978. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,
  979. 1,newreference(p^.left^.location.reference))));
  980. {exprasmlist^.concat(new(pai68k,op_const_loc(A_MOV,S_B,
  981. 1,p^.left^.location)));}
  982. emitl(A_JMP,hlabel);
  983. emitl(A_LABEL,falselabel);
  984. if loc=LOC_CREGISTER then
  985. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_B,
  986. p^.left^.location.register)))
  987. else
  988. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,
  989. 0,newreference(p^.left^.location.reference))));
  990. emitl(A_LABEL,hlabel);
  991. end;
  992. LOC_FLAGS : begin
  993. if loc=LOC_CREGISTER then
  994. begin
  995. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.right^.location.resflags],S_B,
  996. p^.left^.location.register)));
  997. exprasmlist^.concat(new(pai68k,op_reg(A_NEG,S_B,p^.left^.location.register)));
  998. end
  999. else
  1000. begin
  1001. exprasmlist^.concat(new(pai68k,op_ref(flag_2_set[p^.right^.location.resflags],S_B,
  1002. newreference(p^.left^.location.reference))));
  1003. exprasmlist^.concat(new(pai68k,op_ref(A_NEG,S_B,newreference(p^.left^.location.reference))));
  1004. end;
  1005. end;
  1006. end;
  1007. truelabel:=otlabel;
  1008. falselabel:=oflabel;
  1009. end;
  1010. procedure secondderef(var p : ptree);
  1011. var
  1012. hr : tregister;
  1013. begin
  1014. secondpass(p^.left);
  1015. clear_reference(p^.location.reference);
  1016. case p^.left^.location.loc of
  1017. LOC_REGISTER : Begin
  1018. hr := getaddressreg;
  1019. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,hr);
  1020. p^.location.reference.base:=hr;
  1021. ungetregister(p^.left^.location.register);
  1022. end;
  1023. LOC_CREGISTER : begin
  1024. { ... and reserve one for the pointer }
  1025. hr:=getaddressreg;
  1026. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,hr);
  1027. p^.location.reference.base:=hr;
  1028. { LOC_REGISTER indicates that this is a
  1029. variable register which should not be freed. }
  1030. { ungetregister(p^.left^.location.register); }
  1031. end;
  1032. else
  1033. begin
  1034. { free register }
  1035. del_reference(p^.left^.location.reference);
  1036. { ...and reserve one for the pointer }
  1037. hr:=getaddressreg;
  1038. exprasmlist^.concat(new(pai68k,op_ref_reg(
  1039. A_MOVE,S_L,newreference(p^.left^.location.reference),
  1040. hr)));
  1041. p^.location.reference.base:=hr;
  1042. end;
  1043. end;
  1044. end;
  1045. { used D0, D1 as scratch (ok) }
  1046. { arrays ... }
  1047. { Sets up the array and string }
  1048. { references . }
  1049. procedure secondvecn(var p : ptree);
  1050. var
  1051. pushed : boolean;
  1052. ind : tregister;
  1053. _p : ptree;
  1054. procedure calc_emit_mul;
  1055. var
  1056. l1,l2 : longint;
  1057. begin
  1058. l1:=p^.resulttype^.size;
  1059. case l1 of
  1060. 1 : p^.location.reference.scalefactor:=l1;
  1061. 2 : exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,1,ind)));
  1062. 4 : exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,2,ind)));
  1063. 8 : exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,3,ind)));
  1064. else
  1065. begin
  1066. if ispowerof2(l1,l2) then
  1067. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,l2,ind)))
  1068. else
  1069. begin
  1070. { use normal MC68000 signed multiply }
  1071. if (l1 >= -32768) and (l1 <= 32767) then
  1072. exprasmlist^.concat(new(pai68k,op_const_reg(A_MULS,S_W,l1,ind)))
  1073. else
  1074. { use long MC68020 long multiply }
  1075. if (aktoptprocessor
  1076. = MC68020) then
  1077. exprasmlist^.concat(new(pai68k,op_const_reg(A_MULS,S_L,l1,ind)))
  1078. else
  1079. { MC68000 long multiply }
  1080. begin
  1081. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,l1,R_D0)));
  1082. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,ind,R_D1)));
  1083. emitcall('LONGMUL',true);
  1084. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,ind)));
  1085. end;
  1086. end;
  1087. end; { else case }
  1088. end; { end case }
  1089. end; { calc_emit_mul }
  1090. var
  1091. extraoffset : longint;
  1092. t : ptree;
  1093. hp : preference;
  1094. tai:pai68k;
  1095. reg: tregister;
  1096. begin
  1097. secondpass(p^.left);
  1098. { RESULT IS IN p^.location.reference }
  1099. set_location(p^.location,p^.left^.location);
  1100. { offset can only differ from 0 if arraydef }
  1101. if p^.left^.resulttype^.deftype=arraydef then
  1102. dec(p^.location.reference.offset,
  1103. p^.resulttype^.size*
  1104. parraydef(p^.left^.resulttype)^.lowrange);
  1105. if p^.right^.treetype=ordconstn then
  1106. begin
  1107. { offset can only differ from 0 if arraydef }
  1108. if (p^.left^.resulttype^.deftype=arraydef) then
  1109. begin
  1110. if not(is_open_array(p^.left^.resulttype)) then
  1111. begin
  1112. if (p^.right^.value>parraydef(p^.left^.resulttype)^.highrange) or
  1113. (p^.right^.value<parraydef(p^.left^.resulttype)^.lowrange) then
  1114. Message(parser_e_range_check_error);
  1115. dec(p^.left^.location.reference.offset,
  1116. p^.resulttype^.size*parraydef(p^.left^.resulttype)^.lowrange);
  1117. end
  1118. else
  1119. begin
  1120. { range checking for open arrays }
  1121. end;
  1122. end;
  1123. inc(p^.left^.location.reference.offset,
  1124. p^.right^.value*p^.resulttype^.size);
  1125. p^.left^.resulttype:=p^.resulttype;
  1126. disposetree(p^.right);
  1127. _p:=p^.left;
  1128. putnode(p);
  1129. p:=_p;
  1130. end
  1131. else
  1132. begin
  1133. { quick hack, to overcome Delphi 2 }
  1134. if (cs_maxoptimieren in aktswitches) and
  1135. (p^.left^.resulttype^.deftype=arraydef) then
  1136. begin
  1137. extraoffset:=0;
  1138. if (p^.right^.treetype=addn) then
  1139. begin
  1140. if p^.right^.right^.treetype=ordconstn then
  1141. begin
  1142. extraoffset:=p^.right^.right^.value;
  1143. t:=p^.right^.left;
  1144. putnode(p^.right);
  1145. putnode(p^.right^.right);
  1146. p^.right:=t
  1147. end
  1148. else if p^.right^.left^.treetype=ordconstn then
  1149. begin
  1150. extraoffset:=p^.right^.left^.value;
  1151. t:=p^.right^.right;
  1152. putnode(p^.right);
  1153. putnode(p^.right^.left);
  1154. p^.right:=t
  1155. end;
  1156. end
  1157. else if (p^.right^.treetype=subn) then
  1158. begin
  1159. if p^.right^.right^.treetype=ordconstn then
  1160. begin
  1161. extraoffset:=p^.right^.right^.value;
  1162. t:=p^.right^.left;
  1163. putnode(p^.right);
  1164. putnode(p^.right^.right);
  1165. p^.right:=t
  1166. end
  1167. else if p^.right^.left^.treetype=ordconstn then
  1168. begin
  1169. extraoffset:=p^.right^.left^.value;
  1170. t:=p^.right^.right;
  1171. putnode(p^.right);
  1172. putnode(p^.right^.left);
  1173. p^.right:=t
  1174. end;
  1175. end;
  1176. inc(p^.location.reference.offset,
  1177. p^.resulttype^.size*extraoffset);
  1178. end;
  1179. { calculate from left to right }
  1180. if (p^.location.loc<>LOC_REFERENCE) and
  1181. (p^.location.loc<>LOC_MEM) then
  1182. Message(cg_e_illegal_expression);
  1183. pushed:=maybe_push(p^.right^.registers32,p);
  1184. secondpass(p^.right);
  1185. if pushed then restore(p);
  1186. case p^.right^.location.loc of
  1187. LOC_REGISTER : begin
  1188. ind:=p^.right^.location.register;
  1189. case p^.right^.resulttype^.size of
  1190. 1: exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,
  1191. $ff,ind)));
  1192. 2: exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,
  1193. $ffff,ind)));
  1194. end;
  1195. end;
  1196. LOC_CREGISTER : begin
  1197. ind:=getregister32;
  1198. emit_reg_reg(A_MOVE,S_L,p^.right^.location.register,ind);
  1199. case p^.right^.resulttype^.size of
  1200. 1: exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,
  1201. $ff,ind)));
  1202. 2: exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,
  1203. $ffff,ind)));
  1204. end;
  1205. end;
  1206. LOC_FLAGS:
  1207. begin
  1208. ind:=getregister32;
  1209. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.right^.location.resflags],S_B,ind)));
  1210. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$ff,ind)));
  1211. end
  1212. else { else outer case }
  1213. begin
  1214. del_reference(p^.right^.location.reference);
  1215. ind:=getregister32;
  1216. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  1217. newreference(p^.right^.location.reference),ind)));
  1218. {Booleans are stored in an 8 bit memory location, so
  1219. the use of MOVL is not correct.}
  1220. case p^.right^.resulttype^.size of
  1221. 1: exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,
  1222. $ff,ind)));
  1223. 2: exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,
  1224. $ffff,ind)));
  1225. end; { end case }
  1226. end; { end else begin }
  1227. end;
  1228. { produce possible range check code: }
  1229. if cs_rangechecking in aktswitches then
  1230. begin
  1231. if p^.left^.resulttype^.deftype=arraydef then
  1232. begin
  1233. new(hp);
  1234. reset_reference(hp^);
  1235. parraydef(p^.left^.resulttype)^.genrangecheck;
  1236. hp^.symbol:=stringdup('R_'+tostr(parraydef(p^.left^.resulttype)^.rangenr));
  1237. emit_bounds_check(hp^,ind);
  1238. end;
  1239. end;
  1240. { ------------------------ HANDLE INDEXING ----------------------- }
  1241. { In Motorola 680x0 mode, displacement can only be of 64K max. }
  1242. { Therefore instead of doing a direct displacement, we must first }
  1243. { load the new address into an address register. Therefore the }
  1244. { symbol is not used. }
  1245. if assigned(p^.location.reference.symbol) then
  1246. begin
  1247. if p^.location.reference.base <> R_NO then
  1248. Message(cg_f_secondvecn_base_defined_twice);
  1249. p^.location.reference.base:=getaddressreg;
  1250. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_LEA,S_L,newcsymbol(p^.location.reference.symbol^,0),
  1251. p^.location.reference.base)));
  1252. stringdispose(p^.location.reference.symbol);
  1253. end;
  1254. if (p^.location.reference.index=R_NO) then
  1255. begin
  1256. p^.location.reference.index:=ind;
  1257. calc_emit_mul;
  1258. { here we must check for the offset }
  1259. { and if out of bounds for the motorola }
  1260. { eg: out of signed d8 then reload index }
  1261. { with correct value. }
  1262. if p^.location.reference.offset > 127 then
  1263. begin
  1264. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADD,S_L,p^.location.reference.offset,ind)));
  1265. p^.location.reference.offset := 0;
  1266. end
  1267. else
  1268. if p^.location.reference.offset < -128 then
  1269. begin
  1270. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,S_L,-p^.location.reference.offset,ind)));
  1271. p^.location.reference.offset := 0;
  1272. end;
  1273. end
  1274. else
  1275. begin
  1276. if p^.location.reference.base=R_NO then
  1277. begin
  1278. case p^.location.reference.scalefactor of
  1279. 2 : exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,1,p^.location.reference.index)));
  1280. 4 : exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,2,p^.location.reference.index)));
  1281. 8 : exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,3,p^.location.reference.index)));
  1282. end;
  1283. calc_emit_mul;
  1284. { we must use address register to put index in base }
  1285. { compare with cgi386.pas }
  1286. reg := getaddressreg;
  1287. p^.location.reference.base := reg;
  1288. emit_reg_reg(A_MOVE,S_L,p^.location.reference.index,reg);
  1289. ungetregister(p^.location.reference.index);
  1290. p^.location.reference.index:=ind;
  1291. end
  1292. else
  1293. begin
  1294. reg := getaddressreg;
  1295. exprasmlist^.concat(new(pai68k,op_ref_reg(
  1296. A_LEA,S_L,newreference(p^.location.reference),
  1297. reg)));
  1298. ungetregister(p^.location.reference.base);
  1299. { the symbol offset is loaded, }
  1300. { so release the symbol name and set symbol }
  1301. { to nil }
  1302. stringdispose(p^.location.reference.symbol);
  1303. p^.location.reference.offset:=0;
  1304. calc_emit_mul;
  1305. p^.location.reference.base:=reg;
  1306. ungetregister32(p^.location.reference.index);
  1307. p^.location.reference.index:=ind;
  1308. end;
  1309. end;
  1310. end;
  1311. end;
  1312. { *************** Converting Types **************** }
  1313. { produces if necessary rangecheckcode }
  1314. procedure maybe_rangechecking(p : ptree;p2,p1 : pdef);
  1315. var
  1316. hp : preference;
  1317. hregister : tregister;
  1318. neglabel,poslabel : plabel;
  1319. begin
  1320. { convert from p2 to p1 }
  1321. { range check from enums is not made yet !!}
  1322. { and its probably not easy }
  1323. if (p1^.deftype<>orddef) or (p2^.deftype<>orddef) then
  1324. exit;
  1325. { range checking is different for u32bit }
  1326. { lets try to generate it allways }
  1327. if (cs_rangechecking in aktswitches) and
  1328. { with $R+ explicit type conversations in TP aren't range checked! }
  1329. (not(p^.explizit) or not(cs_tp_compatible in aktswitches)) and
  1330. ((porddef(p1)^.low>porddef(p2)^.low) or
  1331. (porddef(p1)^.high<porddef(p2)^.high) or
  1332. (porddef(p1)^.typ=u32bit) or
  1333. (porddef(p2)^.typ=u32bit)) then
  1334. begin
  1335. porddef(p1)^.genrangecheck;
  1336. if porddef(p2)^.typ=u8bit then
  1337. begin
  1338. if (p^.location.loc=LOC_REGISTER) or
  1339. (p^.location.loc=LOC_CREGISTER) then
  1340. begin
  1341. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_B,p^.location.register,R_D6)));
  1342. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$FF,R_D6)));
  1343. end
  1344. else
  1345. begin
  1346. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,newreference(p^.location.reference),R_D6)));
  1347. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$FF,R_D6)));
  1348. end;
  1349. hregister:=R_D6;
  1350. end
  1351. else if porddef(p2)^.typ=s8bit then
  1352. begin
  1353. if (p^.location.loc=LOC_REGISTER) or
  1354. (p^.location.loc=LOC_CREGISTER) then
  1355. begin
  1356. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_B,p^.location.register,R_D6)));
  1357. { byte to long }
  1358. if aktoptprocessor = MC68020 then
  1359. exprasmlist^.concat(new(pai68k,op_reg(A_EXTB,S_L,R_D6)))
  1360. else
  1361. begin
  1362. exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_W,R_D6)));
  1363. exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,R_D6)));
  1364. end;
  1365. end
  1366. else
  1367. begin
  1368. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,newreference(p^.location.reference),R_D6)));
  1369. { byte to long }
  1370. if aktoptprocessor = MC68020 then
  1371. exprasmlist^.concat(new(pai68k,op_reg(A_EXTB,S_L,R_D6)))
  1372. else
  1373. begin
  1374. exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_W,R_D6)));
  1375. exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,R_D6)));
  1376. end;
  1377. end; { end outermost else }
  1378. hregister:=R_D6;
  1379. end
  1380. { rangechecking for u32bit ?? !!!!!!}
  1381. { lets try }
  1382. else if (porddef(p2)^.typ=s32bit) or (porddef(p2)^.typ=u32bit) then
  1383. begin
  1384. if (p^.location.loc=LOC_REGISTER) or
  1385. (p^.location.loc=LOC_CREGISTER) then
  1386. hregister:=p^.location.register
  1387. else
  1388. begin
  1389. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),R_D6)));
  1390. hregister:=R_D6;
  1391. end;
  1392. end
  1393. { rangechecking for u32bit ?? !!!!!!}
  1394. else if porddef(p2)^.typ=u16bit then
  1395. begin
  1396. if (p^.location.loc=LOC_REGISTER) or
  1397. (p^.location.loc=LOC_CREGISTER) then
  1398. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,p^.location.register,R_D6)))
  1399. else
  1400. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,newreference(p^.location.reference),R_D6)));
  1401. { unisgned extend }
  1402. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$FFFF,R_D6)));
  1403. hregister:=R_D6;
  1404. end
  1405. else if porddef(p2)^.typ=s16bit then
  1406. begin
  1407. if (p^.location.loc=LOC_REGISTER) or
  1408. (p^.location.loc=LOC_CREGISTER) then
  1409. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,p^.location.register,R_D6)))
  1410. else
  1411. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,newreference(p^.location.reference),R_D6)));
  1412. { sign extend }
  1413. exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,R_D6)));
  1414. hregister:=R_D6;
  1415. end
  1416. else internalerror(6);
  1417. new(hp);
  1418. reset_reference(hp^);
  1419. hp^.symbol:=stringdup('R_'+tostr(porddef(p1)^.rangenr));
  1420. if porddef(p1)^.low>porddef(p1)^.high then
  1421. begin
  1422. getlabel(neglabel);
  1423. getlabel(poslabel);
  1424. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_L,hregister)));
  1425. emitl(A_BLT,neglabel);
  1426. end;
  1427. emit_bounds_check(hp^,hregister);
  1428. if porddef(p1)^.low>porddef(p1)^.high then
  1429. begin
  1430. new(hp);
  1431. reset_reference(hp^);
  1432. hp^.symbol:=stringdup('R_'+tostr(porddef(p1)^.rangenr+1));
  1433. emitl(A_JMP,poslabel);
  1434. emitl(A_LABEL,neglabel);
  1435. emit_bounds_check(hp^,hregister);
  1436. emitl(A_LABEL,poslabel);
  1437. end;
  1438. end;
  1439. end;
  1440. type
  1441. tsecondconvproc = procedure(p,hp : ptree;convtyp : tconverttype);
  1442. procedure second_nothing(p,hp : ptree;convtyp : tconverttype);
  1443. begin
  1444. end;
  1445. procedure second_only_rangecheck(p,hp : ptree;convtyp : tconverttype);
  1446. begin
  1447. maybe_rangechecking(p,hp^.resulttype,p^.resulttype);
  1448. end;
  1449. procedure second_bigger(p,hp : ptree;convtyp : tconverttype);
  1450. var
  1451. hregister : tregister;
  1452. opsize : topsize;
  1453. op : tasmop;
  1454. is_register : boolean;
  1455. begin
  1456. is_register:=p^.left^.location.loc=LOC_REGISTER;
  1457. if not(is_register) and (p^.left^.location.loc<>LOC_CREGISTER) then
  1458. begin
  1459. del_reference(p^.left^.location.reference);
  1460. { we can do this here as we need no temp inside second_bigger }
  1461. ungetiftemp(p^.left^.location.reference);
  1462. end;
  1463. { this is wrong !!!
  1464. gives me movl (%eax),%eax
  1465. for the length(string !!!
  1466. use only for constant values }
  1467. {Constanst cannot be loaded into registers using MOVZX!}
  1468. if (p^.left^.location.loc<>LOC_MEM) or (not p^.left^.location.reference.isintvalue) then
  1469. case convtyp of
  1470. tc_u8bit_2_s32bit,
  1471. tc_u8bit_2_u32bit,
  1472. tc_s8bit_2_u32bit,
  1473. tc_s8bit_2_s16bit,
  1474. tc_s8bit_2_s32bit,
  1475. tc_u8bit_2_u16bit,
  1476. tc_s8bit_2_u16bit,
  1477. tc_u8bit_2_s16bit: begin
  1478. if is_register then
  1479. hregister := p^.left^.location.register
  1480. else
  1481. hregister := getregister32;
  1482. if is_register then
  1483. emit_reg_reg(A_MOVE,S_B,p^.left^.location.register, hregister)
  1484. else
  1485. begin
  1486. if p^.left^.location.loc = LOC_CREGISTER then
  1487. emit_reg_reg(A_MOVE,S_B,p^.left^.location.register,hregister)
  1488. else
  1489. exprasmlist^.concat(new(pai68k, op_ref_reg(A_MOVE,S_B,
  1490. newreference(P^.left^.location.reference), hregister)));
  1491. end;
  1492. case convtyp of
  1493. tc_u8bit_2_s32bit,
  1494. tc_u8bit_2_u32bit:
  1495. exprasmlist^.concat(new(pai68k, op_const_reg(
  1496. A_AND,S_L,$FF,hregister)));
  1497. tc_s8bit_2_u32bit,
  1498. tc_s8bit_2_s32bit:
  1499. begin
  1500. if aktoptprocessor = MC68020 then
  1501. exprasmlist^.concat(new(pai68k,op_reg
  1502. (A_EXTB,S_L,hregister)))
  1503. else { else if aktoptprocessor }
  1504. begin
  1505. { byte to word }
  1506. exprasmlist^.concat(new(pai68k,op_reg
  1507. (A_EXT,S_W,hregister)));
  1508. { word to long }
  1509. exprasmlist^.concat(new(pai68k,op_reg
  1510. (A_EXT,S_L,hregister)));
  1511. end;
  1512. end;
  1513. tc_s8bit_2_u16bit,
  1514. tc_u8bit_2_s16bit,
  1515. tc_u8bit_2_u16bit:
  1516. exprasmlist^.concat(new(pai68k, op_const_reg(
  1517. A_AND,S_W,$FF,hregister)));
  1518. tc_s8bit_2_s16bit:
  1519. exprasmlist^.concat(new(pai68k, op_reg(
  1520. A_EXT, S_W, hregister)));
  1521. end; { inner case }
  1522. end;
  1523. tc_u16bit_2_u32bit,
  1524. tc_u16bit_2_s32bit,
  1525. tc_s16bit_2_u32bit,
  1526. tc_s16bit_2_s32bit: begin
  1527. if is_register then
  1528. hregister := p^.left^.location.register
  1529. else
  1530. hregister := getregister32;
  1531. if is_register then
  1532. emit_reg_reg(A_MOVE,S_W,p^.left^.location.register, hregister)
  1533. else
  1534. begin
  1535. if p^.left^.location.loc = LOC_CREGISTER then
  1536. emit_reg_reg(A_MOVE,S_W,p^.left^.location.register,hregister)
  1537. else
  1538. exprasmlist^.concat(new(pai68k, op_ref_reg(A_MOVE,S_W,
  1539. newreference(P^.left^.location.reference), hregister)));
  1540. end;
  1541. if (convtyp = tc_u16bit_2_s32bit) or
  1542. (convtyp = tc_u16bit_2_u32bit) then
  1543. exprasmlist^.concat(new(pai68k, op_const_reg(
  1544. A_AND, S_L, $ffff, hregister)))
  1545. else { tc_s16bit_2_s32bit }
  1546. { tc_s16bit_2_u32bit }
  1547. exprasmlist^.concat(new(pai68k, op_reg(A_EXT,S_L,
  1548. hregister)));
  1549. end;
  1550. end { end case }
  1551. else
  1552. begin
  1553. case convtyp of
  1554. tc_u8bit_2_s32bit,
  1555. tc_s8bit_2_s32bit,
  1556. tc_u16bit_2_s32bit,
  1557. tc_s16bit_2_s32bit,
  1558. tc_u8bit_2_u32bit,
  1559. tc_s8bit_2_u32bit,
  1560. tc_u16bit_2_u32bit,
  1561. tc_s16bit_2_u32bit:
  1562. begin
  1563. hregister:=getregister32;
  1564. op:=A_MOVE;
  1565. opsize:=S_L;
  1566. end;
  1567. tc_s8bit_2_u16bit,
  1568. tc_s8bit_2_s16bit,
  1569. tc_u8bit_2_s16bit,
  1570. tc_u8bit_2_u16bit:
  1571. begin
  1572. hregister:=getregister32;
  1573. op:=A_MOVE;
  1574. opsize:=S_W;
  1575. end;
  1576. end;
  1577. if is_register then
  1578. begin
  1579. emit_reg_reg(op,opsize,p^.left^.location.register,hregister);
  1580. end
  1581. else
  1582. begin
  1583. if p^.left^.location.loc=LOC_CREGISTER then
  1584. emit_reg_reg(op,opsize,p^.left^.location.register,hregister)
  1585. else exprasmlist^.concat(new(pai68k,op_ref_reg(op,opsize,
  1586. newreference(p^.left^.location.reference),hregister)));
  1587. end;
  1588. end; { end elseif }
  1589. p^.location.loc:=LOC_REGISTER;
  1590. p^.location.register:=hregister;
  1591. maybe_rangechecking(p,p^.left^.resulttype,p^.resulttype);
  1592. end;
  1593. procedure second_string_string(p,hp : ptree;convtyp : tconverttype);
  1594. var
  1595. pushedregs : tpushed;
  1596. begin
  1597. stringdispose(p^.location.reference.symbol);
  1598. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  1599. del_reference(p^.left^.location.reference);
  1600. copystring(p^.location.reference,p^.left^.location.reference,pstringdef(p^.resulttype)^.len);
  1601. ungetiftemp(p^.left^.location.reference);
  1602. end;
  1603. procedure second_cstring_charpointer(p,hp : ptree;convtyp : tconverttype);
  1604. begin
  1605. p^.location.loc:=LOC_REGISTER;
  1606. p^.location.register:=getregister32;
  1607. inc(p^.left^.location.reference.offset);
  1608. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(p^.left^.location.reference),
  1609. R_A0)));
  1610. emit_reg_reg(A_MOVE, S_L, R_A0, p^.location.register);
  1611. end;
  1612. procedure second_cchar_charpointer(p,hp : ptree;convtyp : tconverttype);
  1613. begin
  1614. {!!!!}
  1615. p^.location.loc:=LOC_REGISTER;
  1616. p^.location.register:=getregister32;
  1617. inc(p^.left^.location.reference.offset);
  1618. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(p^.left^.location.reference),
  1619. R_A0)));
  1620. emit_reg_reg(A_MOVE, S_L, R_A0, p^.location.register);
  1621. end;
  1622. procedure second_string_chararray(p,hp : ptree;convtyp : tconverttype);
  1623. begin
  1624. inc(p^.location.reference.offset);
  1625. end;
  1626. procedure second_array_to_pointer(p,hp : ptree;convtyp : tconverttype);
  1627. begin
  1628. del_reference(p^.left^.location.reference);
  1629. p^.location.loc:=LOC_REGISTER;
  1630. p^.location.register:=getregister32;
  1631. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(p^.left^.location.reference),
  1632. R_A0)));
  1633. emit_reg_reg(A_MOVE,S_L,R_A0, P^.location.register);
  1634. end;
  1635. procedure second_pointer_to_array(p,hp : ptree;convtyp : tconverttype);
  1636. var
  1637. reg: tregister;
  1638. begin
  1639. p^.location.loc:=LOC_REFERENCE;
  1640. clear_reference(p^.location.reference);
  1641. { here, after doing some arithmetic on the pointer }
  1642. { we put it back in an address register }
  1643. if p^.left^.location.loc=LOC_REGISTER then
  1644. begin
  1645. reg := getaddressreg;
  1646. { move the pointer in a data register back into }
  1647. { an address register. }
  1648. emit_reg_reg(A_MOVE, S_L, p^.left^.location.register,reg);
  1649. p^.location.reference.base:=reg;
  1650. ungetregister32(p^.left^.location.register);
  1651. end
  1652. else
  1653. begin
  1654. if p^.left^.location.loc=LOC_CREGISTER then
  1655. begin
  1656. p^.location.reference.base:=getaddressreg;
  1657. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,
  1658. p^.location.reference.base);
  1659. end
  1660. else
  1661. begin
  1662. del_reference(p^.left^.location.reference);
  1663. p^.location.reference.base:=getaddressreg;
  1664. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.left^.location.reference),
  1665. p^.location.reference.base)));
  1666. end;
  1667. end;
  1668. end;
  1669. { generates the code for the type conversion from an array of char }
  1670. { to a string }
  1671. procedure second_chararray_to_string(p,hp : ptree;convtyp : tconverttype);
  1672. var
  1673. l : longint;
  1674. begin
  1675. { this is a type conversion which copies the data, so we can't }
  1676. { return a reference }
  1677. p^.location.loc:=LOC_MEM;
  1678. { first get the memory for the string }
  1679. stringdispose(p^.location.reference.symbol);
  1680. gettempofsizereference(256,p^.location.reference);
  1681. { calc the length of the array }
  1682. l:=parraydef(p^.left^.resulttype)^.highrange-
  1683. parraydef(p^.left^.resulttype)^.lowrange+1;
  1684. if l>255 then
  1685. Message(sym_e_type_mismatch);
  1686. { write the length }
  1687. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,l,
  1688. newreference(p^.location.reference))));
  1689. { copy to first char of string }
  1690. inc(p^.location.reference.offset);
  1691. { generates the copy code }
  1692. { and we need the source never }
  1693. concatcopy(p^.left^.location.reference,p^.location.reference,l,true);
  1694. { correct the string location }
  1695. dec(p^.location.reference.offset);
  1696. end;
  1697. (* procedure second_char_to_string(p,hp : ptree;convtyp : tconverttype);
  1698. begin
  1699. stringdispose(p^.location.reference.symbol);
  1700. gettempofsizereference(256,p^.location.reference);
  1701. { is it a char const ? }
  1702. if p^.left^.treetype=ordconstn then
  1703. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_W,p^.left^.value*256+1,newreference(p^.location.reference))))
  1704. else
  1705. begin
  1706. { not so elegant (goes better with extra register }
  1707. { Here the conversion is done in one shot }
  1708. { i.e we convert to a string with a single word which }
  1709. { will be stored, the length followed by the char }
  1710. { This is of course, endian specific. }
  1711. if (p^.left^.location.loc=LOC_REGISTER) or
  1712. (p^.left^.location.loc=LOC_CREGISTER) then
  1713. begin
  1714. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_B,p^.left^.location.register,R_D6)));
  1715. exprasmlist^.concat(new(pai68k, op_const_reg(A_AND, S_W, $FF, R_D6)));
  1716. ungetregister32(p^.left^.location.register);
  1717. end
  1718. else
  1719. begin
  1720. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,newreference(p^.left^.location.reference),R_D6)));
  1721. exprasmlist^.concat(new(pai68k, op_const_reg(A_AND, S_W, $FF, R_D6)));
  1722. del_reference(p^.left^.location.reference);
  1723. end;
  1724. if (aktoptprocessor = MC68020) then
  1725. { alignment is not a problem on the 68020 and higher processors }
  1726. Begin
  1727. { add length of string to word }
  1728. exprasmlist^.concat(new(pai68k,op_const_reg(A_OR,S_W,$0100,R_D6)));
  1729. { put back into mem ... }
  1730. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_W,R_D6,newreference(p^.location.reference))));
  1731. end
  1732. else
  1733. Begin
  1734. { alignment can cause problems }
  1735. { add length of string to ref }
  1736. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,1,newreference(p^.location.reference))));
  1737. if abs(p^.location.reference.offset) >= 1 then
  1738. Begin
  1739. { temporarily decrease offset }
  1740. Inc(p^.location.reference.offset);
  1741. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_B,R_D6,newreference(p^.location.reference))));
  1742. Dec(p^.location.reference.offset);
  1743. { restore offset }
  1744. end
  1745. else
  1746. Begin
  1747. Comment(V_Debug,'SecondChar2String() internal error.');
  1748. internalerror(34);
  1749. end;
  1750. end;
  1751. end;
  1752. end;*)
  1753. procedure second_char_to_string(p,hp : ptree;convtyp : tconverttype);
  1754. begin
  1755. stringdispose(p^.location.reference.symbol);
  1756. gettempofsizereference(256,p^.location.reference);
  1757. { call loadstring with correct left and right }
  1758. p^.right:=p^.left;
  1759. p^.left:=p;
  1760. loadstring(p);
  1761. p^.left:=nil; { reset left tree, which is empty }
  1762. end;
  1763. procedure second_int_real(p,hp : ptree;convtyp : tconverttype);
  1764. var
  1765. r : preference;
  1766. reg:tregister;
  1767. begin
  1768. emitloadord2reg(p^.left^.location, porddef(p^.left^.resulttype), R_D6, true);
  1769. ungetiftemp(p^.left^.location.reference);
  1770. if porddef(p^.left^.resulttype)^.typ=u32bit then
  1771. push_int(0);
  1772. emit_reg_reg(A_MOVE, S_L, R_D6, R_SPPUSH);
  1773. new(r);
  1774. reset_reference(r^);
  1775. r^.base := R_SP;
  1776. { no emulation }
  1777. { for u32bit a solution would be to push $0 and to load a
  1778. + comp
  1779. + if porddef(p^.left^.resulttype)^.typ=u32bit then
  1780. + exprasmlist^.concat(new(pai386,op_ref(A_FILD,S_IQ,r)))
  1781. + else}
  1782. p^.location.loc := LOC_FPU;
  1783. { get floating point register. }
  1784. if (cs_fp_emulation in aktswitches) then
  1785. begin
  1786. p^.location.fpureg := getregister32;
  1787. exprasmlist^.concat(new(pai68k, op_ref_reg(A_MOVE, S_L, r, R_D0)));
  1788. emitcall('LONG2SINGLE',true);
  1789. emit_reg_reg(A_MOVE,S_L,R_D0,p^.location.fpureg);
  1790. end
  1791. else
  1792. begin
  1793. p^.location.fpureg := getfloatreg;
  1794. exprasmlist^.concat(new(pai68k, op_ref_reg(A_FMOVE, S_L, r, p^.location.fpureg)))
  1795. end;
  1796. if porddef(p^.left^.resulttype)^.typ=u32bit then
  1797. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADD,S_L,8,R_SP)))
  1798. else
  1799. { restore the stack to the previous address }
  1800. exprasmlist^.concat(new(pai68k, op_const_reg(A_ADDQ, S_L, 4, R_SP)));
  1801. end;
  1802. procedure second_real_fix(p,hp : ptree;convtyp : tconverttype);
  1803. var
  1804. {hs : string;}
  1805. rreg : tregister;
  1806. ref : treference;
  1807. begin
  1808. rreg:=getregister32;
  1809. { Are we in a LOC_FPU, if not then use scratch registers }
  1810. { instead of allocating reserved registers. }
  1811. if (p^.left^.location.loc<>LOC_FPU) then
  1812. begin
  1813. if (cs_fp_emulation in aktswitches) then
  1814. begin
  1815. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.left^.location.reference),R_D0)));
  1816. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,65536,R_D1)));
  1817. emitcall('LONGMUL',true);
  1818. emit_reg_reg(A_MOVE,S_L,R_D0,rreg);
  1819. end
  1820. else
  1821. begin
  1822. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,S_L,newreference(p^.left^.location.reference),R_FP0)));
  1823. exprasmlist^.concat(new(pai68k,op_const_reg(A_FMUL,S_L,65536,R_FP0)));
  1824. exprasmlist^.concat(new(pai68k,op_reg_reg(A_FMOVE,S_L,R_FP0,rreg)));
  1825. end;
  1826. end
  1827. else
  1828. begin
  1829. if (cs_fp_emulation in aktswitches) then
  1830. begin
  1831. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,p^.left^.location.fpureg,R_D0)));
  1832. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,65536,R_D1)));
  1833. emitcall('LONGMUL',true);
  1834. emit_reg_reg(A_MOVE,S_L,R_D0,rreg);
  1835. end
  1836. else
  1837. begin
  1838. exprasmlist^.concat(new(pai68k,op_const_reg(A_FMUL,S_L,65536,p^.left^.location.fpureg)));
  1839. exprasmlist^.concat(new(pai68k,op_reg_reg(A_FMOVE,S_L,p^.left^.location.fpureg,rreg)));
  1840. end;
  1841. end;
  1842. p^.location.loc:=LOC_REGISTER;
  1843. p^.location.register:=rreg;
  1844. end;
  1845. procedure second_float_float(p,hp : ptree;convtyp : tconverttype);
  1846. begin
  1847. case p^.left^.location.loc of
  1848. LOC_FPU : begin
  1849. { reload }
  1850. p^.location.loc := LOC_FPU;
  1851. p^.location.fpureg := p^.left^.location.fpureg;
  1852. end;
  1853. LOC_MEM,
  1854. LOC_REFERENCE : floatload(pfloatdef(p^.left^.resulttype)^.typ,
  1855. p^.left^.location.reference,p^.location);
  1856. end;
  1857. { ALREADY HANDLED BY FLOATLOAD }
  1858. { p^.location.loc:=LOC_FPU; }
  1859. end;
  1860. procedure second_fix_real(p,hp : ptree;convtyp : tconverttype);
  1861. var
  1862. startreg : tregister;
  1863. hl : plabel;
  1864. r : treference;
  1865. reg1: tregister;
  1866. hl1,hl2,hl3,hl4,hl5,hl6,hl7,hl8,hl9: plabel;
  1867. begin
  1868. if (p^.left^.location.loc=LOC_REGISTER) or
  1869. (p^.left^.location.loc=LOC_CREGISTER) then
  1870. begin
  1871. startreg:=p^.left^.location.register;
  1872. ungetregister(startreg);
  1873. { move d0,d0 is removed by emit_reg_reg }
  1874. emit_reg_reg(A_MOVE,S_L,startreg,R_D0);
  1875. end
  1876. else
  1877. begin
  1878. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(
  1879. p^.left^.location.reference),R_D0)));
  1880. del_reference(p^.left^.location.reference);
  1881. startreg:=R_NO;
  1882. end;
  1883. reg1 := getregister32;
  1884. { Motorola 68000 equivalent of CDQ }
  1885. { we choose d1:d0 pair for quad word }
  1886. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_L,R_D0)));
  1887. getlabel(hl1);
  1888. emitl(A_BPL,hl1);
  1889. { we copy all bits (-ve number) }
  1890. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,$ffffffff,R_D1)));
  1891. getlabel(hl2);
  1892. emitl(A_BRA,hl2);
  1893. emitl(A_LABEL,hl1);
  1894. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_L,R_D0)));
  1895. emitl(A_LABEL,hl2);
  1896. { end CDQ }
  1897. exprasmlist^.concat(new(pai68k,op_reg_reg(A_EOR,S_L,R_D1,R_D0)));
  1898. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,reg1)));
  1899. getlabel(hl3);
  1900. emitl(A_BEQ,hl3);
  1901. { Motorola 68000 equivalent of RCL }
  1902. getlabel(hl4);
  1903. emitl(A_BCC,hl4);
  1904. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,1,reg1)));
  1905. exprasmlist^.concat(new(pai68k,op_const_reg(A_OR,S_L,1,reg1)));
  1906. getlabel(hl5);
  1907. emitl(A_BRA,hl5);
  1908. emitl(A_LABEL,hl4);
  1909. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,1,reg1)));
  1910. emitl(A_LABEL,hl5);
  1911. { end RCL }
  1912. { Motorola 68000 equivalent of BSR }
  1913. { save register }
  1914. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,R_D6)));
  1915. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,31,R_D0)));
  1916. getlabel(hl6);
  1917. emitl(A_LABEL,hl6);
  1918. exprasmlist^.concat(new(pai68k,op_reg_reg(A_BTST,S_L,R_D0,R_D1)));
  1919. getlabel(hl7);
  1920. emitl(A_BNE,hl7);
  1921. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,S_B,1,R_D0)));
  1922. emitl(A_BPL,hl6);
  1923. { restore register }
  1924. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D6,R_D0)));
  1925. emitl(A_LABEL,hl7);
  1926. { end BSR }
  1927. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,32,R_D6)));
  1928. exprasmlist^.concat(new(pai68k,op_reg_reg(A_SUB,S_B,R_D1,R_D6)));
  1929. exprasmlist^.concat(new(pai68k,op_reg_reg(A_LSL,S_L,R_D6,R_D0)));
  1930. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADD,S_W,1007,R_D1)));
  1931. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,5,R_D1)));
  1932. { Motorola 68000 equivalent of SHLD }
  1933. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_W,11,R_D6)));
  1934. { save register }
  1935. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D1,R_A0)));
  1936. getlabel(hl8);
  1937. emitl(A_LABEL,hl8);
  1938. exprasmlist^.concat(new(pai68k,op_const_reg(A_ROXL,S_W,1,R_D1)));
  1939. exprasmlist^.concat(new(pai68k,op_const_reg(A_ROXL,S_W,1,reg1)));
  1940. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,S_B,1,R_D6)));
  1941. emitl(A_BNE,hl8);
  1942. { restore register }
  1943. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A0,R_D1)));
  1944. { end Motorola equivalent of SHLD }
  1945. { Motorola 68000 equivalent of SHLD }
  1946. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_W,20,R_D6)));
  1947. { save register }
  1948. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,R_A0)));
  1949. getlabel(hl9);
  1950. emitl(A_LABEL,hl9);
  1951. exprasmlist^.concat(new(pai68k,op_const_reg(A_ROXL,S_W,1,R_D0)));
  1952. exprasmlist^.concat(new(pai68k,op_const_reg(A_ROXL,S_W,1,reg1)));
  1953. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,S_B,1,R_D6)));
  1954. emitl(A_BNE,hl9);
  1955. { restore register }
  1956. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A0,R_D0)));
  1957. { end Motorola equivalent of SHLD }
  1958. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,20,R_D6)));
  1959. exprasmlist^.concat(new(pai68k,op_reg_reg(A_SUB,S_L,R_D6,R_D0)));
  1960. emitl(A_LABEL, hl3);
  1961. { create temp values and put on stack }
  1962. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,reg1,R_SPPUSH)));
  1963. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,R_SPPUSH)));
  1964. reset_reference(r);
  1965. r.base:=R_SP;
  1966. if (cs_fp_emulation in aktswitches) then
  1967. begin
  1968. p^.location.loc:=LOC_FPU;
  1969. p^.location.fpureg := getregister32;
  1970. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(r),
  1971. p^.left^.location.fpureg)))
  1972. end
  1973. else
  1974. begin
  1975. p^.location.loc:=LOC_FPU;
  1976. p^.location.fpureg := getfloatreg;
  1977. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,S_L,newreference(r),
  1978. p^.left^.location.fpureg)))
  1979. end;
  1980. { clear temporary space }
  1981. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADDQ,S_L,8,R_SP)));
  1982. ungetregister32(reg1);
  1983. { Alreadu handled above... }
  1984. { p^.location.loc:=LOC_FPU; }
  1985. end;
  1986. procedure second_int_fix(p,hp : ptree;convtyp : tconverttype);
  1987. var
  1988. {hs : string;}
  1989. hregister : tregister;
  1990. begin
  1991. if (p^.left^.location.loc=LOC_REGISTER) then
  1992. hregister:=p^.left^.location.register
  1993. else if (p^.left^.location.loc=LOC_CREGISTER) then
  1994. hregister:=getregister32
  1995. else
  1996. begin
  1997. del_reference(p^.left^.location.reference);
  1998. hregister:=getregister32;
  1999. case porddef(p^.left^.resulttype)^.typ of
  2000. s8bit : begin
  2001. exprasmlist^.concat(new(pai68k, op_ref_reg(A_MOVE,S_B,
  2002. newreference(p^.left^.location.reference),hregister)));
  2003. if aktoptprocessor = MC68020 then
  2004. exprasmlist^.concat(new(pai68k, op_reg(A_EXTB,S_L,hregister)))
  2005. else
  2006. begin
  2007. exprasmlist^.concat(new(pai68k, op_reg(A_EXT,S_W,hregister)));
  2008. exprasmlist^.concat(new(pai68k, op_reg(A_EXT,S_L,hregister)));
  2009. end;
  2010. end;
  2011. u8bit : begin
  2012. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,newreference(p^.left^.location.reference),
  2013. hregister)));
  2014. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$ff,hregister)));
  2015. end;
  2016. s16bit :begin
  2017. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,newreference(p^.left^.location.reference),
  2018. hregister)));
  2019. exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,hregister)));
  2020. end;
  2021. u16bit : begin
  2022. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,newreference(p^.left^.location.reference),
  2023. hregister)));
  2024. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$ffff,hregister)));
  2025. end;
  2026. s32bit,u32bit : exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.left^.location.reference),
  2027. hregister)));
  2028. {!!!! u32bit }
  2029. end;
  2030. end;
  2031. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVEQ,S_L,16,R_D1)));
  2032. exprasmlist^.concat(new(pai68k,op_reg_reg(A_LSL,S_L,R_D1,hregister)));
  2033. p^.location.loc:=LOC_REGISTER;
  2034. p^.location.register:=hregister;
  2035. end;
  2036. procedure second_smaller(p,hp : ptree;convtyp : tconverttype);
  2037. var
  2038. hregister,destregister : tregister;
  2039. {opsize : topsize;}
  2040. ref : boolean;
  2041. hpp : preference;
  2042. begin
  2043. { !!!!!!!! Rangechecking }
  2044. ref:=false;
  2045. { problems with enums !! }
  2046. if (cs_rangechecking in aktswitches) and
  2047. { with $R+ explicit type conversations in TP aren't range checked! }
  2048. (not(p^.explizit) or not(cs_tp_compatible in aktswitches)) and
  2049. (p^.resulttype^.deftype=orddef) and
  2050. (hp^.resulttype^.deftype=orddef) and
  2051. ((porddef(p^.resulttype)^.low>porddef(hp^.resulttype)^.low) or
  2052. (porddef(p^.resulttype)^.high<porddef(hp^.resulttype)^.high)) then
  2053. begin
  2054. porddef(p^.resulttype)^.genrangecheck;
  2055. if porddef(hp^.resulttype)^.typ=s32bit then
  2056. begin
  2057. if (p^.location.loc=LOC_REGISTER) or
  2058. (p^.location.loc=LOC_CREGISTER) then
  2059. hregister:=p^.location.register
  2060. else
  2061. begin
  2062. hregister:=getregister32;
  2063. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),hregister)));
  2064. end;
  2065. end
  2066. { rangechecking for u32bit ?? !!!!!!}
  2067. else if porddef(hp^.resulttype)^.typ=u16bit then
  2068. begin
  2069. hregister:=getregister32;
  2070. if (p^.location.loc=LOC_REGISTER) or
  2071. (p^.location.loc=LOC_CREGISTER) then
  2072. begin
  2073. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,p^.location.register,hregister)));
  2074. end
  2075. else
  2076. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,newreference(p^.location.reference),hregister)));
  2077. { clear unused bits i.e unsigned extend}
  2078. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L, $FFFF, hregister)));
  2079. end
  2080. else if porddef(hp^.resulttype)^.typ=s16bit then
  2081. begin
  2082. hregister:=getregister32;
  2083. if (p^.location.loc=LOC_REGISTER) or
  2084. (p^.location.loc=LOC_CREGISTER) then
  2085. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,p^.location.register,hregister)))
  2086. else
  2087. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,newreference(p^.location.reference),hregister)));
  2088. { sign extend }
  2089. exprasmlist^.concat(new(pai68k,op_reg(A_EXT, S_L, hregister)));
  2090. end
  2091. else internalerror(6);
  2092. new(hpp);
  2093. reset_reference(hpp^);
  2094. hpp^.symbol:=stringdup('R_'+tostr(porddef(p^.resulttype)^.rangenr));
  2095. emit_bounds_check(hpp^, hregister);
  2096. p^.location.loc:=LOC_REGISTER;
  2097. p^.location.register:=hregister;
  2098. exit;
  2099. end;
  2100. if (p^.left^.location.loc=LOC_REGISTER) or
  2101. (p^.left^.location.loc=LOC_CREGISTER) then
  2102. begin
  2103. { handled by secondpas by called routine ??? }
  2104. { p^.location.loc:=p^.left^.location.loc; }
  2105. p^.location.register:=p^.left^.location.register;
  2106. end;
  2107. end;
  2108. procedure second_proc_to_procvar(p,hp : ptree;convtyp : tconverttype);far;
  2109. begin
  2110. secondpass(hp);
  2111. p^.location.loc:=LOC_REGISTER;
  2112. del_reference(hp^.location.reference);
  2113. p^.location.register:=getregister32;
  2114. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  2115. newreference(hp^.location.reference),R_A0)));
  2116. emit_reg_reg(A_MOVE, S_L, R_A0, P^.location.register);
  2117. end;
  2118. procedure second_bool_to_int(p,hp : ptree;convtyp : tconverttype);
  2119. var
  2120. oldtruelabel,oldfalselabel,hlabel : plabel;
  2121. begin
  2122. oldtruelabel:=truelabel;
  2123. oldfalselabel:=falselabel;
  2124. getlabel(truelabel);
  2125. getlabel(falselabel);
  2126. secondpass(hp);
  2127. p^.location.loc:=LOC_REGISTER;
  2128. del_reference(hp^.location.reference);
  2129. p^.location.register:=getregister32;
  2130. case hp^.location.loc of
  2131. LOC_MEM,LOC_REFERENCE :
  2132. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,
  2133. newreference(hp^.location.reference),p^.location.register)));
  2134. LOC_REGISTER,LOC_CREGISTER :
  2135. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_B,
  2136. hp^.location.register,p^.location.register)));
  2137. LOC_FLAGS:
  2138. begin
  2139. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[hp^.location.resflags],S_NO,
  2140. p^.location.register)))
  2141. end;
  2142. LOC_JUMP:
  2143. begin
  2144. getlabel(hlabel);
  2145. emitl(A_LABEL,truelabel);
  2146. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,
  2147. 1,p^.location.register)));
  2148. emitl(A_JMP,hlabel);
  2149. emitl(A_LABEL,falselabel);
  2150. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_B,p^.location.register)));
  2151. emitl(A_LABEL,hlabel);
  2152. end;
  2153. else
  2154. internalerror(10060);
  2155. end;
  2156. truelabel:=oldtruelabel;
  2157. falselabel:=oldfalselabel;
  2158. end;
  2159. procedure second_int_to_bool(p,hp : ptree;convtyp : tconverttype);
  2160. begin
  2161. { !!!!!!!!!!!!!!! }
  2162. end;
  2163. procedure secondtypeconv(var p : ptree);
  2164. const
  2165. secondconvert : array[tc_u8bit_2_s32bit..tc_cchar_charpointer] of
  2166. tsecondconvproc = (second_bigger,second_only_rangecheck,
  2167. second_bigger,second_bigger,second_bigger,
  2168. second_smaller,second_smaller,
  2169. second_smaller,second_string_string,
  2170. second_cstring_charpointer,second_string_chararray,
  2171. second_array_to_pointer,second_pointer_to_array,
  2172. second_char_to_string,second_bigger,
  2173. second_bigger,second_bigger,
  2174. second_smaller,second_smaller,
  2175. second_smaller,second_smaller,
  2176. second_bigger,second_smaller,
  2177. second_only_rangecheck,second_bigger,
  2178. second_bigger,second_bigger,
  2179. second_bigger,second_only_rangecheck,
  2180. second_smaller,second_smaller,
  2181. second_smaller,second_smaller,
  2182. second_int_real,second_real_fix,
  2183. second_fix_real,second_int_fix,second_float_float,
  2184. second_bool_to_int,second_int_to_bool,
  2185. second_chararray_to_string,
  2186. second_proc_to_procvar,
  2187. { is constant char to pchar, is done by firstpass }
  2188. second_nothing);
  2189. begin
  2190. { this isn't good coding, I think tc_bool_2_u8bit, shouldn't be }
  2191. { type conversion (FK) }
  2192. { this is necessary, because second_bool_byte, have to change }
  2193. { true- and false label before calling secondpass }
  2194. if p^.convtyp<>tc_bool_2_int then
  2195. begin
  2196. secondpass(p^.left);
  2197. set_location(p^.location,p^.left^.location);
  2198. end;
  2199. if p^.convtyp<>tc_equal then
  2200. {the second argument only is for maybe_range_checking !}
  2201. secondconvert[p^.convtyp](p,p^.left,p^.convtyp)
  2202. end;
  2203. { save the size of pushed parameter }
  2204. var
  2205. pushedparasize : longint;
  2206. procedure secondcallparan(var p : ptree;defcoll : pdefcoll;
  2207. push_from_left_to_right : boolean);
  2208. var
  2209. size : longint;
  2210. stackref : treference;
  2211. otlabel,hlabel,oflabel : plabel;
  2212. { temporary variables: }
  2213. tempdeftype : tdeftype;
  2214. tempreference : treference;
  2215. r : preference;
  2216. s : topsize;
  2217. op : tasmop;
  2218. begin
  2219. { push from left to right if specified }
  2220. if push_from_left_to_right and assigned(p^.right) then
  2221. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right);
  2222. otlabel:=truelabel;
  2223. oflabel:=falselabel;
  2224. getlabel(truelabel);
  2225. getlabel(falselabel);
  2226. secondpass(p^.left);
  2227. { in codegen.handleread.. defcoll^.data is set to nil }
  2228. if assigned(defcoll^.data) and
  2229. (defcoll^.data^.deftype=formaldef) then
  2230. begin
  2231. { allow @var }
  2232. if p^.left^.treetype=addrn then
  2233. begin
  2234. { allways a register }
  2235. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,p^.left^.location.register,R_SPPUSH)));
  2236. ungetregister32(p^.left^.location.register);
  2237. end
  2238. else
  2239. begin
  2240. if (p^.left^.location.loc<>LOC_REFERENCE) and
  2241. (p^.left^.location.loc<>LOC_MEM) then
  2242. Message(sym_e_type_mismatch)
  2243. else
  2244. begin
  2245. emitpushreferenceaddr(p^.left^.location.reference);
  2246. del_reference(p^.left^.location.reference);
  2247. end;
  2248. end;
  2249. inc(pushedparasize,4);
  2250. end
  2251. { handle call by reference parameter }
  2252. else if (defcoll^.paratyp=vs_var) then
  2253. begin
  2254. if (p^.left^.location.loc<>LOC_REFERENCE) then
  2255. Message(cg_e_var_must_be_reference);
  2256. { open array ? }
  2257. { defcoll^.data can be nil for read/write }
  2258. if assigned(defcoll^.data) and
  2259. is_open_array(defcoll^.data) then
  2260. begin
  2261. { push high }
  2262. if is_open_array(p^.left^.resulttype) then
  2263. begin
  2264. new(r);
  2265. reset_reference(r^);
  2266. r^.base:=highframepointer;
  2267. r^.offset:=highoffset+4;
  2268. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_SPPUSH)));
  2269. end
  2270. else
  2271. push_int(parraydef(p^.left^.resulttype)^.highrange-
  2272. parraydef(p^.left^.resulttype)^.lowrange);
  2273. inc(pushedparasize,4);
  2274. end;
  2275. emitpushreferenceaddr(p^.left^.location.reference);
  2276. del_reference(p^.left^.location.reference);
  2277. inc(pushedparasize,4);
  2278. end
  2279. else
  2280. begin
  2281. tempdeftype:=p^.resulttype^.deftype;
  2282. if tempdeftype=filedef then
  2283. Message(cg_e_file_must_call_by_reference);
  2284. if (defcoll^.paratyp=vs_const) and
  2285. dont_copy_const_param(p^.resulttype) then
  2286. begin
  2287. emitpushreferenceaddr(p^.left^.location.reference);
  2288. del_reference(p^.left^.location.reference);
  2289. inc(pushedparasize,4);
  2290. end
  2291. else
  2292. case p^.left^.location.loc of
  2293. LOC_REGISTER,
  2294. LOC_CREGISTER : begin
  2295. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  2296. p^.left^.location.register,R_SPPUSH)));
  2297. inc(pushedparasize,4);
  2298. ungetregister32(p^.left^.location.register);
  2299. end;
  2300. LOC_FPU : begin
  2301. size:=pfloatdef(p^.left^.resulttype)^.size;
  2302. inc(pushedparasize,size);
  2303. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,S_L,size,R_SP)));
  2304. new(r);
  2305. reset_reference(r^);
  2306. r^.base:=R_SP;
  2307. s:=getfloatsize(pfloatdef(p^.left^.resulttype)^.typ);
  2308. if (cs_fp_emulation in aktswitches) then
  2309. begin
  2310. { when in emulation mode... }
  2311. { only single supported!!! }
  2312. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,
  2313. p^.left^.location.fpureg,r)));
  2314. end
  2315. else
  2316. { convert back from extended to normal type }
  2317. exprasmlist^.concat(new(pai68k,op_reg_ref(A_FMOVE,s,
  2318. p^.left^.location.fpureg,r)));
  2319. end;
  2320. LOC_REFERENCE,LOC_MEM :
  2321. begin
  2322. tempreference:=p^.left^.location.reference;
  2323. del_reference(p^.left^.location.reference);
  2324. case p^.resulttype^.deftype of
  2325. orddef : begin
  2326. case porddef(p^.resulttype)^.typ of
  2327. s32bit,u32bit :
  2328. begin
  2329. emit_push_mem(tempreference);
  2330. inc(pushedparasize,4);
  2331. end;
  2332. s8bit,u8bit,uchar,bool8bit,s16bit,u16bit : begin
  2333. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  2334. newreference(tempreference),R_SPPUSH)));
  2335. inc(pushedparasize,2);
  2336. end;
  2337. end;
  2338. end;
  2339. floatdef : begin
  2340. case pfloatdef(p^.resulttype)^.typ of
  2341. f32bit,
  2342. s32real :
  2343. begin
  2344. emit_push_mem(tempreference);
  2345. inc(pushedparasize,4);
  2346. end;
  2347. s64real:
  2348. {s64bit }
  2349. begin
  2350. inc(tempreference.offset,4);
  2351. emit_push_mem(tempreference);
  2352. dec(tempreference.offset,4);
  2353. emit_push_mem(tempreference);
  2354. inc(pushedparasize,8);
  2355. end;
  2356. {$ifdef use48}
  2357. s48real : begin
  2358. end;
  2359. {$endif}
  2360. s80real : begin
  2361. Message(cg_f_extended_cg68k_not_supported);
  2362. { inc(tempreference.offset,6);
  2363. emit_push_mem(tempreference);
  2364. dec(tempreference.offset,4);
  2365. emit_push_mem(tempreference);
  2366. dec(tempreference.offset,2);
  2367. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  2368. newreference(tempreference),R_SPPUSH)));
  2369. inc(pushedparasize,extended_size);}
  2370. end;
  2371. end;
  2372. end;
  2373. pointerdef,procvardef,
  2374. enumdef,classrefdef: begin
  2375. emit_push_mem(tempreference);
  2376. inc(pushedparasize,4);
  2377. end;
  2378. arraydef,recorddef,stringdef,setdef,objectdef :
  2379. begin
  2380. if ((p^.resulttype^.deftype=setdef) and
  2381. (psetdef(p^.resulttype)^.settype=smallset)) then
  2382. begin
  2383. emit_push_mem(tempreference);
  2384. inc(pushedparasize,4);
  2385. end
  2386. else
  2387. begin
  2388. size:=p^.resulttype^.size;
  2389. { Alignment }
  2390. {
  2391. if (size>=4) and ((size and 3)<>0) then
  2392. inc(size,4-(size and 3))
  2393. else if (size>=2) and ((size and 1)<>0) then
  2394. inc(size,2-(size and 1))
  2395. else
  2396. if size=1 then size:=2;
  2397. }
  2398. { create stack space }
  2399. if (size > 0) and (size < 9) then
  2400. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,S_L,size,R_SP)))
  2401. else
  2402. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBA,
  2403. S_L,size,R_SP)));
  2404. inc(pushedparasize,size);
  2405. { create stack reference }
  2406. stackref.symbol := nil;
  2407. clear_reference(stackref);
  2408. stackref.base:=R_SP;
  2409. { produce copy }
  2410. if p^.resulttype^.deftype=stringdef then
  2411. begin
  2412. copystring(stackref,p^.left^.location.reference,
  2413. pstringdef(p^.resulttype)^.len);
  2414. end
  2415. else
  2416. begin
  2417. concatcopy(p^.left^.location.reference,
  2418. stackref,p^.resulttype^.size,true);
  2419. end;
  2420. end;
  2421. end;
  2422. else Message(cg_e_illegal_expression);
  2423. end;
  2424. end;
  2425. LOC_JUMP : begin
  2426. getlabel(hlabel);
  2427. inc(pushedparasize,2);
  2428. emitl(A_LABEL,truelabel);
  2429. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_W,1,R_SPPUSH)));
  2430. emitl(A_JMP,hlabel);
  2431. emitl(A_LABEL,falselabel);
  2432. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_W,0,R_SPPUSH)));
  2433. emitl(A_LABEL,hlabel);
  2434. end;
  2435. LOC_FLAGS : begin
  2436. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.left^.location.resflags],S_B,
  2437. R_D0)));
  2438. exprasmlist^.concat(new(pai68k,op_reg(A_NEG, S_B, R_D0)));
  2439. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_W,$ff, R_D0)));
  2440. inc(pushedparasize,2);
  2441. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,R_D0,R_SPPUSH)));
  2442. end;
  2443. end;
  2444. end;
  2445. truelabel:=otlabel;
  2446. falselabel:=oflabel;
  2447. { push from right to left }
  2448. if not push_from_left_to_right and assigned(p^.right) then
  2449. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right);
  2450. end;
  2451. procedure secondcalln(var p : ptree);
  2452. var
  2453. unusedregisters : tregisterset;
  2454. pushed : tpushed;
  2455. funcretref : treference;
  2456. hregister : tregister;
  2457. oldpushedparasize : longint;
  2458. { true if a5 must be loaded again after the subroutine }
  2459. loada5 : boolean;
  2460. { true if a virtual method must be called directly }
  2461. no_virtual_call : boolean;
  2462. { true if we produce a con- or destrutor in a call }
  2463. is_con_or_destructor : boolean;
  2464. { true if a constructor is called again }
  2465. extended_new : boolean;
  2466. { adress returned from an I/O-error }
  2467. iolabel : plabel;
  2468. { lexlevel count }
  2469. i : longint;
  2470. { help reference pointer }
  2471. r : preference;
  2472. pp,params : ptree;
  2473. { temp register allocation }
  2474. reg: tregister;
  2475. { help reference pointer }
  2476. ref: preference;
  2477. label
  2478. dont_call;
  2479. begin
  2480. extended_new:=false;
  2481. iolabel:=nil;
  2482. loada5:=true;
  2483. no_virtual_call:=false;
  2484. unusedregisters:=unused;
  2485. if not assigned(p^.procdefinition) then
  2486. exit;
  2487. { only if no proc var }
  2488. if not(assigned(p^.right)) then
  2489. is_con_or_destructor:=((p^.procdefinition^.options and poconstructor)<>0)
  2490. or ((p^.procdefinition^.options and podestructor)<>0);
  2491. { proc variables destroy all registers }
  2492. if (p^.right=nil) and
  2493. { virtual methods too }
  2494. ((p^.procdefinition^.options and povirtualmethod)=0) then
  2495. begin
  2496. if ((p^.procdefinition^.options and poiocheck)<>0)
  2497. and (cs_iocheck in aktswitches) then
  2498. begin
  2499. getlabel(iolabel);
  2500. emitl(A_LABEL,iolabel);
  2501. end
  2502. else iolabel:=nil;
  2503. { save all used registers }
  2504. pushusedregisters(pushed,p^.procdefinition^.usedregisters);
  2505. { give used registers through }
  2506. usedinproc:=usedinproc or p^.procdefinition^.usedregisters;
  2507. end
  2508. else
  2509. begin
  2510. pushusedregisters(pushed,$ffff);
  2511. usedinproc:=$ffff;
  2512. { no IO check for methods and procedure variables }
  2513. iolabel:=nil;
  2514. end;
  2515. { generate the code for the parameter and push them }
  2516. oldpushedparasize:=pushedparasize;
  2517. pushedparasize:=0;
  2518. if (p^.resulttype<>pdef(voiddef)) and
  2519. ret_in_param(p^.resulttype) then
  2520. begin
  2521. funcretref.symbol:=nil;
  2522. {$ifdef test_dest_loc}
  2523. if dest_loc_known and (dest_loc_tree=p) and
  2524. (dest_loc.loc in [LOC_REFERENCE,LOC_MEM]) then
  2525. begin
  2526. funcretref:=dest_loc.reference;
  2527. if assigned(dest_loc.reference.symbol) then
  2528. funcretref.symbol:=stringdup(dest_loc.reference.symbol^);
  2529. in_dest_loc:=true;
  2530. end
  2531. else
  2532. {$endif test_dest_loc}
  2533. gettempofsizereference(p^.procdefinition^.retdef^.size,funcretref);
  2534. end;
  2535. if assigned(p^.left) then
  2536. begin
  2537. pushedparasize:=0;
  2538. { be found elsewhere }
  2539. if assigned(p^.right) then
  2540. secondcallparan(p^.left,pprocvardef(p^.right^.resulttype)^.para1,
  2541. (p^.procdefinition^.options and poleftright)<>0)
  2542. else
  2543. secondcallparan(p^.left,p^.procdefinition^.para1,
  2544. (p^.procdefinition^.options and poleftright)<>0);
  2545. end;
  2546. params:=p^.left;
  2547. p^.left:=nil;
  2548. if ret_in_param(p^.resulttype) then
  2549. begin
  2550. emitpushreferenceaddr(funcretref);
  2551. inc(pushedparasize,4);
  2552. end;
  2553. { overloaded operator have no symtable }
  2554. if (p^.right=nil) then
  2555. begin
  2556. { push self }
  2557. if assigned(p^.symtable) and
  2558. (p^.symtable^.symtabletype=withsymtable) then
  2559. begin
  2560. { dirty trick to avoid the secondcall below }
  2561. p^.methodpointer:=genzeronode(callparan);
  2562. p^.methodpointer^.location.loc:=LOC_REGISTER;
  2563. p^.methodpointer^.location.register:=R_A5;
  2564. { make a reference }
  2565. new(r);
  2566. reset_reference(r^);
  2567. r^.offset:=p^.symtable^.datasize;
  2568. r^.base:=procinfo.framepointer;
  2569. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_A5)));
  2570. end;
  2571. { push self }
  2572. if assigned(p^.symtable) and
  2573. ((p^.symtable^.symtabletype=objectsymtable) or
  2574. (p^.symtable^.symtabletype=withsymtable)) then
  2575. begin
  2576. if assigned(p^.methodpointer) then
  2577. begin
  2578. case p^.methodpointer^.treetype of
  2579. typen : begin
  2580. { direct call to inherited method }
  2581. if (p^.procdefinition^.options and poabstractmethod)<>0 then
  2582. begin
  2583. Message(cg_e_cant_call_abstract_method);
  2584. goto dont_call;
  2585. end;
  2586. { generate no virtual call }
  2587. no_virtual_call:=true;
  2588. if (p^.symtableprocentry^.properties and sp_static)<>0 then
  2589. begin
  2590. { well lets put the VMT address directly into a5 }
  2591. { it is kind of dirty but that is the simplest }
  2592. { way to accept virtual static functions (PM) }
  2593. loada5:=true;
  2594. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2595. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_A5)));
  2596. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2597. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2598. end
  2599. else
  2600. { this is a member call, so A5 isn't modfied }
  2601. loada5:=false;
  2602. if not(is_con_or_destructor and
  2603. pobjectdef(p^.methodpointer^.resulttype)^.isclass and
  2604. assigned(aktprocsym) and
  2605. ((aktprocsym^.definition^.options and
  2606. (poconstructor or podestructor))<>0)) then
  2607. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2608. { if an inherited con- or destructor should be }
  2609. { called in a con- or destructor then a warning }
  2610. { will be made }
  2611. { con- and destructors need a pointer to the vmt }
  2612. if is_con_or_destructor and
  2613. ((pobjectdef(p^.methodpointer^.resulttype)^.options and oois_class)=0) and
  2614. assigned(aktprocsym) then
  2615. begin
  2616. if not ((aktprocsym^.definition^.options
  2617. and (poconstructor or podestructor))<>0) then
  2618. Message(cg_w_member_cd_call_from_method);
  2619. end;
  2620. { con- and destructors need a pointer to the vmt }
  2621. if is_con_or_destructor then
  2622. begin
  2623. { classes need the mem ! }
  2624. if ((pobjectdef(p^.methodpointer^.resulttype)^.options and
  2625. oois_class)=0) then
  2626. push_int(0)
  2627. else
  2628. begin
  2629. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  2630. S_L,newcsymbol(pobjectdef(p^.methodpointer^.
  2631. resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2632. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.
  2633. vmt_mangledname,EXT_NEAR);
  2634. end;
  2635. end;
  2636. end;
  2637. hnewn : begin
  2638. { extended syntax of new }
  2639. { A5 must be zero }
  2640. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,0,R_A5)));
  2641. emit_reg_reg(A_MOVE,S_L,R_A5, R_SPPUSH);
  2642. { insert the vmt }
  2643. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2644. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2645. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2646. extended_new:=true;
  2647. end;
  2648. hdisposen : begin
  2649. secondpass(p^.methodpointer);
  2650. { destructor with extended syntax called from dispose }
  2651. { hdisposen always deliver LOC_REFRENZ }
  2652. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  2653. newreference(p^.methodpointer^.location.reference),R_A5)));
  2654. del_reference(p^.methodpointer^.location.reference);
  2655. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2656. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2657. newcsymbol(pobjectdef
  2658. (p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2659. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2660. end;
  2661. else
  2662. begin
  2663. { call to a instance member }
  2664. if (p^.symtable^.symtabletype<>withsymtable) then
  2665. begin
  2666. secondpass(p^.methodpointer);
  2667. case p^.methodpointer^.location.loc of
  2668. LOC_REGISTER :
  2669. begin
  2670. ungetregister32(p^.methodpointer^.location.register);
  2671. emit_reg_reg(A_MOVE,S_L,p^.methodpointer^.location.register,R_A5);
  2672. end;
  2673. else
  2674. begin
  2675. if (p^.methodpointer^.resulttype^.deftype=objectdef) and
  2676. pobjectdef(p^.methodpointer^.resulttype)^.isclass then
  2677. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  2678. newreference(p^.methodpointer^.location.reference),R_A5)))
  2679. else
  2680. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  2681. newreference(p^.methodpointer^.location.reference),R_A5)));
  2682. del_reference(p^.methodpointer^.location.reference);
  2683. end;
  2684. end;
  2685. end;
  2686. { when calling a class method, we have
  2687. to load ESI with the VMT !
  2688. But that's wrong, if we call a class method via self
  2689. }
  2690. if ((p^.procdefinition^.options and poclassmethod)<>0)
  2691. and not(p^.methodpointer^.treetype=selfn) then
  2692. begin
  2693. { class method needs current VMT }
  2694. new(r);
  2695. reset_reference(r^);
  2696. r^.base:=R_A5;
  2697. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_A5)));
  2698. end;
  2699. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2700. if is_con_or_destructor then
  2701. begin
  2702. { classes don't get a VMT pointer pushed }
  2703. if (p^.methodpointer^.resulttype^.deftype=objectdef) and
  2704. not(pobjectdef(p^.methodpointer^.resulttype)^.isclass) then
  2705. begin
  2706. if ((p^.procdefinition^.options and poconstructor)<>0) then
  2707. begin
  2708. { it's no bad idea, to insert the VMT }
  2709. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2710. newcsymbol(pobjectdef(
  2711. p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2712. concat_external(pobjectdef(
  2713. p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2714. end
  2715. { destructors haven't to dispose the instance, if this is }
  2716. { a direct call }
  2717. else
  2718. push_int(0);
  2719. end;
  2720. end;
  2721. end;
  2722. end;
  2723. end
  2724. else
  2725. begin
  2726. if ((p^.procdefinition^.options and poclassmethod)<>0) and
  2727. not(
  2728. assigned(aktprocsym) and
  2729. ((aktprocsym^.definition^.options and poclassmethod)<>0)
  2730. ) then
  2731. begin
  2732. { class method needs current VMT }
  2733. new(r);
  2734. reset_reference(r^);
  2735. r^.base:=R_A5;
  2736. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_A5)));
  2737. end
  2738. else
  2739. begin
  2740. { member call, A5 isn't modified }
  2741. loada5:=false;
  2742. end;
  2743. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2744. { but a con- or destructor here would probably almost }
  2745. { always be placed wrong }
  2746. if is_con_or_destructor then
  2747. begin
  2748. Message(cg_w_member_cd_call_from_method);
  2749. { not insert VMT pointer } { VMT-Zeiger nicht eintragen }
  2750. push_int(0);
  2751. end;
  2752. end;
  2753. end;
  2754. { push base pointer ?}
  2755. if (lexlevel>1) and assigned(pprocdef(p^.procdefinition)^.parast) and
  2756. ((p^.procdefinition^.parast^.symtablelevel)>2) then
  2757. begin
  2758. { if we call a nested function in a method, we must }
  2759. { push also SELF! }
  2760. { THAT'S NOT TRUE, we have to load ESI via frame pointer }
  2761. { access }
  2762. {
  2763. begin
  2764. loadesi:=false;
  2765. exprasmlist^.concat(new(pai68k,op_reg(A_PUSH,S_L,R_ESI)));
  2766. end;
  2767. }
  2768. if lexlevel=(p^.procdefinition^.parast^.symtablelevel) then
  2769. begin
  2770. new(r);
  2771. reset_reference(r^);
  2772. r^.offset:=procinfo.framepointer_offset;
  2773. r^.base:=procinfo.framepointer;
  2774. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_SPPUSH)))
  2775. end
  2776. { this is only true if the difference is one !!
  2777. but it cannot be more !! }
  2778. else if lexlevel=(p^.procdefinition^.parast^.symtablelevel)-1 then
  2779. begin
  2780. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,procinfo.framepointer,R_SPPUSH)))
  2781. end
  2782. else if lexlevel>(p^.procdefinition^.parast^.symtablelevel) then
  2783. begin
  2784. hregister:=getaddressreg;
  2785. new(r);
  2786. reset_reference(r^);
  2787. r^.offset:=procinfo.framepointer_offset;
  2788. r^.base:=procinfo.framepointer;
  2789. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,hregister)));
  2790. for i:=(p^.procdefinition^.parast^.symtablelevel) to lexlevel-1 do
  2791. begin
  2792. new(r);
  2793. reset_reference(r^);
  2794. {we should get the correct frame_pointer_offset at each level
  2795. how can we do this !!! }
  2796. r^.offset:=procinfo.framepointer_offset;
  2797. r^.base:=hregister;
  2798. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,hregister)));
  2799. end;
  2800. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,hregister,R_SPPUSH)));
  2801. ungetregister32(hregister);
  2802. end
  2803. else
  2804. internalerror(25000);
  2805. end;
  2806. { exported methods should be never called direct }
  2807. if (p^.procdefinition^.options and poexports)<>0 then
  2808. Message(cg_e_dont_call_exported_direct);
  2809. if ((p^.procdefinition^.options and povirtualmethod)<>0) and
  2810. not(no_virtual_call) then
  2811. begin
  2812. { static functions contain the vmt_address in ESI }
  2813. { also class methods }
  2814. if assigned(aktprocsym) then
  2815. begin
  2816. if ((aktprocsym^.properties and sp_static)<>0) or
  2817. ((aktprocsym^.definition^.options and poclassmethod)<>0) or
  2818. ((p^.procdefinition^.options and postaticmethod)<>0) or
  2819. { A5 is already loaded }
  2820. ((p^.procdefinition^.options and poclassmethod)<>0)then
  2821. begin
  2822. new(r);
  2823. reset_reference(r^);
  2824. r^.base:=R_a5;
  2825. end
  2826. else
  2827. begin
  2828. new(r);
  2829. reset_reference(r^);
  2830. r^.base:=R_a5;
  2831. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_a0)));
  2832. new(r);
  2833. reset_reference(r^);
  2834. r^.base:=R_a0;
  2835. end;
  2836. end
  2837. else
  2838. begin
  2839. new(r);
  2840. reset_reference(r^);
  2841. r^.base:=R_a5;
  2842. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_a0)));
  2843. new(r);
  2844. reset_reference(r^);
  2845. r^.base:=R_a0;
  2846. end;
  2847. if p^.procdefinition^.extnumber=-1 then
  2848. internalerror($Da);
  2849. r^.offset:=p^.procdefinition^.extnumber*4+12;
  2850. if (cs_rangechecking in aktswitches) then
  2851. begin
  2852. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,r^.base,R_SPPUSH)));
  2853. emitcall('CHECK_OBJECT',true);
  2854. end;
  2855. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,r)));
  2856. end
  2857. else
  2858. emitcall(p^.procdefinition^.mangledname,
  2859. p^.symtableproc^.symtabletype=unitsymtable);
  2860. if ((p^.procdefinition^.options and poclearstack)<>0) then
  2861. begin
  2862. if (pushedparasize > 0) and (pushedparasize < 9) then
  2863. { restore the stack, to its initial value }
  2864. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADDQ,S_L,pushedparasize,R_SP)))
  2865. else
  2866. { restore the stack, to its initial value }
  2867. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADDA,S_L,pushedparasize,R_SP)));
  2868. end;
  2869. end
  2870. else
  2871. begin
  2872. secondpass(p^.right);
  2873. case p^.right^.location.loc of
  2874. LOC_REGISTER,
  2875. LOC_CREGISTER : begin
  2876. if p^.right^.location.register in [R_D0..R_D7] then
  2877. begin
  2878. reg := getaddressreg;
  2879. emit_reg_reg(A_MOVE,S_L,p^.right^.location.register,reg);
  2880. new(ref);
  2881. reset_reference(ref^);
  2882. ref^.base := reg;
  2883. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,ref)));
  2884. ungetregister(reg);
  2885. end
  2886. else
  2887. begin
  2888. new(ref);
  2889. reset_reference(ref^);
  2890. ref^.base := p^.right^.location.register;
  2891. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,ref)));
  2892. end;
  2893. ungetregister32(p^.right^.location.register);
  2894. end
  2895. else
  2896. begin
  2897. if assigned(p^.right^.location.reference.symbol) then
  2898. { Here we have a symbolic name to the routine, so solve }
  2899. { problem by loading the address first, and then emitting }
  2900. { the call. }
  2901. begin
  2902. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  2903. newreference(p^.right^.location.reference),R_A1)));
  2904. new(ref);
  2905. reset_reference(ref^);
  2906. ref^.base := R_A1;
  2907. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,newreference(ref^))));
  2908. end
  2909. else
  2910. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,newreference(p^.right^.location.reference))));
  2911. del_reference(p^.right^.location.reference);
  2912. end;
  2913. end;
  2914. end;
  2915. dont_call:
  2916. pushedparasize:=oldpushedparasize;
  2917. unused:=unusedregisters;
  2918. { handle function results }
  2919. if p^.resulttype<>pdef(voiddef) then
  2920. begin
  2921. { a contructor could be a function with boolean result }
  2922. if (p^.right=nil) and
  2923. ((p^.procdefinition^.options and poconstructor)<>0) and
  2924. { quick'n'dirty check if it is a class or an object }
  2925. (p^.resulttype^.deftype=orddef) then
  2926. begin
  2927. p^.location.loc:=LOC_FLAGS;
  2928. p^.location.resflags:=F_NE;
  2929. if extended_new then
  2930. begin
  2931. {$ifdef test_dest_loc}
  2932. if dest_loc_known and (dest_loc_tree=p) then
  2933. mov_reg_to_dest(p,S_L,R_EAX)
  2934. else
  2935. {$endif test_dest_loc}
  2936. hregister:=getregister32;
  2937. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2938. p^.location.register:=hregister;
  2939. end;
  2940. end
  2941. { structed results are easy to handle.... }
  2942. else if ret_in_param(p^.resulttype) then
  2943. begin
  2944. p^.location.loc:=LOC_MEM;
  2945. stringdispose(p^.location.reference.symbol);
  2946. p^.location.reference:=funcretref;
  2947. end
  2948. else
  2949. begin
  2950. if (p^.resulttype^.deftype=orddef) then
  2951. begin
  2952. p^.location.loc:=LOC_REGISTER;
  2953. case porddef(p^.resulttype)^.typ of
  2954. s32bit,u32bit :
  2955. begin
  2956. hregister:=getregister32;
  2957. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2958. p^.location.register:=hregister;
  2959. end;
  2960. uchar,u8bit,bool8bit,s8bit :
  2961. begin
  2962. hregister:=getregister32;
  2963. emit_reg_reg(A_MOVE,S_B,R_D0,hregister);
  2964. p^.location.register:=hregister;
  2965. end;
  2966. s16bit,u16bit :
  2967. begin
  2968. hregister:=getregister32;
  2969. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2970. p^.location.register:=hregister;
  2971. end;
  2972. else internalerror(7);
  2973. end
  2974. end
  2975. else if (p^.resulttype^.deftype=floatdef) then
  2976. case pfloatdef(p^.resulttype)^.typ of
  2977. f32bit :
  2978. begin
  2979. p^.location.loc:=LOC_REGISTER;
  2980. hregister:=getregister32;
  2981. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2982. p^.location.register:=hregister;
  2983. end;
  2984. s32real,s64bit,s64real,s80real: begin
  2985. if cs_fp_emulation in aktswitches then
  2986. begin
  2987. p^.location.loc:=LOC_FPU;
  2988. hregister:=getregister32;
  2989. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2990. p^.location.fpureg:=hregister;
  2991. end
  2992. else
  2993. begin
  2994. { TRUE FPU mode }
  2995. p^.location.loc:=LOC_FPU;
  2996. { on exit of function result in R_FP0 }
  2997. p^.location.fpureg:=R_FP0;
  2998. end;
  2999. end;
  3000. else
  3001. begin
  3002. p^.location.loc:=LOC_FPU;
  3003. p^.location.fpureg:=R_FP0;
  3004. end;
  3005. end {end case }
  3006. else
  3007. begin
  3008. p^.location.loc:=LOC_REGISTER;
  3009. hregister:=getregister32;
  3010. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  3011. p^.location.register:=hregister;
  3012. end;
  3013. end;
  3014. end;
  3015. { perhaps i/o check ? }
  3016. if iolabel<>nil then
  3017. begin
  3018. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,newcsymbol(lab2str(iolabel),0),R_SPPUSH)));
  3019. { this was wrong, probably an error due to diff3
  3020. emitcall(p^.procdefinition^.mangledname);}
  3021. emitcall('IOCHECK',true);
  3022. end;
  3023. { restore registers }
  3024. popusedregisters(pushed);
  3025. { at last, restore instance pointer (SELF) }
  3026. if loada5 then
  3027. maybe_loada5;
  3028. pp:=params;
  3029. while assigned(pp) do
  3030. begin
  3031. if assigned(pp^.left) then
  3032. if (pp^.left^.location.loc=LOC_REFERENCE) or
  3033. (pp^.left^.location.loc=LOC_MEM) then
  3034. ungetiftemp(pp^.left^.location.reference);
  3035. pp:=pp^.right;
  3036. end;
  3037. disposetree(params);
  3038. end;
  3039. { reverts the parameter list }
  3040. var nb_para : integer;
  3041. function reversparameter(p : ptree) : ptree;
  3042. var
  3043. hp1,hp2 : ptree;
  3044. begin
  3045. hp1:=nil;
  3046. nb_para := 0;
  3047. while assigned(p) do
  3048. begin
  3049. { pull out }
  3050. hp2:=p;
  3051. p:=p^.right;
  3052. inc(nb_para);
  3053. { pull in }
  3054. hp2^.right:=hp1;
  3055. hp1:=hp2;
  3056. end;
  3057. reversparameter:=hp1;
  3058. end;
  3059. procedure secondloadvmt(var p : ptree);
  3060. begin
  3061. p^.location.loc:=LOC_REGISTER;
  3062. p^.location.register:=getregister32;
  3063. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  3064. S_L,newcsymbol(pobjectdef(pclassrefdef(p^.resulttype)^.definition)^.vmt_mangledname,0),
  3065. p^.location.register)));
  3066. end;
  3067. procedure secondinline(var p : ptree);
  3068. const in2size:array[in_inc_byte..in_dec_dword] of Topsize=
  3069. (S_B,S_W,S_L,S_B,S_W,S_L);
  3070. in2instr:array[in_inc_byte..in_dec_dword] of Tasmop=
  3071. (A_ADDQ,A_ADDQ,A_ADDQ,A_SUBQ,A_SUBQ,A_SUBQ);
  3072. { tfloattype = (f32bit,s32real,s64real,s80real,s64bit); }
  3073. float_name: array[tfloattype] of string[8]=
  3074. { ('FIXED','SINGLE','REAL','EXTENDED','COMP','FIXED'); }
  3075. { Since we only support the REAL (SINGLE IEEE) FLOAT }
  3076. { type, here is what we do... }
  3077. ('FIXED','REAL','REAL','REAL','COMP','FIXED');
  3078. var
  3079. opsize: topsize;
  3080. asmop: tasmop;
  3081. aktfile : treference;
  3082. ft : tfiletype;
  3083. pushed : tpushed;
  3084. dummycoll : tdefcoll;
  3085. { produces code for READ(LN) and WRITE(LN) }
  3086. procedure handlereadwrite(doread,callwriteln : boolean);
  3087. procedure loadstream;
  3088. const io:array[0..1] of string[7]=('_OUTPUT','_INPUT');
  3089. var r : preference;
  3090. begin
  3091. new(r);
  3092. reset_reference(r^);
  3093. r^.symbol:=stringdup('U_'+upper(target_info.system_unit)+io[byte(doread)]);
  3094. if not (cs_compilesystem in aktswitches) then
  3095. concat_external(r^.symbol^,EXT_NEAR);
  3096. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,r,R_A0)))
  3097. end;
  3098. var
  3099. node,hp : ptree;
  3100. typedtyp,pararesult : pdef;
  3101. doflush,has_length : boolean;
  3102. dummycoll : tdefcoll;
  3103. iolabel : plabel;
  3104. npara : longint;
  3105. begin
  3106. { I/O check }
  3107. if cs_iocheck in aktswitches then
  3108. begin
  3109. getlabel(iolabel);
  3110. emitl(A_LABEL,iolabel);
  3111. end
  3112. else iolabel:=nil;
  3113. { no automatic call from flush }
  3114. doflush:=false;
  3115. { for write of real with the length specified }
  3116. has_length:=false;
  3117. hp:=nil;
  3118. { reserve temporary pointer to data variable }
  3119. aktfile.symbol:=nil;
  3120. gettempofsizereference(4,aktfile);
  3121. { first state text data }
  3122. ft:=ft_text;
  3123. { and state a parameter ? }
  3124. if p^.left=nil then
  3125. begin
  3126. { state screen address}
  3127. doflush:=true;
  3128. { the following instructions are for "writeln;" }
  3129. loadstream;
  3130. { save @Dateivarible in temporary variable }
  3131. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,R_A0,newreference(aktfile))));
  3132. end
  3133. else
  3134. begin
  3135. { revers paramters }
  3136. node:=reversparameter(p^.left);
  3137. p^.left := node;
  3138. npara := nb_para;
  3139. { calculate data variable }
  3140. { is first parameter a file type ? }
  3141. if node^.left^.resulttype^.deftype=filedef then
  3142. begin
  3143. ft:=pfiledef(node^.left^.resulttype)^.filetype;
  3144. if ft=ft_typed then
  3145. typedtyp:=pfiledef(node^.left^.resulttype)^.typed_as;
  3146. secondpass(node^.left);
  3147. if codegenerror then
  3148. exit;
  3149. { save reference in temporary variables } { reference in tempor„re Variable retten }
  3150. if node^.left^.location.loc<>LOC_REFERENCE then
  3151. begin
  3152. Message(cg_e_illegal_expression);
  3153. exit;
  3154. end;
  3155. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(node^.left^.location.reference),R_A0)));
  3156. { skip to the next parameter }
  3157. node:=node^.right;
  3158. end
  3159. else
  3160. begin
  3161. { if we write to stdout/in then flush after the write(ln) }
  3162. doflush:=true;
  3163. loadstream;
  3164. end;
  3165. { save @Dateivarible in temporary variable }
  3166. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,R_A0,newreference(aktfile))));
  3167. if doread then
  3168. { parameter by READ gives call by reference }
  3169. dummycoll.paratyp:=vs_var
  3170. { an WRITE Call by "Const" }
  3171. else dummycoll.paratyp:=vs_const;
  3172. { because of secondcallparan, which otherwise attaches }
  3173. if ft=ft_typed then
  3174. begin
  3175. { this is to avoid copy of simple const parameters }
  3176. dummycoll.data:=new(pformaldef,init);
  3177. { use var for write also }
  3178. { avoids problems with const passed by value }
  3179. { but will not accept untyped const }
  3180. { dummycoll.paratyp:=vs_var; }
  3181. end
  3182. else
  3183. { I think, this isn't a good solution (FK) }
  3184. dummycoll.data:=nil;
  3185. while assigned(node) do
  3186. begin
  3187. pushusedregisters(pushed,$ffff);
  3188. hp:=node;
  3189. node:=node^.right;
  3190. hp^.right:=nil;
  3191. if hp^.is_colon_para then
  3192. Message(parser_e_illegal_colon_qualifier);
  3193. if hp^.is_colon_para then
  3194. Message(parser_e_illegal_colon_qualifier);
  3195. if ft=ft_typed then
  3196. never_copy_const_param:=true;
  3197. secondcallparan(hp,@dummycoll,false);
  3198. if ft=ft_typed then
  3199. never_copy_const_param:=false;
  3200. hp^.right:=node;
  3201. if codegenerror then
  3202. exit;
  3203. emit_push_mem(aktfile);
  3204. if (ft=ft_typed) then
  3205. begin
  3206. { OK let's try this }
  3207. { first we must only allow the right type }
  3208. { we have to call blockread or blockwrite }
  3209. { but the real problem is that }
  3210. { reset and rewrite should have set }
  3211. { the type size }
  3212. { as recordsize for that file !!!! }
  3213. { how can we make that }
  3214. { I think that is only possible by adding }
  3215. { reset and rewrite to the inline list a call }
  3216. { allways read only one record by element }
  3217. push_int(typedtyp^.size);
  3218. if doread then
  3219. emitcall('TYPED_READ',true)
  3220. else
  3221. emitcall('TYPED_WRITE',true)
  3222. {!!!!!!!}
  3223. end
  3224. else
  3225. begin
  3226. { save current position }
  3227. pararesult:=hp^.left^.resulttype;
  3228. { handle possible field width }
  3229. { of course only for write(ln) }
  3230. if not doread then
  3231. begin
  3232. { handle total width parameter }
  3233. if assigned(node) and node^.is_colon_para then
  3234. begin
  3235. hp:=node;
  3236. node:=node^.right;
  3237. hp^.right:=nil;
  3238. secondcallparan(hp,@dummycoll,false);
  3239. hp^.right:=node;
  3240. if codegenerror then
  3241. exit;
  3242. has_length:=true;
  3243. end
  3244. else
  3245. if pararesult^.deftype<>floatdef then
  3246. push_int(0)
  3247. else
  3248. push_int(-32767);
  3249. { a second colon para for a float ? }
  3250. if assigned(node) and node^.is_colon_para then
  3251. begin
  3252. hp:=node;
  3253. node:=node^.right;
  3254. hp^.right:=nil;
  3255. secondcallparan(hp,@dummycoll,false);
  3256. hp^.right:=node;
  3257. if pararesult^.deftype<>floatdef then
  3258. Message(parser_e_illegal_colon_qualifier);
  3259. if codegenerror then
  3260. exit;
  3261. end
  3262. else
  3263. begin
  3264. if hp^.left^.resulttype^.deftype=floatdef then
  3265. push_int(-1);
  3266. end;
  3267. end;
  3268. case pararesult^.deftype of
  3269. stringdef : begin
  3270. if doread then
  3271. begin
  3272. { push maximum string length }
  3273. push_int(pstringdef(pararesult)^.len);
  3274. case pstringdef(pararesult)^.string_typ of
  3275. shortstring: emitcall ('READ_TEXT_STRING',true);
  3276. ansistring : emitcall ('READ_TEXT_ANSISTRING',true);
  3277. longstring : emitcall ('READ_TEXT_LONGSTRING',true);
  3278. widestring : emitcall ('READ_TEXT_ANSISTRING',true);
  3279. end
  3280. end
  3281. else
  3282. Case pstringdef(Pararesult)^.string_typ of
  3283. shortstring: emitcall ('WRITE_TEXT_STRING',true);
  3284. ansistring : emitcall ('WRITE_TEXT_ANSISTRING',true);
  3285. longstring : emitcall ('WRITE_TEXT_LONGSTRING',true);
  3286. widestring : emitcall ('WRITE_TEXT_ANSISTRING',true);
  3287. end;
  3288. {ungetiftemp(hp^.left^.location.reference);}
  3289. end;
  3290. end;
  3291. pointerdef : begin
  3292. if is_equal(ppointerdef(pararesult)^.definition,cchardef) then
  3293. begin
  3294. if doread then
  3295. emitcall('READ_TEXT_PCHAR_AS_POINTER',true)
  3296. else
  3297. emitcall('WRITE_TEXT_PCHAR_AS_POINTER',true);
  3298. end
  3299. else Message(parser_e_illegal_parameter_list);
  3300. end;
  3301. arraydef : begin
  3302. if (parraydef(pararesult)^.lowrange=0)
  3303. and is_equal(parraydef(pararesult)^.definition,cchardef) then
  3304. begin
  3305. if doread then
  3306. emitcall('READ_TEXT_PCHAR_AS_ARRAY',true)
  3307. else
  3308. emitcall('WRITE_TEXT_PCHAR_AS_ARRAY',true);
  3309. end
  3310. else Message(parser_e_illegal_parameter_list);
  3311. end;
  3312. floatdef : begin
  3313. if doread then
  3314. emitcall('READ_TEXT_REAL',true)
  3315. else
  3316. emitcall('WRITE_TEXT_'+float_name[pfloatdef(pararesult)^.typ],true);
  3317. end;
  3318. orddef : begin
  3319. case porddef(pararesult)^.typ of
  3320. u8bit : if doread then
  3321. emitcall('READ_TEXT_BYTE',true);
  3322. s8bit : if doread then
  3323. emitcall('READ_TEXT_SHORTINT',true);
  3324. u16bit : if doread then
  3325. emitcall('READ_TEXT_WORD',true);
  3326. s16bit : if doread then
  3327. emitcall('READ_TEXT_INTEGER',true);
  3328. s32bit : if doread then
  3329. emitcall('READ_TEXT_LONGINT',true)
  3330. else
  3331. emitcall('WRITE_TEXT_LONGINT',true);
  3332. u32bit : if doread then
  3333. emitcall('READ_TEXT_CARDINAL',true)
  3334. else
  3335. emitcall('WRITE_TEXT_CARDINAL',true);
  3336. uchar : if doread then
  3337. emitcall('READ_TEXT_CHAR',true)
  3338. else
  3339. emitcall('WRITE_TEXT_CHAR',true);
  3340. bool8bit : if doread then
  3341. { emitcall('READ_TEXT_BOOLEAN',true) }
  3342. Message(parser_e_illegal_parameter_list)
  3343. else
  3344. emitcall('WRITE_TEXT_BOOLEAN',true);
  3345. else Message(parser_e_illegal_parameter_list);
  3346. end;
  3347. end;
  3348. else Message(parser_e_illegal_parameter_list);
  3349. end;
  3350. end;
  3351. { load A5 in methods again }
  3352. popusedregisters(pushed);
  3353. maybe_loada5;
  3354. end;
  3355. end;
  3356. if callwriteln then
  3357. begin
  3358. pushusedregisters(pushed,$ffff);
  3359. emit_push_mem(aktfile);
  3360. { pushexceptlabel; }
  3361. if ft<>ft_text then
  3362. Message(parser_e_illegal_parameter_list);
  3363. emitcall('WRITELN_TEXT',true);
  3364. popusedregisters(pushed);
  3365. maybe_loada5;
  3366. end;
  3367. if doflush and not(doread) then
  3368. begin
  3369. pushusedregisters(pushed,$ffff);
  3370. { pushexceptlabel; }
  3371. emitcall('FLUSH_STDOUT',true);
  3372. popusedregisters(pushed);
  3373. maybe_loada5;
  3374. end;
  3375. if iolabel<>nil then
  3376. begin
  3377. { registers are saved in the procedure }
  3378. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,newcsymbol(lab2str(iolabel),0),R_SPPUSH)));
  3379. emitcall('IOCHECK',true);
  3380. end;
  3381. ungetiftemp(aktfile);
  3382. if assigned(p^.left) then
  3383. begin
  3384. p^.left:=reversparameter(p^.left);
  3385. if npara<>nb_para then
  3386. Message(cg_f_internal_error_in_secondinline);
  3387. hp:=p^.left;
  3388. while assigned(hp) do
  3389. begin
  3390. if assigned(hp^.left) then
  3391. if (hp^.left^.location.loc=LOC_REFERENCE) or
  3392. (hp^.left^.location.loc=LOC_MEM) then
  3393. ungetiftemp(hp^.left^.location.reference);
  3394. hp:=hp^.right;
  3395. end;
  3396. end;
  3397. end;
  3398. procedure handle_str;
  3399. var
  3400. hp,node,lentree,paratree : ptree;
  3401. dummycoll : tdefcoll;
  3402. is_real,has_length : boolean;
  3403. real_type : byte;
  3404. begin
  3405. pushusedregisters(pushed,$ffff);
  3406. node:=p^.left;
  3407. is_real:=false;
  3408. has_length:=false;
  3409. while assigned(node^.right) do node:=node^.right;
  3410. { if a real parameter somewhere then call REALSTR }
  3411. if (node^.left^.resulttype^.deftype=floatdef) then
  3412. is_real:=true;
  3413. node:=p^.left;
  3414. { we have at least two args }
  3415. { with at max 2 colon_para in between }
  3416. { first arg longint or float }
  3417. hp:=node;
  3418. node:=node^.right;
  3419. hp^.right:=nil;
  3420. dummycoll.data:=hp^.resulttype;
  3421. { string arg }
  3422. dummycoll.paratyp:=vs_var;
  3423. secondcallparan(hp,@dummycoll,false);
  3424. if codegenerror then
  3425. exit;
  3426. dummycoll.paratyp:=vs_const;
  3427. { second arg }
  3428. hp:=node;
  3429. node:=node^.right;
  3430. hp^.right:=nil;
  3431. { frac para }
  3432. if hp^.is_colon_para and assigned(node) and
  3433. node^.is_colon_para then
  3434. begin
  3435. dummycoll.data:=hp^.resulttype;
  3436. secondcallparan(hp,@dummycoll,false);
  3437. if codegenerror then
  3438. exit;
  3439. hp:=node;
  3440. node:=node^.right;
  3441. hp^.right:=nil;
  3442. has_length:=true;
  3443. end
  3444. else
  3445. if is_real then
  3446. push_int(-1);
  3447. { third arg, length only if is_real }
  3448. if hp^.is_colon_para then
  3449. begin
  3450. dummycoll.data:=hp^.resulttype;
  3451. secondcallparan(hp,@dummycoll,false);
  3452. if codegenerror then
  3453. exit;
  3454. hp:=node;
  3455. node:=node^.right;
  3456. hp^.right:=nil;
  3457. end
  3458. else
  3459. if is_real then
  3460. push_int(-32767)
  3461. else
  3462. push_int(-1);
  3463. { last arg longint or real }
  3464. secondcallparan(hp,@dummycoll,false);
  3465. if codegenerror then
  3466. exit;
  3467. if is_real then
  3468. emitcall('STR_'+float_name[pfloatdef(hp^.resulttype)^.typ],true)
  3469. else if porddef(hp^.resulttype)^.typ=u32bit then
  3470. emitcall('STR_CARDINAL',true)
  3471. else
  3472. emitcall('STR_LONGINT',true);
  3473. popusedregisters(pushed);
  3474. end;
  3475. var
  3476. r : preference;
  3477. begin
  3478. case p^.inlinenumber of
  3479. in_lo_word,
  3480. in_hi_word : begin
  3481. secondpass(p^.left);
  3482. p^.location.loc:=LOC_REGISTER;
  3483. if p^.left^.location.loc<>LOC_REGISTER then
  3484. begin
  3485. if p^.left^.location.loc=LOC_CREGISTER then
  3486. begin
  3487. p^.location.register:=getregister32;
  3488. emit_reg_reg(A_MOVE,S_W,p^.left^.location.register,
  3489. p^.location.register);
  3490. end
  3491. else
  3492. begin
  3493. del_reference(p^.left^.location.reference);
  3494. p^.location.register:=getregister32;
  3495. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  3496. newreference(p^.left^.location.reference),
  3497. p^.location.register)));
  3498. end;
  3499. end
  3500. else p^.location.register:=p^.left^.location.register;
  3501. if p^.inlinenumber=in_hi_word then
  3502. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSR,S_W,8,p^.location.register)));
  3503. p^.location.register:=p^.location.register;
  3504. end;
  3505. in_high_x :
  3506. begin
  3507. if is_open_array(p^.left^.resulttype) then
  3508. begin
  3509. secondpass(p^.left);
  3510. del_reference(p^.left^.location.reference);
  3511. p^.location.register:=getregister32;
  3512. new(r);
  3513. reset_reference(r^);
  3514. r^.base:=highframepointer;
  3515. r^.offset:=highoffset+4;
  3516. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3517. r,p^.location.register)));
  3518. end
  3519. end;
  3520. in_sizeof_x,
  3521. in_typeof_x:
  3522. begin
  3523. { load vmt }
  3524. if p^.left^.treetype=typen then
  3525. begin
  3526. p^.location.register:=getregister32;
  3527. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  3528. S_L,newcsymbol(pobjectdef(p^.left^.resulttype)^.vmt_mangledname,0),
  3529. p^.location.register)));
  3530. end
  3531. else
  3532. begin
  3533. secondpass(p^.left);
  3534. del_reference(p^.left^.location.reference);
  3535. p^.location.loc:=LOC_REGISTER;
  3536. p^.location.register:=getregister32;
  3537. { load VMT pointer }
  3538. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3539. newreference(p^.left^.location.reference),
  3540. p^.location.register)));
  3541. end;
  3542. { in sizeof load size }
  3543. if p^.inlinenumber=in_sizeof_x then
  3544. begin
  3545. new(r);
  3546. reset_reference(r^);
  3547. { load the address in A0 }
  3548. { because now supposedly p^.location.register is an }
  3549. { address. }
  3550. emit_reg_reg(A_MOVE, S_L, p^.location.register, R_A0);
  3551. r^.base:=R_A0;
  3552. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,
  3553. p^.location.register)));
  3554. end;
  3555. end;
  3556. in_lo_long,
  3557. in_hi_long : begin
  3558. secondpass(p^.left);
  3559. p^.location.loc:=LOC_REGISTER;
  3560. if p^.left^.location.loc<>LOC_REGISTER then
  3561. begin
  3562. if p^.left^.location.loc=LOC_CREGISTER then
  3563. begin
  3564. p^.location.register:=getregister32;
  3565. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,
  3566. p^.location.register);
  3567. end
  3568. else
  3569. begin
  3570. del_reference(p^.left^.location.reference);
  3571. p^.location.register:=getregister32;
  3572. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3573. newreference(p^.left^.location.reference),
  3574. p^.location.register)));
  3575. end;
  3576. end
  3577. else p^.location.register:=p^.left^.location.register;
  3578. if p^.inlinenumber=in_hi_long then
  3579. begin
  3580. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVEQ, S_L, 16, R_D1)));
  3581. exprasmlist^.concat(new(pai68k,op_reg_reg(A_LSR,S_L,R_D1,p^.location.register)));
  3582. end;
  3583. p^.location.register:=p^.location.register;
  3584. end;
  3585. {We can now comment them out, as they are handled as typecast.
  3586. Saves an incredible amount of 8 bytes code.
  3587. I'am not lucky about this, because it's _not_ a type cast (FK) }
  3588. { in_ord_char,
  3589. in_chr_byte,}
  3590. in_length_string : begin
  3591. secondpass(p^.left);
  3592. set_location(p^.location,p^.left^.location);
  3593. end;
  3594. in_inc_byte..in_dec_dword:
  3595. begin
  3596. secondpass(p^.left);
  3597. exprasmlist^.concat(new(pai68k,op_const_ref(in2instr[p^.inlinenumber],
  3598. in2size[p^.inlinenumber],1,newreference(p^.left^.location.reference))));
  3599. emitoverflowcheck(p^.left);
  3600. end;
  3601. in_pred_x,
  3602. in_succ_x:
  3603. begin
  3604. secondpass(p^.left);
  3605. if p^.inlinenumber=in_pred_x then
  3606. asmop:=A_SUB
  3607. else
  3608. asmop:=A_ADD;
  3609. case p^.resulttype^.size of
  3610. 4 : opsize:=S_L;
  3611. 2 : opsize:=S_W;
  3612. 1 : opsize:=S_B;
  3613. else
  3614. internalerror(10080);
  3615. end;
  3616. p^.location.loc:=LOC_REGISTER;
  3617. if p^.left^.location.loc<>LOC_REGISTER then
  3618. begin
  3619. p^.location.register:=getregister32;
  3620. if p^.left^.location.loc=LOC_CREGISTER then
  3621. emit_reg_reg(A_MOVE,opsize,p^.left^.location.register,
  3622. p^.location.register)
  3623. else
  3624. if p^.left^.location.loc=LOC_FLAGS then
  3625. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.left^.location.resflags],S_NO,
  3626. p^.location.register)))
  3627. else
  3628. begin
  3629. del_reference(p^.left^.location.reference);
  3630. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,newreference(p^.left^.location.reference),
  3631. p^.location.register)));
  3632. end;
  3633. end
  3634. else p^.location.register:=p^.left^.location.register;
  3635. exprasmlist^.concat(new(pai68k,op_reg(asmop,opsize,
  3636. p^.location.register)))
  3637. { here we should insert bounds check ? }
  3638. { and direct call to bounds will crash the program }
  3639. { if we are at the limit }
  3640. { we could also simply say that pred(first)=first and succ(last)=last }
  3641. { could this be usefull I don't think so (PM)
  3642. emitoverflowcheck;}
  3643. end;
  3644. in_assigned_x:
  3645. begin
  3646. secondpass(p^.left^.left);
  3647. p^.location.loc:=LOC_FLAGS;
  3648. if (p^.left^.left^.location.loc=LOC_REGISTER) or
  3649. (p^.left^.left^.location.loc=LOC_CREGISTER) then
  3650. begin
  3651. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_L,
  3652. p^.left^.left^.location.register)));
  3653. ungetregister32(p^.left^.left^.location.register);
  3654. end
  3655. else
  3656. begin
  3657. exprasmlist^.concat(new(pai68k,op_ref(A_TST,S_L,
  3658. newreference(p^.left^.left^.location.reference))));
  3659. del_reference(p^.left^.left^.location.reference);
  3660. end;
  3661. p^.location.resflags:=F_NE;
  3662. end;
  3663. in_reset_typedfile,in_rewrite_typedfile :
  3664. begin
  3665. pushusedregisters(pushed,$ffff);
  3666. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,
  3667. pfiledef(p^.left^.resulttype)^.typed_as^.size,R_SPPUSH)));
  3668. secondload(p^.left);
  3669. emitpushreferenceaddr(p^.left^.location.reference);
  3670. if p^.inlinenumber=in_reset_typedfile then
  3671. emitcall('RESET_TYPED',true)
  3672. else
  3673. emitcall('REWRITE_TYPED',true);
  3674. popusedregisters(pushed);
  3675. end;
  3676. in_write_x :
  3677. handlereadwrite(false,false);
  3678. in_writeln_x :
  3679. handlereadwrite(false,true);
  3680. in_read_x :
  3681. handlereadwrite(true,false);
  3682. in_readln_x :
  3683. begin
  3684. handlereadwrite(true,false);
  3685. pushusedregisters(pushed,$ffff);
  3686. emit_push_mem(aktfile);
  3687. { pushexceptlabel; }
  3688. if ft<>ft_text then
  3689. Message(parser_e_illegal_parameter_list);
  3690. emitcall('READLN_TEXT',true);
  3691. popusedregisters(pushed);
  3692. maybe_loada5;
  3693. end;
  3694. in_str_x_string : begin
  3695. handle_str;
  3696. maybe_loada5;
  3697. end;
  3698. else internalerror(9);
  3699. end;
  3700. end;
  3701. procedure secondsubscriptn(var p : ptree);
  3702. var
  3703. hr: tregister;
  3704. begin
  3705. secondpass(p^.left);
  3706. if codegenerror then
  3707. exit;
  3708. { classes must be dereferenced implicit }
  3709. if (p^.left^.resulttype^.deftype=objectdef) and
  3710. pobjectdef(p^.left^.resulttype)^.isclass then
  3711. begin
  3712. clear_reference(p^.location.reference);
  3713. case p^.left^.location.loc of
  3714. LOC_REGISTER:
  3715. begin
  3716. { move it to an address register...}
  3717. hr:=getaddressreg;
  3718. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,hr);
  3719. p^.location.reference.base:=hr;
  3720. { free register }
  3721. ungetregister(p^.left^.location.register);
  3722. end;
  3723. LOC_CREGISTER:
  3724. begin
  3725. { ... and reserve one for the pointer }
  3726. hr:=getaddressreg;
  3727. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,hr);
  3728. p^.location.reference.base:=hr;
  3729. end;
  3730. else
  3731. begin
  3732. { free register }
  3733. del_reference(p^.left^.location.reference);
  3734. { ... and reserve one for the pointer }
  3735. hr:=getaddressreg;
  3736. exprasmlist^.concat(new(pai68k,op_ref_reg(
  3737. A_MOVE,S_L,newreference(p^.left^.location.reference),
  3738. hr)));
  3739. p^.location.reference.base:=hr;
  3740. end;
  3741. end;
  3742. end
  3743. else
  3744. set_location(p^.location,p^.left^.location);
  3745. inc(p^.location.reference.offset,p^.vs^.address);
  3746. end;
  3747. procedure secondselfn(var p : ptree);
  3748. begin
  3749. clear_reference(p^.location.reference);
  3750. p^.location.reference.base:=R_A5;
  3751. end;
  3752. procedure secondhdisposen(var p : ptree);
  3753. begin
  3754. secondpass(p^.left);
  3755. if codegenerror then
  3756. exit;
  3757. clear_reference(p^.location.reference);
  3758. case p^.left^.location.loc of
  3759. LOC_REGISTER,
  3760. LOC_CREGISTER : begin
  3761. p^.location.reference.index:=getregister32;
  3762. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  3763. p^.left^.location.register,
  3764. p^.location.reference.index)));
  3765. end;
  3766. LOC_MEM,LOC_REFERENCE :
  3767. begin
  3768. del_reference(p^.left^.location.reference);
  3769. p^.location.reference.index:=getregister32;
  3770. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.left^.location.reference),
  3771. p^.location.reference.index)));
  3772. end;
  3773. end;
  3774. end;
  3775. procedure secondhnewn(var p : ptree);
  3776. begin
  3777. end;
  3778. procedure secondnewn(var p : ptree);
  3779. begin
  3780. secondpass(p^.left);
  3781. if codegenerror then
  3782. exit;
  3783. p^.location.register:=p^.left^.location.register;
  3784. end;
  3785. procedure secondsimplenewdispose(var p : ptree);
  3786. var
  3787. pushed : tpushed;
  3788. begin
  3789. secondpass(p^.left);
  3790. if codegenerror then
  3791. exit;
  3792. pushusedregisters(pushed,$ffff);
  3793. { determines the size of the mem block }
  3794. push_int(ppointerdef(p^.left^.resulttype)^.definition^.size);
  3795. { push pointer adress }
  3796. case p^.left^.location.loc of
  3797. LOC_CREGISTER : exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  3798. p^.left^.location.register,R_SPPUSH)));
  3799. LOC_REFERENCE : emitpushreferenceaddr(p^.left^.location.reference);
  3800. end;
  3801. { call the mem handling procedures }
  3802. case p^.treetype of
  3803. simpledisposen :
  3804. emitcall('FREEMEM',true);
  3805. simplenewn :
  3806. emitcall('GETMEM',true);
  3807. end;
  3808. popusedregisters(pushed);
  3809. { may be load ESI }
  3810. maybe_loada5;
  3811. end;
  3812. procedure secondsetcons(var p : ptree);
  3813. var
  3814. l : plabel;
  3815. i,smallsetvalue : longint;
  3816. hp : ptree;
  3817. href,sref : treference;
  3818. hl1,hl2: plabel;
  3819. begin
  3820. { this should be reimplemented for smallsets }
  3821. { differently (PM) }
  3822. { produce constant part }
  3823. href.symbol := Nil;
  3824. clear_reference(href);
  3825. getlabel(l);
  3826. href.symbol:=stringdup(lab2str(l));
  3827. stringdispose(p^.location.reference.symbol);
  3828. datasegment^.concat(new(pai_label,init(l)));
  3829. {if psetdef(p^.resulttype)=smallset then
  3830. begin
  3831. smallsetvalue:=(p^.constset^[3]*256)+p^.constset^[2];
  3832. smallsetvalue:=((smallset*256+p^.constset^[1])*256+p^.constset^[1];
  3833. datasegment^.concat(new(pai_const,init_32bit(smallsetvalue)));
  3834. hp:=p^.left;
  3835. if assigned(hp) then
  3836. begin
  3837. sref.symbol:=nil;
  3838. gettempofsizereference(32,sref);
  3839. concatcopy(href,sref,32,false);
  3840. while assigned(hp) do
  3841. begin
  3842. secondpass(hp^.left);
  3843. if codegenerror then
  3844. exit;
  3845. pushsetelement(hp^.left);
  3846. emitpushreferenceaddr(sref);
  3847. register is save in subroutine
  3848. emitcall('SET_SET_BYTE',true);
  3849. hp:=hp^.right;
  3850. end;
  3851. p^.location.reference:=sref;
  3852. end
  3853. else p^.location.reference:=href;
  3854. end
  3855. else }
  3856. begin
  3857. for i:=0 to 31 do
  3858. datasegment^.concat(new(pai_const,init_8bit(p^.constset^[i])));
  3859. hp:=p^.left;
  3860. if assigned(hp) then
  3861. begin
  3862. sref.symbol:=nil;
  3863. gettempofsizereference(32,sref);
  3864. concatcopy(href,sref,32,false);
  3865. while assigned(hp) do
  3866. begin
  3867. secondpass(hp^.left);
  3868. if codegenerror then
  3869. exit;
  3870. pushsetelement(hp^.left);
  3871. emitpushreferenceaddr(sref);
  3872. { register is save in subroutine }
  3873. emitcall('SET_SET_BYTE',true);
  3874. { here we must set the flags manually }
  3875. { on returne from the routine, because }
  3876. { falgs are corrupt when restoring the }
  3877. { stack }
  3878. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_B,R_D0)));
  3879. getlabel(hl1);
  3880. emitl(A_BEQ,hl1);
  3881. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_B,
  3882. $fe,R_CCR)));
  3883. getlabel(hl2);
  3884. emitl(A_BRA,hl2);
  3885. emitl(A_LABEL,hl1);
  3886. exprasmlist^.concat(new(pai68k,op_const_reg(A_OR,S_B,
  3887. $01,R_CCR)));
  3888. emitl(A_LABEL,hl2);
  3889. hp:=hp^.right;
  3890. end;
  3891. p^.location.reference:=sref;
  3892. end
  3893. else p^.location.reference:=href;
  3894. end;
  3895. end;
  3896. procedure secondcontinuen(var p : ptree);
  3897. begin
  3898. if aktcontinuelabel<>nil then
  3899. emitl(A_JMP,aktcontinuelabel)
  3900. else
  3901. Message(cg_e_continue_not_allowed);
  3902. end;
  3903. { var
  3904. hs : string; }
  3905. procedure secondexitn(var p : ptree);
  3906. var
  3907. is_mem : boolean;
  3908. {op : tasmop;
  3909. s : topsize;}
  3910. otlabel,oflabel : plabel;
  3911. label
  3912. do_jmp;
  3913. begin
  3914. if assigned(p^.left) then
  3915. begin
  3916. otlabel:=truelabel;
  3917. oflabel:=falselabel;
  3918. getlabel(truelabel);
  3919. getlabel(falselabel);
  3920. secondpass(p^.left);
  3921. case p^.left^.location.loc of
  3922. LOC_FPU : goto do_jmp;
  3923. LOC_MEM,LOC_REFERENCE : is_mem:=true;
  3924. LOC_CREGISTER,
  3925. LOC_REGISTER : is_mem:=false;
  3926. LOC_FLAGS : begin
  3927. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.right^.location.resflags],S_B,R_D0)));
  3928. exprasmlist^.concat(new(pai68k,op_reg(A_NEG, S_B, R_D0)));
  3929. goto do_jmp;
  3930. end;
  3931. LOC_JUMP : begin
  3932. emitl(A_LABEL,truelabel);
  3933. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,1,R_D0)));
  3934. emitl(A_JMP,aktexit2label);
  3935. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_B,R_D0)));
  3936. goto do_jmp;
  3937. end;
  3938. else internalerror(2001);
  3939. end;
  3940. if (procinfo.retdef^.deftype=orddef) then
  3941. begin
  3942. case porddef(procinfo.retdef)^.typ of
  3943. s32bit,u32bit : if is_mem then
  3944. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3945. newreference(p^.left^.location.reference),R_D0)))
  3946. else
  3947. emit_reg_reg(A_MOVE,S_L,
  3948. p^.left^.location.register,R_D0);
  3949. u8bit,s8bit,uchar,bool8bit : if is_mem then
  3950. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,
  3951. newreference(p^.left^.location.reference),R_D0)))
  3952. else
  3953. emit_reg_reg(A_MOVE,S_B,
  3954. p^.left^.location.register,R_D0);
  3955. s16bit,u16bit : if is_mem then
  3956. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  3957. newreference(p^.left^.location.reference),R_D0)))
  3958. else
  3959. emit_reg_reg(A_MOVE,S_W,
  3960. p^.left^.location.register,R_D0);
  3961. end;
  3962. end
  3963. else
  3964. if (procinfo.retdef^.deftype in
  3965. [pointerdef,enumdef,procvardef]) then
  3966. begin
  3967. if is_mem then
  3968. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3969. newreference(p^.left^.location.reference),R_D0)))
  3970. else
  3971. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  3972. p^.left^.location.register,R_D0)));
  3973. end
  3974. else
  3975. if (procinfo.retdef^.deftype=floatdef) then
  3976. { floating point return values .... }
  3977. { single are returned in d0 }
  3978. begin
  3979. if (pfloatdef(procinfo.retdef)^.typ=f32bit) or
  3980. (pfloatdef(procinfo.retdef)^.typ=s32real) then
  3981. begin
  3982. if is_mem then
  3983. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3984. newreference(p^.left^.location.reference),R_D0)))
  3985. else
  3986. begin
  3987. if pfloatdef(procinfo.retdef)^.typ=f32bit then
  3988. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,R_D0)
  3989. else
  3990. begin
  3991. { single values are in the floating point registers }
  3992. if cs_fp_emulation in aktswitches then
  3993. emit_reg_reg(A_MOVE,S_L,p^.left^.location.fpureg,R_D0)
  3994. else
  3995. exprasmlist^.concat(
  3996. new(pai68k,op_reg_reg(A_FMOVE,S_FS,p^.left^.location.fpureg,R_D0)));
  3997. end;
  3998. end;
  3999. end
  4000. else
  4001. { this is only possible in real non emulation mode }
  4002. { LOC_MEM,LOC_REFERENCE }
  4003. if is_mem then
  4004. begin
  4005. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,
  4006. getfloatsize(pfloatdef(procinfo.retdef)^.typ),newreference(p^.left^.location.reference),R_FP0)));
  4007. end
  4008. else
  4009. { LOC_FPU }
  4010. begin
  4011. { convert from extended to correct type }
  4012. { when storing }
  4013. exprasmlist^.concat(new(pai68k,op_reg_reg(A_FMOVE,
  4014. getfloatsize(pfloatdef(procinfo.retdef)^.typ),p^.left^.location.fpureg,R_FP0)));
  4015. end;
  4016. end;
  4017. do_jmp:
  4018. truelabel:=otlabel;
  4019. falselabel:=oflabel;
  4020. emitl(A_JMP,aktexit2label);
  4021. end
  4022. else
  4023. begin
  4024. emitl(A_JMP,aktexitlabel);
  4025. end;
  4026. end;
  4027. procedure secondgoto(var p : ptree);
  4028. begin
  4029. emitl(A_JMP,p^.labelnr);
  4030. end;
  4031. procedure secondlabel(var p : ptree);
  4032. begin
  4033. emitl(A_LABEL,p^.labelnr);
  4034. cleartempgen;
  4035. secondpass(p^.left);
  4036. end;
  4037. procedure secondasm(var p : ptree);
  4038. begin
  4039. exprasmlist^.concatlist(p^.p_asm);
  4040. end;
  4041. procedure secondcase(var p : ptree);
  4042. var
  4043. with_sign : boolean;
  4044. opsize : topsize;
  4045. jmp_gt,jmp_le,jmp_lee : tasmop;
  4046. hp : ptree;
  4047. { register with case expression }
  4048. hregister : tregister;
  4049. endlabel,elselabel : plabel;
  4050. { true, if we can omit the range check of the jump table }
  4051. jumptable_no_range : boolean;
  4052. procedure gentreejmp(p : pcaserecord);
  4053. var
  4054. lesslabel,greaterlabel : plabel;
  4055. begin
  4056. emitl(A_LABEL,p^._at);
  4057. { calculate labels for left and right }
  4058. if (p^.less=nil) then
  4059. lesslabel:=elselabel
  4060. else
  4061. lesslabel:=p^.less^._at;
  4062. if (p^.greater=nil) then
  4063. greaterlabel:=elselabel
  4064. else
  4065. greaterlabel:=p^.greater^._at;
  4066. { calculate labels for left and right }
  4067. { no range label: }
  4068. if p^._low=p^._high then
  4069. begin
  4070. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,p^._low,hregister)));
  4071. if greaterlabel=lesslabel then
  4072. begin
  4073. emitl(A_BNE,lesslabel);
  4074. end
  4075. else
  4076. begin
  4077. emitl(jmp_le,lesslabel);
  4078. emitl(jmp_gt,greaterlabel);
  4079. end;
  4080. emitl(A_JMP,p^.statement);
  4081. end
  4082. else
  4083. begin
  4084. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,p^._low,hregister)));
  4085. emitl(jmp_le,lesslabel);
  4086. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,p^._high,hregister)));
  4087. emitl(jmp_gt,greaterlabel);
  4088. emitl(A_JMP,p^.statement);
  4089. end;
  4090. if assigned(p^.less) then
  4091. gentreejmp(p^.less);
  4092. if assigned(p^.greater) then
  4093. gentreejmp(p^.greater);
  4094. end;
  4095. procedure genlinearlist(hp : pcaserecord);
  4096. var
  4097. first : boolean;
  4098. last : longint;
  4099. procedure genitem(t : pcaserecord);
  4100. begin
  4101. if assigned(t^.less) then
  4102. genitem(t^.less);
  4103. if t^._low=t^._high then
  4104. begin
  4105. if (t^._low-last > 0) and (t^._low-last < 9) then
  4106. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,opsize,t^._low-last,hregister)))
  4107. else
  4108. if (t^._low-last = 0) then
  4109. exprasmlist^.concat(new(pai68k,op_reg(A_TST,opsize,hregister)))
  4110. else
  4111. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._low-last,hregister)));
  4112. last:=t^._low;
  4113. emitl(A_BEQ,t^.statement);
  4114. end
  4115. else
  4116. begin
  4117. { it begins with the smallest label, if the value }
  4118. { is even smaller then jump immediately to the }
  4119. { ELSE-label }
  4120. if first then
  4121. begin
  4122. if (t^._low-1 > 0) and (t^._low < 9) then
  4123. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,opsize,t^._low-1,hregister)))
  4124. else
  4125. if t^._low-1=0 then
  4126. exprasmlist^.concat(new(pai68k,op_reg(A_TST,opsize,hregister)))
  4127. else
  4128. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._low-1,hregister)));
  4129. if t^._low = 0 then
  4130. emitl(A_BLE,elselabel)
  4131. else
  4132. emitl(jmp_lee,elselabel);
  4133. end
  4134. { if there is no unused label between the last and the }
  4135. { present label then the lower limit can be checked }
  4136. { immediately. else check the range in between: }
  4137. else if (t^._low-last>1)then
  4138. begin
  4139. if ((t^._low-last-1) > 0) and ((t^._low-last-1) < 9) then
  4140. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,opsize,t^._low-last-1,hregister)))
  4141. else
  4142. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._low-last-1,hregister)));
  4143. emitl(jmp_lee,elselabel);
  4144. end;
  4145. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._high-t^._low+1,hregister)));
  4146. emitl(jmp_lee,t^.statement);
  4147. last:=t^._high;
  4148. end;
  4149. first:=false;
  4150. if assigned(t^.greater) then
  4151. genitem(t^.greater);
  4152. end;
  4153. var
  4154. hr : tregister;
  4155. begin
  4156. { case register is modified by the list evalution }
  4157. if (p^.left^.location.loc=LOC_CREGISTER) then
  4158. begin
  4159. hr:=getregister32;
  4160. end;
  4161. last:=0;
  4162. first:=true;
  4163. genitem(hp);
  4164. emitl(A_JMP,elselabel);
  4165. end;
  4166. procedure genjumptable(hp : pcaserecord;min_,max_ : longint);
  4167. var
  4168. table : plabel;
  4169. last : longint;
  4170. hr : preference;
  4171. procedure genitem(t : pcaserecord);
  4172. var
  4173. i : longint;
  4174. begin
  4175. if assigned(t^.less) then
  4176. genitem(t^.less);
  4177. { fill possible hole }
  4178. for i:=last+1 to t^._low-1 do
  4179. datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str
  4180. (elselabel)))));
  4181. for i:=t^._low to t^._high do
  4182. datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str
  4183. (t^.statement)))));
  4184. last:=t^._high;
  4185. if assigned(t^.greater) then
  4186. genitem(t^.greater);
  4187. end;
  4188. begin
  4189. if not(jumptable_no_range) then
  4190. begin
  4191. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,min_,hregister)));
  4192. { case expr less than min_ => goto elselabel }
  4193. emitl(jmp_le,elselabel);
  4194. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,max_,hregister)));
  4195. emitl(jmp_gt,elselabel);
  4196. end;
  4197. getlabel(table);
  4198. { extend with sign }
  4199. if opsize=S_W then
  4200. begin
  4201. { word to long - unsigned }
  4202. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$ffff,hregister)));
  4203. end
  4204. else if opsize=S_B then
  4205. begin
  4206. { byte to long - unsigned }
  4207. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$ff,hregister)));
  4208. end;
  4209. new(hr);
  4210. reset_reference(hr^);
  4211. hr^.symbol:=stringdup(lab2str(table));
  4212. hr^.offset:=(-min_)*4;
  4213. { add scalefactor *4 to index }
  4214. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,2,hregister)));
  4215. { hr^.scalefactor:=4; }
  4216. hr^.base:=getaddressreg;
  4217. emit_reg_reg(A_MOVE,S_L,hregister,hr^.base);
  4218. exprasmlist^.concat(new(pai68k,op_ref(A_JMP,S_NO,hr)));
  4219. { if not(cs_littlesize in aktswitches^ ) then
  4220. datasegment^.concat(new(pai68k,op_const(A_ALIGN,S_NO,4))); }
  4221. datasegment^.concat(new(pai_label,init(table)));
  4222. last:=min_;
  4223. genitem(hp);
  4224. if hr^.base <> R_NO then ungetregister(hr^.base);
  4225. { !!!!!!!
  4226. if not(cs_littlesize in aktswitches^ ) then
  4227. exprasmlist^.concat(new(pai68k,op_const(A_ALIGN,S_NO,4)));
  4228. }
  4229. end;
  4230. var
  4231. lv,hv,min_label,max_label,labels : longint;
  4232. max_linear_list : longint;
  4233. begin
  4234. getlabel(endlabel);
  4235. getlabel(elselabel);
  4236. with_sign:=is_signed(p^.left^.resulttype);
  4237. if with_sign then
  4238. begin
  4239. jmp_gt:=A_BGT;
  4240. jmp_le:=A_BLT;
  4241. jmp_lee:=A_BLE;
  4242. end
  4243. else
  4244. begin
  4245. jmp_gt:=A_BHI;
  4246. jmp_le:=A_BCS;
  4247. jmp_lee:=A_BLS;
  4248. end;
  4249. cleartempgen;
  4250. secondpass(p^.left);
  4251. { determines the size of the operand }
  4252. { determines the size of the operand }
  4253. opsize:=bytes2Sxx[p^.left^.resulttype^.size];
  4254. { copy the case expression to a register }
  4255. { copy the case expression to a register }
  4256. case p^.left^.location.loc of
  4257. LOC_REGISTER,
  4258. LOC_CREGISTER : hregister:=p^.left^.location.register;
  4259. LOC_MEM,LOC_REFERENCE : begin
  4260. del_reference(p^.left^.location.reference);
  4261. hregister:=getregister32;
  4262. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,newreference(
  4263. p^.left^.location.reference),hregister)));
  4264. end;
  4265. else internalerror(2002);
  4266. end;
  4267. { now generate the jumps }
  4268. if cs_optimize in aktswitches then
  4269. begin
  4270. { procedures are empirically passed on }
  4271. { consumption can also be calculated }
  4272. { but does it pay on the different }
  4273. { processors? }
  4274. { moreover can the size only be appro- }
  4275. { ximated as it is not known if rel8, }
  4276. { rel16 or rel32 jumps are used }
  4277. min_label:=case_get_min(p^.nodes);
  4278. max_label:=case_get_max(p^.nodes);
  4279. labels:=case_count_labels(p^.nodes);
  4280. { can we omit the range check of the jump table }
  4281. getrange(p^.left^.resulttype,lv,hv);
  4282. jumptable_no_range:=(lv=min_label) and (hv=max_label);
  4283. { optimize for size ? }
  4284. if cs_littlesize in aktswitches then
  4285. begin
  4286. if (labels<=2) or ((max_label-min_label)>3*labels) then
  4287. { a linear list is always smaller than a jump tree }
  4288. genlinearlist(p^.nodes)
  4289. else
  4290. { if the labels less or more a continuum then }
  4291. genjumptable(p^.nodes,min_label,max_label);
  4292. end
  4293. else
  4294. begin
  4295. if jumptable_no_range then
  4296. max_linear_list:=4
  4297. else
  4298. max_linear_list:=2;
  4299. if (labels<=max_linear_list) then
  4300. genlinearlist(p^.nodes)
  4301. else
  4302. begin
  4303. if ((max_label-min_label)>4*labels) then
  4304. begin
  4305. if labels>16 then
  4306. gentreejmp(p^.nodes)
  4307. else
  4308. genlinearlist(p^.nodes);
  4309. end
  4310. else
  4311. genjumptable(p^.nodes,min_label,max_label);
  4312. end;
  4313. end;
  4314. end
  4315. else
  4316. { it's always not bad }
  4317. genlinearlist(p^.nodes);
  4318. { now generate the instructions }
  4319. hp:=p^.right;
  4320. while assigned(hp) do
  4321. begin
  4322. cleartempgen;
  4323. secondpass(hp^.right);
  4324. emitl(A_JMP,endlabel);
  4325. hp:=hp^.left;
  4326. end;
  4327. emitl(A_LABEL,elselabel);
  4328. { ... and the else block }
  4329. if assigned(p^.elseblock) then
  4330. begin
  4331. cleartempgen;
  4332. secondpass(p^.elseblock);
  4333. end;
  4334. emitl(A_LABEL,endlabel);
  4335. end;
  4336. procedure secondtryexcept(var p : ptree);
  4337. begin
  4338. end;
  4339. procedure secondtryfinally(var p : ptree);
  4340. begin
  4341. end;
  4342. procedure secondfail(var p : ptree);
  4343. var hp : preference;
  4344. begin
  4345. {if procinfo.exceptions then
  4346. aktproccode.concat(gennasmrec(CALL,S_NO,'HELP_DESTRUCTOR_E'))
  4347. else }
  4348. { we should know if the constructor is called with a new or not,
  4349. how can we do that ???
  4350. exprasmlist^.concat(new(pai68k,op_csymbol(A_CALL,S_NO,newcsymbol('HELP_DESTRUCTOR',0))));
  4351. }
  4352. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_L,R_A5)));
  4353. { also reset to zero in the stack }
  4354. new(hp);
  4355. reset_reference(hp^);
  4356. hp^.offset:=procinfo.ESI_offset;
  4357. hp^.base:=procinfo.framepointer;
  4358. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,R_A5,hp)));
  4359. exprasmlist^.concat(new(pai_labeled,init(A_JMP,quickexitlabel)));
  4360. end;
  4361. procedure secondas(var p : ptree);
  4362. var
  4363. pushed : tpushed;
  4364. begin
  4365. set_location(p^.location,p^.left^.location);
  4366. { save all used registers }
  4367. pushusedregisters(pushed,$ffff);
  4368. { push the vmt of the class }
  4369. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  4370. S_L,newcsymbol(pobjectdef(p^.right^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  4371. concat_external(pobjectdef(p^.right^.resulttype)^.vmt_mangledname,EXT_NEAR);
  4372. emitpushreferenceaddr(p^.location.reference);
  4373. emitcall('DO_AS',true);
  4374. popusedregisters(pushed);
  4375. end;
  4376. procedure secondis(var p : ptree);
  4377. var
  4378. pushed : tpushed;
  4379. begin
  4380. { save all used registers }
  4381. pushusedregisters(pushed,$ffff);
  4382. secondpass(p^.left);
  4383. p^.location.loc:=LOC_FLAGS;
  4384. p^.location.resflags:=F_NE;
  4385. { push instance to check: }
  4386. case p^.left^.location.loc of
  4387. LOC_REGISTER,LOC_CREGISTER:
  4388. begin
  4389. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,
  4390. S_L,p^.left^.location.register,R_SPPUSH)));
  4391. ungetregister32(p^.left^.location.register);
  4392. end;
  4393. LOC_MEM,LOC_REFERENCE:
  4394. begin
  4395. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,
  4396. S_L,newreference(p^.left^.location.reference),R_SPPUSH)));
  4397. del_reference(p^.left^.location.reference);
  4398. end;
  4399. else internalerror(100);
  4400. end;
  4401. { generate type checking }
  4402. secondpass(p^.right);
  4403. case p^.right^.location.loc of
  4404. LOC_REGISTER,LOC_CREGISTER:
  4405. begin
  4406. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,
  4407. S_L,p^.right^.location.register,R_SPPUSH)));
  4408. ungetregister32(p^.right^.location.register);
  4409. end;
  4410. LOC_MEM,LOC_REFERENCE:
  4411. begin
  4412. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,
  4413. S_L,newreference(p^.right^.location.reference),R_SPPUSH)));
  4414. del_reference(p^.right^.location.reference);
  4415. end;
  4416. else internalerror(100);
  4417. end;
  4418. emitcall('DO_IS',true);
  4419. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_B,R_D0)));
  4420. popusedregisters(pushed);
  4421. end;
  4422. procedure secondwith(var p : ptree);
  4423. var
  4424. ref : treference;
  4425. symtable : psymtable;
  4426. i : longint;
  4427. begin
  4428. if assigned(p^.left) then
  4429. begin
  4430. secondpass(p^.left);
  4431. ref.symbol:=nil;
  4432. gettempofsizereference(4,ref);
  4433. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  4434. newreference(p^.left^.location.reference),R_A0)));
  4435. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,
  4436. R_A0,newreference(ref))));
  4437. del_reference(p^.left^.location.reference);
  4438. { the offset relative to (%ebp) is only needed here! }
  4439. symtable:=p^.withsymtable;
  4440. for i:=1 to p^.tablecount do
  4441. begin
  4442. symtable^.datasize:=ref.offset;
  4443. symtable:=symtable^.next;
  4444. end;
  4445. { p^.right can be optimize out !!! }
  4446. if p^.right<>nil then
  4447. secondpass(p^.right);
  4448. { clear some stuff }
  4449. ungetiftemp(ref);
  4450. end;
  4451. end;
  4452. procedure secondprocinline(var p:ptree);
  4453. begin
  4454. end;
  4455. procedure secondpass(var p : ptree);
  4456. const
  4457. procedures : array[ttreetyp] of secondpassproc =
  4458. (secondadd,secondadd,secondadd,secondmoddiv,secondadd,
  4459. secondmoddiv,secondassignment,secondload,secondnothing,
  4460. secondadd,secondadd,secondadd,secondadd,
  4461. secondadd,secondadd,secondin,secondadd,
  4462. secondadd,secondshlshr,secondshlshr,secondadd,
  4463. secondadd,secondsubscriptn,secondderef,secondaddr,
  4464. seconddoubleaddr,
  4465. secondordconst,secondtypeconv,secondcalln,secondnothing,
  4466. secondrealconst,secondfixconst,secondumminus,
  4467. secondasm,secondvecn,
  4468. secondstringconst,secondfuncret,secondselfn,
  4469. secondnot,secondinline,secondniln,seconderror,
  4470. secondnothing,secondhnewn,secondhdisposen,secondnewn,
  4471. secondsimplenewdispose,secondnothing,secondsetcons,secondblockn,
  4472. secondstatement,secondnothing,secondifn,secondbreakn,
  4473. secondcontinuen,second_while_repeatn,second_while_repeatn,secondfor,
  4474. secondexitn,secondwith,secondcase,secondlabel,
  4475. secondgoto,secondsimplenewdispose,secondtryexcept,secondraise,
  4476. secondnothing,secondtryfinally,secondis,secondas,seconderror,
  4477. secondfail,secondadd,secondprocinline,
  4478. secondnothing,secondloadvmt);
  4479. var
  4480. oldcodegenerror : boolean;
  4481. oldswitches : Tcswitches;
  4482. oldpos : tfileposinfo;
  4483. begin
  4484. oldcodegenerror:=codegenerror;
  4485. oldswitches:=aktswitches;
  4486. get_cur_file_pos(oldpos);
  4487. codegenerror:=false;
  4488. set_cur_file_pos(p^.fileinfo);
  4489. aktswitches:=p^.pragmas;
  4490. if not(p^.error) then
  4491. begin
  4492. procedures[p^.treetype](p);
  4493. p^.error:=codegenerror;
  4494. codegenerror:=codegenerror or oldcodegenerror;
  4495. end
  4496. else
  4497. codegenerror:=true;
  4498. aktswitches:=oldswitches;
  4499. set_cur_file_pos(oldpos);
  4500. end;
  4501. function do_secondpass(var p : ptree) : boolean;
  4502. begin
  4503. codegenerror:=false;
  4504. if not(p^.error) then
  4505. secondpass(p);
  4506. do_secondpass:=codegenerror;
  4507. end;
  4508. var
  4509. regvars : array[1..maxvarregs] of pvarsym;
  4510. regvars_para : array[1..maxvarregs] of boolean;
  4511. regvars_refs : array[1..maxvarregs] of longint;
  4512. parasym : boolean;
  4513. procedure searchregvars(p : psym);
  4514. var
  4515. i,j,k : longint;
  4516. begin
  4517. if (p^.typ=varsym) and ((pvarsym(p)^.var_options and vo_regable)<>0) then
  4518. begin
  4519. { walk through all momentary register variables }
  4520. for i:=1 to maxvarregs do
  4521. begin
  4522. { free register ? }
  4523. if regvars[i]=nil then
  4524. begin
  4525. regvars[i]:=pvarsym(p);
  4526. regvars_para[i]:=parasym;
  4527. break;
  4528. end;
  4529. { else throw out a variable ? }
  4530. j:=pvarsym(p)^.refs;
  4531. { parameter get a less value }
  4532. if parasym then
  4533. begin
  4534. if cs_littlesize in aktswitches then
  4535. dec(j,1)
  4536. else
  4537. dec(j,100);
  4538. end;
  4539. if (j>regvars_refs[i]) and (j>0) then
  4540. begin
  4541. for k:=maxvarregs-1 downto i do
  4542. begin
  4543. regvars[k+1]:=regvars[k];
  4544. regvars_para[k+1]:=regvars_para[k];
  4545. end;
  4546. { calc the new refs
  4547. pvarsym(p)^.refs:=j; }
  4548. regvars[i]:=pvarsym(p);
  4549. regvars_para[i]:=parasym;
  4550. regvars_refs[i]:=j;
  4551. break;
  4552. end;
  4553. end;
  4554. end;
  4555. end;
  4556. procedure generatecode(var p : ptree);
  4557. var
  4558. { *pass modifies with every node aktlinenr and current_module^.current_inputfile, }
  4559. { to constantly contain the right line numbers }
  4560. oldis : pinputfile;
  4561. oldnr,i : longint;
  4562. regsize : topsize;
  4563. regi : tregister;
  4564. hr : preference;
  4565. label
  4566. nextreg;
  4567. begin
  4568. cleartempgen;
  4569. oldis:=current_module^.current_inputfile;
  4570. oldnr:=current_module^.current_inputfile^.line_no;
  4571. { when size optimization only count occurrence }
  4572. if cs_littlesize in aktswitches then
  4573. t_times:=1
  4574. else
  4575. { reference for repetition is 100 }
  4576. t_times:=100;
  4577. { clear register count }
  4578. for regi:=R_D0 to R_A6 do
  4579. begin
  4580. reg_pushes[regi]:=0;
  4581. is_reg_var[regi]:=false;
  4582. end;
  4583. use_esp_stackframe:=false;
  4584. if not(do_firstpass(p)) then
  4585. begin
  4586. { max. optimizations }
  4587. { only if no asm is used }
  4588. if (cs_maxoptimieren in aktswitches) and
  4589. ((procinfo.flags and pi_uses_asm)=0) then
  4590. begin
  4591. { can we omit the stack frame ? }
  4592. { conditions:
  4593. 1. procedure (not main block)
  4594. 2. no constructor or destructor
  4595. 3. no call to other procedures
  4596. 4. no interrupt handler
  4597. }
  4598. if assigned(aktprocsym) then
  4599. begin
  4600. if (aktprocsym^.definition^.options and poconstructor+podestructor+poinline+pointerrupt=0) and
  4601. ((procinfo.flags and pi_do_call)=0) and (lexlevel>1) then
  4602. begin
  4603. { use ESP as frame pointer }
  4604. procinfo.framepointer:=R_SP;
  4605. use_esp_stackframe:=true;
  4606. { calc parameter distance new }
  4607. dec(procinfo.framepointer_offset,4);
  4608. dec(procinfo.ESI_offset,4);
  4609. dec(procinfo.retoffset,4);
  4610. dec(procinfo.call_offset,4);
  4611. aktprocsym^.definition^.parast^.call_offset:=procinfo.call_offset;
  4612. end;
  4613. end; { endif assigned }
  4614. if (p^.registers32<4) then
  4615. begin
  4616. for i:=1 to maxvarregs do
  4617. regvars[i]:=nil;
  4618. parasym:=false;
  4619. {$ifdef tp}
  4620. symtablestack^.foreach(searchregvars);
  4621. {$else}
  4622. symtablestack^.foreach(@searchregvars);
  4623. {$endif}
  4624. { copy parameter into a register ? }
  4625. parasym:=true;
  4626. {$ifdef tp}
  4627. symtablestack^.next^.foreach(searchregvars);
  4628. {$else}
  4629. symtablestack^.next^.foreach(@searchregvars);
  4630. {$endif}
  4631. { hold needed registers free }
  4632. for i:=maxvarregs downto maxvarregs-p^.registers32+1 do
  4633. regvars[i]:=nil;
  4634. { now assign register }
  4635. for i:=1 to maxvarregs do
  4636. begin
  4637. if assigned(regvars[i]) then
  4638. begin
  4639. { it is nonsens, to copy the variable to }
  4640. { a register because we need then much }
  4641. { pushes ? }
  4642. if reg_pushes[varregs[i]]>=regvars[i]^.refs then
  4643. begin
  4644. regvars[i]:=nil;
  4645. goto nextreg;
  4646. end;
  4647. { register is no longer available for }
  4648. { expressions }
  4649. { search the register which is the most }
  4650. { unused }
  4651. usableregs:=usableregs-[varregs[i]];
  4652. is_reg_var[varregs[i]]:=true;
  4653. dec(c_usableregs);
  4654. { possibly no 32 bit register are needed }
  4655. if (regvars[i]^.definition^.deftype=orddef) and
  4656. (
  4657. (porddef(regvars[i]^.definition)^.typ=bool8bit) or
  4658. (porddef(regvars[i]^.definition)^.typ=uchar) or
  4659. (porddef(regvars[i]^.definition)^.typ=u8bit) or
  4660. (porddef(regvars[i]^.definition)^.typ=s8bit)
  4661. ) then
  4662. begin
  4663. regvars[i]^.reg:=varregs[i];
  4664. regsize:=S_B;
  4665. end
  4666. else if (regvars[i]^.definition^.deftype=orddef) and
  4667. (
  4668. (porddef(regvars[i]^.definition)^.typ=u16bit) or
  4669. (porddef(regvars[i]^.definition)^.typ=s16bit)
  4670. ) then
  4671. begin
  4672. regvars[i]^.reg:=varregs[i];
  4673. regsize:=S_W;
  4674. end
  4675. else
  4676. begin
  4677. regvars[i]^.reg:=varregs[i];
  4678. regsize:=S_L;
  4679. end;
  4680. { parameter must be load }
  4681. if regvars_para[i] then
  4682. begin
  4683. { procinfo is there actual, }
  4684. { because we can't never be in a }
  4685. { nested procedure }
  4686. { when loading parameter to reg }
  4687. new(hr);
  4688. reset_reference(hr^);
  4689. hr^.offset:=pvarsym(regvars[i])^.address+procinfo.call_offset;
  4690. hr^.base:=procinfo.framepointer;
  4691. procinfo.aktentrycode^.concat(new(pai68k,op_ref_reg(A_MOVE,regsize,
  4692. hr,regvars[i]^.reg)));
  4693. unused:=unused - [regvars[i]^.reg];
  4694. end;
  4695. { procedure uses this register }
  4696. usedinproc:=usedinproc or ($800 shr word(varregs[i]));
  4697. end;
  4698. nextreg:
  4699. { dummy }
  4700. regsize:=S_W;
  4701. end;
  4702. if (verbosity and v_debug)=v_debug then
  4703. begin
  4704. for i:=1 to maxvarregs do
  4705. begin
  4706. if assigned(regvars[i]) then
  4707. Message3(cg_d_register_weight,reg2str(regvars[i]^.reg),
  4708. tostr(regvars[i]^.refs),regvars[i]^.name);
  4709. end;
  4710. end;
  4711. end;
  4712. end;
  4713. do_secondpass(p);
  4714. { all registers can be used again }
  4715. { contains both information on Address registers and data registers }
  4716. { even if they are allocated separately. }
  4717. usableregs:=[R_D0,R_D1,R_D2,R_D3,R_D4,R_D5,R_D6,R_D7,R_A0,R_A1,R_A2,R_A3,R_A4,
  4718. R_FP0,R_FP1,R_FP2,R_FP3,R_FP4,R_FP5,R_FP6,R_FP7];
  4719. c_usableregs:=4;
  4720. end;
  4721. procinfo.aktproccode^.concatlist(exprasmlist);
  4722. current_module^.current_inputfile:=oldis;
  4723. current_module^.current_inputfile^.line_no:=oldnr;
  4724. end;
  4725. end.
  4726. {
  4727. $Log$
  4728. Revision 1.9 1998-07-06 15:51:16 michael
  4729. Added length checking for string reading
  4730. Revision 1.8 1998/06/12 10:32:22 pierre
  4731. * column problem hopefully solved
  4732. + C vars declaration changed
  4733. Revision 1.7 1998/06/09 16:01:36 pierre
  4734. + added procedure directive parsing for procvars
  4735. (accepted are popstack cdecl and pascal)
  4736. + added C vars with the following syntax
  4737. var C calias 'true_c_name';(can be followed by external)
  4738. reason is that you must add the Cprefix
  4739. which is target dependent
  4740. Revision 1.6 1998/06/08 13:13:36 pierre
  4741. + temporary variables now in temp_gen.pas unit
  4742. because it is processor independent
  4743. * mppc68k.bat modified to undefine i386 and support_mmx
  4744. (which are defaults for i386)
  4745. Revision 1.5 1998/06/04 23:51:34 peter
  4746. * m68k compiles
  4747. + .def file creation moved to gendef.pas so it could also be used
  4748. for win32
  4749. Revision 1.4 1998/04/29 10:33:44 pierre
  4750. + added some code for ansistring (not complete nor working yet)
  4751. * corrected operator overloading
  4752. * corrected nasm output
  4753. + started inline procedures
  4754. + added starstarn : use ** for exponentiation (^ gave problems)
  4755. + started UseTokenInfo cond to get accurate positions
  4756. Revision 1.3 1998/04/07 22:45:03 florian
  4757. * bug0092, bug0115 and bug0121 fixed
  4758. + packed object/class/array
  4759. Revision 1.2 1998/03/28 23:09:54 florian
  4760. * secondin bugfix (m68k and i386)
  4761. * overflow checking bugfix (m68k and i386) -- pretty useless in
  4762. secondadd, since everything is done using 32-bit
  4763. * loading pointer to routines hopefully fixed (m68k)
  4764. * flags problem with calls to RTL internal routines fixed (still strcmp
  4765. to fix) (m68k)
  4766. * #ELSE was still incorrect (didn't take care of the previous level)
  4767. * problem with filenames in the command line solved
  4768. * problem with mangledname solved
  4769. * linking name problem solved (was case insensitive)
  4770. * double id problem and potential crash solved
  4771. * stop after first error
  4772. * and=>test problem removed
  4773. * correct read for all float types
  4774. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  4775. * push/pop is now correct optimized (=> mov (%esp),reg)
  4776. Revision 1.1.1.1 1998/03/25 11:18:16 root
  4777. * Restored version
  4778. Revision 1.51 1998/03/22 12:45:37 florian
  4779. * changes of Carl-Eric to m68k target commit:
  4780. - wrong nodes because of the new string cg in intel, I had to create
  4781. this under m68k also ... had to work it out to fix potential alignment
  4782. problems --> this removes the crash of the m68k compiler.
  4783. - added absolute addressing in m68k assembler (required for Amiga startup)
  4784. - fixed alignment problems (because of byte return values, alignment
  4785. would not be always valid) -- is this ok if i change the offset if odd in
  4786. setfirsttemp ?? -- it seems ok...
  4787. Revision 1.50 2036/02/07 09:29:32 florian
  4788. * patch of Carl applied
  4789. Revision 1.49 1998/03/10 16:27:36 pierre
  4790. * better line info in stabs debug
  4791. * symtabletype and lexlevel separated into two fields of tsymtable
  4792. + ifdef MAKELIB for direct library output, not complete
  4793. + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  4794. working
  4795. + ifdef TESTFUNCRET for setting func result in underfunction, not
  4796. working
  4797. Revision 1.48 1998/03/10 15:25:31 carl
  4798. + put back $L switch for debugging
  4799. Revision 1.47 1998/03/10 04:19:24 carl
  4800. - removed string:=char optimization because would give A LOT of
  4801. register problems
  4802. Revision 1.46 1998/03/10 01:17:15 peter
  4803. * all files have the same header
  4804. * messages are fully implemented, EXTDEBUG uses Comment()
  4805. + AG... files for the Assembler generation
  4806. Revision 1.45 1998/03/09 10:44:33 peter
  4807. + string='', string<>'', string:='', string:=char optimizes (the first 2
  4808. were already in cg68k2)
  4809. Revision 1.44 1998/03/06 00:51:57 peter
  4810. * replaced all old messages from errore.msg, only ExtDebug and some
  4811. Comment() calls are left
  4812. * fixed options.pas
  4813. Revision 1.43 1998/03/05 04:37:46 carl
  4814. + small optimization
  4815. Revision 1.42 1998/03/03 04:13:31 carl
  4816. - removed generate_xxxx and put them in cga68k
  4817. Revision 1.41 1998/03/03 01:08:17 florian
  4818. * bug0105 and bug0106 problem solved
  4819. Revision 1.40 1998/03/02 16:25:25 carl
  4820. * bugfix #95
  4821. Revision 1.39 1998/03/02 01:48:11 peter
  4822. * renamed target_DOS to target_GO32V1
  4823. + new verbose system, merged old errors and verbose units into one new
  4824. verbose.pas, so errors.pas is obsolete
  4825. Revision 1.38 1998/02/25 02:36:29 carl
  4826. * small bugfix with range checking
  4827. Revision 1.37 1998/02/24 16:49:48 peter
  4828. * stackframe ommiting generated 'ret $-4'
  4829. + timer.pp bp7 version
  4830. * innr.inc are now the same files
  4831. Revision 1.36 1998/02/24 16:42:49 carl
  4832. + reinstated __EXIT
  4833. Revision 1.35 1998/02/23 02:56:38 carl
  4834. * bugfix of writing real type values qith m68k target
  4835. Revision 1.34 1998/02/22 23:03:05 peter
  4836. * renamed msource->mainsource and name->unitname
  4837. * optimized filename handling, filename is not seperate anymore with
  4838. path+name+ext, this saves stackspace and a lot of fsplit()'s
  4839. * recompiling of some units in libraries fixed
  4840. * shared libraries are working again
  4841. + $LINKLIB <lib> to support automatic linking to libraries
  4842. + libraries are saved/read from the ppufile, also allows more libraries
  4843. per ppufile
  4844. Revision 1.33 1998/02/22 18:50:12 carl
  4845. * bugfix of stupid diffs!!!!! Recursive crash fix!
  4846. Revision 1.30 1998/02/19 12:22:29 daniel
  4847. * Optimized a statement that did pain to my eyes.
  4848. Revision 1.29 1998/02/17 21:20:31 peter
  4849. + Script unit
  4850. + __EXIT is called again to exit a program
  4851. - target_info.link/assembler calls
  4852. * linking works again for dos
  4853. * optimized a few filehandling functions
  4854. * fixed stabs generation for procedures
  4855. Revision 1.28 1998/02/15 21:16:04 peter
  4856. * all assembler outputs supported by assemblerobject
  4857. * cleanup with assembleroutputs, better .ascii generation
  4858. * help_constructor/destructor are now added to the externals
  4859. - generation of asmresponse is not outputformat depended
  4860. Revision 1.27 1998/02/14 05:06:47 carl
  4861. + now works with TP with overlays
  4862. Revision 1.26 1998/02/14 01:45:06 peter
  4863. * more fixes
  4864. - pmode target is removed
  4865. - search_as_ld is removed, this is done in the link.pas/assemble.pas
  4866. + findexe() to search for an executable (linker,assembler,binder)
  4867. Revision 1.25 1998/02/13 10:34:40 daniel
  4868. * Made Motorola version compilable.
  4869. * Fixed optimizer
  4870. Revision 1.24 1998/02/12 11:49:45 daniel
  4871. Yes! Finally! After three retries, my patch!
  4872. Changes:
  4873. Complete rewrite of psub.pas.
  4874. Added support for DLL's.
  4875. Compiler requires less memory.
  4876. Platform units for each platform.
  4877. Revision 1.23 1998/02/07 18:00:45 carl
  4878. * bugfix in secondin (from Peter Vreman a while ago)
  4879. Revision 1.21 1998/02/05 00:58:05 carl
  4880. + secondas and secondis now work as expected.
  4881. - moved secondas to cg68k2, otherwise problems with symbols
  4882. Revision 1.20 1998/02/01 19:38:41 florian
  4883. * bug0029 fixed, Carl please check it !!!
  4884. Revision 1.19 1998/01/24 21:05:41 carl
  4885. * nested comment bugfix
  4886. Revision 1.18 1998/01/24 00:37:47 florian
  4887. * small fix for DOM
  4888. Revision 1.17 1998/01/21 21:29:46 florian
  4889. * some fixes for Delphi classes
  4890. Revision 1.16 1998/01/20 23:51:59 carl
  4891. * bugfix 74 (FINAL, Pierre's one was incomplete under BP)
  4892. Revision 1.15 1998/01/19 10:25:21 pierre
  4893. * bug in object function call in main program or unit init fixed
  4894. Revision 1.14 1998/01/16 22:34:23 michael
  4895. * Changed 'conversation' to 'conversion'. Waayyy too much chatting going on
  4896. in this compiler :)
  4897. Revision 1.13 1998/01/16 02:18:25 carl
  4898. * second_char_to_string align problem fix (N/A for MC68020 target)
  4899. Revision 1.12 1998/01/13 23:11:02 florian
  4900. + class methods
  4901. Revision 1.11 1998/01/11 03:36:14 carl
  4902. * fixed indexing problem with stack
  4903. * reference on stack bugfix
  4904. * second_bigger sign extension bugfix
  4905. * array scaling bugfix
  4906. * secondderef bugfix
  4907. * bugfix with MOVEQ opcode
  4908. * bugfix of linear list generation
  4909. Revision 1.6 1997/12/10 23:07:12 florian
  4910. * bugs fixed: 12,38 (also m68k),39,40,41
  4911. + warning if a system unit is without -Us compiled
  4912. + warning if a method is virtual and private (was an error)
  4913. * some indentions changed
  4914. + factor does a better error recovering (omit some crashes)
  4915. + problem with @type(x) removed (crashed the compiler)
  4916. Revision 1.5 1997/12/09 13:28:48 carl
  4917. + added s80 real (will presently stop the compiler though)
  4918. + renamed some stuff
  4919. * some bugfixes (can't remember what exactly..)
  4920. Revision 1.4 1997/12/05 14:51:09 carl
  4921. * bugfix of secondfor
  4922. cmpreg was never initialized.
  4923. one of the jump conditionals was wrong (downto would not work)
  4924. Revision 1.3 1997/12/04 14:47:05 carl
  4925. + updated tov09...
  4926. Revision 1.2 1997/11/28 18:14:20 pierre
  4927. working version with several bug fixes
  4928. Revision 1.1.1.1 1997/11/27 08:32:51 michael
  4929. FPC Compiler CVS start
  4930. Pre-CVS log:
  4931. CEC Carl-Eric Codere
  4932. FK Florian Klaempfl
  4933. PM Pierre Muller
  4934. + feature added
  4935. - removed
  4936. * bug fixed or changed
  4937. History (started with version 0.9.0):
  4938. 23th october 1996:
  4939. + some emit calls replaced (FK)
  4940. 24th october 1996:
  4941. * for bug fixed (FK)
  4942. 26th october 1996:
  4943. * english comments (FK)
  4944. 5th november 1996:
  4945. * new init and terminate code (FK)
  4946. ...... some items missed
  4947. 19th september 1997:
  4948. * a call to a function procedure a;[ C ]; doesn't crash the stack
  4949. furthermore (FK)
  4950. 22th september 1997:
  4951. * stack layout for nested procedures in methods modified:
  4952. ESI is no more pushed (must be loaded via framepointer) (FK)
  4953. 27th september 1997:
  4954. + Start of conversion to motorola MC68000 (CEC)
  4955. 29th september 1997:
  4956. + Updated to version 0.9.4 of Intel code generator (CEC)
  4957. 3th october 1997:
  4958. + function second_bool_to_byte for ord(boolean) (PM)
  4959. 4th october 1997: (CEC)
  4960. + first compilation
  4961. 5th octover 1997:
  4962. check floating point negate when i can test everything,
  4963. to see if it makes any sense , according SINGLE_NEG from
  4964. sozobon, it does not.??
  4965. 8th october 1997:
  4966. + ord(x) support (FK)
  4967. + some stuff for typed file support (FK)
  4968. 9 october 1997:
  4969. + converted code to motorola for v096 (CEC)
  4970. 18 october 1997:
  4971. +* removed bugs relating to floating point condition codes. (CEC).
  4972. (in secondadd).
  4973. + had to put secondadd in another routine to compile in tp. (CEC).
  4974. + updated second_bool_to_byte,secondtypeconv and secondinline, secondvecn to v097 (CEC)
  4975. + updated secondload and secondstringconst (merging duplicate strings),secondfor to v95/v97 (CEC).
  4976. + finally converted second_fix_real (very difficult and untested!). (CEC)
  4977. 23 october 1997:
  4978. * bugfix of address register in usableregs set. (They were not defined...) (CEC).
  4979. 24 october 1997:
  4980. * bugfix of scalefactor, allowed unrolled using lsl. (CEC).
  4981. 27th october 1997:
  4982. + now all general purpose registers are in the unused list, so this fixes problems
  4983. regarding pushing registers (such as d0) which were actually never used. (CEC)
  4984. + added secondin (FK) (all credit goes to him).
  4985. + converted second_real_fix thanks to Daniel Mantione for the information
  4986. he gave me on the fixed format. Thanks to W. Metzenthen who did WMEmu
  4987. (which in turn gave me information on the control word of the intel fpu). (CEC)
  4988. 23rd november 1997:
  4989. + changed second_int_real to apply correct calling conventions of rtl.
  4990. 26th november 1997:
  4991. + changed secondmoddiv to apply correct calling conventions of rtl
  4992. and also optimized it a bit.
  4993. }