cg68k.pas 232 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404
  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_FX,
  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_FX,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:=false;
  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_IQ,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_smaller,second_smaller,
  2153. second_smaller,second_smaller,
  2154. second_int_real,second_real_fix,
  2155. second_fix_real,second_int_fix,second_float_float,
  2156. second_chararray_to_string,second_bool_to_byte,
  2157. second_proc_to_procvar,
  2158. { is constant char to pchar, is done by firstpass }
  2159. second_nothing);
  2160. begin
  2161. { this isn't good coding, I think tc_bool_2_u8bit, shouldn't be }
  2162. { type conversion (FK) }
  2163. { this is necessary, because second_bool_byte, have to change }
  2164. { true- and false label before calling secondpass }
  2165. if p^.convtyp<>tc_bool_2_u8bit then
  2166. begin
  2167. secondpass(p^.left);
  2168. set_location(p^.location,p^.left^.location);
  2169. end;
  2170. if p^.convtyp<>tc_equal then
  2171. {the second argument only is for maybe_range_checking !}
  2172. secondconvert[p^.convtyp](p,p^.left,p^.convtyp)
  2173. end;
  2174. { save the size of pushed parameter }
  2175. var
  2176. pushedparasize : longint;
  2177. procedure secondcallparan(var p : ptree;defcoll : pdefcoll;
  2178. push_from_left_to_right : boolean);
  2179. var
  2180. size : longint;
  2181. stackref : treference;
  2182. otlabel,hlabel,oflabel : plabel;
  2183. { temporary variables: }
  2184. tempdeftype : tdeftype;
  2185. tempreference : treference;
  2186. r : preference;
  2187. s : topsize;
  2188. op : tasmop;
  2189. begin
  2190. { push from left to right if specified }
  2191. if push_from_left_to_right and assigned(p^.right) then
  2192. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right);
  2193. otlabel:=truelabel;
  2194. oflabel:=falselabel;
  2195. getlabel(truelabel);
  2196. getlabel(falselabel);
  2197. secondpass(p^.left);
  2198. { in codegen.handleread.. defcoll^.data is set to nil }
  2199. if assigned(defcoll^.data) and
  2200. (defcoll^.data^.deftype=formaldef) then
  2201. begin
  2202. { allow @var }
  2203. if p^.left^.treetype=addrn then
  2204. begin
  2205. { allways a register }
  2206. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,p^.left^.location.register,R_SPPUSH)));
  2207. ungetregister32(p^.left^.location.register);
  2208. end
  2209. else
  2210. begin
  2211. if (p^.left^.location.loc<>LOC_REFERENCE) and
  2212. (p^.left^.location.loc<>LOC_MEM) then
  2213. Message(sym_e_type_mismatch)
  2214. else
  2215. begin
  2216. emitpushreferenceaddr(p^.left^.location.reference);
  2217. del_reference(p^.left^.location.reference);
  2218. end;
  2219. end;
  2220. inc(pushedparasize,4);
  2221. end
  2222. { handle call by reference parameter }
  2223. else if (defcoll^.paratyp=vs_var) then
  2224. begin
  2225. if (p^.left^.location.loc<>LOC_REFERENCE) then
  2226. Message(cg_e_var_must_be_reference);
  2227. { open array ? }
  2228. { defcoll^.data can be nil for read/write }
  2229. if assigned(defcoll^.data) and
  2230. is_open_array(defcoll^.data) then
  2231. begin
  2232. { push high }
  2233. if is_open_array(p^.left^.resulttype) then
  2234. begin
  2235. new(r);
  2236. reset_reference(r^);
  2237. r^.base:=highframepointer;
  2238. r^.offset:=highoffset+4;
  2239. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_SPPUSH)));
  2240. end
  2241. else
  2242. push_int(parraydef(p^.left^.resulttype)^.highrange-
  2243. parraydef(p^.left^.resulttype)^.lowrange);
  2244. inc(pushedparasize,4);
  2245. end;
  2246. emitpushreferenceaddr(p^.left^.location.reference);
  2247. del_reference(p^.left^.location.reference);
  2248. inc(pushedparasize,4);
  2249. end
  2250. else
  2251. begin
  2252. tempdeftype:=p^.resulttype^.deftype;
  2253. if tempdeftype=filedef then
  2254. Message(cg_e_file_must_call_by_reference);
  2255. if (defcoll^.paratyp=vs_const) and
  2256. dont_copy_const_param(p^.resulttype) then
  2257. begin
  2258. emitpushreferenceaddr(p^.left^.location.reference);
  2259. del_reference(p^.left^.location.reference);
  2260. inc(pushedparasize,4);
  2261. end
  2262. else
  2263. case p^.left^.location.loc of
  2264. LOC_REGISTER,
  2265. LOC_CREGISTER : begin
  2266. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  2267. p^.left^.location.register,R_SPPUSH)));
  2268. inc(pushedparasize,4);
  2269. ungetregister32(p^.left^.location.register);
  2270. end;
  2271. LOC_FPU : begin
  2272. size:=pfloatdef(p^.left^.resulttype)^.size;
  2273. inc(pushedparasize,size);
  2274. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,S_L,size,R_SP)));
  2275. new(r);
  2276. reset_reference(r^);
  2277. r^.base:=R_SP;
  2278. s:=getfloatsize(pfloatdef(p^.left^.resulttype)^.typ);
  2279. if (cs_fp_emulation in aktswitches) then
  2280. begin
  2281. { when in emulation mode... }
  2282. { only single supported!!! }
  2283. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,
  2284. p^.left^.location.fpureg,r)));
  2285. end
  2286. else
  2287. { convert back from extended to normal type }
  2288. exprasmlist^.concat(new(pai68k,op_reg_ref(A_FMOVE,s,
  2289. p^.left^.location.fpureg,r)));
  2290. end;
  2291. LOC_REFERENCE,LOC_MEM :
  2292. begin
  2293. tempreference:=p^.left^.location.reference;
  2294. del_reference(p^.left^.location.reference);
  2295. case p^.resulttype^.deftype of
  2296. orddef : begin
  2297. case porddef(p^.resulttype)^.typ of
  2298. s32bit,u32bit :
  2299. begin
  2300. emit_push_mem(tempreference);
  2301. inc(pushedparasize,4);
  2302. end;
  2303. s8bit,u8bit,uchar,bool8bit,s16bit,u16bit : begin
  2304. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  2305. newreference(tempreference),R_SPPUSH)));
  2306. inc(pushedparasize,2);
  2307. end;
  2308. end;
  2309. end;
  2310. floatdef : begin
  2311. case pfloatdef(p^.resulttype)^.typ of
  2312. f32bit,
  2313. s32real :
  2314. begin
  2315. emit_push_mem(tempreference);
  2316. inc(pushedparasize,4);
  2317. end;
  2318. s64real:
  2319. {s64bit }
  2320. begin
  2321. inc(tempreference.offset,4);
  2322. emit_push_mem(tempreference);
  2323. dec(tempreference.offset,4);
  2324. emit_push_mem(tempreference);
  2325. inc(pushedparasize,8);
  2326. end;
  2327. {$ifdef use48}
  2328. s48real : begin
  2329. end;
  2330. {$endif}
  2331. s80real : begin
  2332. Message(cg_f_extended_cg68k_not_supported);
  2333. { inc(tempreference.offset,6);
  2334. emit_push_mem(tempreference);
  2335. dec(tempreference.offset,4);
  2336. emit_push_mem(tempreference);
  2337. dec(tempreference.offset,2);
  2338. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  2339. newreference(tempreference),R_SPPUSH)));
  2340. inc(pushedparasize,extended_size);}
  2341. end;
  2342. end;
  2343. end;
  2344. pointerdef,procvardef,
  2345. enumdef,classrefdef: begin
  2346. emit_push_mem(tempreference);
  2347. inc(pushedparasize,4);
  2348. end;
  2349. arraydef,recorddef,stringdef,setdef,objectdef :
  2350. begin
  2351. if ((p^.resulttype^.deftype=setdef) and
  2352. (psetdef(p^.resulttype)^.settype=smallset)) then
  2353. begin
  2354. emit_push_mem(tempreference);
  2355. inc(pushedparasize,4);
  2356. end
  2357. else
  2358. begin
  2359. size:=p^.resulttype^.size;
  2360. { Alignment }
  2361. {
  2362. if (size>=4) and ((size and 3)<>0) then
  2363. inc(size,4-(size and 3))
  2364. else if (size>=2) and ((size and 1)<>0) then
  2365. inc(size,2-(size and 1))
  2366. else
  2367. if size=1 then size:=2;
  2368. }
  2369. { create stack space }
  2370. if (size > 0) and (size < 9) then
  2371. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,S_L,size,R_SP)))
  2372. else
  2373. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBA,
  2374. S_L,size,R_SP)));
  2375. inc(pushedparasize,size);
  2376. { create stack reference }
  2377. stackref.symbol := nil;
  2378. clear_reference(stackref);
  2379. stackref.base:=R_SP;
  2380. { produce copy }
  2381. if p^.resulttype^.deftype=stringdef then
  2382. begin
  2383. copystring(stackref,p^.left^.location.reference,
  2384. pstringdef(p^.resulttype)^.len);
  2385. end
  2386. else
  2387. begin
  2388. concatcopy(p^.left^.location.reference,
  2389. stackref,p^.resulttype^.size,true);
  2390. end;
  2391. end;
  2392. end;
  2393. else Message(cg_e_illegal_expression);
  2394. end;
  2395. end;
  2396. LOC_JUMP : begin
  2397. getlabel(hlabel);
  2398. inc(pushedparasize,2);
  2399. emitl(A_LABEL,truelabel);
  2400. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_W,1,R_SPPUSH)));
  2401. emitl(A_JMP,hlabel);
  2402. emitl(A_LABEL,falselabel);
  2403. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_W,0,R_SPPUSH)));
  2404. emitl(A_LABEL,hlabel);
  2405. end;
  2406. LOC_FLAGS : begin
  2407. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.left^.location.resflags],S_B,
  2408. R_D0)));
  2409. exprasmlist^.concat(new(pai68k,op_reg(A_NEG, S_B, R_D0)));
  2410. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_W,$ff, R_D0)));
  2411. inc(pushedparasize,2);
  2412. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,R_D0,R_SPPUSH)));
  2413. end;
  2414. end;
  2415. end;
  2416. truelabel:=otlabel;
  2417. falselabel:=oflabel;
  2418. { push from right to left }
  2419. if not push_from_left_to_right and assigned(p^.right) then
  2420. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right);
  2421. end;
  2422. procedure secondcalln(var p : ptree);
  2423. var
  2424. unusedregisters : tregisterset;
  2425. pushed : tpushed;
  2426. funcretref : treference;
  2427. hregister : tregister;
  2428. oldpushedparasize : longint;
  2429. { true if a5 must be loaded again after the subroutine }
  2430. loada5 : boolean;
  2431. { true if a virtual method must be called directly }
  2432. no_virtual_call : boolean;
  2433. { true if we produce a con- or destrutor in a call }
  2434. is_con_or_destructor : boolean;
  2435. { true if a constructor is called again }
  2436. extended_new : boolean;
  2437. { adress returned from an I/O-error }
  2438. iolabel : plabel;
  2439. { lexlevel count }
  2440. i : longint;
  2441. { help reference pointer }
  2442. r : preference;
  2443. pp,params : ptree;
  2444. { temp register allocation }
  2445. reg: tregister;
  2446. { help reference pointer }
  2447. ref: preference;
  2448. label
  2449. dont_call;
  2450. begin
  2451. extended_new:=false;
  2452. iolabel:=nil;
  2453. loada5:=true;
  2454. no_virtual_call:=false;
  2455. unusedregisters:=unused;
  2456. if not assigned(p^.procdefinition) then
  2457. exit;
  2458. { only if no proc var }
  2459. if not(assigned(p^.right)) then
  2460. is_con_or_destructor:=((p^.procdefinition^.options and poconstructor)<>0)
  2461. or ((p^.procdefinition^.options and podestructor)<>0);
  2462. { proc variables destroy all registers }
  2463. if (p^.right=nil) and
  2464. { virtual methods too }
  2465. ((p^.procdefinition^.options and povirtualmethod)=0) then
  2466. begin
  2467. if ((p^.procdefinition^.options and poiocheck)<>0)
  2468. and (cs_iocheck in aktswitches) then
  2469. begin
  2470. getlabel(iolabel);
  2471. emitl(A_LABEL,iolabel);
  2472. end
  2473. else iolabel:=nil;
  2474. { save all used registers }
  2475. pushusedregisters(pushed,p^.procdefinition^.usedregisters);
  2476. { give used registers through }
  2477. usedinproc:=usedinproc or p^.procdefinition^.usedregisters;
  2478. end
  2479. else
  2480. begin
  2481. pushusedregisters(pushed,$ffff);
  2482. usedinproc:=$ffff;
  2483. { no IO check for methods and procedure variables }
  2484. iolabel:=nil;
  2485. end;
  2486. { generate the code for the parameter and push them }
  2487. oldpushedparasize:=pushedparasize;
  2488. pushedparasize:=0;
  2489. if (p^.resulttype<>pdef(voiddef)) and
  2490. ret_in_param(p^.resulttype) then
  2491. begin
  2492. funcretref.symbol:=nil;
  2493. {$ifdef test_dest_loc}
  2494. if dest_loc_known and (dest_loc_tree=p) and
  2495. (dest_loc.loc in [LOC_REFERENCE,LOC_MEM]) then
  2496. begin
  2497. funcretref:=dest_loc.reference;
  2498. if assigned(dest_loc.reference.symbol) then
  2499. funcretref.symbol:=stringdup(dest_loc.reference.symbol^);
  2500. in_dest_loc:=true;
  2501. end
  2502. else
  2503. {$endif test_dest_loc}
  2504. gettempofsizereference(p^.procdefinition^.retdef^.size,funcretref);
  2505. end;
  2506. if assigned(p^.left) then
  2507. begin
  2508. pushedparasize:=0;
  2509. { be found elsewhere }
  2510. if assigned(p^.right) then
  2511. secondcallparan(p^.left,pprocvardef(p^.right^.resulttype)^.para1,
  2512. (p^.procdefinition^.options and poleftright)<>0)
  2513. else
  2514. secondcallparan(p^.left,p^.procdefinition^.para1,
  2515. (p^.procdefinition^.options and poleftright)<>0);
  2516. end;
  2517. params:=p^.left;
  2518. p^.left:=nil;
  2519. if ret_in_param(p^.resulttype) then
  2520. begin
  2521. emitpushreferenceaddr(funcretref);
  2522. inc(pushedparasize,4);
  2523. end;
  2524. { overloaded operator have no symtable }
  2525. if (p^.right=nil) then
  2526. begin
  2527. { push self }
  2528. if assigned(p^.symtable) and
  2529. (p^.symtable^.symtabletype=withsymtable) then
  2530. begin
  2531. { dirty trick to avoid the secondcall below }
  2532. p^.methodpointer:=genzeronode(callparan);
  2533. p^.methodpointer^.location.loc:=LOC_REGISTER;
  2534. p^.methodpointer^.location.register:=R_A5;
  2535. { make a reference }
  2536. new(r);
  2537. reset_reference(r^);
  2538. r^.offset:=p^.symtable^.datasize;
  2539. r^.base:=procinfo.framepointer;
  2540. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_A5)));
  2541. end;
  2542. { push self }
  2543. if assigned(p^.symtable) and
  2544. ((p^.symtable^.symtabletype=objectsymtable) or
  2545. (p^.symtable^.symtabletype=withsymtable)) then
  2546. begin
  2547. if assigned(p^.methodpointer) then
  2548. begin
  2549. case p^.methodpointer^.treetype of
  2550. typen : begin
  2551. { direct call to inherited method }
  2552. if (p^.procdefinition^.options and poabstractmethod)<>0 then
  2553. begin
  2554. Message(cg_e_cant_call_abstract_method);
  2555. goto dont_call;
  2556. end;
  2557. { generate no virtual call }
  2558. no_virtual_call:=true;
  2559. if (p^.symtableprocentry^.properties and sp_static)<>0 then
  2560. begin
  2561. { well lets put the VMT address directly into a5 }
  2562. { it is kind of dirty but that is the simplest }
  2563. { way to accept virtual static functions (PM) }
  2564. loada5:=true;
  2565. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2566. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_A5)));
  2567. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2568. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2569. end
  2570. else
  2571. { this is a member call, so A5 isn't modfied }
  2572. loada5:=false;
  2573. if not(is_con_or_destructor and
  2574. pobjectdef(p^.methodpointer^.resulttype)^.isclass and
  2575. assigned(aktprocsym) and
  2576. ((aktprocsym^.definition^.options and
  2577. (poconstructor or podestructor))<>0)) then
  2578. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2579. { if an inherited con- or destructor should be }
  2580. { called in a con- or destructor then a warning }
  2581. { will be made }
  2582. { con- and destructors need a pointer to the vmt }
  2583. if is_con_or_destructor and
  2584. ((pobjectdef(p^.methodpointer^.resulttype)^.options and oois_class)=0) and
  2585. assigned(aktprocsym) then
  2586. begin
  2587. if not ((aktprocsym^.definition^.options
  2588. and (poconstructor or podestructor))<>0) then
  2589. Message(cg_w_member_cd_call_from_method);
  2590. end;
  2591. { con- and destructors need a pointer to the vmt }
  2592. if is_con_or_destructor then
  2593. begin
  2594. { classes need the mem ! }
  2595. if ((pobjectdef(p^.methodpointer^.resulttype)^.options and
  2596. oois_class)=0) then
  2597. push_int(0)
  2598. else
  2599. begin
  2600. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  2601. S_L,newcsymbol(pobjectdef(p^.methodpointer^.
  2602. resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2603. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.
  2604. vmt_mangledname,EXT_NEAR);
  2605. end;
  2606. end;
  2607. end;
  2608. hnewn : begin
  2609. { extended syntax of new }
  2610. { A5 must be zero }
  2611. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,0,R_A5)));
  2612. emit_reg_reg(A_MOVE,S_L,R_A5, R_SPPUSH);
  2613. { insert the vmt }
  2614. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2615. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2616. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2617. extended_new:=true;
  2618. end;
  2619. hdisposen : begin
  2620. secondpass(p^.methodpointer);
  2621. { destructor with extended syntax called from dispose }
  2622. { hdisposen always deliver LOC_REFRENZ }
  2623. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  2624. newreference(p^.methodpointer^.location.reference),R_A5)));
  2625. del_reference(p^.methodpointer^.location.reference);
  2626. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2627. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2628. newcsymbol(pobjectdef
  2629. (p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2630. concat_external(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2631. end;
  2632. else
  2633. begin
  2634. { call to a instance member }
  2635. if (p^.symtable^.symtabletype<>withsymtable) then
  2636. begin
  2637. secondpass(p^.methodpointer);
  2638. case p^.methodpointer^.location.loc of
  2639. LOC_REGISTER :
  2640. begin
  2641. ungetregister32(p^.methodpointer^.location.register);
  2642. emit_reg_reg(A_MOVE,S_L,p^.methodpointer^.location.register,R_A5);
  2643. end;
  2644. else
  2645. begin
  2646. if (p^.methodpointer^.resulttype^.deftype=objectdef) and
  2647. pobjectdef(p^.methodpointer^.resulttype)^.isclass then
  2648. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  2649. newreference(p^.methodpointer^.location.reference),R_A5)))
  2650. else
  2651. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  2652. newreference(p^.methodpointer^.location.reference),R_A5)));
  2653. del_reference(p^.methodpointer^.location.reference);
  2654. end;
  2655. end;
  2656. end;
  2657. { when calling a class method, we have
  2658. to load ESI with the VMT !
  2659. But that's wrong, if we call a class method via self
  2660. }
  2661. if ((p^.procdefinition^.options and poclassmethod)<>0)
  2662. and not(p^.methodpointer^.treetype=selfn) then
  2663. begin
  2664. { class method needs current VMT }
  2665. new(r);
  2666. reset_reference(r^);
  2667. r^.base:=R_A5;
  2668. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_A5)));
  2669. end;
  2670. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2671. if is_con_or_destructor then
  2672. begin
  2673. { classes don't get a VMT pointer pushed }
  2674. if (p^.methodpointer^.resulttype^.deftype=objectdef) and
  2675. not(pobjectdef(p^.methodpointer^.resulttype)^.isclass) then
  2676. begin
  2677. if ((p^.procdefinition^.options and poconstructor)<>0) then
  2678. begin
  2679. { it's no bad idea, to insert the VMT }
  2680. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,
  2681. newcsymbol(pobjectdef(
  2682. p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  2683. concat_external(pobjectdef(
  2684. p^.methodpointer^.resulttype)^.vmt_mangledname,EXT_NEAR);
  2685. end
  2686. { destructors haven't to dispose the instance, if this is }
  2687. { a direct call }
  2688. else
  2689. push_int(0);
  2690. end;
  2691. end;
  2692. end;
  2693. end;
  2694. end
  2695. else
  2696. begin
  2697. if ((p^.procdefinition^.options and poclassmethod)<>0) and
  2698. not(
  2699. assigned(aktprocsym) and
  2700. ((aktprocsym^.definition^.options and poclassmethod)<>0)
  2701. ) then
  2702. begin
  2703. { class method needs current VMT }
  2704. new(r);
  2705. reset_reference(r^);
  2706. r^.base:=R_A5;
  2707. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_A5)));
  2708. end
  2709. else
  2710. begin
  2711. { member call, A5 isn't modified }
  2712. loada5:=false;
  2713. end;
  2714. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_SPPUSH)));
  2715. { but a con- or destructor here would probably almost }
  2716. { always be placed wrong }
  2717. if is_con_or_destructor then
  2718. begin
  2719. Message(cg_w_member_cd_call_from_method);
  2720. { not insert VMT pointer } { VMT-Zeiger nicht eintragen }
  2721. push_int(0);
  2722. end;
  2723. end;
  2724. end;
  2725. { push base pointer ?}
  2726. if (lexlevel>1) and assigned(pprocdef(p^.procdefinition)^.parast) and
  2727. ((p^.procdefinition^.parast^.symtablelevel)>2) then
  2728. begin
  2729. { if we call a nested function in a method, we must }
  2730. { push also SELF! }
  2731. { THAT'S NOT TRUE, we have to load ESI via frame pointer }
  2732. { access }
  2733. {
  2734. begin
  2735. loadesi:=false;
  2736. exprasmlist^.concat(new(pai68k,op_reg(A_PUSH,S_L,R_ESI)));
  2737. end;
  2738. }
  2739. if lexlevel=(p^.procdefinition^.parast^.symtablelevel) then
  2740. begin
  2741. new(r);
  2742. reset_reference(r^);
  2743. r^.offset:=procinfo.framepointer_offset;
  2744. r^.base:=procinfo.framepointer;
  2745. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_SPPUSH)))
  2746. end
  2747. { this is only true if the difference is one !!
  2748. but it cannot be more !! }
  2749. else if lexlevel=(p^.procdefinition^.parast^.symtablelevel)-1 then
  2750. begin
  2751. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,procinfo.framepointer,R_SPPUSH)))
  2752. end
  2753. else if lexlevel>(p^.procdefinition^.parast^.symtablelevel) then
  2754. begin
  2755. hregister:=getaddressreg;
  2756. new(r);
  2757. reset_reference(r^);
  2758. r^.offset:=procinfo.framepointer_offset;
  2759. r^.base:=procinfo.framepointer;
  2760. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,hregister)));
  2761. for i:=(p^.procdefinition^.parast^.symtablelevel) to lexlevel-1 do
  2762. begin
  2763. new(r);
  2764. reset_reference(r^);
  2765. {we should get the correct frame_pointer_offset at each level
  2766. how can we do this !!! }
  2767. r^.offset:=procinfo.framepointer_offset;
  2768. r^.base:=hregister;
  2769. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,hregister)));
  2770. end;
  2771. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,hregister,R_SPPUSH)));
  2772. ungetregister32(hregister);
  2773. end
  2774. else
  2775. internalerror(25000);
  2776. end;
  2777. { exported methods should be never called direct }
  2778. if (p^.procdefinition^.options and poexports)<>0 then
  2779. Message(cg_e_dont_call_exported_direct);
  2780. if ((p^.procdefinition^.options and povirtualmethod)<>0) and
  2781. not(no_virtual_call) then
  2782. begin
  2783. { static functions contain the vmt_address in ESI }
  2784. { also class methods }
  2785. if assigned(aktprocsym) then
  2786. begin
  2787. if ((aktprocsym^.properties and sp_static)<>0) or
  2788. ((aktprocsym^.definition^.options and poclassmethod)<>0) or
  2789. ((p^.procdefinition^.options and postaticmethod)<>0) or
  2790. { A5 is already loaded }
  2791. ((p^.procdefinition^.options and poclassmethod)<>0)then
  2792. begin
  2793. new(r);
  2794. reset_reference(r^);
  2795. r^.base:=R_a5;
  2796. end
  2797. else
  2798. begin
  2799. new(r);
  2800. reset_reference(r^);
  2801. r^.base:=R_a5;
  2802. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_a0)));
  2803. new(r);
  2804. reset_reference(r^);
  2805. r^.base:=R_a0;
  2806. end;
  2807. end
  2808. else
  2809. begin
  2810. new(r);
  2811. reset_reference(r^);
  2812. r^.base:=R_a5;
  2813. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,R_a0)));
  2814. new(r);
  2815. reset_reference(r^);
  2816. r^.base:=R_a0;
  2817. end;
  2818. if p^.procdefinition^.extnumber=-1 then
  2819. internalerror($Da);
  2820. r^.offset:=p^.procdefinition^.extnumber*4+12;
  2821. if (cs_rangechecking in aktswitches) then
  2822. begin
  2823. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,r^.base,R_SPPUSH)));
  2824. emitcall('CHECK_OBJECT',true);
  2825. end;
  2826. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,r)));
  2827. end
  2828. else
  2829. emitcall(p^.procdefinition^.mangledname,
  2830. p^.symtableproc^.symtabletype=unitsymtable);
  2831. if ((p^.procdefinition^.options and poclearstack)<>0) then
  2832. begin
  2833. if (pushedparasize > 0) and (pushedparasize < 9) then
  2834. { restore the stack, to its initial value }
  2835. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADDQ,S_L,pushedparasize,R_SP)))
  2836. else
  2837. { restore the stack, to its initial value }
  2838. exprasmlist^.concat(new(pai68k,op_const_reg(A_ADDA,S_L,pushedparasize,R_SP)));
  2839. end;
  2840. end
  2841. else
  2842. begin
  2843. secondpass(p^.right);
  2844. case p^.right^.location.loc of
  2845. LOC_REGISTER,
  2846. LOC_CREGISTER : begin
  2847. if p^.right^.location.register in [R_D0..R_D7] then
  2848. begin
  2849. reg := getaddressreg;
  2850. emit_reg_reg(A_MOVE,S_L,p^.right^.location.register,reg);
  2851. new(ref);
  2852. reset_reference(ref^);
  2853. ref^.base := reg;
  2854. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,ref)));
  2855. ungetregister(reg);
  2856. end
  2857. else
  2858. begin
  2859. new(ref);
  2860. reset_reference(ref^);
  2861. ref^.base := p^.right^.location.register;
  2862. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,ref)));
  2863. end;
  2864. ungetregister32(p^.right^.location.register);
  2865. end
  2866. else
  2867. begin
  2868. if assigned(p^.right^.location.reference.symbol) then
  2869. { Here we have a symbolic name to the routine, so solve }
  2870. { problem by loading the address first, and then emitting }
  2871. { the call. }
  2872. begin
  2873. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  2874. newreference(p^.right^.location.reference),R_A1)));
  2875. new(ref);
  2876. reset_reference(ref^);
  2877. ref^.base := R_A1;
  2878. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,newreference(ref^))));
  2879. end
  2880. else
  2881. exprasmlist^.concat(new(pai68k,op_ref(A_JSR,S_NO,newreference(p^.right^.location.reference))));
  2882. del_reference(p^.right^.location.reference);
  2883. end;
  2884. end;
  2885. end;
  2886. dont_call:
  2887. pushedparasize:=oldpushedparasize;
  2888. unused:=unusedregisters;
  2889. { handle function results }
  2890. if p^.resulttype<>pdef(voiddef) then
  2891. begin
  2892. { a contructor could be a function with boolean result }
  2893. if (p^.right=nil) and
  2894. ((p^.procdefinition^.options and poconstructor)<>0) and
  2895. { quick'n'dirty check if it is a class or an object }
  2896. (p^.resulttype^.deftype=orddef) then
  2897. begin
  2898. p^.location.loc:=LOC_FLAGS;
  2899. p^.location.resflags:=F_NE;
  2900. if extended_new then
  2901. begin
  2902. {$ifdef test_dest_loc}
  2903. if dest_loc_known and (dest_loc_tree=p) then
  2904. mov_reg_to_dest(p,S_L,R_EAX)
  2905. else
  2906. {$endif test_dest_loc}
  2907. hregister:=getregister32;
  2908. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2909. p^.location.register:=hregister;
  2910. end;
  2911. end
  2912. { structed results are easy to handle.... }
  2913. else if ret_in_param(p^.resulttype) then
  2914. begin
  2915. p^.location.loc:=LOC_MEM;
  2916. stringdispose(p^.location.reference.symbol);
  2917. p^.location.reference:=funcretref;
  2918. end
  2919. else
  2920. begin
  2921. if (p^.resulttype^.deftype=orddef) then
  2922. begin
  2923. p^.location.loc:=LOC_REGISTER;
  2924. case porddef(p^.resulttype)^.typ of
  2925. s32bit,u32bit :
  2926. begin
  2927. hregister:=getregister32;
  2928. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2929. p^.location.register:=hregister;
  2930. end;
  2931. uchar,u8bit,bool8bit,s8bit :
  2932. begin
  2933. hregister:=getregister32;
  2934. emit_reg_reg(A_MOVE,S_B,R_D0,hregister);
  2935. p^.location.register:=hregister;
  2936. end;
  2937. s16bit,u16bit :
  2938. begin
  2939. hregister:=getregister32;
  2940. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2941. p^.location.register:=hregister;
  2942. end;
  2943. else internalerror(7);
  2944. end
  2945. end
  2946. else if (p^.resulttype^.deftype=floatdef) then
  2947. case pfloatdef(p^.resulttype)^.typ of
  2948. f32bit :
  2949. begin
  2950. p^.location.loc:=LOC_REGISTER;
  2951. hregister:=getregister32;
  2952. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2953. p^.location.register:=hregister;
  2954. end;
  2955. s32real,s64bit,s64real,s80real: begin
  2956. if cs_fp_emulation in aktswitches then
  2957. begin
  2958. p^.location.loc:=LOC_FPU;
  2959. hregister:=getregister32;
  2960. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2961. p^.location.fpureg:=hregister;
  2962. end
  2963. else
  2964. begin
  2965. { TRUE FPU mode }
  2966. p^.location.loc:=LOC_FPU;
  2967. { on exit of function result in R_FP0 }
  2968. p^.location.fpureg:=R_FP0;
  2969. end;
  2970. end;
  2971. else
  2972. begin
  2973. p^.location.loc:=LOC_FPU;
  2974. p^.location.fpureg:=R_FP0;
  2975. end;
  2976. end {end case }
  2977. else
  2978. begin
  2979. p^.location.loc:=LOC_REGISTER;
  2980. hregister:=getregister32;
  2981. emit_reg_reg(A_MOVE,S_L,R_D0,hregister);
  2982. p^.location.register:=hregister;
  2983. end;
  2984. end;
  2985. end;
  2986. { perhaps i/o check ? }
  2987. if iolabel<>nil then
  2988. begin
  2989. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,newcsymbol(lab2str(iolabel),0),R_SPPUSH)));
  2990. { this was wrong, probably an error due to diff3
  2991. emitcall(p^.procdefinition^.mangledname);}
  2992. emitcall('IOCHECK',true);
  2993. end;
  2994. { restore registers }
  2995. popusedregisters(pushed);
  2996. { at last, restore instance pointer (SELF) }
  2997. if loada5 then
  2998. maybe_loada5;
  2999. pp:=params;
  3000. while assigned(pp) do
  3001. begin
  3002. if assigned(pp^.left) then
  3003. if (pp^.left^.location.loc=LOC_REFERENCE) or
  3004. (pp^.left^.location.loc=LOC_MEM) then
  3005. ungetiftemp(pp^.left^.location.reference);
  3006. pp:=pp^.right;
  3007. end;
  3008. disposetree(params);
  3009. end;
  3010. { reverts the parameter list }
  3011. var nb_para : integer;
  3012. function reversparameter(p : ptree) : ptree;
  3013. var
  3014. hp1,hp2 : ptree;
  3015. begin
  3016. hp1:=nil;
  3017. nb_para := 0;
  3018. while assigned(p) do
  3019. begin
  3020. { pull out }
  3021. hp2:=p;
  3022. p:=p^.right;
  3023. inc(nb_para);
  3024. { pull in }
  3025. hp2^.right:=hp1;
  3026. hp1:=hp2;
  3027. end;
  3028. reversparameter:=hp1;
  3029. end;
  3030. procedure secondloadvmt(var p : ptree);
  3031. begin
  3032. p^.location.loc:=LOC_REGISTER;
  3033. p^.location.register:=getregister32;
  3034. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  3035. S_L,newcsymbol(pobjectdef(pclassrefdef(p^.resulttype)^.definition)^.vmt_mangledname,0),
  3036. p^.location.register)));
  3037. end;
  3038. procedure secondinline(var p : ptree);
  3039. const in2size:array[in_inc_byte..in_dec_dword] of Topsize=
  3040. (S_B,S_W,S_L,S_B,S_W,S_L);
  3041. in2instr:array[in_inc_byte..in_dec_dword] of Tasmop=
  3042. (A_ADDQ,A_ADDQ,A_ADDQ,A_SUBQ,A_SUBQ,A_SUBQ);
  3043. { tfloattype = (f32bit,s32real,s64real,s80real,s64bit); }
  3044. float_name: array[tfloattype] of string[8]=
  3045. { ('FIXED','SINGLE','REAL','EXTENDED','COMP','FIXED'); }
  3046. { Since we only support the REAL (SINGLE IEEE) FLOAT }
  3047. { type, here is what we do... }
  3048. ('FIXED','REAL','REAL','REAL','COMP','FIXED');
  3049. var
  3050. opsize: topsize;
  3051. asmop: tasmop;
  3052. aktfile : treference;
  3053. ft : tfiletype;
  3054. pushed : tpushed;
  3055. dummycoll : tdefcoll;
  3056. { produces code for READ(LN) and WRITE(LN) }
  3057. procedure handlereadwrite(doread,callwriteln : boolean);
  3058. procedure loadstream;
  3059. const io:array[0..1] of string[7]=('_OUTPUT','_INPUT');
  3060. var r : preference;
  3061. begin
  3062. new(r);
  3063. reset_reference(r^);
  3064. r^.symbol:=stringdup('U_'+upper(target_info.system_unit)+io[byte(doread)]);
  3065. if assem_need_external_list and not (cs_compilesystem in aktswitches) then
  3066. concat_external(r^.symbol^,EXT_NEAR);
  3067. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,r,R_A0)))
  3068. end;
  3069. var
  3070. node,hp : ptree;
  3071. typedtyp,pararesult : pdef;
  3072. doflush,has_length : boolean;
  3073. dummycoll : tdefcoll;
  3074. iolabel : plabel;
  3075. npara : longint;
  3076. begin
  3077. { I/O check }
  3078. if cs_iocheck in aktswitches then
  3079. begin
  3080. getlabel(iolabel);
  3081. emitl(A_LABEL,iolabel);
  3082. end
  3083. else iolabel:=nil;
  3084. { no automatic call from flush }
  3085. doflush:=false;
  3086. { for write of real with the length specified }
  3087. has_length:=false;
  3088. hp:=nil;
  3089. { reserve temporary pointer to data variable }
  3090. aktfile.symbol:=nil;
  3091. gettempofsizereference(4,aktfile);
  3092. { first state text data }
  3093. ft:=ft_text;
  3094. { and state a parameter ? }
  3095. if p^.left=nil then
  3096. begin
  3097. { state screen address}
  3098. doflush:=true;
  3099. { the following instructions are for "writeln;" }
  3100. loadstream;
  3101. { save @Dateivarible in temporary variable }
  3102. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,R_A0,newreference(aktfile))));
  3103. end
  3104. else
  3105. begin
  3106. { revers paramters }
  3107. node:=reversparameter(p^.left);
  3108. p^.left := node;
  3109. npara := nb_para;
  3110. { calculate data variable }
  3111. { is first parameter a file type ? }
  3112. if node^.left^.resulttype^.deftype=filedef then
  3113. begin
  3114. ft:=pfiledef(node^.left^.resulttype)^.filetype;
  3115. if ft=ft_typed then
  3116. typedtyp:=pfiledef(node^.left^.resulttype)^.typed_as;
  3117. secondpass(node^.left);
  3118. if codegenerror then
  3119. exit;
  3120. { save reference in temporary variables } { reference in tempor„re Variable retten }
  3121. if node^.left^.location.loc<>LOC_REFERENCE then
  3122. begin
  3123. Message(cg_e_illegal_expression);
  3124. exit;
  3125. end;
  3126. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(node^.left^.location.reference),R_A0)));
  3127. { skip to the next parameter }
  3128. node:=node^.right;
  3129. end
  3130. else
  3131. begin
  3132. { if we write to stdout/in then flush after the write(ln) }
  3133. doflush:=true;
  3134. loadstream;
  3135. end;
  3136. { save @Dateivarible in temporary variable }
  3137. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,R_A0,newreference(aktfile))));
  3138. if doread then
  3139. { parameter by READ gives call by reference }
  3140. dummycoll.paratyp:=vs_var
  3141. { an WRITE Call by "Const" }
  3142. else dummycoll.paratyp:=vs_const;
  3143. { because of secondcallparan, which otherwise attaches }
  3144. if ft=ft_typed then
  3145. begin
  3146. { this is to avoid copy of simple const parameters }
  3147. dummycoll.data:=new(pformaldef,init);
  3148. { use var for write also }
  3149. { avoids problems with const passed by value }
  3150. { but will not accept untyped const }
  3151. { dummycoll.paratyp:=vs_var; }
  3152. end
  3153. else
  3154. { I think, this isn't a good solution (FK) }
  3155. dummycoll.data:=nil;
  3156. while assigned(node) do
  3157. begin
  3158. pushusedregisters(pushed,$ffff);
  3159. hp:=node;
  3160. node:=node^.right;
  3161. hp^.right:=nil;
  3162. if hp^.is_colon_para then
  3163. Message(parser_e_illegal_colon_qualifier);
  3164. if hp^.is_colon_para then
  3165. Message(parser_e_illegal_colon_qualifier);
  3166. if ft=ft_typed then
  3167. never_copy_const_param:=true;
  3168. secondcallparan(hp,@dummycoll,false);
  3169. if ft=ft_typed then
  3170. never_copy_const_param:=false;
  3171. hp^.right:=node;
  3172. if codegenerror then
  3173. exit;
  3174. emit_push_mem(aktfile);
  3175. if (ft=ft_typed) then
  3176. begin
  3177. { OK let's try this }
  3178. { first we must only allow the right type }
  3179. { we have to call blockread or blockwrite }
  3180. { but the real problem is that }
  3181. { reset and rewrite should have set }
  3182. { the type size }
  3183. { as recordsize for that file !!!! }
  3184. { how can we make that }
  3185. { I think that is only possible by adding }
  3186. { reset and rewrite to the inline list a call }
  3187. { allways read only one record by element }
  3188. push_int(typedtyp^.size);
  3189. if doread then
  3190. emitcall('TYPED_READ',true)
  3191. else
  3192. emitcall('TYPED_WRITE',true)
  3193. {!!!!!!!}
  3194. end
  3195. else
  3196. begin
  3197. { save current position }
  3198. pararesult:=hp^.left^.resulttype;
  3199. { handle possible field width }
  3200. { of course only for write(ln) }
  3201. if not doread then
  3202. begin
  3203. { handle total width parameter }
  3204. if assigned(node) and node^.is_colon_para then
  3205. begin
  3206. hp:=node;
  3207. node:=node^.right;
  3208. hp^.right:=nil;
  3209. secondcallparan(hp,@dummycoll,false);
  3210. hp^.right:=node;
  3211. if codegenerror then
  3212. exit;
  3213. has_length:=true;
  3214. end
  3215. else
  3216. if pararesult^.deftype<>floatdef then
  3217. push_int(0)
  3218. else
  3219. push_int(-32767);
  3220. { a second colon para for a float ? }
  3221. if assigned(node) and node^.is_colon_para then
  3222. begin
  3223. hp:=node;
  3224. node:=node^.right;
  3225. hp^.right:=nil;
  3226. secondcallparan(hp,@dummycoll,false);
  3227. hp^.right:=node;
  3228. if pararesult^.deftype<>floatdef then
  3229. Message(parser_e_illegal_colon_qualifier);
  3230. if codegenerror then
  3231. exit;
  3232. end
  3233. else
  3234. begin
  3235. if hp^.left^.resulttype^.deftype=floatdef then
  3236. push_int(-1);
  3237. end;
  3238. end;
  3239. case pararesult^.deftype of
  3240. stringdef : begin
  3241. if doread then
  3242. emitcall('READ_TEXT_STRING',true)
  3243. else
  3244. begin
  3245. emitcall('WRITE_TEXT_STRING',true);
  3246. {ungetiftemp(hp^.left^.location.reference);}
  3247. end;
  3248. end;
  3249. pointerdef : begin
  3250. if is_equal(ppointerdef(pararesult)^.definition,cchardef) then
  3251. begin
  3252. if doread then
  3253. emitcall('READ_TEXT_PCHAR_AS_POINTER',true)
  3254. else
  3255. emitcall('WRITE_TEXT_PCHAR_AS_POINTER',true);
  3256. end
  3257. else Message(parser_e_illegal_parameter_list);
  3258. end;
  3259. arraydef : begin
  3260. if (parraydef(pararesult)^.lowrange=0)
  3261. and is_equal(parraydef(pararesult)^.definition,cchardef) then
  3262. begin
  3263. if doread then
  3264. emitcall('READ_TEXT_PCHAR_AS_ARRAY',true)
  3265. else
  3266. emitcall('WRITE_TEXT_PCHAR_AS_ARRAY',true);
  3267. end
  3268. else Message(parser_e_illegal_parameter_list);
  3269. end;
  3270. floatdef : begin
  3271. if doread then
  3272. emitcall('READ_TEXT_REAL',true)
  3273. else
  3274. emitcall('WRITE_TEXT_'+float_name[pfloatdef(pararesult)^.typ],true);
  3275. end;
  3276. orddef : begin
  3277. case porddef(pararesult)^.typ of
  3278. u8bit : if doread then
  3279. emitcall('READ_TEXT_BYTE',true);
  3280. s8bit : if doread then
  3281. emitcall('READ_TEXT_SHORTINT',true);
  3282. u16bit : if doread then
  3283. emitcall('READ_TEXT_WORD',true);
  3284. s16bit : if doread then
  3285. emitcall('READ_TEXT_INTEGER',true);
  3286. s32bit : if doread then
  3287. emitcall('READ_TEXT_LONGINT',true)
  3288. else
  3289. emitcall('WRITE_TEXT_LONGINT',true);
  3290. u32bit : if doread then
  3291. emitcall('READ_TEXT_CARDINAL',true)
  3292. else
  3293. emitcall('WRITE_TEXT_CARDINAL',true);
  3294. uchar : if doread then
  3295. emitcall('READ_TEXT_CHAR',true)
  3296. else
  3297. emitcall('WRITE_TEXT_CHAR',true);
  3298. bool8bit : if doread then
  3299. { emitcall('READ_TEXT_BOOLEAN',true) }
  3300. Message(parser_e_illegal_parameter_list)
  3301. else
  3302. emitcall('WRITE_TEXT_BOOLEAN',true);
  3303. else Message(parser_e_illegal_parameter_list);
  3304. end;
  3305. end;
  3306. else Message(parser_e_illegal_parameter_list);
  3307. end;
  3308. end;
  3309. { load A5 in methods again }
  3310. popusedregisters(pushed);
  3311. maybe_loada5;
  3312. end;
  3313. end;
  3314. if callwriteln then
  3315. begin
  3316. pushusedregisters(pushed,$ffff);
  3317. emit_push_mem(aktfile);
  3318. { pushexceptlabel; }
  3319. if ft<>ft_text then
  3320. Message(parser_e_illegal_parameter_list);
  3321. emitcall('WRITELN_TEXT',true);
  3322. popusedregisters(pushed);
  3323. maybe_loada5;
  3324. end;
  3325. if doflush and not(doread) then
  3326. begin
  3327. pushusedregisters(pushed,$ffff);
  3328. { pushexceptlabel; }
  3329. emitcall('FLUSH_STDOUT',true);
  3330. popusedregisters(pushed);
  3331. maybe_loada5;
  3332. end;
  3333. if iolabel<>nil then
  3334. begin
  3335. { registers are saved in the procedure }
  3336. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,S_L,newcsymbol(lab2str(iolabel),0),R_SPPUSH)));
  3337. emitcall('IOCHECK',true);
  3338. end;
  3339. ungetiftemp(aktfile);
  3340. if assigned(p^.left) then
  3341. begin
  3342. p^.left:=reversparameter(p^.left);
  3343. if npara<>nb_para then
  3344. Message(cg_f_internal_error_in_secondinline);
  3345. hp:=p^.left;
  3346. while assigned(hp) do
  3347. begin
  3348. if assigned(hp^.left) then
  3349. if (hp^.left^.location.loc=LOC_REFERENCE) or
  3350. (hp^.left^.location.loc=LOC_MEM) then
  3351. ungetiftemp(hp^.left^.location.reference);
  3352. hp:=hp^.right;
  3353. end;
  3354. end;
  3355. end;
  3356. procedure handle_str;
  3357. var
  3358. hp,node,lentree,paratree : ptree;
  3359. dummycoll : tdefcoll;
  3360. is_real,has_length : boolean;
  3361. real_type : byte;
  3362. begin
  3363. pushusedregisters(pushed,$ffff);
  3364. node:=p^.left;
  3365. is_real:=false;
  3366. has_length:=false;
  3367. while assigned(node^.right) do node:=node^.right;
  3368. { if a real parameter somewhere then call REALSTR }
  3369. if (node^.left^.resulttype^.deftype=floatdef) then
  3370. is_real:=true;
  3371. node:=p^.left;
  3372. { we have at least two args }
  3373. { with at max 2 colon_para in between }
  3374. { first arg longint or float }
  3375. hp:=node;
  3376. node:=node^.right;
  3377. hp^.right:=nil;
  3378. dummycoll.data:=hp^.resulttype;
  3379. { string arg }
  3380. dummycoll.paratyp:=vs_var;
  3381. secondcallparan(hp,@dummycoll,false);
  3382. if codegenerror then
  3383. exit;
  3384. dummycoll.paratyp:=vs_const;
  3385. { second arg }
  3386. hp:=node;
  3387. node:=node^.right;
  3388. hp^.right:=nil;
  3389. { frac para }
  3390. if hp^.is_colon_para and assigned(node) and
  3391. node^.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. has_length:=true;
  3401. end
  3402. else
  3403. if is_real then
  3404. push_int(-1);
  3405. { third arg, length only if is_real }
  3406. if hp^.is_colon_para then
  3407. begin
  3408. dummycoll.data:=hp^.resulttype;
  3409. secondcallparan(hp,@dummycoll,false);
  3410. if codegenerror then
  3411. exit;
  3412. hp:=node;
  3413. node:=node^.right;
  3414. hp^.right:=nil;
  3415. end
  3416. else
  3417. if is_real then
  3418. push_int(-32767)
  3419. else
  3420. push_int(-1);
  3421. { last arg longint or real }
  3422. secondcallparan(hp,@dummycoll,false);
  3423. if codegenerror then
  3424. exit;
  3425. if is_real then
  3426. emitcall('STR_'+float_name[pfloatdef(hp^.resulttype)^.typ],true)
  3427. else if porddef(hp^.resulttype)^.typ=u32bit then
  3428. emitcall('STR_CARDINAL',true)
  3429. else
  3430. emitcall('STR_LONGINT',true);
  3431. popusedregisters(pushed);
  3432. end;
  3433. var
  3434. r : preference;
  3435. begin
  3436. case p^.inlinenumber of
  3437. in_lo_word,
  3438. in_hi_word : begin
  3439. secondpass(p^.left);
  3440. p^.location.loc:=LOC_REGISTER;
  3441. if p^.left^.location.loc<>LOC_REGISTER then
  3442. begin
  3443. if p^.left^.location.loc=LOC_CREGISTER then
  3444. begin
  3445. p^.location.register:=getregister32;
  3446. emit_reg_reg(A_MOVE,S_W,p^.left^.location.register,
  3447. p^.location.register);
  3448. end
  3449. else
  3450. begin
  3451. del_reference(p^.left^.location.reference);
  3452. p^.location.register:=getregister32;
  3453. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  3454. newreference(p^.left^.location.reference),
  3455. p^.location.register)));
  3456. end;
  3457. end
  3458. else p^.location.register:=p^.left^.location.register;
  3459. if p^.inlinenumber=in_hi_word then
  3460. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSR,S_W,8,p^.location.register)));
  3461. p^.location.register:=p^.location.register;
  3462. end;
  3463. in_high_x :
  3464. begin
  3465. if is_open_array(p^.left^.resulttype) then
  3466. begin
  3467. secondpass(p^.left);
  3468. del_reference(p^.left^.location.reference);
  3469. p^.location.register:=getregister32;
  3470. new(r);
  3471. reset_reference(r^);
  3472. r^.base:=highframepointer;
  3473. r^.offset:=highoffset+4;
  3474. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3475. r,p^.location.register)));
  3476. end
  3477. end;
  3478. in_sizeof_x,
  3479. in_typeof_x:
  3480. begin
  3481. { load vmt }
  3482. if p^.left^.treetype=typen then
  3483. begin
  3484. p^.location.register:=getregister32;
  3485. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  3486. S_L,newcsymbol(pobjectdef(p^.left^.resulttype)^.vmt_mangledname,0),
  3487. p^.location.register)));
  3488. end
  3489. else
  3490. begin
  3491. secondpass(p^.left);
  3492. del_reference(p^.left^.location.reference);
  3493. p^.location.loc:=LOC_REGISTER;
  3494. p^.location.register:=getregister32;
  3495. { load VMT pointer }
  3496. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3497. newreference(p^.left^.location.reference),
  3498. p^.location.register)));
  3499. end;
  3500. { in sizeof load size }
  3501. if p^.inlinenumber=in_sizeof_x then
  3502. begin
  3503. new(r);
  3504. reset_reference(r^);
  3505. { load the address in A0 }
  3506. { because now supposedly p^.location.register is an }
  3507. { address. }
  3508. emit_reg_reg(A_MOVE, S_L, p^.location.register, R_A0);
  3509. r^.base:=R_A0;
  3510. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,
  3511. p^.location.register)));
  3512. end;
  3513. end;
  3514. in_lo_long,
  3515. in_hi_long : begin
  3516. secondpass(p^.left);
  3517. p^.location.loc:=LOC_REGISTER;
  3518. if p^.left^.location.loc<>LOC_REGISTER then
  3519. begin
  3520. if p^.left^.location.loc=LOC_CREGISTER then
  3521. begin
  3522. p^.location.register:=getregister32;
  3523. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,
  3524. p^.location.register);
  3525. end
  3526. else
  3527. begin
  3528. del_reference(p^.left^.location.reference);
  3529. p^.location.register:=getregister32;
  3530. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3531. newreference(p^.left^.location.reference),
  3532. p^.location.register)));
  3533. end;
  3534. end
  3535. else p^.location.register:=p^.left^.location.register;
  3536. if p^.inlinenumber=in_hi_long then
  3537. begin
  3538. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVEQ, S_L, 16, R_D1)));
  3539. exprasmlist^.concat(new(pai68k,op_reg_reg(A_LSR,S_L,R_D1,p^.location.register)));
  3540. end;
  3541. p^.location.register:=p^.location.register;
  3542. end;
  3543. {We can now comment them out, as they are handled as typecast.
  3544. Saves an incredible amount of 8 bytes code.
  3545. I'am not lucky about this, because it's _not_ a type cast (FK) }
  3546. { in_ord_char,
  3547. in_chr_byte,}
  3548. in_length_string : begin
  3549. secondpass(p^.left);
  3550. set_location(p^.location,p^.left^.location);
  3551. end;
  3552. in_inc_byte..in_dec_dword:
  3553. begin
  3554. secondpass(p^.left);
  3555. exprasmlist^.concat(new(pai68k,op_const_ref(in2instr[p^.inlinenumber],
  3556. in2size[p^.inlinenumber],1,newreference(p^.left^.location.reference))));
  3557. emitoverflowcheck(p^.left);
  3558. end;
  3559. in_pred_x,
  3560. in_succ_x:
  3561. begin
  3562. secondpass(p^.left);
  3563. if p^.inlinenumber=in_pred_x then
  3564. asmop:=A_SUB
  3565. else
  3566. asmop:=A_ADD;
  3567. case p^.resulttype^.size of
  3568. 4 : opsize:=S_L;
  3569. 2 : opsize:=S_W;
  3570. 1 : opsize:=S_B;
  3571. else
  3572. internalerror(10080);
  3573. end;
  3574. p^.location.loc:=LOC_REGISTER;
  3575. if p^.left^.location.loc<>LOC_REGISTER then
  3576. begin
  3577. p^.location.register:=getregister32;
  3578. if p^.left^.location.loc=LOC_CREGISTER then
  3579. emit_reg_reg(A_MOVE,opsize,p^.left^.location.register,
  3580. p^.location.register)
  3581. else
  3582. if p^.left^.location.loc=LOC_FLAGS then
  3583. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.left^.location.resflags],S_NO,
  3584. p^.location.register)))
  3585. else
  3586. begin
  3587. del_reference(p^.left^.location.reference);
  3588. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,newreference(p^.left^.location.reference),
  3589. p^.location.register)));
  3590. end;
  3591. end
  3592. else p^.location.register:=p^.left^.location.register;
  3593. exprasmlist^.concat(new(pai68k,op_reg(asmop,opsize,
  3594. p^.location.register)))
  3595. { here we should insert bounds check ? }
  3596. { and direct call to bounds will crash the program }
  3597. { if we are at the limit }
  3598. { we could also simply say that pred(first)=first and succ(last)=last }
  3599. { could this be usefull I don't think so (PM)
  3600. emitoverflowcheck;}
  3601. end;
  3602. in_assigned_x:
  3603. begin
  3604. secondpass(p^.left^.left);
  3605. p^.location.loc:=LOC_FLAGS;
  3606. if (p^.left^.left^.location.loc=LOC_REGISTER) or
  3607. (p^.left^.left^.location.loc=LOC_CREGISTER) then
  3608. begin
  3609. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_L,
  3610. p^.left^.left^.location.register)));
  3611. ungetregister32(p^.left^.left^.location.register);
  3612. end
  3613. else
  3614. begin
  3615. exprasmlist^.concat(new(pai68k,op_ref(A_TST,S_L,
  3616. newreference(p^.left^.left^.location.reference))));
  3617. del_reference(p^.left^.left^.location.reference);
  3618. end;
  3619. p^.location.resflags:=F_NE;
  3620. end;
  3621. in_reset_typedfile,in_rewrite_typedfile :
  3622. begin
  3623. pushusedregisters(pushed,$ffff);
  3624. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,
  3625. pfiledef(p^.left^.resulttype)^.typed_as^.size,R_SPPUSH)));
  3626. secondload(p^.left);
  3627. emitpushreferenceaddr(p^.left^.location.reference);
  3628. if p^.inlinenumber=in_reset_typedfile then
  3629. emitcall('RESET_TYPED',true)
  3630. else
  3631. emitcall('REWRITE_TYPED',true);
  3632. popusedregisters(pushed);
  3633. end;
  3634. in_write_x :
  3635. handlereadwrite(false,false);
  3636. in_writeln_x :
  3637. handlereadwrite(false,true);
  3638. in_read_x :
  3639. handlereadwrite(true,false);
  3640. in_readln_x :
  3641. begin
  3642. handlereadwrite(true,false);
  3643. pushusedregisters(pushed,$ffff);
  3644. emit_push_mem(aktfile);
  3645. { pushexceptlabel; }
  3646. if ft<>ft_text then
  3647. Message(parser_e_illegal_parameter_list);
  3648. emitcall('READLN_TEXT',true);
  3649. popusedregisters(pushed);
  3650. maybe_loada5;
  3651. end;
  3652. in_str_x_string : begin
  3653. handle_str;
  3654. maybe_loada5;
  3655. end;
  3656. else internalerror(9);
  3657. end;
  3658. end;
  3659. procedure secondsubscriptn(var p : ptree);
  3660. var
  3661. hr: tregister;
  3662. begin
  3663. secondpass(p^.left);
  3664. if codegenerror then
  3665. exit;
  3666. { classes must be dereferenced implicit }
  3667. if (p^.left^.resulttype^.deftype=objectdef) and
  3668. pobjectdef(p^.left^.resulttype)^.isclass then
  3669. begin
  3670. clear_reference(p^.location.reference);
  3671. case p^.left^.location.loc of
  3672. LOC_REGISTER:
  3673. begin
  3674. { move it to an address register...}
  3675. hr:=getaddressreg;
  3676. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,hr);
  3677. p^.location.reference.base:=hr;
  3678. { free register }
  3679. ungetregister(p^.left^.location.register);
  3680. end;
  3681. LOC_CREGISTER:
  3682. begin
  3683. { ... and reserve one for the pointer }
  3684. hr:=getaddressreg;
  3685. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,hr);
  3686. p^.location.reference.base:=hr;
  3687. end;
  3688. else
  3689. begin
  3690. { free register }
  3691. del_reference(p^.left^.location.reference);
  3692. { ... and reserve one for the pointer }
  3693. hr:=getaddressreg;
  3694. exprasmlist^.concat(new(pai68k,op_ref_reg(
  3695. A_MOVE,S_L,newreference(p^.left^.location.reference),
  3696. hr)));
  3697. p^.location.reference.base:=hr;
  3698. end;
  3699. end;
  3700. end
  3701. else
  3702. set_location(p^.location,p^.left^.location);
  3703. inc(p^.location.reference.offset,p^.vs^.address);
  3704. end;
  3705. procedure secondselfn(var p : ptree);
  3706. begin
  3707. clear_reference(p^.location.reference);
  3708. p^.location.reference.base:=R_A5;
  3709. end;
  3710. procedure secondhdisposen(var p : ptree);
  3711. begin
  3712. secondpass(p^.left);
  3713. if codegenerror then
  3714. exit;
  3715. clear_reference(p^.location.reference);
  3716. case p^.left^.location.loc of
  3717. LOC_REGISTER,
  3718. LOC_CREGISTER : begin
  3719. p^.location.reference.index:=getregister32;
  3720. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  3721. p^.left^.location.register,
  3722. p^.location.reference.index)));
  3723. end;
  3724. LOC_MEM,LOC_REFERENCE :
  3725. begin
  3726. del_reference(p^.left^.location.reference);
  3727. p^.location.reference.index:=getregister32;
  3728. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.left^.location.reference),
  3729. p^.location.reference.index)));
  3730. end;
  3731. end;
  3732. end;
  3733. procedure secondhnewn(var p : ptree);
  3734. begin
  3735. end;
  3736. procedure secondnewn(var p : ptree);
  3737. begin
  3738. secondpass(p^.left);
  3739. if codegenerror then
  3740. exit;
  3741. p^.location.register:=p^.left^.location.register;
  3742. end;
  3743. procedure secondsimplenewdispose(var p : ptree);
  3744. var
  3745. pushed : tpushed;
  3746. begin
  3747. secondpass(p^.left);
  3748. if codegenerror then
  3749. exit;
  3750. pushusedregisters(pushed,$ffff);
  3751. { determines the size of the mem block }
  3752. push_int(ppointerdef(p^.left^.resulttype)^.definition^.size);
  3753. { push pointer adress }
  3754. case p^.left^.location.loc of
  3755. LOC_CREGISTER : exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  3756. p^.left^.location.register,R_SPPUSH)));
  3757. LOC_REFERENCE : emitpushreferenceaddr(p^.left^.location.reference);
  3758. end;
  3759. { call the mem handling procedures }
  3760. case p^.treetype of
  3761. simpledisposen :
  3762. emitcall('FREEMEM',true);
  3763. simplenewn :
  3764. emitcall('GETMEM',true);
  3765. end;
  3766. popusedregisters(pushed);
  3767. { may be load ESI }
  3768. maybe_loada5;
  3769. end;
  3770. procedure secondsetcons(var p : ptree);
  3771. var
  3772. l : plabel;
  3773. i,smallsetvalue : longint;
  3774. hp : ptree;
  3775. href,sref : treference;
  3776. hl1,hl2: plabel;
  3777. begin
  3778. { this should be reimplemented for smallsets }
  3779. { differently (PM) }
  3780. { produce constant part }
  3781. href.symbol := Nil;
  3782. clear_reference(href);
  3783. getlabel(l);
  3784. href.symbol:=stringdup(lab2str(l));
  3785. stringdispose(p^.location.reference.symbol);
  3786. datasegment^.concat(new(pai_label,init(l)));
  3787. {if psetdef(p^.resulttype)=smallset then
  3788. begin
  3789. smallsetvalue:=(p^.constset^[3]*256)+p^.constset^[2];
  3790. smallsetvalue:=((smallset*256+p^.constset^[1])*256+p^.constset^[1];
  3791. datasegment^.concat(new(pai_const,init_32bit(smallsetvalue)));
  3792. hp:=p^.left;
  3793. if assigned(hp) then
  3794. begin
  3795. sref.symbol:=nil;
  3796. gettempofsizereference(32,sref);
  3797. concatcopy(href,sref,32,false);
  3798. while assigned(hp) do
  3799. begin
  3800. secondpass(hp^.left);
  3801. if codegenerror then
  3802. exit;
  3803. pushsetelement(hp^.left);
  3804. emitpushreferenceaddr(sref);
  3805. register is save in subroutine
  3806. emitcall('SET_SET_BYTE',true);
  3807. hp:=hp^.right;
  3808. end;
  3809. p^.location.reference:=sref;
  3810. end
  3811. else p^.location.reference:=href;
  3812. end
  3813. else }
  3814. begin
  3815. for i:=0 to 31 do
  3816. datasegment^.concat(new(pai_const,init_8bit(p^.constset^[i])));
  3817. hp:=p^.left;
  3818. if assigned(hp) then
  3819. begin
  3820. sref.symbol:=nil;
  3821. gettempofsizereference(32,sref);
  3822. concatcopy(href,sref,32,false);
  3823. while assigned(hp) do
  3824. begin
  3825. secondpass(hp^.left);
  3826. if codegenerror then
  3827. exit;
  3828. pushsetelement(hp^.left);
  3829. emitpushreferenceaddr(sref);
  3830. { register is save in subroutine }
  3831. emitcall('SET_SET_BYTE',true);
  3832. { here we must set the flags manually }
  3833. { on returne from the routine, because }
  3834. { falgs are corrupt when restoring the }
  3835. { stack }
  3836. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_B,R_D0)));
  3837. getlabel(hl1);
  3838. emitl(A_BEQ,hl1);
  3839. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_B,
  3840. $fe,R_CCR)));
  3841. getlabel(hl2);
  3842. emitl(A_BRA,hl2);
  3843. emitl(A_LABEL,hl1);
  3844. exprasmlist^.concat(new(pai68k,op_const_reg(A_OR,S_B,
  3845. $01,R_CCR)));
  3846. emitl(A_LABEL,hl2);
  3847. hp:=hp^.right;
  3848. end;
  3849. p^.location.reference:=sref;
  3850. end
  3851. else p^.location.reference:=href;
  3852. end;
  3853. end;
  3854. procedure secondcontinuen(var p : ptree);
  3855. begin
  3856. if aktcontinuelabel<>nil then
  3857. emitl(A_JMP,aktcontinuelabel)
  3858. else
  3859. Message(cg_e_continue_not_allowed);
  3860. end;
  3861. { var
  3862. hs : string; }
  3863. procedure secondexitn(var p : ptree);
  3864. var
  3865. is_mem : boolean;
  3866. {op : tasmop;
  3867. s : topsize;}
  3868. otlabel,oflabel : plabel;
  3869. label
  3870. do_jmp;
  3871. begin
  3872. if assigned(p^.left) then
  3873. begin
  3874. otlabel:=truelabel;
  3875. oflabel:=falselabel;
  3876. getlabel(truelabel);
  3877. getlabel(falselabel);
  3878. secondpass(p^.left);
  3879. case p^.left^.location.loc of
  3880. LOC_FPU : goto do_jmp;
  3881. LOC_MEM,LOC_REFERENCE : is_mem:=true;
  3882. LOC_CREGISTER,
  3883. LOC_REGISTER : is_mem:=false;
  3884. LOC_FLAGS : begin
  3885. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.right^.location.resflags],S_B,R_D0)));
  3886. exprasmlist^.concat(new(pai68k,op_reg(A_NEG, S_B, R_D0)));
  3887. goto do_jmp;
  3888. end;
  3889. LOC_JUMP : begin
  3890. emitl(A_LABEL,truelabel);
  3891. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,1,R_D0)));
  3892. emitl(A_JMP,aktexit2label);
  3893. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_B,R_D0)));
  3894. goto do_jmp;
  3895. end;
  3896. else internalerror(2001);
  3897. end;
  3898. if (procinfo.retdef^.deftype=orddef) then
  3899. begin
  3900. case porddef(procinfo.retdef)^.typ of
  3901. s32bit,u32bit : if is_mem then
  3902. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3903. newreference(p^.left^.location.reference),R_D0)))
  3904. else
  3905. emit_reg_reg(A_MOVE,S_L,
  3906. p^.left^.location.register,R_D0);
  3907. u8bit,s8bit,uchar,bool8bit : if is_mem then
  3908. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,
  3909. newreference(p^.left^.location.reference),R_D0)))
  3910. else
  3911. emit_reg_reg(A_MOVE,S_B,
  3912. p^.left^.location.register,R_D0);
  3913. s16bit,u16bit : if is_mem then
  3914. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,
  3915. newreference(p^.left^.location.reference),R_D0)))
  3916. else
  3917. emit_reg_reg(A_MOVE,S_W,
  3918. p^.left^.location.register,R_D0);
  3919. end;
  3920. end
  3921. else
  3922. if (procinfo.retdef^.deftype in
  3923. [pointerdef,enumdef,procvardef]) then
  3924. begin
  3925. if is_mem then
  3926. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3927. newreference(p^.left^.location.reference),R_D0)))
  3928. else
  3929. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  3930. p^.left^.location.register,R_D0)));
  3931. end
  3932. else
  3933. if (procinfo.retdef^.deftype=floatdef) then
  3934. { floating point return values .... }
  3935. { single are returned in d0 }
  3936. begin
  3937. if (pfloatdef(procinfo.retdef)^.typ=f32bit) or
  3938. (pfloatdef(procinfo.retdef)^.typ=s32real) then
  3939. begin
  3940. if is_mem then
  3941. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  3942. newreference(p^.left^.location.reference),R_D0)))
  3943. else
  3944. begin
  3945. if pfloatdef(procinfo.retdef)^.typ=f32bit then
  3946. emit_reg_reg(A_MOVE,S_L,p^.left^.location.register,R_D0)
  3947. else
  3948. begin
  3949. { single values are in the floating point registers }
  3950. if cs_fp_emulation in aktswitches then
  3951. emit_reg_reg(A_MOVE,S_L,p^.left^.location.fpureg,R_D0)
  3952. else
  3953. exprasmlist^.concat(
  3954. new(pai68k,op_reg_reg(A_FMOVE,S_FS,p^.left^.location.fpureg,R_D0)));
  3955. end;
  3956. end;
  3957. end
  3958. else
  3959. { this is only possible in real non emulation mode }
  3960. { LOC_MEM,LOC_REFERENCE }
  3961. if is_mem then
  3962. begin
  3963. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,
  3964. getfloatsize(pfloatdef(procinfo.retdef)^.typ),newreference(p^.left^.location.reference),R_FP0)));
  3965. end
  3966. else
  3967. { LOC_FPU }
  3968. begin
  3969. { convert from extended to correct type }
  3970. { when storing }
  3971. exprasmlist^.concat(new(pai68k,op_reg_reg(A_FMOVE,
  3972. getfloatsize(pfloatdef(procinfo.retdef)^.typ),p^.left^.location.fpureg,R_FP0)));
  3973. end;
  3974. end;
  3975. do_jmp:
  3976. truelabel:=otlabel;
  3977. falselabel:=oflabel;
  3978. emitl(A_JMP,aktexit2label);
  3979. end
  3980. else
  3981. begin
  3982. emitl(A_JMP,aktexitlabel);
  3983. end;
  3984. end;
  3985. procedure secondgoto(var p : ptree);
  3986. begin
  3987. emitl(A_JMP,p^.labelnr);
  3988. end;
  3989. procedure secondlabel(var p : ptree);
  3990. begin
  3991. emitl(A_LABEL,p^.labelnr);
  3992. cleartempgen;
  3993. secondpass(p^.left);
  3994. end;
  3995. procedure secondasm(var p : ptree);
  3996. begin
  3997. exprasmlist^.concatlist(p^.p_asm);
  3998. end;
  3999. procedure secondcase(var p : ptree);
  4000. var
  4001. with_sign : boolean;
  4002. opsize : topsize;
  4003. jmp_gt,jmp_le,jmp_lee : tasmop;
  4004. hp : ptree;
  4005. { register with case expression }
  4006. hregister : tregister;
  4007. endlabel,elselabel : plabel;
  4008. { true, if we can omit the range check of the jump table }
  4009. jumptable_no_range : boolean;
  4010. procedure gentreejmp(p : pcaserecord);
  4011. var
  4012. lesslabel,greaterlabel : plabel;
  4013. begin
  4014. emitl(A_LABEL,p^._at);
  4015. { calculate labels for left and right }
  4016. if (p^.less=nil) then
  4017. lesslabel:=elselabel
  4018. else
  4019. lesslabel:=p^.less^._at;
  4020. if (p^.greater=nil) then
  4021. greaterlabel:=elselabel
  4022. else
  4023. greaterlabel:=p^.greater^._at;
  4024. { calculate labels for left and right }
  4025. { no range label: }
  4026. if p^._low=p^._high then
  4027. begin
  4028. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,p^._low,hregister)));
  4029. if greaterlabel=lesslabel then
  4030. begin
  4031. emitl(A_BNE,lesslabel);
  4032. end
  4033. else
  4034. begin
  4035. emitl(jmp_le,lesslabel);
  4036. emitl(jmp_gt,greaterlabel);
  4037. end;
  4038. emitl(A_JMP,p^.statement);
  4039. end
  4040. else
  4041. begin
  4042. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,p^._low,hregister)));
  4043. emitl(jmp_le,lesslabel);
  4044. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,p^._high,hregister)));
  4045. emitl(jmp_gt,greaterlabel);
  4046. emitl(A_JMP,p^.statement);
  4047. end;
  4048. if assigned(p^.less) then
  4049. gentreejmp(p^.less);
  4050. if assigned(p^.greater) then
  4051. gentreejmp(p^.greater);
  4052. end;
  4053. procedure genlinearlist(hp : pcaserecord);
  4054. var
  4055. first : boolean;
  4056. last : longint;
  4057. procedure genitem(t : pcaserecord);
  4058. begin
  4059. if assigned(t^.less) then
  4060. genitem(t^.less);
  4061. if t^._low=t^._high then
  4062. begin
  4063. if (t^._low-last > 0) and (t^._low-last < 9) then
  4064. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,opsize,t^._low-last,hregister)))
  4065. else
  4066. if (t^._low-last = 0) then
  4067. exprasmlist^.concat(new(pai68k,op_reg(A_TST,opsize,hregister)))
  4068. else
  4069. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._low-last,hregister)));
  4070. last:=t^._low;
  4071. emitl(A_BEQ,t^.statement);
  4072. end
  4073. else
  4074. begin
  4075. { it begins with the smallest label, if the value }
  4076. { is even smaller then jump immediately to the }
  4077. { ELSE-label }
  4078. if first then
  4079. begin
  4080. if (t^._low-1 > 0) and (t^._low < 9) then
  4081. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,opsize,t^._low-1,hregister)))
  4082. else
  4083. if t^._low-1=0 then
  4084. exprasmlist^.concat(new(pai68k,op_reg(A_TST,opsize,hregister)))
  4085. else
  4086. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._low-1,hregister)));
  4087. if t^._low = 0 then
  4088. emitl(A_BLE,elselabel)
  4089. else
  4090. emitl(jmp_lee,elselabel);
  4091. end
  4092. { if there is no unused label between the last and the }
  4093. { present label then the lower limit can be checked }
  4094. { immediately. else check the range in between: }
  4095. else if (t^._low-last>1)then
  4096. begin
  4097. if ((t^._low-last-1) > 0) and ((t^._low-last-1) < 9) then
  4098. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUBQ,opsize,t^._low-last-1,hregister)))
  4099. else
  4100. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._low-last-1,hregister)));
  4101. emitl(jmp_lee,elselabel);
  4102. end;
  4103. exprasmlist^.concat(new(pai68k,op_const_reg(A_SUB,opsize,t^._high-t^._low+1,hregister)));
  4104. emitl(jmp_lee,t^.statement);
  4105. last:=t^._high;
  4106. end;
  4107. first:=false;
  4108. if assigned(t^.greater) then
  4109. genitem(t^.greater);
  4110. end;
  4111. var
  4112. hr : tregister;
  4113. begin
  4114. { case register is modified by the list evalution }
  4115. if (p^.left^.location.loc=LOC_CREGISTER) then
  4116. begin
  4117. hr:=getregister32;
  4118. end;
  4119. last:=0;
  4120. first:=true;
  4121. genitem(hp);
  4122. emitl(A_JMP,elselabel);
  4123. end;
  4124. procedure genjumptable(hp : pcaserecord;min_,max_ : longint);
  4125. var
  4126. table : plabel;
  4127. last : longint;
  4128. hr : preference;
  4129. procedure genitem(t : pcaserecord);
  4130. var
  4131. i : longint;
  4132. begin
  4133. if assigned(t^.less) then
  4134. genitem(t^.less);
  4135. { fill possible hole }
  4136. for i:=last+1 to t^._low-1 do
  4137. datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str
  4138. (elselabel)))));
  4139. for i:=t^._low to t^._high do
  4140. datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str
  4141. (t^.statement)))));
  4142. last:=t^._high;
  4143. if assigned(t^.greater) then
  4144. genitem(t^.greater);
  4145. end;
  4146. begin
  4147. if not(jumptable_no_range) then
  4148. begin
  4149. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,min_,hregister)));
  4150. { case expr less than min_ => goto elselabel }
  4151. emitl(jmp_le,elselabel);
  4152. exprasmlist^.concat(new(pai68k,op_const_reg(A_CMP,opsize,max_,hregister)));
  4153. emitl(jmp_gt,elselabel);
  4154. end;
  4155. getlabel(table);
  4156. { extend with sign }
  4157. if opsize=S_W then
  4158. begin
  4159. { word to long - unsigned }
  4160. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$ffff,hregister)));
  4161. end
  4162. else if opsize=S_B then
  4163. begin
  4164. { byte to long - unsigned }
  4165. exprasmlist^.concat(new(pai68k,op_const_reg(A_AND,S_L,$ff,hregister)));
  4166. end;
  4167. new(hr);
  4168. reset_reference(hr^);
  4169. hr^.symbol:=stringdup(lab2str(table));
  4170. hr^.offset:=(-min_)*4;
  4171. { add scalefactor *4 to index }
  4172. exprasmlist^.concat(new(pai68k,op_const_reg(A_LSL,S_L,2,hregister)));
  4173. { hr^.scalefactor:=4; }
  4174. hr^.base:=getaddressreg;
  4175. emit_reg_reg(A_MOVE,S_L,hregister,hr^.base);
  4176. exprasmlist^.concat(new(pai68k,op_ref(A_JMP,S_NO,hr)));
  4177. { if not(cs_littlesize in aktswitches^ ) then
  4178. datasegment^.concat(new(pai68k,op_const(A_ALIGN,S_NO,4))); }
  4179. datasegment^.concat(new(pai_label,init(table)));
  4180. last:=min_;
  4181. genitem(hp);
  4182. if hr^.base <> R_NO then ungetregister(hr^.base);
  4183. { !!!!!!!
  4184. if not(cs_littlesize in aktswitches^ ) then
  4185. exprasmlist^.concat(new(pai68k,op_const(A_ALIGN,S_NO,4)));
  4186. }
  4187. end;
  4188. var
  4189. lv,hv,min_label,max_label,labels : longint;
  4190. max_linear_list : longint;
  4191. begin
  4192. getlabel(endlabel);
  4193. getlabel(elselabel);
  4194. with_sign:=is_signed(p^.left^.resulttype);
  4195. if with_sign then
  4196. begin
  4197. jmp_gt:=A_BGT;
  4198. jmp_le:=A_BLT;
  4199. jmp_lee:=A_BLE;
  4200. end
  4201. else
  4202. begin
  4203. jmp_gt:=A_BHI;
  4204. jmp_le:=A_BCS;
  4205. jmp_lee:=A_BLS;
  4206. end;
  4207. cleartempgen;
  4208. secondpass(p^.left);
  4209. { determines the size of the operand }
  4210. { determines the size of the operand }
  4211. opsize:=bytes2Sxx[p^.left^.resulttype^.size];
  4212. { copy the case expression to a register }
  4213. { copy the case expression to a register }
  4214. case p^.left^.location.loc of
  4215. LOC_REGISTER,
  4216. LOC_CREGISTER : hregister:=p^.left^.location.register;
  4217. LOC_MEM,LOC_REFERENCE : begin
  4218. del_reference(p^.left^.location.reference);
  4219. hregister:=getregister32;
  4220. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,newreference(
  4221. p^.left^.location.reference),hregister)));
  4222. end;
  4223. else internalerror(2002);
  4224. end;
  4225. { now generate the jumps }
  4226. if cs_optimize in aktswitches then
  4227. begin
  4228. { procedures are empirically passed on }
  4229. { consumption can also be calculated }
  4230. { but does it pay on the different }
  4231. { processors? }
  4232. { moreover can the size only be appro- }
  4233. { ximated as it is not known if rel8, }
  4234. { rel16 or rel32 jumps are used }
  4235. min_label:=case_get_min(p^.nodes);
  4236. max_label:=case_get_max(p^.nodes);
  4237. labels:=case_count_labels(p^.nodes);
  4238. { can we omit the range check of the jump table }
  4239. getrange(p^.left^.resulttype,lv,hv);
  4240. jumptable_no_range:=(lv=min_label) and (hv=max_label);
  4241. { optimize for size ? }
  4242. if cs_littlesize in aktswitches then
  4243. begin
  4244. if (labels<=2) or ((max_label-min_label)>3*labels) then
  4245. { a linear list is always smaller than a jump tree }
  4246. genlinearlist(p^.nodes)
  4247. else
  4248. { if the labels less or more a continuum then }
  4249. genjumptable(p^.nodes,min_label,max_label);
  4250. end
  4251. else
  4252. begin
  4253. if jumptable_no_range then
  4254. max_linear_list:=4
  4255. else
  4256. max_linear_list:=2;
  4257. if (labels<=max_linear_list) then
  4258. genlinearlist(p^.nodes)
  4259. else
  4260. begin
  4261. if ((max_label-min_label)>4*labels) then
  4262. begin
  4263. if labels>16 then
  4264. gentreejmp(p^.nodes)
  4265. else
  4266. genlinearlist(p^.nodes);
  4267. end
  4268. else
  4269. genjumptable(p^.nodes,min_label,max_label);
  4270. end;
  4271. end;
  4272. end
  4273. else
  4274. { it's always not bad }
  4275. genlinearlist(p^.nodes);
  4276. { now generate the instructions }
  4277. hp:=p^.right;
  4278. while assigned(hp) do
  4279. begin
  4280. cleartempgen;
  4281. secondpass(hp^.right);
  4282. emitl(A_JMP,endlabel);
  4283. hp:=hp^.left;
  4284. end;
  4285. emitl(A_LABEL,elselabel);
  4286. { ... and the else block }
  4287. if assigned(p^.elseblock) then
  4288. begin
  4289. cleartempgen;
  4290. secondpass(p^.elseblock);
  4291. end;
  4292. emitl(A_LABEL,endlabel);
  4293. end;
  4294. procedure secondtryexcept(var p : ptree);
  4295. begin
  4296. end;
  4297. procedure secondtryfinally(var p : ptree);
  4298. begin
  4299. end;
  4300. procedure secondfail(var p : ptree);
  4301. var hp : preference;
  4302. begin
  4303. {if procinfo.exceptions then
  4304. aktproccode.concat(gennasmrec(CALL,S_NO,'HELP_DESTRUCTOR_E'))
  4305. else }
  4306. { we should know if the constructor is called with a new or not,
  4307. how can we do that ???
  4308. exprasmlist^.concat(new(pai68k,op_csymbol(A_CALL,S_NO,newcsymbol('HELP_DESTRUCTOR',0))));
  4309. }
  4310. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_L,R_A5)));
  4311. { also reset to zero in the stack }
  4312. new(hp);
  4313. reset_reference(hp^);
  4314. hp^.offset:=procinfo.ESI_offset;
  4315. hp^.base:=procinfo.framepointer;
  4316. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,R_A5,hp)));
  4317. exprasmlist^.concat(new(pai_labeled,init(A_JMP,quickexitlabel)));
  4318. end;
  4319. procedure secondas(var p : ptree);
  4320. var
  4321. pushed : tpushed;
  4322. begin
  4323. set_location(p^.location,p^.left^.location);
  4324. { save all used registers }
  4325. pushusedregisters(pushed,$ffff);
  4326. { push the vmt of the class }
  4327. exprasmlist^.concat(new(pai68k,op_csymbol_reg(A_MOVE,
  4328. S_L,newcsymbol(pobjectdef(p^.right^.resulttype)^.vmt_mangledname,0),R_SPPUSH)));
  4329. concat_external(pobjectdef(p^.right^.resulttype)^.vmt_mangledname,EXT_NEAR);
  4330. emitpushreferenceaddr(p^.location.reference);
  4331. emitcall('DO_AS',true);
  4332. popusedregisters(pushed);
  4333. end;
  4334. procedure secondis(var p : ptree);
  4335. var
  4336. pushed : tpushed;
  4337. begin
  4338. { save all used registers }
  4339. pushusedregisters(pushed,$ffff);
  4340. secondpass(p^.left);
  4341. p^.location.loc:=LOC_FLAGS;
  4342. p^.location.resflags:=F_NE;
  4343. { push instance to check: }
  4344. case p^.left^.location.loc of
  4345. LOC_REGISTER,LOC_CREGISTER:
  4346. begin
  4347. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,
  4348. S_L,p^.left^.location.register,R_SPPUSH)));
  4349. ungetregister32(p^.left^.location.register);
  4350. end;
  4351. LOC_MEM,LOC_REFERENCE:
  4352. begin
  4353. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,
  4354. S_L,newreference(p^.left^.location.reference),R_SPPUSH)));
  4355. del_reference(p^.left^.location.reference);
  4356. end;
  4357. else internalerror(100);
  4358. end;
  4359. { generate type checking }
  4360. secondpass(p^.right);
  4361. case p^.right^.location.loc of
  4362. LOC_REGISTER,LOC_CREGISTER:
  4363. begin
  4364. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,
  4365. S_L,p^.right^.location.register,R_SPPUSH)));
  4366. ungetregister32(p^.right^.location.register);
  4367. end;
  4368. LOC_MEM,LOC_REFERENCE:
  4369. begin
  4370. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,
  4371. S_L,newreference(p^.right^.location.reference),R_SPPUSH)));
  4372. del_reference(p^.right^.location.reference);
  4373. end;
  4374. else internalerror(100);
  4375. end;
  4376. emitcall('DO_IS',true);
  4377. exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_B,R_D0)));
  4378. popusedregisters(pushed);
  4379. end;
  4380. procedure secondwith(var p : ptree);
  4381. var
  4382. ref : treference;
  4383. symtable : psymtable;
  4384. i : longint;
  4385. begin
  4386. if assigned(p^.left) then
  4387. begin
  4388. secondpass(p^.left);
  4389. ref.symbol:=nil;
  4390. gettempofsizereference(4,ref);
  4391. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,
  4392. newreference(p^.left^.location.reference),R_A0)));
  4393. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,
  4394. R_A0,newreference(ref))));
  4395. del_reference(p^.left^.location.reference);
  4396. { the offset relative to (%ebp) is only needed here! }
  4397. symtable:=p^.withsymtable;
  4398. for i:=1 to p^.tablecount do
  4399. begin
  4400. symtable^.datasize:=ref.offset;
  4401. symtable:=symtable^.next;
  4402. end;
  4403. { p^.right can be optimize out !!! }
  4404. if p^.right<>nil then
  4405. secondpass(p^.right);
  4406. { clear some stuff }
  4407. ungetiftemp(ref);
  4408. end;
  4409. end;
  4410. procedure secondpass(var p : ptree);
  4411. const
  4412. procedures : array[ttreetyp] of secondpassproc =
  4413. (secondadd,secondadd,secondadd,secondmoddiv,secondadd,
  4414. secondmoddiv,secondassignment,secondload,secondnothing,
  4415. secondadd,secondadd,secondadd,secondadd,
  4416. secondadd,secondadd,secondin,secondadd,
  4417. secondadd,secondshlshr,secondshlshr,secondadd,
  4418. secondadd,secondsubscriptn,secondderef,secondaddr,
  4419. seconddoubleaddr,
  4420. secondordconst,secondtypeconv,secondcalln,secondnothing,
  4421. secondrealconst,secondfixconst,secondumminus,
  4422. secondasm,secondvecn,
  4423. secondstringconst,secondfuncret,secondselfn,
  4424. secondnot,secondinline,secondniln,seconderror,
  4425. secondnothing,secondhnewn,secondhdisposen,secondnewn,
  4426. secondsimplenewdispose,secondnothing,secondsetcons,secondblockn,
  4427. secondnothing,secondnothing,secondifn,secondbreakn,
  4428. secondcontinuen,second_while_repeatn,second_while_repeatn,secondfor,
  4429. secondexitn,secondwith,secondcase,secondlabel,
  4430. secondgoto,secondsimplenewdispose,secondtryexcept,secondraise,
  4431. secondnothing,secondtryfinally,secondis,secondas,seconderror,
  4432. secondfail,
  4433. secondnothing,secondloadvmt);
  4434. var
  4435. oldcodegenerror : boolean;
  4436. oldswitches : Tcswitches;
  4437. oldis : pinputfile;
  4438. oldnr : longint;
  4439. begin
  4440. oldcodegenerror:=codegenerror;
  4441. oldswitches:=aktswitches;
  4442. oldis:=current_module^.current_inputfile;
  4443. oldnr:=current_module^.current_inputfile^.line_no;
  4444. codegenerror:=false;
  4445. current_module^.current_inputfile:=p^.inputfile;
  4446. current_module^.current_inputfile^.line_no:=p^.line;
  4447. aktswitches:=p^.pragmas;
  4448. if not(p^.error) then
  4449. begin
  4450. procedures[p^.treetype](p);
  4451. p^.error:=codegenerror;
  4452. codegenerror:=codegenerror or oldcodegenerror;
  4453. end
  4454. else codegenerror:=true;
  4455. aktswitches:=oldswitches;
  4456. current_module^.current_inputfile:=oldis;
  4457. current_module^.current_inputfile^.line_no:=oldnr;
  4458. end;
  4459. function do_secondpass(var p : ptree) : boolean;
  4460. begin
  4461. codegenerror:=false;
  4462. if not(p^.error) then
  4463. secondpass(p);
  4464. do_secondpass:=codegenerror;
  4465. end;
  4466. var
  4467. regvars : array[1..maxvarregs] of pvarsym;
  4468. regvars_para : array[1..maxvarregs] of boolean;
  4469. regvars_refs : array[1..maxvarregs] of longint;
  4470. parasym : boolean;
  4471. procedure searchregvars(p : psym);
  4472. var
  4473. i,j,k : longint;
  4474. begin
  4475. if (p^.typ=varsym) and (pvarsym(p)^.regable) then
  4476. begin
  4477. { walk through all momentary register variables }
  4478. for i:=1 to maxvarregs do
  4479. begin
  4480. { free register ? }
  4481. if regvars[i]=nil then
  4482. begin
  4483. regvars[i]:=pvarsym(p);
  4484. regvars_para[i]:=parasym;
  4485. break;
  4486. end;
  4487. { else throw out a variable ? }
  4488. j:=pvarsym(p)^.refs;
  4489. { parameter get a less value }
  4490. if parasym then
  4491. begin
  4492. if cs_littlesize in aktswitches then
  4493. dec(j,1)
  4494. else
  4495. dec(j,100);
  4496. end;
  4497. if (j>regvars_refs[i]) and (j>0) then
  4498. begin
  4499. for k:=maxvarregs-1 downto i do
  4500. begin
  4501. regvars[k+1]:=regvars[k];
  4502. regvars_para[k+1]:=regvars_para[k];
  4503. end;
  4504. { calc the new refs
  4505. pvarsym(p)^.refs:=j; }
  4506. regvars[i]:=pvarsym(p);
  4507. regvars_para[i]:=parasym;
  4508. regvars_refs[i]:=j;
  4509. break;
  4510. end;
  4511. end;
  4512. end;
  4513. end;
  4514. procedure generatecode(var p : ptree);
  4515. var
  4516. { *pass modifies with every node aktlinenr and current_module^.current_inputfile, }
  4517. { to constantly contain the right line numbers }
  4518. oldis : pinputfile;
  4519. oldnr,i : longint;
  4520. regsize : topsize;
  4521. regi : tregister;
  4522. hr : preference;
  4523. label
  4524. nextreg;
  4525. begin
  4526. cleartempgen;
  4527. oldis:=current_module^.current_inputfile;
  4528. oldnr:=current_module^.current_inputfile^.line_no;
  4529. { when size optimization only count occurrence }
  4530. if cs_littlesize in aktswitches then
  4531. t_times:=1
  4532. else
  4533. { reference for repetition is 100 }
  4534. t_times:=100;
  4535. { clear register count }
  4536. for regi:=R_D0 to R_A6 do
  4537. begin
  4538. reg_pushes[regi]:=0;
  4539. is_reg_var[regi]:=false;
  4540. end;
  4541. use_esp_stackframe:=false;
  4542. if not(do_firstpass(p)) then
  4543. begin
  4544. { max. optimizations }
  4545. { only if no asm is used }
  4546. if (cs_maxoptimieren in aktswitches) and
  4547. ((procinfo.flags and pi_uses_asm)=0) then
  4548. begin
  4549. { can we omit the stack frame ? }
  4550. { conditions:
  4551. 1. procedure (not main block)
  4552. 2. no constructor or destructor
  4553. 3. no call to other procedures
  4554. 4. no interrupt handler
  4555. }
  4556. if assigned(aktprocsym) then
  4557. begin
  4558. if (aktprocsym^.definition^.options and poconstructor+podestructor+poinline+pointerrupt=0) and
  4559. ((procinfo.flags and pi_do_call)=0) and (lexlevel>1) then
  4560. begin
  4561. { use ESP as frame pointer }
  4562. procinfo.framepointer:=R_SP;
  4563. use_esp_stackframe:=true;
  4564. { calc parameter distance new }
  4565. dec(procinfo.framepointer_offset,4);
  4566. dec(procinfo.ESI_offset,4);
  4567. dec(procinfo.retoffset,4);
  4568. dec(procinfo.call_offset,4);
  4569. aktprocsym^.definition^.parast^.call_offset:=procinfo.call_offset;
  4570. end;
  4571. end; { endif assigned }
  4572. if (p^.registers32<4) then
  4573. begin
  4574. for i:=1 to maxvarregs do
  4575. regvars[i]:=nil;
  4576. parasym:=false;
  4577. {$ifdef tp}
  4578. symtablestack^.foreach(searchregvars);
  4579. {$else}
  4580. symtablestack^.foreach(@searchregvars);
  4581. {$endif}
  4582. { copy parameter into a register ? }
  4583. parasym:=true;
  4584. {$ifdef tp}
  4585. symtablestack^.next^.foreach(searchregvars);
  4586. {$else}
  4587. symtablestack^.next^.foreach(@searchregvars);
  4588. {$endif}
  4589. { hold needed registers free }
  4590. for i:=maxvarregs downto maxvarregs-p^.registers32+1 do
  4591. regvars[i]:=nil;
  4592. { now assign register }
  4593. for i:=1 to maxvarregs do
  4594. begin
  4595. if assigned(regvars[i]) then
  4596. begin
  4597. { it is nonsens, to copy the variable to }
  4598. { a register because we need then much }
  4599. { pushes ? }
  4600. if reg_pushes[varregs[i]]>=regvars[i]^.refs then
  4601. begin
  4602. regvars[i]:=nil;
  4603. goto nextreg;
  4604. end;
  4605. { register is no longer available for }
  4606. { expressions }
  4607. { search the register which is the most }
  4608. { unused }
  4609. usableregs:=usableregs-[varregs[i]];
  4610. is_reg_var[varregs[i]]:=true;
  4611. dec(c_usableregs);
  4612. { possibly no 32 bit register are needed }
  4613. if (regvars[i]^.definition^.deftype=orddef) and
  4614. (
  4615. (porddef(regvars[i]^.definition)^.typ=bool8bit) or
  4616. (porddef(regvars[i]^.definition)^.typ=uchar) or
  4617. (porddef(regvars[i]^.definition)^.typ=u8bit) or
  4618. (porddef(regvars[i]^.definition)^.typ=s8bit)
  4619. ) then
  4620. begin
  4621. regvars[i]^.reg:=varregs[i];
  4622. regsize:=S_B;
  4623. end
  4624. else if (regvars[i]^.definition^.deftype=orddef) and
  4625. (
  4626. (porddef(regvars[i]^.definition)^.typ=u16bit) or
  4627. (porddef(regvars[i]^.definition)^.typ=s16bit)
  4628. ) then
  4629. begin
  4630. regvars[i]^.reg:=varregs[i];
  4631. regsize:=S_W;
  4632. end
  4633. else
  4634. begin
  4635. regvars[i]^.reg:=varregs[i];
  4636. regsize:=S_L;
  4637. end;
  4638. { parameter must be load }
  4639. if regvars_para[i] then
  4640. begin
  4641. { procinfo is there actual, }
  4642. { because we can't never be in a }
  4643. { nested procedure }
  4644. { when loading parameter to reg }
  4645. new(hr);
  4646. reset_reference(hr^);
  4647. hr^.offset:=pvarsym(regvars[i])^.address+procinfo.call_offset;
  4648. hr^.base:=procinfo.framepointer;
  4649. procinfo.aktentrycode^.concat(new(pai68k,op_ref_reg(A_MOVE,regsize,
  4650. hr,regvars[i]^.reg)));
  4651. unused:=unused - [regvars[i]^.reg];
  4652. end;
  4653. { procedure uses this register }
  4654. usedinproc:=usedinproc or ($800 shr word(varregs[i]));
  4655. end;
  4656. nextreg:
  4657. { dummy }
  4658. regsize:=S_W;
  4659. end;
  4660. if (verbosity and v_debug)=v_debug then
  4661. begin
  4662. for i:=1 to maxvarregs do
  4663. begin
  4664. if assigned(regvars[i]) then
  4665. Message3(cg_d_register_weight,reg2str(regvars[i]^.reg),
  4666. tostr(regvars[i]^.refs),regvars[i]^.name);
  4667. end;
  4668. end;
  4669. end;
  4670. end;
  4671. do_secondpass(p);
  4672. { all registers can be used again }
  4673. { contains both information on Address registers and data registers }
  4674. { even if they are allocated separately. }
  4675. 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,
  4676. R_FP0,R_FP1,R_FP2,R_FP3,R_FP4,R_FP5,R_FP6,R_FP7];
  4677. c_usableregs:=4;
  4678. end;
  4679. procinfo.aktproccode^.concatlist(exprasmlist);
  4680. current_module^.current_inputfile:=oldis;
  4681. current_module^.current_inputfile^.line_no:=oldnr;
  4682. end;
  4683. end.
  4684. {
  4685. $Log$
  4686. Revision 1.4 1998-04-29 10:33:44 pierre
  4687. + added some code for ansistring (not complete nor working yet)
  4688. * corrected operator overloading
  4689. * corrected nasm output
  4690. + started inline procedures
  4691. + added starstarn : use ** for exponentiation (^ gave problems)
  4692. + started UseTokenInfo cond to get accurate positions
  4693. Revision 1.3 1998/04/07 22:45:03 florian
  4694. * bug0092, bug0115 and bug0121 fixed
  4695. + packed object/class/array
  4696. Revision 1.2 1998/03/28 23:09:54 florian
  4697. * secondin bugfix (m68k and i386)
  4698. * overflow checking bugfix (m68k and i386) -- pretty useless in
  4699. secondadd, since everything is done using 32-bit
  4700. * loading pointer to routines hopefully fixed (m68k)
  4701. * flags problem with calls to RTL internal routines fixed (still strcmp
  4702. to fix) (m68k)
  4703. * #ELSE was still incorrect (didn't take care of the previous level)
  4704. * problem with filenames in the command line solved
  4705. * problem with mangledname solved
  4706. * linking name problem solved (was case insensitive)
  4707. * double id problem and potential crash solved
  4708. * stop after first error
  4709. * and=>test problem removed
  4710. * correct read for all float types
  4711. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  4712. * push/pop is now correct optimized (=> mov (%esp),reg)
  4713. Revision 1.1.1.1 1998/03/25 11:18:16 root
  4714. * Restored version
  4715. Revision 1.51 1998/03/22 12:45:37 florian
  4716. * changes of Carl-Eric to m68k target commit:
  4717. - wrong nodes because of the new string cg in intel, I had to create
  4718. this under m68k also ... had to work it out to fix potential alignment
  4719. problems --> this removes the crash of the m68k compiler.
  4720. - added absolute addressing in m68k assembler (required for Amiga startup)
  4721. - fixed alignment problems (because of byte return values, alignment
  4722. would not be always valid) -- is this ok if i change the offset if odd in
  4723. setfirsttemp ?? -- it seems ok...
  4724. Revision 1.50 2036/02/07 09:29:32 florian
  4725. * patch of Carl applied
  4726. Revision 1.49 1998/03/10 16:27:36 pierre
  4727. * better line info in stabs debug
  4728. * symtabletype and lexlevel separated into two fields of tsymtable
  4729. + ifdef MAKELIB for direct library output, not complete
  4730. + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  4731. working
  4732. + ifdef TESTFUNCRET for setting func result in underfunction, not
  4733. working
  4734. Revision 1.48 1998/03/10 15:25:31 carl
  4735. + put back $L switch for debugging
  4736. Revision 1.47 1998/03/10 04:19:24 carl
  4737. - removed string:=char optimization because would give A LOT of
  4738. register problems
  4739. Revision 1.46 1998/03/10 01:17:15 peter
  4740. * all files have the same header
  4741. * messages are fully implemented, EXTDEBUG uses Comment()
  4742. + AG... files for the Assembler generation
  4743. Revision 1.45 1998/03/09 10:44:33 peter
  4744. + string='', string<>'', string:='', string:=char optimizes (the first 2
  4745. were already in cg68k2)
  4746. Revision 1.44 1998/03/06 00:51:57 peter
  4747. * replaced all old messages from errore.msg, only ExtDebug and some
  4748. Comment() calls are left
  4749. * fixed options.pas
  4750. Revision 1.43 1998/03/05 04:37:46 carl
  4751. + small optimization
  4752. Revision 1.42 1998/03/03 04:13:31 carl
  4753. - removed generate_xxxx and put them in cga68k
  4754. Revision 1.41 1998/03/03 01:08:17 florian
  4755. * bug0105 and bug0106 problem solved
  4756. Revision 1.40 1998/03/02 16:25:25 carl
  4757. * bugfix #95
  4758. Revision 1.39 1998/03/02 01:48:11 peter
  4759. * renamed target_DOS to target_GO32V1
  4760. + new verbose system, merged old errors and verbose units into one new
  4761. verbose.pas, so errors.pas is obsolete
  4762. Revision 1.38 1998/02/25 02:36:29 carl
  4763. * small bugfix with range checking
  4764. Revision 1.37 1998/02/24 16:49:48 peter
  4765. * stackframe ommiting generated 'ret $-4'
  4766. + timer.pp bp7 version
  4767. * innr.inc are now the same files
  4768. Revision 1.36 1998/02/24 16:42:49 carl
  4769. + reinstated __EXIT
  4770. Revision 1.35 1998/02/23 02:56:38 carl
  4771. * bugfix of writing real type values qith m68k target
  4772. Revision 1.34 1998/02/22 23:03:05 peter
  4773. * renamed msource->mainsource and name->unitname
  4774. * optimized filename handling, filename is not seperate anymore with
  4775. path+name+ext, this saves stackspace and a lot of fsplit()'s
  4776. * recompiling of some units in libraries fixed
  4777. * shared libraries are working again
  4778. + $LINKLIB <lib> to support automatic linking to libraries
  4779. + libraries are saved/read from the ppufile, also allows more libraries
  4780. per ppufile
  4781. Revision 1.33 1998/02/22 18:50:12 carl
  4782. * bugfix of stupid diffs!!!!! Recursive crash fix!
  4783. Revision 1.30 1998/02/19 12:22:29 daniel
  4784. * Optimized a statement that did pain to my eyes.
  4785. Revision 1.29 1998/02/17 21:20:31 peter
  4786. + Script unit
  4787. + __EXIT is called again to exit a program
  4788. - target_info.link/assembler calls
  4789. * linking works again for dos
  4790. * optimized a few filehandling functions
  4791. * fixed stabs generation for procedures
  4792. Revision 1.28 1998/02/15 21:16:04 peter
  4793. * all assembler outputs supported by assemblerobject
  4794. * cleanup with assembleroutputs, better .ascii generation
  4795. * help_constructor/destructor are now added to the externals
  4796. - generation of asmresponse is not outputformat depended
  4797. Revision 1.27 1998/02/14 05:06:47 carl
  4798. + now works with TP with overlays
  4799. Revision 1.26 1998/02/14 01:45:06 peter
  4800. * more fixes
  4801. - pmode target is removed
  4802. - search_as_ld is removed, this is done in the link.pas/assemble.pas
  4803. + findexe() to search for an executable (linker,assembler,binder)
  4804. Revision 1.25 1998/02/13 10:34:40 daniel
  4805. * Made Motorola version compilable.
  4806. * Fixed optimizer
  4807. Revision 1.24 1998/02/12 11:49:45 daniel
  4808. Yes! Finally! After three retries, my patch!
  4809. Changes:
  4810. Complete rewrite of psub.pas.
  4811. Added support for DLL's.
  4812. Compiler requires less memory.
  4813. Platform units for each platform.
  4814. Revision 1.23 1998/02/07 18:00:45 carl
  4815. * bugfix in secondin (from Peter Vreman a while ago)
  4816. Revision 1.21 1998/02/05 00:58:05 carl
  4817. + secondas and secondis now work as expected.
  4818. - moved secondas to cg68k2, otherwise problems with symbols
  4819. Revision 1.20 1998/02/01 19:38:41 florian
  4820. * bug0029 fixed, Carl please check it !!!
  4821. Revision 1.19 1998/01/24 21:05:41 carl
  4822. * nested comment bugfix
  4823. Revision 1.18 1998/01/24 00:37:47 florian
  4824. * small fix for DOM
  4825. Revision 1.17 1998/01/21 21:29:46 florian
  4826. * some fixes for Delphi classes
  4827. Revision 1.16 1998/01/20 23:51:59 carl
  4828. * bugfix 74 (FINAL, Pierre's one was incomplete under BP)
  4829. Revision 1.15 1998/01/19 10:25:21 pierre
  4830. * bug in object function call in main program or unit init fixed
  4831. Revision 1.14 1998/01/16 22:34:23 michael
  4832. * Changed 'conversation' to 'conversion'. Waayyy too much chatting going on
  4833. in this compiler :)
  4834. Revision 1.13 1998/01/16 02:18:25 carl
  4835. * second_char_to_string align problem fix (N/A for MC68020 target)
  4836. Revision 1.12 1998/01/13 23:11:02 florian
  4837. + class methods
  4838. Revision 1.11 1998/01/11 03:36:14 carl
  4839. * fixed indexing problem with stack
  4840. * reference on stack bugfix
  4841. * second_bigger sign extension bugfix
  4842. * array scaling bugfix
  4843. * secondderef bugfix
  4844. * bugfix with MOVEQ opcode
  4845. * bugfix of linear list generation
  4846. Revision 1.6 1997/12/10 23:07:12 florian
  4847. * bugs fixed: 12,38 (also m68k),39,40,41
  4848. + warning if a system unit is without -Us compiled
  4849. + warning if a method is virtual and private (was an error)
  4850. * some indentions changed
  4851. + factor does a better error recovering (omit some crashes)
  4852. + problem with @type(x) removed (crashed the compiler)
  4853. Revision 1.5 1997/12/09 13:28:48 carl
  4854. + added s80 real (will presently stop the compiler though)
  4855. + renamed some stuff
  4856. * some bugfixes (can't remember what exactly..)
  4857. Revision 1.4 1997/12/05 14:51:09 carl
  4858. * bugfix of secondfor
  4859. cmpreg was never initialized.
  4860. one of the jump conditionals was wrong (downto would not work)
  4861. Revision 1.3 1997/12/04 14:47:05 carl
  4862. + updated tov09...
  4863. Revision 1.2 1997/11/28 18:14:20 pierre
  4864. working version with several bug fixes
  4865. Revision 1.1.1.1 1997/11/27 08:32:51 michael
  4866. FPC Compiler CVS start
  4867. Pre-CVS log:
  4868. CEC Carl-Eric Codere
  4869. FK Florian Klaempfl
  4870. PM Pierre Muller
  4871. + feature added
  4872. - removed
  4873. * bug fixed or changed
  4874. History (started with version 0.9.0):
  4875. 23th october 1996:
  4876. + some emit calls replaced (FK)
  4877. 24th october 1996:
  4878. * for bug fixed (FK)
  4879. 26th october 1996:
  4880. * english comments (FK)
  4881. 5th november 1996:
  4882. * new init and terminate code (FK)
  4883. ...... some items missed
  4884. 19th september 1997:
  4885. * a call to a function procedure a;[ C ]; doesn't crash the stack
  4886. furthermore (FK)
  4887. 22th september 1997:
  4888. * stack layout for nested procedures in methods modified:
  4889. ESI is no more pushed (must be loaded via framepointer) (FK)
  4890. 27th september 1997:
  4891. + Start of conversion to motorola MC68000 (CEC)
  4892. 29th september 1997:
  4893. + Updated to version 0.9.4 of Intel code generator (CEC)
  4894. 3th october 1997:
  4895. + function second_bool_to_byte for ord(boolean) (PM)
  4896. 4th october 1997: (CEC)
  4897. + first compilation
  4898. 5th octover 1997:
  4899. check floating point negate when i can test everything,
  4900. to see if it makes any sense , according SINGLE_NEG from
  4901. sozobon, it does not.??
  4902. 8th october 1997:
  4903. + ord(x) support (FK)
  4904. + some stuff for typed file support (FK)
  4905. 9 october 1997:
  4906. + converted code to motorola for v096 (CEC)
  4907. 18 october 1997:
  4908. +* removed bugs relating to floating point condition codes. (CEC).
  4909. (in secondadd).
  4910. + had to put secondadd in another routine to compile in tp. (CEC).
  4911. + updated second_bool_to_byte,secondtypeconv and secondinline, secondvecn to v097 (CEC)
  4912. + updated secondload and secondstringconst (merging duplicate strings),secondfor to v95/v97 (CEC).
  4913. + finally converted second_fix_real (very difficult and untested!). (CEC)
  4914. 23 october 1997:
  4915. * bugfix of address register in usableregs set. (They were not defined...) (CEC).
  4916. 24 october 1997:
  4917. * bugfix of scalefactor, allowed unrolled using lsl. (CEC).
  4918. 27th october 1997:
  4919. + now all general purpose registers are in the unused list, so this fixes problems
  4920. regarding pushing registers (such as d0) which were actually never used. (CEC)
  4921. + added secondin (FK) (all credit goes to him).
  4922. + converted second_real_fix thanks to Daniel Mantione for the information
  4923. he gave me on the fixed format. Thanks to W. Metzenthen who did WMEmu
  4924. (which in turn gave me information on the control word of the intel fpu). (CEC)
  4925. 23rd november 1997:
  4926. + changed second_int_real to apply correct calling conventions of rtl.
  4927. 26th november 1997:
  4928. + changed secondmoddiv to apply correct calling conventions of rtl
  4929. and also optimized it a bit.
  4930. }