cg68k.pas 229 KB

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