cg68k.pas 233 KB

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