isp.S 124 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299
  1. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
  3. M68000 Hi-Performance Microprocessor Division
  4. M68060 Software Package
  5. Production Release P1.00 -- October 10, 1994
  6. M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
  7. THE SOFTWARE is provided on an "AS IS" basis and without warranty.
  8. To the maximum extent permitted by applicable law,
  9. MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
  10. INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  11. and any warranty against infringement with regard to the SOFTWARE
  12. (INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
  13. To the maximum extent permitted by applicable law,
  14. IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
  15. (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
  16. BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
  17. ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
  18. Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
  19. You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
  20. so long as this entire notice is retained without alteration in any modified and/or
  21. redistributed versions, and that such modified versions are clearly identified as such.
  22. No licenses are granted by implication, estoppel or otherwise under any patents
  23. or trademarks of Motorola, Inc.
  24. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25. # ireal.s:
  26. # This file is appended to the top of the 060ISP package
  27. # and contains the entry points into the package. The user, in
  28. # effect, branches to one of the branch table entries located
  29. # after _060ISP_TABLE.
  30. # Also, subroutine stubs exist in this file (_isp_done for
  31. # example) that are referenced by the ISP package itself in order
  32. # to call a given routine. The stub routine actually performs the
  33. # callout. The ISP code does a "bsr" to the stub routine. This
  34. # extra layer of hierarchy adds a slight performance penalty but
  35. # it makes the ISP code easier to read and more mainatinable.
  36. #
  37. set _off_chk, 0x00
  38. set _off_divbyzero, 0x04
  39. set _off_trace, 0x08
  40. set _off_access, 0x0c
  41. set _off_done, 0x10
  42. set _off_cas, 0x14
  43. set _off_cas2, 0x18
  44. set _off_lock, 0x1c
  45. set _off_unlock, 0x20
  46. set _off_imr, 0x40
  47. set _off_dmr, 0x44
  48. set _off_dmw, 0x48
  49. set _off_irw, 0x4c
  50. set _off_irl, 0x50
  51. set _off_drb, 0x54
  52. set _off_drw, 0x58
  53. set _off_drl, 0x5c
  54. set _off_dwb, 0x60
  55. set _off_dww, 0x64
  56. set _off_dwl, 0x68
  57. _060ISP_TABLE:
  58. # Here's the table of ENTRY POINTS for those linking the package.
  59. bra.l _isp_unimp
  60. short 0x0000
  61. bra.l _isp_cas
  62. short 0x0000
  63. bra.l _isp_cas2
  64. short 0x0000
  65. bra.l _isp_cas_finish
  66. short 0x0000
  67. bra.l _isp_cas2_finish
  68. short 0x0000
  69. bra.l _isp_cas_inrange
  70. short 0x0000
  71. bra.l _isp_cas_terminate
  72. short 0x0000
  73. bra.l _isp_cas_restart
  74. short 0x0000
  75. space 64
  76. #############################################################
  77. global _real_chk
  78. _real_chk:
  79. mov.l %d0,-(%sp)
  80. mov.l (_060ISP_TABLE-0x80+_off_chk,%pc),%d0
  81. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  82. mov.l 0x4(%sp),%d0
  83. rtd &0x4
  84. global _real_divbyzero
  85. _real_divbyzero:
  86. mov.l %d0,-(%sp)
  87. mov.l (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
  88. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  89. mov.l 0x4(%sp),%d0
  90. rtd &0x4
  91. global _real_trace
  92. _real_trace:
  93. mov.l %d0,-(%sp)
  94. mov.l (_060ISP_TABLE-0x80+_off_trace,%pc),%d0
  95. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  96. mov.l 0x4(%sp),%d0
  97. rtd &0x4
  98. global _real_access
  99. _real_access:
  100. mov.l %d0,-(%sp)
  101. mov.l (_060ISP_TABLE-0x80+_off_access,%pc),%d0
  102. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  103. mov.l 0x4(%sp),%d0
  104. rtd &0x4
  105. global _isp_done
  106. _isp_done:
  107. mov.l %d0,-(%sp)
  108. mov.l (_060ISP_TABLE-0x80+_off_done,%pc),%d0
  109. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  110. mov.l 0x4(%sp),%d0
  111. rtd &0x4
  112. #######################################
  113. global _real_cas
  114. _real_cas:
  115. mov.l %d0,-(%sp)
  116. mov.l (_060ISP_TABLE-0x80+_off_cas,%pc),%d0
  117. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  118. mov.l 0x4(%sp),%d0
  119. rtd &0x4
  120. global _real_cas2
  121. _real_cas2:
  122. mov.l %d0,-(%sp)
  123. mov.l (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
  124. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  125. mov.l 0x4(%sp),%d0
  126. rtd &0x4
  127. global _real_lock_page
  128. _real_lock_page:
  129. mov.l %d0,-(%sp)
  130. mov.l (_060ISP_TABLE-0x80+_off_lock,%pc),%d0
  131. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  132. mov.l 0x4(%sp),%d0
  133. rtd &0x4
  134. global _real_unlock_page
  135. _real_unlock_page:
  136. mov.l %d0,-(%sp)
  137. mov.l (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
  138. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  139. mov.l 0x4(%sp),%d0
  140. rtd &0x4
  141. #######################################
  142. global _imem_read
  143. _imem_read:
  144. mov.l %d0,-(%sp)
  145. mov.l (_060ISP_TABLE-0x80+_off_imr,%pc),%d0
  146. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  147. mov.l 0x4(%sp),%d0
  148. rtd &0x4
  149. global _dmem_read
  150. _dmem_read:
  151. mov.l %d0,-(%sp)
  152. mov.l (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
  153. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  154. mov.l 0x4(%sp),%d0
  155. rtd &0x4
  156. global _dmem_write
  157. _dmem_write:
  158. mov.l %d0,-(%sp)
  159. mov.l (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
  160. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  161. mov.l 0x4(%sp),%d0
  162. rtd &0x4
  163. global _imem_read_word
  164. _imem_read_word:
  165. mov.l %d0,-(%sp)
  166. mov.l (_060ISP_TABLE-0x80+_off_irw,%pc),%d0
  167. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  168. mov.l 0x4(%sp),%d0
  169. rtd &0x4
  170. global _imem_read_long
  171. _imem_read_long:
  172. mov.l %d0,-(%sp)
  173. mov.l (_060ISP_TABLE-0x80+_off_irl,%pc),%d0
  174. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  175. mov.l 0x4(%sp),%d0
  176. rtd &0x4
  177. global _dmem_read_byte
  178. _dmem_read_byte:
  179. mov.l %d0,-(%sp)
  180. mov.l (_060ISP_TABLE-0x80+_off_drb,%pc),%d0
  181. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  182. mov.l 0x4(%sp),%d0
  183. rtd &0x4
  184. global _dmem_read_word
  185. _dmem_read_word:
  186. mov.l %d0,-(%sp)
  187. mov.l (_060ISP_TABLE-0x80+_off_drw,%pc),%d0
  188. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  189. mov.l 0x4(%sp),%d0
  190. rtd &0x4
  191. global _dmem_read_long
  192. _dmem_read_long:
  193. mov.l %d0,-(%sp)
  194. mov.l (_060ISP_TABLE-0x80+_off_drl,%pc),%d0
  195. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  196. mov.l 0x4(%sp),%d0
  197. rtd &0x4
  198. global _dmem_write_byte
  199. _dmem_write_byte:
  200. mov.l %d0,-(%sp)
  201. mov.l (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
  202. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  203. mov.l 0x4(%sp),%d0
  204. rtd &0x4
  205. global _dmem_write_word
  206. _dmem_write_word:
  207. mov.l %d0,-(%sp)
  208. mov.l (_060ISP_TABLE-0x80+_off_dww,%pc),%d0
  209. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  210. mov.l 0x4(%sp),%d0
  211. rtd &0x4
  212. global _dmem_write_long
  213. _dmem_write_long:
  214. mov.l %d0,-(%sp)
  215. mov.l (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
  216. pea.l (_060ISP_TABLE-0x80,%pc,%d0)
  217. mov.l 0x4(%sp),%d0
  218. rtd &0x4
  219. #
  220. # This file contains a set of define statements for constants
  221. # in oreder to promote readability within the core code itself.
  222. #
  223. set LOCAL_SIZE, 96 # stack frame size(bytes)
  224. set LV, -LOCAL_SIZE # stack offset
  225. set EXC_ISR, 0x4 # stack status register
  226. set EXC_IPC, 0x6 # stack pc
  227. set EXC_IVOFF, 0xa # stacked vector offset
  228. set EXC_AREGS, LV+64 # offset of all address regs
  229. set EXC_DREGS, LV+32 # offset of all data regs
  230. set EXC_A7, EXC_AREGS+(7*4) # offset of a7
  231. set EXC_A6, EXC_AREGS+(6*4) # offset of a6
  232. set EXC_A5, EXC_AREGS+(5*4) # offset of a5
  233. set EXC_A4, EXC_AREGS+(4*4) # offset of a4
  234. set EXC_A3, EXC_AREGS+(3*4) # offset of a3
  235. set EXC_A2, EXC_AREGS+(2*4) # offset of a2
  236. set EXC_A1, EXC_AREGS+(1*4) # offset of a1
  237. set EXC_A0, EXC_AREGS+(0*4) # offset of a0
  238. set EXC_D7, EXC_DREGS+(7*4) # offset of d7
  239. set EXC_D6, EXC_DREGS+(6*4) # offset of d6
  240. set EXC_D5, EXC_DREGS+(5*4) # offset of d5
  241. set EXC_D4, EXC_DREGS+(4*4) # offset of d4
  242. set EXC_D3, EXC_DREGS+(3*4) # offset of d3
  243. set EXC_D2, EXC_DREGS+(2*4) # offset of d2
  244. set EXC_D1, EXC_DREGS+(1*4) # offset of d1
  245. set EXC_D0, EXC_DREGS+(0*4) # offset of d0
  246. set EXC_TEMP, LV+16 # offset of temp stack space
  247. set EXC_SAVVAL, LV+12 # offset of old areg value
  248. set EXC_SAVREG, LV+11 # offset of old areg index
  249. set SPCOND_FLG, LV+10 # offset of spc condition flg
  250. set EXC_CC, LV+8 # offset of cc register
  251. set EXC_EXTWPTR, LV+4 # offset of current PC
  252. set EXC_EXTWORD, LV+2 # offset of current ext opword
  253. set EXC_OPWORD, LV+0 # offset of current opword
  254. ###########################
  255. # SPecial CONDition FLaGs #
  256. ###########################
  257. set mia7_flg, 0x04 # (a7)+ flag
  258. set mda7_flg, 0x08 # -(a7) flag
  259. set ichk_flg, 0x10 # chk exception flag
  260. set idbyz_flg, 0x20 # divbyzero flag
  261. set restore_flg, 0x40 # restore -(an)+ flag
  262. set immed_flg, 0x80 # immediate data flag
  263. set mia7_bit, 0x2 # (a7)+ bit
  264. set mda7_bit, 0x3 # -(a7) bit
  265. set ichk_bit, 0x4 # chk exception bit
  266. set idbyz_bit, 0x5 # divbyzero bit
  267. set restore_bit, 0x6 # restore -(a7)+ bit
  268. set immed_bit, 0x7 # immediate data bit
  269. #########
  270. # Misc. #
  271. #########
  272. set BYTE, 1 # len(byte) == 1 byte
  273. set WORD, 2 # len(word) == 2 bytes
  274. set LONG, 4 # len(longword) == 4 bytes
  275. #########################################################################
  276. # XDEF **************************************************************** #
  277. # _isp_unimp(): 060ISP entry point for Unimplemented Instruction #
  278. # #
  279. # This handler should be the first code executed upon taking the #
  280. # "Unimplemented Integer Instruction" exception in an operating #
  281. # system. #
  282. # #
  283. # XREF **************************************************************** #
  284. # _imem_read_{word,long}() - read instruction word/longword #
  285. # _mul64() - emulate 64-bit multiply #
  286. # _div64() - emulate 64-bit divide #
  287. # _moveperipheral() - emulate "movep" #
  288. # _compandset() - emulate misaligned "cas" #
  289. # _compandset2() - emulate "cas2" #
  290. # _chk2_cmp2() - emulate "cmp2" and "chk2" #
  291. # _isp_done() - "callout" for normal final exit #
  292. # _real_trace() - "callout" for Trace exception #
  293. # _real_chk() - "callout" for Chk exception #
  294. # _real_divbyzero() - "callout" for DZ exception #
  295. # _real_access() - "callout" for access error exception #
  296. # #
  297. # INPUT *************************************************************** #
  298. # - The system stack contains the Unimp Int Instr stack frame #
  299. # #
  300. # OUTPUT ************************************************************** #
  301. # If Trace exception: #
  302. # - The system stack changed to contain Trace exc stack frame #
  303. # If Chk exception: #
  304. # - The system stack changed to contain Chk exc stack frame #
  305. # If DZ exception: #
  306. # - The system stack changed to contain DZ exc stack frame #
  307. # If access error exception: #
  308. # - The system stack changed to contain access err exc stk frame #
  309. # Else: #
  310. # - Results saved as appropriate #
  311. # #
  312. # ALGORITHM *********************************************************** #
  313. # This handler fetches the first instruction longword from #
  314. # memory and decodes it to determine which of the unimplemented #
  315. # integer instructions caused this exception. This handler then calls #
  316. # one of _mul64(), _div64(), _moveperipheral(), _compandset(), #
  317. # _compandset2(), or _chk2_cmp2() as appropriate. #
  318. # Some of these instructions, by their nature, may produce other #
  319. # types of exceptions. "div" can produce a divide-by-zero exception, #
  320. # and "chk2" can cause a "Chk" exception. In both cases, the current #
  321. # exception stack frame must be converted to an exception stack frame #
  322. # of the correct exception type and an exit must be made through #
  323. # _real_divbyzero() or _real_chk() as appropriate. In addition, all #
  324. # instructions may be executing while Trace is enabled. If so, then #
  325. # a Trace exception stack frame must be created and an exit made #
  326. # through _real_trace(). #
  327. # Meanwhile, if any read or write to memory using the #
  328. # _mem_{read,write}() "callout"s returns a failing value, then an #
  329. # access error frame must be created and an exit made through #
  330. # _real_access(). #
  331. # If none of these occur, then a normal exit is made through #
  332. # _isp_done(). #
  333. # #
  334. # This handler, upon entry, saves almost all user-visible #
  335. # address and data registers to the stack. Although this may seem to #
  336. # cause excess memory traffic, it was found that due to having to #
  337. # access these register files for things like data retrieval and <ea> #
  338. # calculations, it was more efficient to have them on the stack where #
  339. # they could be accessed by indexing rather than to make subroutine #
  340. # calls to retrieve a register of a particular index. #
  341. # #
  342. #########################################################################
  343. global _isp_unimp
  344. _isp_unimp:
  345. link.w %a6,&-LOCAL_SIZE # create room for stack frame
  346. movm.l &0x3fff,EXC_DREGS(%a6) # store d0-d7/a0-a5
  347. mov.l (%a6),EXC_A6(%a6) # store a6
  348. btst &0x5,EXC_ISR(%a6) # from s or u mode?
  349. bne.b uieh_s # supervisor mode
  350. uieh_u:
  351. mov.l %usp,%a0 # fetch user stack pointer
  352. mov.l %a0,EXC_A7(%a6) # store a7
  353. bra.b uieh_cont
  354. uieh_s:
  355. lea 0xc(%a6),%a0
  356. mov.l %a0,EXC_A7(%a6) # store corrected sp
  357. ###############################################################################
  358. uieh_cont:
  359. clr.b SPCOND_FLG(%a6) # clear "special case" flag
  360. mov.w EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
  361. mov.l EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
  362. #
  363. # fetch the opword and first extension word pointed to by the stacked pc
  364. # and store them to the stack for now
  365. #
  366. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  367. addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
  368. bsr.l _imem_read_long # fetch opword & extword
  369. mov.l %d0,EXC_OPWORD(%a6) # store extword on stack
  370. #########################################################################
  371. # muls.l 0100 1100 00 |<ea>| 0*** 1100 0000 0*** #
  372. # mulu.l 0100 1100 00 |<ea>| 0*** 0100 0000 0*** #
  373. # #
  374. # divs.l 0100 1100 01 |<ea>| 0*** 1100 0000 0*** #
  375. # divu.l 0100 1100 01 |<ea>| 0*** 0100 0000 0*** #
  376. # #
  377. # movep.w m2r 0000 ***1 00 001*** | <displacement> | #
  378. # movep.l m2r 0000 ***1 01 001*** | <displacement> | #
  379. # movep.w r2m 0000 ***1 10 001*** | <displacement> | #
  380. # movep.l r2m 0000 ***1 11 001*** | <displacement> | #
  381. # #
  382. # cas.w 0000 1100 11 |<ea>| 0000 000* **00 0*** #
  383. # cas.l 0000 1110 11 |<ea>| 0000 000* **00 0*** #
  384. # #
  385. # cas2.w 0000 1100 11 111100 **** 000* **00 0*** #
  386. # **** 000* **00 0*** #
  387. # cas2.l 0000 1110 11 111100 **** 000* **00 0*** #
  388. # **** 000* **00 0*** #
  389. # #
  390. # chk2.b 0000 0000 11 |<ea>| **** 1000 0000 0000 #
  391. # chk2.w 0000 0010 11 |<ea>| **** 1000 0000 0000 #
  392. # chk2.l 0000 0100 11 |<ea>| **** 1000 0000 0000 #
  393. # #
  394. # cmp2.b 0000 0000 11 |<ea>| **** 0000 0000 0000 #
  395. # cmp2.w 0000 0010 11 |<ea>| **** 0000 0000 0000 #
  396. # cmp2.l 0000 0100 11 |<ea>| **** 0000 0000 0000 #
  397. #########################################################################
  398. #
  399. # using bit 14 of the operation word, separate into 2 groups:
  400. # (group1) mul64, div64
  401. # (group2) movep, chk2, cmp2, cas2, cas
  402. #
  403. btst &0x1e,%d0 # group1 or group2
  404. beq.b uieh_group2 # go handle group2
  405. #
  406. # now, w/ group1, make mul64's decode the fastest since it will
  407. # most likely be used the most.
  408. #
  409. uieh_group1:
  410. btst &0x16,%d0 # test for div64
  411. bne.b uieh_div64 # go handle div64
  412. uieh_mul64:
  413. # mul64() may use ()+ addressing and may, therefore, alter a7
  414. bsr.l _mul64 # _mul64()
  415. btst &0x5,EXC_ISR(%a6) # supervisor mode?
  416. beq.w uieh_done
  417. btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
  418. beq.w uieh_done # no
  419. btst &0x7,EXC_ISR(%a6) # is trace enabled?
  420. bne.w uieh_trace_a7 # yes
  421. bra.w uieh_a7 # no
  422. uieh_div64:
  423. # div64() may use ()+ addressing and may, therefore, alter a7.
  424. # div64() may take a divide by zero exception.
  425. bsr.l _div64 # _div64()
  426. # here, we sort out all of the special cases that may have happened.
  427. btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
  428. bne.b uieh_div64_a7 # yes
  429. uieh_div64_dbyz:
  430. btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
  431. bne.w uieh_divbyzero # yes
  432. bra.w uieh_done # no
  433. uieh_div64_a7:
  434. btst &0x5,EXC_ISR(%a6) # supervisor mode?
  435. beq.b uieh_div64_dbyz # no
  436. # here, a7 has been incremented by 4 bytes in supervisor mode. we still
  437. # may have the following 3 cases:
  438. # (i) (a7)+
  439. # (ii) (a7)+; trace
  440. # (iii) (a7)+; divide-by-zero
  441. #
  442. btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
  443. bne.w uieh_divbyzero_a7 # yes
  444. tst.b EXC_ISR(%a6) # no; is trace enabled?
  445. bmi.w uieh_trace_a7 # yes
  446. bra.w uieh_a7 # no
  447. #
  448. # now, w/ group2, make movep's decode the fastest since it will
  449. # most likely be used the most.
  450. #
  451. uieh_group2:
  452. btst &0x18,%d0 # test for not movep
  453. beq.b uieh_not_movep
  454. bsr.l _moveperipheral # _movep()
  455. bra.w uieh_done
  456. uieh_not_movep:
  457. btst &0x1b,%d0 # test for chk2,cmp2
  458. beq.b uieh_chk2cmp2 # go handle chk2,cmp2
  459. swap %d0 # put opword in lo word
  460. cmpi.b %d0,&0xfc # test for cas2
  461. beq.b uieh_cas2 # go handle cas2
  462. uieh_cas:
  463. bsr.l _compandset # _cas()
  464. # the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
  465. # mode are simply not considered valid and therefore are not handled.
  466. bra.w uieh_done
  467. uieh_cas2:
  468. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  469. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  470. bsr.l _imem_read_word # read extension word
  471. tst.l %d1 # ifetch error?
  472. bne.w isp_iacc # yes
  473. bsr.l _compandset2 # _cas2()
  474. bra.w uieh_done
  475. uieh_chk2cmp2:
  476. # chk2 may take a chk exception
  477. bsr.l _chk2_cmp2 # _chk2_cmp2()
  478. # here we check to see if a chk trap should be taken
  479. cmpi.b SPCOND_FLG(%a6),&ichk_flg
  480. bne.w uieh_done
  481. bra.b uieh_chk_trap
  482. ###########################################################################
  483. #
  484. # the required emulation has been completed. now, clean up the necessary stack
  485. # info and prepare for rte
  486. #
  487. uieh_done:
  488. mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
  489. # if exception occurred in user mode, then we have to restore a7 in case it
  490. # changed. we don't have to update a7 for supervisor mose because that case
  491. # doesn't flow through here
  492. btst &0x5,EXC_ISR(%a6) # user or supervisor?
  493. bne.b uieh_finish # supervisor
  494. mov.l EXC_A7(%a6),%a0 # fetch user stack pointer
  495. mov.l %a0,%usp # restore it
  496. uieh_finish:
  497. movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
  498. btst &0x7,EXC_ISR(%a6) # is trace mode on?
  499. bne.b uieh_trace # yes;go handle trace mode
  500. mov.l EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
  501. mov.l EXC_A6(%a6),(%a6) # prepare new a6 for unlink
  502. unlk %a6 # unlink stack frame
  503. bra.l _isp_done
  504. #
  505. # The instruction that was just emulated was also being traced. The trace
  506. # trap for this instruction will be lost unless we jump to the trace handler.
  507. # So, here we create a Trace Exception format number two exception stack
  508. # frame from the Unimplemented Integer Intruction Exception stack frame
  509. # format number zero and jump to the user supplied hook "_real_trace()".
  510. #
  511. # UIEH FRAME TRACE FRAME
  512. # ***************** *****************
  513. # * 0x0 * 0x0f4 * * Current *
  514. # ***************** * PC *
  515. # * Current * *****************
  516. # * PC * * 0x2 * 0x024 *
  517. # ***************** *****************
  518. # * SR * * Next *
  519. # ***************** * PC *
  520. # ->* Old * *****************
  521. # from link -->* A6 * * SR *
  522. # ***************** *****************
  523. # /* A7 * * New * <-- for final unlink
  524. # / * * * A6 *
  525. # link frame < ***************** *****************
  526. # \ ~ ~ ~ ~
  527. # \***************** *****************
  528. #
  529. uieh_trace:
  530. mov.l EXC_A6(%a6),-0x4(%a6)
  531. mov.w EXC_ISR(%a6),0x0(%a6)
  532. mov.l EXC_IPC(%a6),0x8(%a6)
  533. mov.l EXC_EXTWPTR(%a6),0x2(%a6)
  534. mov.w &0x2024,0x6(%a6)
  535. sub.l &0x4,%a6
  536. unlk %a6
  537. bra.l _real_trace
  538. #
  539. # UIEH FRAME CHK FRAME
  540. # ***************** *****************
  541. # * 0x0 * 0x0f4 * * Current *
  542. # ***************** * PC *
  543. # * Current * *****************
  544. # * PC * * 0x2 * 0x018 *
  545. # ***************** *****************
  546. # * SR * * Next *
  547. # ***************** * PC *
  548. # (4 words) *****************
  549. # * SR *
  550. # *****************
  551. # (6 words)
  552. #
  553. # the chk2 instruction should take a chk trap. so, here we must create a
  554. # chk stack frame from an unimplemented integer instruction exception frame
  555. # and jump to the user supplied entry point "_real_chk()".
  556. #
  557. uieh_chk_trap:
  558. mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
  559. movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
  560. mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
  561. mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
  562. mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
  563. mov.w &0x2018,0x6(%a6) # put Vector Offset on stack
  564. mov.l EXC_A6(%a6),%a6 # restore a6
  565. add.l &LOCAL_SIZE,%sp # clear stack frame
  566. bra.l _real_chk
  567. #
  568. # UIEH FRAME DIVBYZERO FRAME
  569. # ***************** *****************
  570. # * 0x0 * 0x0f4 * * Current *
  571. # ***************** * PC *
  572. # * Current * *****************
  573. # * PC * * 0x2 * 0x014 *
  574. # ***************** *****************
  575. # * SR * * Next *
  576. # ***************** * PC *
  577. # (4 words) *****************
  578. # * SR *
  579. # *****************
  580. # (6 words)
  581. #
  582. # the divide instruction should take an integer divide by zero trap. so, here
  583. # we must create a divbyzero stack frame from an unimplemented integer
  584. # instruction exception frame and jump to the user supplied entry point
  585. # "_real_divbyzero()".
  586. #
  587. uieh_divbyzero:
  588. mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
  589. movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
  590. mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
  591. mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
  592. mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
  593. mov.w &0x2014,0x6(%a6) # put Vector Offset on stack
  594. mov.l EXC_A6(%a6),%a6 # restore a6
  595. add.l &LOCAL_SIZE,%sp # clear stack frame
  596. bra.l _real_divbyzero
  597. #
  598. # DIVBYZERO FRAME
  599. # *****************
  600. # * Current *
  601. # UIEH FRAME * PC *
  602. # ***************** *****************
  603. # * 0x0 * 0x0f4 * * 0x2 * 0x014 *
  604. # ***************** *****************
  605. # * Current * * Next *
  606. # * PC * * PC *
  607. # ***************** *****************
  608. # * SR * * SR *
  609. # ***************** *****************
  610. # (4 words) (6 words)
  611. #
  612. # the divide instruction should take an integer divide by zero trap. so, here
  613. # we must create a divbyzero stack frame from an unimplemented integer
  614. # instruction exception frame and jump to the user supplied entry point
  615. # "_real_divbyzero()".
  616. #
  617. # However, we must also deal with the fact that (a7)+ was used from supervisor
  618. # mode, thereby shifting the stack frame up 4 bytes.
  619. #
  620. uieh_divbyzero_a7:
  621. mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
  622. movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
  623. mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
  624. mov.w &0x2014,0xa(%a6) # put Vector Offset on stack
  625. mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
  626. mov.l EXC_A6(%a6),%a6 # restore a6
  627. add.l &4+LOCAL_SIZE,%sp # clear stack frame
  628. bra.l _real_divbyzero
  629. #
  630. # TRACE FRAME
  631. # *****************
  632. # * Current *
  633. # UIEH FRAME * PC *
  634. # ***************** *****************
  635. # * 0x0 * 0x0f4 * * 0x2 * 0x024 *
  636. # ***************** *****************
  637. # * Current * * Next *
  638. # * PC * * PC *
  639. # ***************** *****************
  640. # * SR * * SR *
  641. # ***************** *****************
  642. # (4 words) (6 words)
  643. #
  644. #
  645. # The instruction that was just emulated was also being traced. The trace
  646. # trap for this instruction will be lost unless we jump to the trace handler.
  647. # So, here we create a Trace Exception format number two exception stack
  648. # frame from the Unimplemented Integer Intruction Exception stack frame
  649. # format number zero and jump to the user supplied hook "_real_trace()".
  650. #
  651. # However, we must also deal with the fact that (a7)+ was used from supervisor
  652. # mode, thereby shifting the stack frame up 4 bytes.
  653. #
  654. uieh_trace_a7:
  655. mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
  656. movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
  657. mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
  658. mov.w &0x2024,0xa(%a6) # put Vector Offset on stack
  659. mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
  660. mov.l EXC_A6(%a6),%a6 # restore a6
  661. add.l &4+LOCAL_SIZE,%sp # clear stack frame
  662. bra.l _real_trace
  663. #
  664. # UIEH FRAME
  665. # *****************
  666. # * 0x0 * 0x0f4 *
  667. # UIEH FRAME *****************
  668. # ***************** * Next *
  669. # * 0x0 * 0x0f4 * * PC *
  670. # ***************** *****************
  671. # * Current * * SR *
  672. # * PC * *****************
  673. # ***************** (4 words)
  674. # * SR *
  675. # *****************
  676. # (4 words)
  677. uieh_a7:
  678. mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
  679. movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
  680. mov.w &0x00f4,0xe(%a6) # put Vector Offset on stack
  681. mov.l EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
  682. mov.w EXC_ISR(%a6),0x8(%a6) # put SR on stack
  683. mov.l EXC_A6(%a6),%a6 # restore a6
  684. add.l &8+LOCAL_SIZE,%sp # clear stack frame
  685. bra.l _isp_done
  686. ##########
  687. # this is the exit point if a data read or write fails.
  688. # a0 = failing address
  689. # d0 = fslw
  690. isp_dacc:
  691. mov.l %a0,(%a6) # save address
  692. mov.l %d0,-0x4(%a6) # save partial fslw
  693. lea -64(%a6),%sp
  694. movm.l (%sp)+,&0x7fff # restore d0-d7/a0-a6
  695. mov.l 0xc(%sp),-(%sp) # move voff,hi(pc)
  696. mov.l 0x4(%sp),0x10(%sp) # store fslw
  697. mov.l 0xc(%sp),0x4(%sp) # store sr,lo(pc)
  698. mov.l 0x8(%sp),0xc(%sp) # store address
  699. mov.l (%sp)+,0x4(%sp) # store voff,hi(pc)
  700. mov.w &0x4008,0x6(%sp) # store new voff
  701. bra.b isp_acc_exit
  702. # this is the exit point if an instruction word read fails.
  703. # FSLW:
  704. # misaligned = true
  705. # read = true
  706. # size = word
  707. # instruction = true
  708. # software emulation error = true
  709. isp_iacc:
  710. movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
  711. unlk %a6 # unlink frame
  712. sub.w &0x8,%sp # make room for acc frame
  713. mov.l 0x8(%sp),(%sp) # store sr,lo(pc)
  714. mov.w 0xc(%sp),0x4(%sp) # store hi(pc)
  715. mov.w &0x4008,0x6(%sp) # store new voff
  716. mov.l 0x2(%sp),0x8(%sp) # store address (=pc)
  717. mov.l &0x09428001,0xc(%sp) # store fslw
  718. isp_acc_exit:
  719. btst &0x5,(%sp) # user or supervisor?
  720. beq.b isp_acc_exit2 # user
  721. bset &0x2,0xd(%sp) # set supervisor TM bit
  722. isp_acc_exit2:
  723. bra.l _real_access
  724. # if the addressing mode was (an)+ or -(an), the address register must
  725. # be restored to its pre-exception value before entering _real_access.
  726. isp_restore:
  727. cmpi.b SPCOND_FLG(%a6),&restore_flg # do we need a restore?
  728. bne.b isp_restore_done # no
  729. clr.l %d0
  730. mov.b EXC_SAVREG(%a6),%d0 # regno to restore
  731. mov.l EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
  732. isp_restore_done:
  733. rts
  734. #########################################################################
  735. # XDEF **************************************************************** #
  736. # _calc_ea(): routine to calculate effective address #
  737. # #
  738. # XREF **************************************************************** #
  739. # _imem_read_word() - read instruction word #
  740. # _imem_read_long() - read instruction longword #
  741. # _dmem_read_long() - read data longword (for memory indirect) #
  742. # isp_iacc() - handle instruction access error exception #
  743. # isp_dacc() - handle data access error exception #
  744. # #
  745. # INPUT *************************************************************** #
  746. # d0 = number of bytes related to effective address (w,l) #
  747. # #
  748. # OUTPUT ************************************************************** #
  749. # If exiting through isp_dacc... #
  750. # a0 = failing address #
  751. # d0 = FSLW #
  752. # elsif exiting though isp_iacc... #
  753. # none #
  754. # else #
  755. # a0 = effective address #
  756. # #
  757. # ALGORITHM *********************************************************** #
  758. # The effective address type is decoded from the opword residing #
  759. # on the stack. A jump table is used to vector to a routine for the #
  760. # appropriate mode. Since none of the emulated integer instructions #
  761. # uses byte-sized operands, only handle word and long operations. #
  762. # #
  763. # Dn,An - shouldn't enter here #
  764. # (An) - fetch An value from stack #
  765. # -(An) - fetch An value from stack; return decr value; #
  766. # place decr value on stack; store old value in case of #
  767. # future access error; if -(a7), set mda7_flg in #
  768. # SPCOND_FLG #
  769. # (An)+ - fetch An value from stack; return value; #
  770. # place incr value on stack; store old value in case of #
  771. # future access error; if (a7)+, set mia7_flg in #
  772. # SPCOND_FLG #
  773. # (d16,An) - fetch An value from stack; read d16 using #
  774. # _imem_read_word(); fetch may fail -> branch to #
  775. # isp_iacc() #
  776. # (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch #
  777. # address; fetch may fail #
  778. # #<data> - return address of immediate value; set immed_flg #
  779. # in SPCOND_FLG #
  780. # (d16,PC) - fetch stacked PC value; read d16 using #
  781. # _imem_read_word(); fetch may fail -> branch to #
  782. # isp_iacc() #
  783. # everything else - read needed displacements as appropriate w/ #
  784. # _imem_read_{word,long}(); read may fail; if memory #
  785. # indirect, read indirect address using #
  786. # _dmem_read_long() which may also fail #
  787. # #
  788. #########################################################################
  789. global _calc_ea
  790. _calc_ea:
  791. mov.l %d0,%a0 # move # bytes to a0
  792. # MODE and REG are taken from the EXC_OPWORD.
  793. mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
  794. mov.w %d0,%d1 # make a copy
  795. andi.w &0x3f,%d0 # extract mode field
  796. andi.l &0x7,%d1 # extract reg field
  797. # jump to the corresponding function for each {MODE,REG} pair.
  798. mov.w (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
  799. jmp (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
  800. swbeg &64
  801. tbl_ea_mode:
  802. short tbl_ea_mode - tbl_ea_mode
  803. short tbl_ea_mode - tbl_ea_mode
  804. short tbl_ea_mode - tbl_ea_mode
  805. short tbl_ea_mode - tbl_ea_mode
  806. short tbl_ea_mode - tbl_ea_mode
  807. short tbl_ea_mode - tbl_ea_mode
  808. short tbl_ea_mode - tbl_ea_mode
  809. short tbl_ea_mode - tbl_ea_mode
  810. short tbl_ea_mode - tbl_ea_mode
  811. short tbl_ea_mode - tbl_ea_mode
  812. short tbl_ea_mode - tbl_ea_mode
  813. short tbl_ea_mode - tbl_ea_mode
  814. short tbl_ea_mode - tbl_ea_mode
  815. short tbl_ea_mode - tbl_ea_mode
  816. short tbl_ea_mode - tbl_ea_mode
  817. short tbl_ea_mode - tbl_ea_mode
  818. short addr_ind_a0 - tbl_ea_mode
  819. short addr_ind_a1 - tbl_ea_mode
  820. short addr_ind_a2 - tbl_ea_mode
  821. short addr_ind_a3 - tbl_ea_mode
  822. short addr_ind_a4 - tbl_ea_mode
  823. short addr_ind_a5 - tbl_ea_mode
  824. short addr_ind_a6 - tbl_ea_mode
  825. short addr_ind_a7 - tbl_ea_mode
  826. short addr_ind_p_a0 - tbl_ea_mode
  827. short addr_ind_p_a1 - tbl_ea_mode
  828. short addr_ind_p_a2 - tbl_ea_mode
  829. short addr_ind_p_a3 - tbl_ea_mode
  830. short addr_ind_p_a4 - tbl_ea_mode
  831. short addr_ind_p_a5 - tbl_ea_mode
  832. short addr_ind_p_a6 - tbl_ea_mode
  833. short addr_ind_p_a7 - tbl_ea_mode
  834. short addr_ind_m_a0 - tbl_ea_mode
  835. short addr_ind_m_a1 - tbl_ea_mode
  836. short addr_ind_m_a2 - tbl_ea_mode
  837. short addr_ind_m_a3 - tbl_ea_mode
  838. short addr_ind_m_a4 - tbl_ea_mode
  839. short addr_ind_m_a5 - tbl_ea_mode
  840. short addr_ind_m_a6 - tbl_ea_mode
  841. short addr_ind_m_a7 - tbl_ea_mode
  842. short addr_ind_disp_a0 - tbl_ea_mode
  843. short addr_ind_disp_a1 - tbl_ea_mode
  844. short addr_ind_disp_a2 - tbl_ea_mode
  845. short addr_ind_disp_a3 - tbl_ea_mode
  846. short addr_ind_disp_a4 - tbl_ea_mode
  847. short addr_ind_disp_a5 - tbl_ea_mode
  848. short addr_ind_disp_a6 - tbl_ea_mode
  849. short addr_ind_disp_a7 - tbl_ea_mode
  850. short _addr_ind_ext - tbl_ea_mode
  851. short _addr_ind_ext - tbl_ea_mode
  852. short _addr_ind_ext - tbl_ea_mode
  853. short _addr_ind_ext - tbl_ea_mode
  854. short _addr_ind_ext - tbl_ea_mode
  855. short _addr_ind_ext - tbl_ea_mode
  856. short _addr_ind_ext - tbl_ea_mode
  857. short _addr_ind_ext - tbl_ea_mode
  858. short abs_short - tbl_ea_mode
  859. short abs_long - tbl_ea_mode
  860. short pc_ind - tbl_ea_mode
  861. short pc_ind_ext - tbl_ea_mode
  862. short immediate - tbl_ea_mode
  863. short tbl_ea_mode - tbl_ea_mode
  864. short tbl_ea_mode - tbl_ea_mode
  865. short tbl_ea_mode - tbl_ea_mode
  866. ###################################
  867. # Address register indirect: (An) #
  868. ###################################
  869. addr_ind_a0:
  870. mov.l EXC_A0(%a6),%a0 # Get current a0
  871. rts
  872. addr_ind_a1:
  873. mov.l EXC_A1(%a6),%a0 # Get current a1
  874. rts
  875. addr_ind_a2:
  876. mov.l EXC_A2(%a6),%a0 # Get current a2
  877. rts
  878. addr_ind_a3:
  879. mov.l EXC_A3(%a6),%a0 # Get current a3
  880. rts
  881. addr_ind_a4:
  882. mov.l EXC_A4(%a6),%a0 # Get current a4
  883. rts
  884. addr_ind_a5:
  885. mov.l EXC_A5(%a6),%a0 # Get current a5
  886. rts
  887. addr_ind_a6:
  888. mov.l EXC_A6(%a6),%a0 # Get current a6
  889. rts
  890. addr_ind_a7:
  891. mov.l EXC_A7(%a6),%a0 # Get current a7
  892. rts
  893. #####################################################
  894. # Address register indirect w/ postincrement: (An)+ #
  895. #####################################################
  896. addr_ind_p_a0:
  897. mov.l %a0,%d0 # copy no. bytes
  898. mov.l EXC_A0(%a6),%a0 # load current value
  899. add.l %a0,%d0 # increment
  900. mov.l %d0,EXC_A0(%a6) # save incremented value
  901. mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
  902. mov.b &0x0,EXC_SAVREG(%a6) # save regno, too
  903. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  904. rts
  905. addr_ind_p_a1:
  906. mov.l %a0,%d0 # copy no. bytes
  907. mov.l EXC_A1(%a6),%a0 # load current value
  908. add.l %a0,%d0 # increment
  909. mov.l %d0,EXC_A1(%a6) # save incremented value
  910. mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
  911. mov.b &0x1,EXC_SAVREG(%a6) # save regno, too
  912. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  913. rts
  914. addr_ind_p_a2:
  915. mov.l %a0,%d0 # copy no. bytes
  916. mov.l EXC_A2(%a6),%a0 # load current value
  917. add.l %a0,%d0 # increment
  918. mov.l %d0,EXC_A2(%a6) # save incremented value
  919. mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
  920. mov.b &0x2,EXC_SAVREG(%a6) # save regno, too
  921. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  922. rts
  923. addr_ind_p_a3:
  924. mov.l %a0,%d0 # copy no. bytes
  925. mov.l EXC_A3(%a6),%a0 # load current value
  926. add.l %a0,%d0 # increment
  927. mov.l %d0,EXC_A3(%a6) # save incremented value
  928. mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
  929. mov.b &0x3,EXC_SAVREG(%a6) # save regno, too
  930. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  931. rts
  932. addr_ind_p_a4:
  933. mov.l %a0,%d0 # copy no. bytes
  934. mov.l EXC_A4(%a6),%a0 # load current value
  935. add.l %a0,%d0 # increment
  936. mov.l %d0,EXC_A4(%a6) # save incremented value
  937. mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
  938. mov.b &0x4,EXC_SAVREG(%a6) # save regno, too
  939. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  940. rts
  941. addr_ind_p_a5:
  942. mov.l %a0,%d0 # copy no. bytes
  943. mov.l EXC_A5(%a6),%a0 # load current value
  944. add.l %a0,%d0 # increment
  945. mov.l %d0,EXC_A5(%a6) # save incremented value
  946. mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
  947. mov.b &0x5,EXC_SAVREG(%a6) # save regno, too
  948. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  949. rts
  950. addr_ind_p_a6:
  951. mov.l %a0,%d0 # copy no. bytes
  952. mov.l EXC_A6(%a6),%a0 # load current value
  953. add.l %a0,%d0 # increment
  954. mov.l %d0,EXC_A6(%a6) # save incremented value
  955. mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
  956. mov.b &0x6,EXC_SAVREG(%a6) # save regno, too
  957. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  958. rts
  959. addr_ind_p_a7:
  960. mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
  961. mov.l %a0,%d0 # copy no. bytes
  962. mov.l EXC_A7(%a6),%a0 # load current value
  963. add.l %a0,%d0 # increment
  964. mov.l %d0,EXC_A7(%a6) # save incremented value
  965. rts
  966. ####################################################
  967. # Address register indirect w/ predecrement: -(An) #
  968. ####################################################
  969. addr_ind_m_a0:
  970. mov.l EXC_A0(%a6),%d0 # Get current a0
  971. mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
  972. sub.l %a0,%d0 # Decrement
  973. mov.l %d0,EXC_A0(%a6) # Save decr value
  974. mov.l %d0,%a0
  975. mov.b &0x0,EXC_SAVREG(%a6) # save regno, too
  976. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  977. rts
  978. addr_ind_m_a1:
  979. mov.l EXC_A1(%a6),%d0 # Get current a1
  980. mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
  981. sub.l %a0,%d0 # Decrement
  982. mov.l %d0,EXC_A1(%a6) # Save decr value
  983. mov.l %d0,%a0
  984. mov.b &0x1,EXC_SAVREG(%a6) # save regno, too
  985. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  986. rts
  987. addr_ind_m_a2:
  988. mov.l EXC_A2(%a6),%d0 # Get current a2
  989. mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
  990. sub.l %a0,%d0 # Decrement
  991. mov.l %d0,EXC_A2(%a6) # Save decr value
  992. mov.l %d0,%a0
  993. mov.b &0x2,EXC_SAVREG(%a6) # save regno, too
  994. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  995. rts
  996. addr_ind_m_a3:
  997. mov.l EXC_A3(%a6),%d0 # Get current a3
  998. mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
  999. sub.l %a0,%d0 # Decrement
  1000. mov.l %d0,EXC_A3(%a6) # Save decr value
  1001. mov.l %d0,%a0
  1002. mov.b &0x3,EXC_SAVREG(%a6) # save regno, too
  1003. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  1004. rts
  1005. addr_ind_m_a4:
  1006. mov.l EXC_A4(%a6),%d0 # Get current a4
  1007. mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
  1008. sub.l %a0,%d0 # Decrement
  1009. mov.l %d0,EXC_A4(%a6) # Save decr value
  1010. mov.l %d0,%a0
  1011. mov.b &0x4,EXC_SAVREG(%a6) # save regno, too
  1012. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  1013. rts
  1014. addr_ind_m_a5:
  1015. mov.l EXC_A5(%a6),%d0 # Get current a5
  1016. mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
  1017. sub.l %a0,%d0 # Decrement
  1018. mov.l %d0,EXC_A5(%a6) # Save decr value
  1019. mov.l %d0,%a0
  1020. mov.b &0x5,EXC_SAVREG(%a6) # save regno, too
  1021. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  1022. rts
  1023. addr_ind_m_a6:
  1024. mov.l EXC_A6(%a6),%d0 # Get current a6
  1025. mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
  1026. sub.l %a0,%d0 # Decrement
  1027. mov.l %d0,EXC_A6(%a6) # Save decr value
  1028. mov.l %d0,%a0
  1029. mov.b &0x6,EXC_SAVREG(%a6) # save regno, too
  1030. mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
  1031. rts
  1032. addr_ind_m_a7:
  1033. mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
  1034. mov.l EXC_A7(%a6),%d0 # Get current a7
  1035. sub.l %a0,%d0 # Decrement
  1036. mov.l %d0,EXC_A7(%a6) # Save decr value
  1037. mov.l %d0,%a0
  1038. rts
  1039. ########################################################
  1040. # Address register indirect w/ displacement: (d16, An) #
  1041. ########################################################
  1042. addr_ind_disp_a0:
  1043. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1044. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1045. bsr.l _imem_read_word
  1046. tst.l %d1 # ifetch error?
  1047. bne.l isp_iacc # yes
  1048. mov.w %d0,%a0 # sign extend displacement
  1049. add.l EXC_A0(%a6),%a0 # a0 + d16
  1050. rts
  1051. addr_ind_disp_a1:
  1052. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1053. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1054. bsr.l _imem_read_word
  1055. tst.l %d1 # ifetch error?
  1056. bne.l isp_iacc # yes
  1057. mov.w %d0,%a0 # sign extend displacement
  1058. add.l EXC_A1(%a6),%a0 # a1 + d16
  1059. rts
  1060. addr_ind_disp_a2:
  1061. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1062. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1063. bsr.l _imem_read_word
  1064. tst.l %d1 # ifetch error?
  1065. bne.l isp_iacc # yes
  1066. mov.w %d0,%a0 # sign extend displacement
  1067. add.l EXC_A2(%a6),%a0 # a2 + d16
  1068. rts
  1069. addr_ind_disp_a3:
  1070. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1071. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1072. bsr.l _imem_read_word
  1073. tst.l %d1 # ifetch error?
  1074. bne.l isp_iacc # yes
  1075. mov.w %d0,%a0 # sign extend displacement
  1076. add.l EXC_A3(%a6),%a0 # a3 + d16
  1077. rts
  1078. addr_ind_disp_a4:
  1079. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1080. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1081. bsr.l _imem_read_word
  1082. tst.l %d1 # ifetch error?
  1083. bne.l isp_iacc # yes
  1084. mov.w %d0,%a0 # sign extend displacement
  1085. add.l EXC_A4(%a6),%a0 # a4 + d16
  1086. rts
  1087. addr_ind_disp_a5:
  1088. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1089. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1090. bsr.l _imem_read_word
  1091. tst.l %d1 # ifetch error?
  1092. bne.l isp_iacc # yes
  1093. mov.w %d0,%a0 # sign extend displacement
  1094. add.l EXC_A5(%a6),%a0 # a5 + d16
  1095. rts
  1096. addr_ind_disp_a6:
  1097. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1098. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1099. bsr.l _imem_read_word
  1100. tst.l %d1 # ifetch error?
  1101. bne.l isp_iacc # yes
  1102. mov.w %d0,%a0 # sign extend displacement
  1103. add.l EXC_A6(%a6),%a0 # a6 + d16
  1104. rts
  1105. addr_ind_disp_a7:
  1106. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1107. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1108. bsr.l _imem_read_word
  1109. tst.l %d1 # ifetch error?
  1110. bne.l isp_iacc # yes
  1111. mov.w %d0,%a0 # sign extend displacement
  1112. add.l EXC_A7(%a6),%a0 # a7 + d16
  1113. rts
  1114. ########################################################################
  1115. # Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
  1116. # " " " w/ " (base displacement): (bd, An, Xn) #
  1117. # Memory indirect postindexed: ([bd, An], Xn, od) #
  1118. # Memory indirect preindexed: ([bd, An, Xn], od) #
  1119. ########################################################################
  1120. _addr_ind_ext:
  1121. mov.l %d1,-(%sp)
  1122. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1123. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1124. bsr.l _imem_read_word # fetch extword in d0
  1125. tst.l %d1 # ifetch error?
  1126. bne.l isp_iacc # yes
  1127. mov.l (%sp)+,%d1
  1128. mov.l (EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
  1129. btst &0x8,%d0
  1130. beq.b addr_ind_index_8bit # for ext word or not?
  1131. movm.l &0x3c00,-(%sp) # save d2-d5
  1132. mov.l %d0,%d5 # put extword in d5
  1133. mov.l %a0,%d3 # put base in d3
  1134. bra.l calc_mem_ind # calc memory indirect
  1135. addr_ind_index_8bit:
  1136. mov.l %d2,-(%sp) # save old d2
  1137. mov.l %d0,%d1
  1138. rol.w &0x4,%d1
  1139. andi.w &0xf,%d1 # extract index regno
  1140. mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
  1141. btst &0xb,%d0 # is it word or long?
  1142. bne.b aii8_long
  1143. ext.l %d1 # sign extend word index
  1144. aii8_long:
  1145. mov.l %d0,%d2
  1146. rol.w &0x7,%d2
  1147. andi.l &0x3,%d2 # extract scale value
  1148. lsl.l %d2,%d1 # shift index by scale
  1149. extb.l %d0 # sign extend displacement
  1150. add.l %d1,%d0 # index + disp
  1151. add.l %d0,%a0 # An + (index + disp)
  1152. mov.l (%sp)+,%d2 # restore old d2
  1153. rts
  1154. ######################
  1155. # Immediate: #<data> #
  1156. #########################################################################
  1157. # word, long: <ea> of the data is the current extension word #
  1158. # pointer value. new extension word pointer is simply the old #
  1159. # plus the number of bytes in the data type(2 or 4). #
  1160. #########################################################################
  1161. immediate:
  1162. mov.b &immed_flg,SPCOND_FLG(%a6) # set immediate flag
  1163. mov.l EXC_EXTWPTR(%a6),%a0 # fetch extension word ptr
  1164. rts
  1165. ###########################
  1166. # Absolute short: (XXX).W #
  1167. ###########################
  1168. abs_short:
  1169. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1170. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1171. bsr.l _imem_read_word # fetch short address
  1172. tst.l %d1 # ifetch error?
  1173. bne.l isp_iacc # yes
  1174. mov.w %d0,%a0 # return <ea> in a0
  1175. rts
  1176. ##########################
  1177. # Absolute long: (XXX).L #
  1178. ##########################
  1179. abs_long:
  1180. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1181. addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
  1182. bsr.l _imem_read_long # fetch long address
  1183. tst.l %d1 # ifetch error?
  1184. bne.l isp_iacc # yes
  1185. mov.l %d0,%a0 # return <ea> in a0
  1186. rts
  1187. #######################################################
  1188. # Program counter indirect w/ displacement: (d16, PC) #
  1189. #######################################################
  1190. pc_ind:
  1191. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1192. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1193. bsr.l _imem_read_word # fetch word displacement
  1194. tst.l %d1 # ifetch error?
  1195. bne.l isp_iacc # yes
  1196. mov.w %d0,%a0 # sign extend displacement
  1197. add.l EXC_EXTWPTR(%a6),%a0 # pc + d16
  1198. # _imem_read_word() increased the extwptr by 2. need to adjust here.
  1199. subq.l &0x2,%a0 # adjust <ea>
  1200. rts
  1201. ##########################################################
  1202. # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
  1203. # " " w/ " (base displacement): (bd, PC, An) #
  1204. # PC memory indirect postindexed: ([bd, PC], Xn, od) #
  1205. # PC memory indirect preindexed: ([bd, PC, Xn], od) #
  1206. ##########################################################
  1207. pc_ind_ext:
  1208. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1209. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1210. bsr.l _imem_read_word # fetch ext word
  1211. tst.l %d1 # ifetch error?
  1212. bne.l isp_iacc # yes
  1213. mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0
  1214. subq.l &0x2,%a0 # adjust base
  1215. btst &0x8,%d0 # is disp only 8 bits?
  1216. beq.b pc_ind_index_8bit # yes
  1217. # the indexed addressing mode uses a base displacement of size
  1218. # word or long
  1219. movm.l &0x3c00,-(%sp) # save d2-d5
  1220. mov.l %d0,%d5 # put extword in d5
  1221. mov.l %a0,%d3 # put base in d3
  1222. bra.l calc_mem_ind # calc memory indirect
  1223. pc_ind_index_8bit:
  1224. mov.l %d2,-(%sp) # create a temp register
  1225. mov.l %d0,%d1 # make extword copy
  1226. rol.w &0x4,%d1 # rotate reg num into place
  1227. andi.w &0xf,%d1 # extract register number
  1228. mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
  1229. btst &0xb,%d0 # is index word or long?
  1230. bne.b pii8_long # long
  1231. ext.l %d1 # sign extend word index
  1232. pii8_long:
  1233. mov.l %d0,%d2 # make extword copy
  1234. rol.w &0x7,%d2 # rotate scale value into place
  1235. andi.l &0x3,%d2 # extract scale value
  1236. lsl.l %d2,%d1 # shift index by scale
  1237. extb.l %d0 # sign extend displacement
  1238. add.l %d1,%d0 # index + disp
  1239. add.l %d0,%a0 # An + (index + disp)
  1240. mov.l (%sp)+,%d2 # restore temp register
  1241. rts
  1242. # a5 = exc_extwptr (global to uaeh)
  1243. # a4 = exc_opword (global to uaeh)
  1244. # a3 = exc_dregs (global to uaeh)
  1245. # d2 = index (internal " " )
  1246. # d3 = base (internal " " )
  1247. # d4 = od (internal " " )
  1248. # d5 = extword (internal " " )
  1249. calc_mem_ind:
  1250. btst &0x6,%d5 # is the index suppressed?
  1251. beq.b calc_index
  1252. clr.l %d2 # yes, so index = 0
  1253. bra.b base_supp_ck
  1254. calc_index:
  1255. bfextu %d5{&16:&4},%d2
  1256. mov.l (EXC_DREGS,%a6,%d2.w*4),%d2
  1257. btst &0xb,%d5 # is index word or long?
  1258. bne.b no_ext
  1259. ext.l %d2
  1260. no_ext:
  1261. bfextu %d5{&21:&2},%d0
  1262. lsl.l %d0,%d2
  1263. base_supp_ck:
  1264. btst &0x7,%d5 # is the bd suppressed?
  1265. beq.b no_base_sup
  1266. clr.l %d3
  1267. no_base_sup:
  1268. bfextu %d5{&26:&2},%d0 # get bd size
  1269. # beq.l _error # if (size == 0) it's reserved
  1270. cmpi.b %d0,&2
  1271. blt.b no_bd
  1272. beq.b get_word_bd
  1273. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1274. addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
  1275. bsr.l _imem_read_long
  1276. tst.l %d1 # ifetch error?
  1277. bne.l isp_iacc # yes
  1278. bra.b chk_ind
  1279. get_word_bd:
  1280. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1281. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1282. bsr.l _imem_read_word
  1283. tst.l %d1 # ifetch error?
  1284. bne.l isp_iacc # yes
  1285. ext.l %d0 # sign extend bd
  1286. chk_ind:
  1287. add.l %d0,%d3 # base += bd
  1288. no_bd:
  1289. bfextu %d5{&30:&2},%d0 # is od suppressed?
  1290. beq.w aii_bd
  1291. cmpi.b %d0,&0x2
  1292. blt.b null_od
  1293. beq.b word_od
  1294. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1295. addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
  1296. bsr.l _imem_read_long
  1297. tst.l %d1 # ifetch error?
  1298. bne.l isp_iacc # yes
  1299. bra.b add_them
  1300. word_od:
  1301. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1302. addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
  1303. bsr.l _imem_read_word
  1304. tst.l %d1 # ifetch error?
  1305. bne.l isp_iacc # yes
  1306. ext.l %d0 # sign extend od
  1307. bra.b add_them
  1308. null_od:
  1309. clr.l %d0
  1310. add_them:
  1311. mov.l %d0,%d4
  1312. btst &0x2,%d5 # pre or post indexing?
  1313. beq.b pre_indexed
  1314. mov.l %d3,%a0
  1315. bsr.l _dmem_read_long
  1316. tst.l %d1 # dfetch error?
  1317. bne.b calc_ea_err # yes
  1318. add.l %d2,%d0 # <ea> += index
  1319. add.l %d4,%d0 # <ea> += od
  1320. bra.b done_ea
  1321. pre_indexed:
  1322. add.l %d2,%d3 # preindexing
  1323. mov.l %d3,%a0
  1324. bsr.l _dmem_read_long
  1325. tst.l %d1 # ifetch error?
  1326. bne.b calc_ea_err # yes
  1327. add.l %d4,%d0 # ea += od
  1328. bra.b done_ea
  1329. aii_bd:
  1330. add.l %d2,%d3 # ea = (base + bd) + index
  1331. mov.l %d3,%d0
  1332. done_ea:
  1333. mov.l %d0,%a0
  1334. movm.l (%sp)+,&0x003c # restore d2-d5
  1335. rts
  1336. # if dmem_read_long() returns a fail message in d1, the package
  1337. # must create an access error frame. here, we pass a skeleton fslw
  1338. # and the failing address to the routine that creates the new frame.
  1339. # FSLW:
  1340. # read = true
  1341. # size = longword
  1342. # TM = data
  1343. # software emulation error = true
  1344. calc_ea_err:
  1345. mov.l %d3,%a0 # pass failing address
  1346. mov.l &0x01010001,%d0 # pass fslw
  1347. bra.l isp_dacc
  1348. #########################################################################
  1349. # XDEF **************************************************************** #
  1350. # _moveperipheral(): routine to emulate movep instruction #
  1351. # #
  1352. # XREF **************************************************************** #
  1353. # _dmem_read_byte() - read byte from memory #
  1354. # _dmem_write_byte() - write byte to memory #
  1355. # isp_dacc() - handle data access error exception #
  1356. # #
  1357. # INPUT *************************************************************** #
  1358. # none #
  1359. # #
  1360. # OUTPUT ************************************************************** #
  1361. # If exiting through isp_dacc... #
  1362. # a0 = failing address #
  1363. # d0 = FSLW #
  1364. # else #
  1365. # none #
  1366. # #
  1367. # ALGORITHM *********************************************************** #
  1368. # Decode the movep instruction words stored at EXC_OPWORD and #
  1369. # either read or write the required bytes from/to memory. Use the #
  1370. # _dmem_{read,write}_byte() routines. If one of the memory routines #
  1371. # returns a failing value, we must pass the failing address and a FSLW #
  1372. # to the _isp_dacc() routine. #
  1373. # Since this instruction is used to access peripherals, make sure #
  1374. # to only access the required bytes. #
  1375. # #
  1376. #########################################################################
  1377. ###########################
  1378. # movep.(w,l) Dx,(d,Ay) #
  1379. # movep.(w,l) (d,Ay),Dx #
  1380. ###########################
  1381. global _moveperipheral
  1382. _moveperipheral:
  1383. mov.w EXC_OPWORD(%a6),%d1 # fetch the opcode word
  1384. mov.b %d1,%d0
  1385. and.w &0x7,%d0 # extract Ay from opcode word
  1386. mov.l (EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
  1387. add.w EXC_EXTWORD(%a6),%a0 # add: an + sgn_ext(disp)
  1388. btst &0x7,%d1 # (reg 2 mem) or (mem 2 reg)
  1389. beq.w mem2reg
  1390. # reg2mem: fetch dx, then write it to memory
  1391. reg2mem:
  1392. mov.w %d1,%d0
  1393. rol.w &0x7,%d0
  1394. and.w &0x7,%d0 # extract Dx from opcode word
  1395. mov.l (EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
  1396. btst &0x6,%d1 # word or long operation?
  1397. beq.b r2mwtrans
  1398. # a0 = dst addr
  1399. # d0 = Dx
  1400. r2mltrans:
  1401. mov.l %d0,%d2 # store data
  1402. mov.l %a0,%a2 # store addr
  1403. rol.l &0x8,%d2
  1404. mov.l %d2,%d0
  1405. bsr.l _dmem_write_byte # os : write hi
  1406. tst.l %d1 # dfetch error?
  1407. bne.w movp_write_err # yes
  1408. add.w &0x2,%a2 # incr addr
  1409. mov.l %a2,%a0
  1410. rol.l &0x8,%d2
  1411. mov.l %d2,%d0
  1412. bsr.l _dmem_write_byte # os : write lo
  1413. tst.l %d1 # dfetch error?
  1414. bne.w movp_write_err # yes
  1415. add.w &0x2,%a2 # incr addr
  1416. mov.l %a2,%a0
  1417. rol.l &0x8,%d2
  1418. mov.l %d2,%d0
  1419. bsr.l _dmem_write_byte # os : write lo
  1420. tst.l %d1 # dfetch error?
  1421. bne.w movp_write_err # yes
  1422. add.w &0x2,%a2 # incr addr
  1423. mov.l %a2,%a0
  1424. rol.l &0x8,%d2
  1425. mov.l %d2,%d0
  1426. bsr.l _dmem_write_byte # os : write lo
  1427. tst.l %d1 # dfetch error?
  1428. bne.w movp_write_err # yes
  1429. rts
  1430. # a0 = dst addr
  1431. # d0 = Dx
  1432. r2mwtrans:
  1433. mov.l %d0,%d2 # store data
  1434. mov.l %a0,%a2 # store addr
  1435. lsr.w &0x8,%d0
  1436. bsr.l _dmem_write_byte # os : write hi
  1437. tst.l %d1 # dfetch error?
  1438. bne.w movp_write_err # yes
  1439. add.w &0x2,%a2
  1440. mov.l %a2,%a0
  1441. mov.l %d2,%d0
  1442. bsr.l _dmem_write_byte # os : write lo
  1443. tst.l %d1 # dfetch error?
  1444. bne.w movp_write_err # yes
  1445. rts
  1446. # mem2reg: read bytes from memory.
  1447. # determines the dest register, and then writes the bytes into it.
  1448. mem2reg:
  1449. btst &0x6,%d1 # word or long operation?
  1450. beq.b m2rwtrans
  1451. # a0 = dst addr
  1452. m2rltrans:
  1453. mov.l %a0,%a2 # store addr
  1454. bsr.l _dmem_read_byte # read first byte
  1455. tst.l %d1 # dfetch error?
  1456. bne.w movp_read_err # yes
  1457. mov.l %d0,%d2
  1458. add.w &0x2,%a2 # incr addr by 2 bytes
  1459. mov.l %a2,%a0
  1460. bsr.l _dmem_read_byte # read second byte
  1461. tst.l %d1 # dfetch error?
  1462. bne.w movp_read_err # yes
  1463. lsl.w &0x8,%d2
  1464. mov.b %d0,%d2 # append bytes
  1465. add.w &0x2,%a2 # incr addr by 2 bytes
  1466. mov.l %a2,%a0
  1467. bsr.l _dmem_read_byte # read second byte
  1468. tst.l %d1 # dfetch error?
  1469. bne.w movp_read_err # yes
  1470. lsl.l &0x8,%d2
  1471. mov.b %d0,%d2 # append bytes
  1472. add.w &0x2,%a2 # incr addr by 2 bytes
  1473. mov.l %a2,%a0
  1474. bsr.l _dmem_read_byte # read second byte
  1475. tst.l %d1 # dfetch error?
  1476. bne.w movp_read_err # yes
  1477. lsl.l &0x8,%d2
  1478. mov.b %d0,%d2 # append bytes
  1479. mov.b EXC_OPWORD(%a6),%d1
  1480. lsr.b &0x1,%d1
  1481. and.w &0x7,%d1 # extract Dx from opcode word
  1482. mov.l %d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
  1483. rts
  1484. # a0 = dst addr
  1485. m2rwtrans:
  1486. mov.l %a0,%a2 # store addr
  1487. bsr.l _dmem_read_byte # read first byte
  1488. tst.l %d1 # dfetch error?
  1489. bne.w movp_read_err # yes
  1490. mov.l %d0,%d2
  1491. add.w &0x2,%a2 # incr addr by 2 bytes
  1492. mov.l %a2,%a0
  1493. bsr.l _dmem_read_byte # read second byte
  1494. tst.l %d1 # dfetch error?
  1495. bne.w movp_read_err # yes
  1496. lsl.w &0x8,%d2
  1497. mov.b %d0,%d2 # append bytes
  1498. mov.b EXC_OPWORD(%a6),%d1
  1499. lsr.b &0x1,%d1
  1500. and.w &0x7,%d1 # extract Dx from opcode word
  1501. mov.w %d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
  1502. rts
  1503. # if dmem_{read,write}_byte() returns a fail message in d1, the package
  1504. # must create an access error frame. here, we pass a skeleton fslw
  1505. # and the failing address to the routine that creates the new frame.
  1506. # FSLW:
  1507. # write = true
  1508. # size = byte
  1509. # TM = data
  1510. # software emulation error = true
  1511. movp_write_err:
  1512. mov.l %a2,%a0 # pass failing address
  1513. mov.l &0x00a10001,%d0 # pass fslw
  1514. bra.l isp_dacc
  1515. # FSLW:
  1516. # read = true
  1517. # size = byte
  1518. # TM = data
  1519. # software emulation error = true
  1520. movp_read_err:
  1521. mov.l %a2,%a0 # pass failing address
  1522. mov.l &0x01210001,%d0 # pass fslw
  1523. bra.l isp_dacc
  1524. #########################################################################
  1525. # XDEF **************************************************************** #
  1526. # _chk2_cmp2(): routine to emulate chk2/cmp2 instructions #
  1527. # #
  1528. # XREF **************************************************************** #
  1529. # _calc_ea(): calculate effective address #
  1530. # _dmem_read_long(): read operands #
  1531. # _dmem_read_word(): read operands #
  1532. # isp_dacc(): handle data access error exception #
  1533. # #
  1534. # INPUT *************************************************************** #
  1535. # none #
  1536. # #
  1537. # OUTPUT ************************************************************** #
  1538. # If exiting through isp_dacc... #
  1539. # a0 = failing address #
  1540. # d0 = FSLW #
  1541. # else #
  1542. # none #
  1543. # #
  1544. # ALGORITHM *********************************************************** #
  1545. # First, calculate the effective address, then fetch the byte, #
  1546. # word, or longword sized operands. Then, in the interest of #
  1547. # simplicity, all operands are converted to longword size whether the #
  1548. # operation is byte, word, or long. The bounds are sign extended #
  1549. # accordingly. If Rn is a data regsiter, Rn is also sign extended. If #
  1550. # Rn is an address register, it need not be sign extended since the #
  1551. # full register is always used. #
  1552. # The comparisons are made and the condition codes calculated. #
  1553. # If the instruction is chk2 and the Rn value is out-of-bounds, set #
  1554. # the ichk_flg in SPCOND_FLG. #
  1555. # If the memory fetch returns a failing value, pass the failing #
  1556. # address and FSLW to the isp_dacc() routine. #
  1557. # #
  1558. #########################################################################
  1559. global _chk2_cmp2
  1560. _chk2_cmp2:
  1561. # passing size parameter doesn't matter since chk2 & cmp2 can't do
  1562. # either predecrement, postincrement, or immediate.
  1563. bsr.l _calc_ea # calculate <ea>
  1564. mov.b EXC_EXTWORD(%a6), %d0 # fetch hi extension word
  1565. rol.b &0x4, %d0 # rotate reg bits into lo
  1566. and.w &0xf, %d0 # extract reg bits
  1567. mov.l (EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
  1568. cmpi.b EXC_OPWORD(%a6), &0x2 # what size is operation?
  1569. blt.b chk2_cmp2_byte # size == byte
  1570. beq.b chk2_cmp2_word # size == word
  1571. # the bounds are longword size. call routine to read the lower
  1572. # bound into d0 and the higher bound into d1.
  1573. chk2_cmp2_long:
  1574. mov.l %a0,%a2 # save copy of <ea>
  1575. bsr.l _dmem_read_long # fetch long lower bound
  1576. tst.l %d1 # dfetch error?
  1577. bne.w chk2_cmp2_err_l # yes
  1578. mov.l %d0,%d3 # save long lower bound
  1579. addq.l &0x4,%a2
  1580. mov.l %a2,%a0 # pass <ea> of long upper bound
  1581. bsr.l _dmem_read_long # fetch long upper bound
  1582. tst.l %d1 # dfetch error?
  1583. bne.w chk2_cmp2_err_l # yes
  1584. mov.l %d0,%d1 # long upper bound in d1
  1585. mov.l %d3,%d0 # long lower bound in d0
  1586. bra.w chk2_cmp2_compare # go do the compare emulation
  1587. # the bounds are word size. fetch them in one subroutine call by
  1588. # reading a longword. sign extend both. if it's a data operation,
  1589. # sign extend Rn to long, also.
  1590. chk2_cmp2_word:
  1591. mov.l %a0,%a2
  1592. bsr.l _dmem_read_long # fetch 2 word bounds
  1593. tst.l %d1 # dfetch error?
  1594. bne.w chk2_cmp2_err_l # yes
  1595. mov.w %d0, %d1 # place hi in %d1
  1596. swap %d0 # place lo in %d0
  1597. ext.l %d0 # sign extend lo bnd
  1598. ext.l %d1 # sign extend hi bnd
  1599. btst &0x7, EXC_EXTWORD(%a6) # address compare?
  1600. bne.w chk2_cmp2_compare # yes; don't sign extend
  1601. # operation is a data register compare.
  1602. # sign extend word to long so we can do simple longword compares.
  1603. ext.l %d2 # sign extend data word
  1604. bra.w chk2_cmp2_compare # go emulate compare
  1605. # the bounds are byte size. fetch them in one subroutine call by
  1606. # reading a word. sign extend both. if it's a data operation,
  1607. # sign extend Rn to long, also.
  1608. chk2_cmp2_byte:
  1609. mov.l %a0,%a2
  1610. bsr.l _dmem_read_word # fetch 2 byte bounds
  1611. tst.l %d1 # dfetch error?
  1612. bne.w chk2_cmp2_err_w # yes
  1613. mov.b %d0, %d1 # place hi in %d1
  1614. lsr.w &0x8, %d0 # place lo in %d0
  1615. extb.l %d0 # sign extend lo bnd
  1616. extb.l %d1 # sign extend hi bnd
  1617. btst &0x7, EXC_EXTWORD(%a6) # address compare?
  1618. bne.b chk2_cmp2_compare # yes; don't sign extend
  1619. # operation is a data register compare.
  1620. # sign extend byte to long so we can do simple longword compares.
  1621. extb.l %d2 # sign extend data byte
  1622. #
  1623. # To set the ccodes correctly:
  1624. # (1) save 'Z' bit from (Rn - lo)
  1625. # (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
  1626. # (3) keep 'X', 'N', and 'V' from before instruction
  1627. # (4) combine ccodes
  1628. #
  1629. chk2_cmp2_compare:
  1630. sub.l %d0, %d2 # (Rn - lo)
  1631. mov.w %cc, %d3 # fetch resulting ccodes
  1632. andi.b &0x4, %d3 # keep 'Z' bit
  1633. sub.l %d0, %d1 # (hi - lo)
  1634. cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi))
  1635. mov.w %cc, %d4 # fetch resulting ccodes
  1636. or.b %d4, %d3 # combine w/ earlier ccodes
  1637. andi.b &0x5, %d3 # keep 'Z' and 'N'
  1638. mov.w EXC_CC(%a6), %d4 # fetch old ccodes
  1639. andi.b &0x1a, %d4 # keep 'X','N','V' bits
  1640. or.b %d3, %d4 # insert new ccodes
  1641. mov.w %d4, EXC_CC(%a6) # save new ccodes
  1642. btst &0x3, EXC_EXTWORD(%a6) # separate chk2,cmp2
  1643. bne.b chk2_finish # it's a chk2
  1644. rts
  1645. # this code handles the only difference between chk2 and cmp2. chk2 would
  1646. # have trapped out if the value was out of bounds. we check this by seeing
  1647. # if the 'N' bit was set by the operation.
  1648. chk2_finish:
  1649. btst &0x0, %d4 # is 'N' bit set?
  1650. bne.b chk2_trap # yes;chk2 should trap
  1651. rts
  1652. chk2_trap:
  1653. mov.b &ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
  1654. rts
  1655. # if dmem_read_{long,word}() returns a fail message in d1, the package
  1656. # must create an access error frame. here, we pass a skeleton fslw
  1657. # and the failing address to the routine that creates the new frame.
  1658. # FSLW:
  1659. # read = true
  1660. # size = longword
  1661. # TM = data
  1662. # software emulation error = true
  1663. chk2_cmp2_err_l:
  1664. mov.l %a2,%a0 # pass failing address
  1665. mov.l &0x01010001,%d0 # pass fslw
  1666. bra.l isp_dacc
  1667. # FSLW:
  1668. # read = true
  1669. # size = word
  1670. # TM = data
  1671. # software emulation error = true
  1672. chk2_cmp2_err_w:
  1673. mov.l %a2,%a0 # pass failing address
  1674. mov.l &0x01410001,%d0 # pass fslw
  1675. bra.l isp_dacc
  1676. #########################################################################
  1677. # XDEF **************************************************************** #
  1678. # _div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq #
  1679. # 64/32->32r:32q #
  1680. # #
  1681. # XREF **************************************************************** #
  1682. # _calc_ea() - calculate effective address #
  1683. # isp_iacc() - handle instruction access error exception #
  1684. # isp_dacc() - handle data access error exception #
  1685. # isp_restore() - restore An on access error w/ -() or ()+ #
  1686. # #
  1687. # INPUT *************************************************************** #
  1688. # none #
  1689. # #
  1690. # OUTPUT ************************************************************** #
  1691. # If exiting through isp_dacc... #
  1692. # a0 = failing address #
  1693. # d0 = FSLW #
  1694. # else #
  1695. # none #
  1696. # #
  1697. # ALGORITHM *********************************************************** #
  1698. # First, decode the operand location. If it's in Dn, fetch from #
  1699. # the stack. If it's in memory, use _calc_ea() to calculate the #
  1700. # effective address. Use _dmem_read_long() to fetch at that address. #
  1701. # Unless the operand is immediate data. Then use _imem_read_long(). #
  1702. # Send failures to isp_dacc() or isp_iacc() as appropriate. #
  1703. # If the operands are signed, make them unsigned and save the #
  1704. # sign info for later. Separate out special cases like divide-by-zero #
  1705. # or 32-bit divides if possible. Else, use a special math algorithm #
  1706. # to calculate the result. #
  1707. # Restore sign info if signed instruction. Set the condition #
  1708. # codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the #
  1709. # quotient and remainder in the appropriate data registers on the stack.#
  1710. # #
  1711. #########################################################################
  1712. set NDIVISOR, EXC_TEMP+0x0
  1713. set NDIVIDEND, EXC_TEMP+0x1
  1714. set NDRSAVE, EXC_TEMP+0x2
  1715. set NDQSAVE, EXC_TEMP+0x4
  1716. set DDSECOND, EXC_TEMP+0x6
  1717. set DDQUOTIENT, EXC_TEMP+0x8
  1718. set DDNORMAL, EXC_TEMP+0xc
  1719. global _div64
  1720. #############
  1721. # div(u,s)l #
  1722. #############
  1723. _div64:
  1724. mov.b EXC_OPWORD+1(%a6), %d0
  1725. andi.b &0x38, %d0 # extract src mode
  1726. bne.w dcontrolmodel_s # %dn dest or control mode?
  1727. mov.b EXC_OPWORD+1(%a6), %d0 # extract Dn from opcode
  1728. andi.w &0x7, %d0
  1729. mov.l (EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
  1730. dgotsrcl:
  1731. beq.w div64eq0 # divisor is = 0!!!
  1732. mov.b EXC_EXTWORD+1(%a6), %d0 # extract Dr from extword
  1733. mov.b EXC_EXTWORD(%a6), %d1 # extract Dq from extword
  1734. and.w &0x7, %d0
  1735. lsr.b &0x4, %d1
  1736. and.w &0x7, %d1
  1737. mov.w %d0, NDRSAVE(%a6) # save Dr for later
  1738. mov.w %d1, NDQSAVE(%a6) # save Dq for later
  1739. # fetch %dr and %dq directly off stack since all regs are saved there
  1740. mov.l (EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
  1741. mov.l (EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
  1742. # separate signed and unsigned divide
  1743. btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned?
  1744. beq.b dspecialcases # use positive divide
  1745. # save the sign of the divisor
  1746. # make divisor unsigned if it's negative
  1747. tst.l %d7 # chk sign of divisor
  1748. slt NDIVISOR(%a6) # save sign of divisor
  1749. bpl.b dsgndividend
  1750. neg.l %d7 # complement negative divisor
  1751. # save the sign of the dividend
  1752. # make dividend unsigned if it's negative
  1753. dsgndividend:
  1754. tst.l %d5 # chk sign of hi(dividend)
  1755. slt NDIVIDEND(%a6) # save sign of dividend
  1756. bpl.b dspecialcases
  1757. mov.w &0x0, %cc # clear 'X' cc bit
  1758. negx.l %d6 # complement signed dividend
  1759. negx.l %d5
  1760. # extract some special cases:
  1761. # - is (dividend == 0) ?
  1762. # - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
  1763. dspecialcases:
  1764. tst.l %d5 # is (hi(dividend) == 0)
  1765. bne.b dnormaldivide # no, so try it the long way
  1766. tst.l %d6 # is (lo(dividend) == 0), too
  1767. beq.w ddone # yes, so (dividend == 0)
  1768. cmp.l %d7,%d6 # is (divisor <= lo(dividend))
  1769. bls.b d32bitdivide # yes, so use 32 bit divide
  1770. exg %d5,%d6 # q = 0, r = dividend
  1771. bra.w divfinish # can't divide, we're done.
  1772. d32bitdivide:
  1773. tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div!
  1774. bra.b divfinish
  1775. dnormaldivide:
  1776. # last special case:
  1777. # - is hi(dividend) >= divisor ? if yes, then overflow
  1778. cmp.l %d7,%d5
  1779. bls.b ddovf # answer won't fit in 32 bits
  1780. # perform the divide algorithm:
  1781. bsr.l dclassical # do int divide
  1782. # separate into signed and unsigned finishes.
  1783. divfinish:
  1784. btst &0x3, EXC_EXTWORD(%a6) # do divs, divu separately
  1785. beq.b ddone # divu has no processing!!!
  1786. # it was a divs.l, so ccode setting is a little more complicated...
  1787. tst.b NDIVIDEND(%a6) # remainder has same sign
  1788. beq.b dcc # as dividend.
  1789. neg.l %d5 # sgn(rem) = sgn(dividend)
  1790. dcc:
  1791. mov.b NDIVISOR(%a6), %d0
  1792. eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative
  1793. beq.b dqpos # branch to quot positive
  1794. # 0x80000000 is the largest number representable as a 32-bit negative
  1795. # number. the negative of 0x80000000 is 0x80000000.
  1796. cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits?
  1797. bhi.b ddovf
  1798. neg.l %d6 # make (-quot) 2's comp
  1799. bra.b ddone
  1800. dqpos:
  1801. btst &0x1f, %d6 # will (+quot) fit in 32 bits?
  1802. bne.b ddovf
  1803. ddone:
  1804. # at this point, result is normal so ccodes are set based on result.
  1805. mov.w EXC_CC(%a6), %cc
  1806. tst.l %d6 # set %ccode bits
  1807. mov.w %cc, EXC_CC(%a6)
  1808. mov.w NDRSAVE(%a6), %d0 # get Dr off stack
  1809. mov.w NDQSAVE(%a6), %d1 # get Dq off stack
  1810. # if the register numbers are the same, only the quotient gets saved.
  1811. # so, if we always save the quotient second, we save ourselves a cmp&beq
  1812. mov.l %d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
  1813. mov.l %d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
  1814. rts
  1815. ddovf:
  1816. bset &0x1, EXC_CC+1(%a6) # 'V' set on overflow
  1817. bclr &0x0, EXC_CC+1(%a6) # 'C' cleared on overflow
  1818. rts
  1819. div64eq0:
  1820. andi.b &0x1e, EXC_CC+1(%a6) # clear 'C' bit on divbyzero
  1821. ori.b &idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
  1822. rts
  1823. ###########################################################################
  1824. #########################################################################
  1825. # This routine uses the 'classical' Algorithm D from Donald Knuth's #
  1826. # Art of Computer Programming, vol II, Seminumerical Algorithms. #
  1827. # For this implementation b=2**16, and the target is U1U2U3U4/V1V2, #
  1828. # where U,V are words of the quadword dividend and longword divisor, #
  1829. # and U1, V1 are the most significant words. #
  1830. # #
  1831. # The most sig. longword of the 64 bit dividend must be in %d5, least #
  1832. # in %d6. The divisor must be in the variable ddivisor, and the #
  1833. # signed/unsigned flag ddusign must be set (0=unsigned,1=signed). #
  1834. # The quotient is returned in %d6, remainder in %d5, unless the #
  1835. # v (overflow) bit is set in the saved %ccr. If overflow, the dividend #
  1836. # is unchanged. #
  1837. #########################################################################
  1838. dclassical:
  1839. # if the divisor msw is 0, use simpler algorithm then the full blown
  1840. # one at ddknuth:
  1841. cmpi.l %d7, &0xffff
  1842. bhi.b ddknuth # go use D. Knuth algorithm
  1843. # Since the divisor is only a word (and larger than the mslw of the dividend),
  1844. # a simpler algorithm may be used :
  1845. # In the general case, four quotient words would be created by
  1846. # dividing the divisor word into each dividend word. In this case,
  1847. # the first two quotient words must be zero, or overflow would occur.
  1848. # Since we already checked this case above, we can treat the most significant
  1849. # longword of the dividend as (0) remainder (see Knuth) and merely complete
  1850. # the last two divisions to get a quotient longword and word remainder:
  1851. clr.l %d1
  1852. swap %d5 # same as r*b if previous step rqd
  1853. swap %d6 # get u3 to lsw position
  1854. mov.w %d6, %d5 # rb + u3
  1855. divu.w %d7, %d5
  1856. mov.w %d5, %d1 # first quotient word
  1857. swap %d6 # get u4
  1858. mov.w %d6, %d5 # rb + u4
  1859. divu.w %d7, %d5
  1860. swap %d1
  1861. mov.w %d5, %d1 # 2nd quotient 'digit'
  1862. clr.w %d5
  1863. swap %d5 # now remainder
  1864. mov.l %d1, %d6 # and quotient
  1865. rts
  1866. ddknuth:
  1867. # In this algorithm, the divisor is treated as a 2 digit (word) number
  1868. # which is divided into a 3 digit (word) dividend to get one quotient
  1869. # digit (word). After subtraction, the dividend is shifted and the
  1870. # process repeated. Before beginning, the divisor and quotient are
  1871. # 'normalized' so that the process of estimating the quotient digit
  1872. # will yield verifiably correct results..
  1873. clr.l DDNORMAL(%a6) # count of shifts for normalization
  1874. clr.b DDSECOND(%a6) # clear flag for quotient digits
  1875. clr.l %d1 # %d1 will hold trial quotient
  1876. ddnchk:
  1877. btst &31, %d7 # must we normalize? first word of
  1878. bne.b ddnormalized # divisor (V1) must be >= 65536/2
  1879. addq.l &0x1, DDNORMAL(%a6) # count normalization shifts
  1880. lsl.l &0x1, %d7 # shift the divisor
  1881. lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2
  1882. roxl.l &0x1, %d5 # shift u1,u2
  1883. bra.w ddnchk
  1884. ddnormalized:
  1885. # Now calculate an estimate of the quotient words (msw first, then lsw).
  1886. # The comments use subscripts for the first quotient digit determination.
  1887. mov.l %d7, %d3 # divisor
  1888. mov.l %d5, %d2 # dividend mslw
  1889. swap %d2
  1890. swap %d3
  1891. cmp.w %d2, %d3 # V1 = U1 ?
  1892. bne.b ddqcalc1
  1893. mov.w &0xffff, %d1 # use max trial quotient word
  1894. bra.b ddadj0
  1895. ddqcalc1:
  1896. mov.l %d5, %d1
  1897. divu.w %d3, %d1 # use quotient of mslw/msw
  1898. andi.l &0x0000ffff, %d1 # zero any remainder
  1899. ddadj0:
  1900. # now test the trial quotient and adjust. This step plus the
  1901. # normalization assures (according to Knuth) that the trial
  1902. # quotient will be at worst 1 too large.
  1903. mov.l %d6, -(%sp)
  1904. clr.w %d6 # word u3 left
  1905. swap %d6 # in lsw position
  1906. ddadj1: mov.l %d7, %d3
  1907. mov.l %d1, %d2
  1908. mulu.w %d7, %d2 # V2q
  1909. swap %d3
  1910. mulu.w %d1, %d3 # V1q
  1911. mov.l %d5, %d4 # U1U2
  1912. sub.l %d3, %d4 # U1U2 - V1q
  1913. swap %d4
  1914. mov.w %d4,%d0
  1915. mov.w %d6,%d4 # insert lower word (U3)
  1916. tst.w %d0 # is upper word set?
  1917. bne.w ddadjd1
  1918. # add.l %d6, %d4 # (U1U2 - V1q) + U3
  1919. cmp.l %d2, %d4
  1920. bls.b ddadjd1 # is V2q > (U1U2-V1q) + U3 ?
  1921. subq.l &0x1, %d1 # yes, decrement and recheck
  1922. bra.b ddadj1
  1923. ddadjd1:
  1924. # now test the word by multiplying it by the divisor (V1V2) and comparing
  1925. # the 3 digit (word) result with the current dividend words
  1926. mov.l %d5, -(%sp) # save %d5 (%d6 already saved)
  1927. mov.l %d1, %d6
  1928. swap %d6 # shift answer to ms 3 words
  1929. mov.l %d7, %d5
  1930. bsr.l dmm2
  1931. mov.l %d5, %d2 # now %d2,%d3 are trial*divisor
  1932. mov.l %d6, %d3
  1933. mov.l (%sp)+, %d5 # restore dividend
  1934. mov.l (%sp)+, %d6
  1935. sub.l %d3, %d6
  1936. subx.l %d2, %d5 # subtract double precision
  1937. bcc dd2nd # no carry, do next quotient digit
  1938. subq.l &0x1, %d1 # q is one too large
  1939. # need to add back divisor longword to current ms 3 digits of dividend
  1940. # - according to Knuth, this is done only 2 out of 65536 times for random
  1941. # divisor, dividend selection.
  1942. clr.l %d2
  1943. mov.l %d7, %d3
  1944. swap %d3
  1945. clr.w %d3 # %d3 now ls word of divisor
  1946. add.l %d3, %d6 # aligned with 3rd word of dividend
  1947. addx.l %d2, %d5
  1948. mov.l %d7, %d3
  1949. clr.w %d3 # %d3 now ms word of divisor
  1950. swap %d3 # aligned with 2nd word of dividend
  1951. add.l %d3, %d5
  1952. dd2nd:
  1953. tst.b DDSECOND(%a6) # both q words done?
  1954. bne.b ddremain
  1955. # first quotient digit now correct. store digit and shift the
  1956. # (subtracted) dividend
  1957. mov.w %d1, DDQUOTIENT(%a6)
  1958. clr.l %d1
  1959. swap %d5
  1960. swap %d6
  1961. mov.w %d6, %d5
  1962. clr.w %d6
  1963. st DDSECOND(%a6) # second digit
  1964. bra.w ddnormalized
  1965. ddremain:
  1966. # add 2nd word to quotient, get the remainder.
  1967. mov.w %d1, DDQUOTIENT+2(%a6)
  1968. # shift down one word/digit to renormalize remainder.
  1969. mov.w %d5, %d6
  1970. swap %d6
  1971. swap %d5
  1972. mov.l DDNORMAL(%a6), %d7 # get norm shift count
  1973. beq.b ddrn
  1974. subq.l &0x1, %d7 # set for loop count
  1975. ddnlp:
  1976. lsr.l &0x1, %d5 # shift into %d6
  1977. roxr.l &0x1, %d6
  1978. dbf %d7, ddnlp
  1979. ddrn:
  1980. mov.l %d6, %d5 # remainder
  1981. mov.l DDQUOTIENT(%a6), %d6 # quotient
  1982. rts
  1983. dmm2:
  1984. # factors for the 32X32->64 multiplication are in %d5 and %d6.
  1985. # returns 64 bit result in %d5 (hi) %d6(lo).
  1986. # destroys %d2,%d3,%d4.
  1987. # multiply hi,lo words of each factor to get 4 intermediate products
  1988. mov.l %d6, %d2
  1989. mov.l %d6, %d3
  1990. mov.l %d5, %d4
  1991. swap %d3
  1992. swap %d4
  1993. mulu.w %d5, %d6 # %d6 <- lsw*lsw
  1994. mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source
  1995. mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest
  1996. mulu.w %d4, %d3 # %d3 <- msw*msw
  1997. # now use swap and addx to consolidate to two longwords
  1998. clr.l %d4
  1999. swap %d6
  2000. add.w %d5, %d6 # add msw of l*l to lsw of m*l product
  2001. addx.w %d4, %d3 # add any carry to m*m product
  2002. add.w %d2, %d6 # add in lsw of other m*l product
  2003. addx.w %d4, %d3 # add any carry to m*m product
  2004. swap %d6 # %d6 is low 32 bits of final product
  2005. clr.w %d5
  2006. clr.w %d2 # lsw of two mixed products used,
  2007. swap %d5 # now use msws of longwords
  2008. swap %d2
  2009. add.l %d2, %d5
  2010. add.l %d3, %d5 # %d5 now ms 32 bits of final product
  2011. rts
  2012. ##########
  2013. dcontrolmodel_s:
  2014. movq.l &LONG,%d0
  2015. bsr.l _calc_ea # calc <ea>
  2016. cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
  2017. beq.b dimmed # yes
  2018. mov.l %a0,%a2
  2019. bsr.l _dmem_read_long # fetch divisor from <ea>
  2020. tst.l %d1 # dfetch error?
  2021. bne.b div64_err # yes
  2022. mov.l %d0, %d7
  2023. bra.w dgotsrcl
  2024. # we have to split out immediate data here because it must be read using
  2025. # imem_read() instead of dmem_read(). this becomes especially important
  2026. # if the fetch runs into some deadly fault.
  2027. dimmed:
  2028. addq.l &0x4,EXC_EXTWPTR(%a6)
  2029. bsr.l _imem_read_long # read immediate value
  2030. tst.l %d1 # ifetch error?
  2031. bne.l isp_iacc # yes
  2032. mov.l %d0,%d7
  2033. bra.w dgotsrcl
  2034. ##########
  2035. # if dmem_read_long() returns a fail message in d1, the package
  2036. # must create an access error frame. here, we pass a skeleton fslw
  2037. # and the failing address to the routine that creates the new frame.
  2038. # also, we call isp_restore in case the effective addressing mode was
  2039. # (an)+ or -(an) in which case the previous "an" value must be restored.
  2040. # FSLW:
  2041. # read = true
  2042. # size = longword
  2043. # TM = data
  2044. # software emulation error = true
  2045. div64_err:
  2046. bsr.l isp_restore # restore addr reg
  2047. mov.l %a2,%a0 # pass failing address
  2048. mov.l &0x01010001,%d0 # pass fslw
  2049. bra.l isp_dacc
  2050. #########################################################################
  2051. # XDEF **************************************************************** #
  2052. # _mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64 #
  2053. # #
  2054. # XREF **************************************************************** #
  2055. # _calc_ea() - calculate effective address #
  2056. # isp_iacc() - handle instruction access error exception #
  2057. # isp_dacc() - handle data access error exception #
  2058. # isp_restore() - restore An on access error w/ -() or ()+ #
  2059. # #
  2060. # INPUT *************************************************************** #
  2061. # none #
  2062. # #
  2063. # OUTPUT ************************************************************** #
  2064. # If exiting through isp_dacc... #
  2065. # a0 = failing address #
  2066. # d0 = FSLW #
  2067. # else #
  2068. # none #
  2069. # #
  2070. # ALGORITHM *********************************************************** #
  2071. # First, decode the operand location. If it's in Dn, fetch from #
  2072. # the stack. If it's in memory, use _calc_ea() to calculate the #
  2073. # effective address. Use _dmem_read_long() to fetch at that address. #
  2074. # Unless the operand is immediate data. Then use _imem_read_long(). #
  2075. # Send failures to isp_dacc() or isp_iacc() as appropriate. #
  2076. # If the operands are signed, make them unsigned and save the #
  2077. # sign info for later. Perform the multiplication using 16x16->32 #
  2078. # unsigned multiplies and "add" instructions. Store the high and low #
  2079. # portions of the result in the appropriate data registers on the #
  2080. # stack. Calculate the condition codes, also. #
  2081. # #
  2082. #########################################################################
  2083. #############
  2084. # mul(u,s)l #
  2085. #############
  2086. global _mul64
  2087. _mul64:
  2088. mov.b EXC_OPWORD+1(%a6), %d0 # extract src {mode,reg}
  2089. cmpi.b %d0, &0x7 # is src mode Dn or other?
  2090. bgt.w mul64_memop # src is in memory
  2091. # multiplier operand in the data register file.
  2092. # must extract the register number and fetch the operand from the stack.
  2093. mul64_regop:
  2094. andi.w &0x7, %d0 # extract Dn
  2095. mov.l (EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
  2096. # multiplier is in %d3. now, extract Dl and Dh fields and fetch the
  2097. # multiplicand from the data register specified by Dl.
  2098. mul64_multiplicand:
  2099. mov.w EXC_EXTWORD(%a6), %d2 # fetch ext word
  2100. clr.w %d1 # clear Dh reg
  2101. mov.b %d2, %d1 # grab Dh
  2102. rol.w &0x4, %d2 # align Dl byte
  2103. andi.w &0x7, %d2 # extract Dl
  2104. mov.l (EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
  2105. # check for the case of "zero" result early
  2106. tst.l %d4 # test multiplicand
  2107. beq.w mul64_zero # handle zero separately
  2108. tst.l %d3 # test multiplier
  2109. beq.w mul64_zero # handle zero separately
  2110. # multiplier is in %d3 and multiplicand is in %d4.
  2111. # if the operation is to be signed, then the operands are converted
  2112. # to unsigned and the result sign is saved for the end.
  2113. clr.b EXC_TEMP(%a6) # clear temp space
  2114. btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned?
  2115. beq.b mul64_alg # unsigned; skip sgn calc
  2116. tst.l %d3 # is multiplier negative?
  2117. bge.b mul64_chk_md_sgn # no
  2118. neg.l %d3 # make multiplier positive
  2119. ori.b &0x1, EXC_TEMP(%a6) # save multiplier sgn
  2120. # the result sign is the exclusive or of the operand sign bits.
  2121. mul64_chk_md_sgn:
  2122. tst.l %d4 # is multiplicand negative?
  2123. bge.b mul64_alg # no
  2124. neg.l %d4 # make multiplicand positive
  2125. eori.b &0x1, EXC_TEMP(%a6) # calculate correct sign
  2126. #########################################################################
  2127. # 63 32 0 #
  2128. # ---------------------------- #
  2129. # | hi(mplier) * hi(mplicand)| #
  2130. # ---------------------------- #
  2131. # ----------------------------- #
  2132. # | hi(mplier) * lo(mplicand) | #
  2133. # ----------------------------- #
  2134. # ----------------------------- #
  2135. # | lo(mplier) * hi(mplicand) | #
  2136. # ----------------------------- #
  2137. # | ----------------------------- #
  2138. # --|-- | lo(mplier) * lo(mplicand) | #
  2139. # | ----------------------------- #
  2140. # ======================================================== #
  2141. # -------------------------------------------------------- #
  2142. # | hi(result) | lo(result) | #
  2143. # -------------------------------------------------------- #
  2144. #########################################################################
  2145. mul64_alg:
  2146. # load temp registers with operands
  2147. mov.l %d3, %d5 # mr in %d5
  2148. mov.l %d3, %d6 # mr in %d6
  2149. mov.l %d4, %d7 # md in %d7
  2150. swap %d6 # hi(mr) in lo %d6
  2151. swap %d7 # hi(md) in lo %d7
  2152. # complete necessary multiplies:
  2153. mulu.w %d4, %d3 # [1] lo(mr) * lo(md)
  2154. mulu.w %d6, %d4 # [2] hi(mr) * lo(md)
  2155. mulu.w %d7, %d5 # [3] lo(mr) * hi(md)
  2156. mulu.w %d7, %d6 # [4] hi(mr) * hi(md)
  2157. # add lo portions of [2],[3] to hi portion of [1].
  2158. # add carries produced from these adds to [4].
  2159. # lo([1]) is the final lo 16 bits of the result.
  2160. clr.l %d7 # load %d7 w/ zero value
  2161. swap %d3 # hi([1]) <==> lo([1])
  2162. add.w %d4, %d3 # hi([1]) + lo([2])
  2163. addx.l %d7, %d6 # [4] + carry
  2164. add.w %d5, %d3 # hi([1]) + lo([3])
  2165. addx.l %d7, %d6 # [4] + carry
  2166. swap %d3 # lo([1]) <==> hi([1])
  2167. # lo portions of [2],[3] have been added in to final result.
  2168. # now, clear lo, put hi in lo reg, and add to [4]
  2169. clr.w %d4 # clear lo([2])
  2170. clr.w %d5 # clear hi([3])
  2171. swap %d4 # hi([2]) in lo %d4
  2172. swap %d5 # hi([3]) in lo %d5
  2173. add.l %d5, %d4 # [4] + hi([2])
  2174. add.l %d6, %d4 # [4] + hi([3])
  2175. # unsigned result is now in {%d4,%d3}
  2176. tst.b EXC_TEMP(%a6) # should result be signed?
  2177. beq.b mul64_done # no
  2178. # result should be a signed negative number.
  2179. # compute 2's complement of the unsigned number:
  2180. # -negate all bits and add 1
  2181. mul64_neg:
  2182. not.l %d3 # negate lo(result) bits
  2183. not.l %d4 # negate hi(result) bits
  2184. addq.l &1, %d3 # add 1 to lo(result)
  2185. addx.l %d7, %d4 # add carry to hi(result)
  2186. # the result is saved to the register file.
  2187. # for '040 compatibility, if Dl == Dh then only the hi(result) is
  2188. # saved. so, saving hi after lo accomplishes this without need to
  2189. # check Dl,Dh equality.
  2190. mul64_done:
  2191. mov.l %d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
  2192. mov.w &0x0, %cc
  2193. mov.l %d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
  2194. # now, grab the condition codes. only one that can be set is 'N'.
  2195. # 'N' CAN be set if the operation is unsigned if bit 63 is set.
  2196. mov.w %cc, %d7 # fetch %ccr to see if 'N' set
  2197. andi.b &0x8, %d7 # extract 'N' bit
  2198. mul64_ccode_set:
  2199. mov.b EXC_CC+1(%a6), %d6 # fetch previous %ccr
  2200. andi.b &0x10, %d6 # all but 'X' bit changes
  2201. or.b %d7, %d6 # group 'X' and 'N'
  2202. mov.b %d6, EXC_CC+1(%a6) # save new %ccr
  2203. rts
  2204. # one or both of the operands is zero so the result is also zero.
  2205. # save the zero result to the register file and set the 'Z' ccode bit.
  2206. mul64_zero:
  2207. clr.l (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
  2208. clr.l (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
  2209. movq.l &0x4, %d7 # set 'Z' ccode bit
  2210. bra.b mul64_ccode_set # finish ccode set
  2211. ##########
  2212. # multiplier operand is in memory at the effective address.
  2213. # must calculate the <ea> and go fetch the 32-bit operand.
  2214. mul64_memop:
  2215. movq.l &LONG, %d0 # pass # of bytes
  2216. bsr.l _calc_ea # calculate <ea>
  2217. cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
  2218. beq.b mul64_immed # yes
  2219. mov.l %a0,%a2
  2220. bsr.l _dmem_read_long # fetch src from addr (%a0)
  2221. tst.l %d1 # dfetch error?
  2222. bne.w mul64_err # yes
  2223. mov.l %d0, %d3 # store multiplier in %d3
  2224. bra.w mul64_multiplicand
  2225. # we have to split out immediate data here because it must be read using
  2226. # imem_read() instead of dmem_read(). this becomes especially important
  2227. # if the fetch runs into some deadly fault.
  2228. mul64_immed:
  2229. addq.l &0x4,EXC_EXTWPTR(%a6)
  2230. bsr.l _imem_read_long # read immediate value
  2231. tst.l %d1 # ifetch error?
  2232. bne.l isp_iacc # yes
  2233. mov.l %d0,%d3
  2234. bra.w mul64_multiplicand
  2235. ##########
  2236. # if dmem_read_long() returns a fail message in d1, the package
  2237. # must create an access error frame. here, we pass a skeleton fslw
  2238. # and the failing address to the routine that creates the new frame.
  2239. # also, we call isp_restore in case the effective addressing mode was
  2240. # (an)+ or -(an) in which case the previous "an" value must be restored.
  2241. # FSLW:
  2242. # read = true
  2243. # size = longword
  2244. # TM = data
  2245. # software emulation error = true
  2246. mul64_err:
  2247. bsr.l isp_restore # restore addr reg
  2248. mov.l %a2,%a0 # pass failing address
  2249. mov.l &0x01010001,%d0 # pass fslw
  2250. bra.l isp_dacc
  2251. #########################################################################
  2252. # XDEF **************************************************************** #
  2253. # _compandset2(): routine to emulate cas2() #
  2254. # (internal to package) #
  2255. # #
  2256. # _isp_cas2_finish(): store ccodes, store compare regs #
  2257. # (external to package) #
  2258. # #
  2259. # XREF **************************************************************** #
  2260. # _real_lock_page() - "callout" to lock op's page from page-outs #
  2261. # _cas_terminate2() - access error exit #
  2262. # _real_cas2() - "callout" to core cas2 emulation code #
  2263. # _real_unlock_page() - "callout" to unlock page #
  2264. # #
  2265. # INPUT *************************************************************** #
  2266. # _compandset2(): #
  2267. # d0 = instruction extension word #
  2268. # #
  2269. # _isp_cas2_finish(): #
  2270. # see cas2 core emulation code #
  2271. # #
  2272. # OUTPUT ************************************************************** #
  2273. # _compandset2(): #
  2274. # see cas2 core emulation code #
  2275. # #
  2276. # _isp_cas_finish(): #
  2277. # None (register file or memroy changed as appropriate) #
  2278. # #
  2279. # ALGORITHM *********************************************************** #
  2280. # compandset2(): #
  2281. # Decode the instruction and fetch the appropriate Update and #
  2282. # Compare operands. Then call the "callout" _real_lock_page() for each #
  2283. # memory operand address so that the operating system can keep these #
  2284. # pages from being paged out. If either _real_lock_page() fails, exit #
  2285. # through _cas_terminate2(). Don't forget to unlock the 1st locked page #
  2286. # using _real_unlock_paged() if the 2nd lock-page fails. #
  2287. # Finally, branch to the core cas2 emulation code by calling the #
  2288. # "callout" _real_cas2(). #
  2289. # #
  2290. # _isp_cas2_finish(): #
  2291. # Re-perform the comparison so we can determine the condition #
  2292. # codes which were too much trouble to keep around during the locked #
  2293. # emulation. Then unlock each operands page by calling the "callout" #
  2294. # _real_unlock_page(). #
  2295. # #
  2296. #########################################################################
  2297. set ADDR1, EXC_TEMP+0xc
  2298. set ADDR2, EXC_TEMP+0x0
  2299. set DC2, EXC_TEMP+0xa
  2300. set DC1, EXC_TEMP+0x8
  2301. global _compandset2
  2302. _compandset2:
  2303. mov.l %d0,EXC_TEMP+0x4(%a6) # store for possible restart
  2304. mov.l %d0,%d1 # extension word in d0
  2305. rol.w &0x4,%d0
  2306. andi.w &0xf,%d0 # extract Rn2
  2307. mov.l (EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
  2308. mov.l %a1,ADDR2(%a6)
  2309. mov.l %d1,%d0
  2310. lsr.w &0x6,%d1
  2311. andi.w &0x7,%d1 # extract Du2
  2312. mov.l (EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
  2313. andi.w &0x7,%d0 # extract Dc2
  2314. mov.l (EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
  2315. mov.w %d0,DC2(%a6)
  2316. mov.w EXC_EXTWORD(%a6),%d0
  2317. mov.l %d0,%d1
  2318. rol.w &0x4,%d0
  2319. andi.w &0xf,%d0 # extract Rn1
  2320. mov.l (EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
  2321. mov.l %a0,ADDR1(%a6)
  2322. mov.l %d1,%d0
  2323. lsr.w &0x6,%d1
  2324. andi.w &0x7,%d1 # extract Du1
  2325. mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
  2326. andi.w &0x7,%d0 # extract Dc1
  2327. mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
  2328. mov.w %d0,DC1(%a6)
  2329. btst &0x1,EXC_OPWORD(%a6) # word or long?
  2330. sne %d7
  2331. btst &0x5,EXC_ISR(%a6) # user or supervisor?
  2332. sne %d6
  2333. mov.l %a0,%a2
  2334. mov.l %a1,%a3
  2335. mov.l %d7,%d1 # pass size
  2336. mov.l %d6,%d0 # pass mode
  2337. bsr.l _real_lock_page # lock page
  2338. mov.l %a2,%a0
  2339. tst.l %d0 # error?
  2340. bne.l _cas_terminate2 # yes
  2341. mov.l %d7,%d1 # pass size
  2342. mov.l %d6,%d0 # pass mode
  2343. mov.l %a3,%a0 # pass addr
  2344. bsr.l _real_lock_page # lock page
  2345. mov.l %a3,%a0
  2346. tst.l %d0 # error?
  2347. bne.b cas_preterm # yes
  2348. mov.l %a2,%a0
  2349. mov.l %a3,%a1
  2350. bra.l _real_cas2
  2351. # if the 2nd lock attempt fails, then we must still unlock the
  2352. # first page(s).
  2353. cas_preterm:
  2354. mov.l %d0,-(%sp) # save FSLW
  2355. mov.l %d7,%d1 # pass size
  2356. mov.l %d6,%d0 # pass mode
  2357. mov.l %a2,%a0 # pass ADDR1
  2358. bsr.l _real_unlock_page # unlock first page(s)
  2359. mov.l (%sp)+,%d0 # restore FSLW
  2360. mov.l %a3,%a0 # pass failing addr
  2361. bra.l _cas_terminate2
  2362. #############################################################
  2363. global _isp_cas2_finish
  2364. _isp_cas2_finish:
  2365. btst &0x1,EXC_OPWORD(%a6)
  2366. bne.b cas2_finish_l
  2367. mov.w EXC_CC(%a6),%cc # load old ccodes
  2368. cmp.w %d0,%d2
  2369. bne.b cas2_finish_w_save
  2370. cmp.w %d1,%d3
  2371. cas2_finish_w_save:
  2372. mov.w %cc,EXC_CC(%a6) # save new ccodes
  2373. tst.b %d4 # update compare reg?
  2374. bne.b cas2_finish_w_done # no
  2375. mov.w DC2(%a6),%d3 # fetch Dc2
  2376. mov.w %d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
  2377. mov.w DC1(%a6),%d2 # fetch Dc1
  2378. mov.w %d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
  2379. cas2_finish_w_done:
  2380. btst &0x5,EXC_ISR(%a6)
  2381. sne %d2
  2382. mov.l %d2,%d0 # pass mode
  2383. sf %d1 # pass size
  2384. mov.l ADDR1(%a6),%a0 # pass ADDR1
  2385. bsr.l _real_unlock_page # unlock page
  2386. mov.l %d2,%d0 # pass mode
  2387. sf %d1 # pass size
  2388. mov.l ADDR2(%a6),%a0 # pass ADDR2
  2389. bsr.l _real_unlock_page # unlock page
  2390. rts
  2391. cas2_finish_l:
  2392. mov.w EXC_CC(%a6),%cc # load old ccodes
  2393. cmp.l %d0,%d2
  2394. bne.b cas2_finish_l_save
  2395. cmp.l %d1,%d3
  2396. cas2_finish_l_save:
  2397. mov.w %cc,EXC_CC(%a6) # save new ccodes
  2398. tst.b %d4 # update compare reg?
  2399. bne.b cas2_finish_l_done # no
  2400. mov.w DC2(%a6),%d3 # fetch Dc2
  2401. mov.l %d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
  2402. mov.w DC1(%a6),%d2 # fetch Dc1
  2403. mov.l %d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
  2404. cas2_finish_l_done:
  2405. btst &0x5,EXC_ISR(%a6)
  2406. sne %d2
  2407. mov.l %d2,%d0 # pass mode
  2408. st %d1 # pass size
  2409. mov.l ADDR1(%a6),%a0 # pass ADDR1
  2410. bsr.l _real_unlock_page # unlock page
  2411. mov.l %d2,%d0 # pass mode
  2412. st %d1 # pass size
  2413. mov.l ADDR2(%a6),%a0 # pass ADDR2
  2414. bsr.l _real_unlock_page # unlock page
  2415. rts
  2416. ########
  2417. global cr_cas2
  2418. cr_cas2:
  2419. mov.l EXC_TEMP+0x4(%a6),%d0
  2420. bra.w _compandset2
  2421. #########################################################################
  2422. # XDEF **************************************************************** #
  2423. # _compandset(): routine to emulate cas w/ misaligned <ea> #
  2424. # (internal to package) #
  2425. # _isp_cas_finish(): routine called when cas emulation completes #
  2426. # (external and internal to package) #
  2427. # _isp_cas_restart(): restart cas emulation after a fault #
  2428. # (external to package) #
  2429. # _isp_cas_terminate(): create access error stack frame on fault #
  2430. # (external and internal to package) #
  2431. # _isp_cas_inrange(): checks whether instr addess is within range #
  2432. # of core cas/cas2emulation code #
  2433. # (external to package) #
  2434. # #
  2435. # XREF **************************************************************** #
  2436. # _calc_ea(): calculate effective address #
  2437. # #
  2438. # INPUT *************************************************************** #
  2439. # compandset(): #
  2440. # none #
  2441. # _isp_cas_restart(): #
  2442. # d6 = previous sfc/dfc #
  2443. # _isp_cas_finish(): #
  2444. # _isp_cas_terminate(): #
  2445. # a0 = failing address #
  2446. # d0 = FSLW #
  2447. # d6 = previous sfc/dfc #
  2448. # _isp_cas_inrange(): #
  2449. # a0 = instruction address to be checked #
  2450. # #
  2451. # OUTPUT ************************************************************** #
  2452. # compandset(): #
  2453. # none #
  2454. # _isp_cas_restart(): #
  2455. # a0 = effective address #
  2456. # d7 = word or longword flag #
  2457. # _isp_cas_finish(): #
  2458. # a0 = effective address #
  2459. # _isp_cas_terminate(): #
  2460. # initial register set before emulation exception #
  2461. # _isp_cas_inrange(): #
  2462. # d0 = 0 => in range; -1 => out of range #
  2463. # #
  2464. # ALGORITHM *********************************************************** #
  2465. # #
  2466. # compandset(): #
  2467. # First, calculate the effective address. Then, decode the #
  2468. # instruction word and fetch the "compare" (DC) and "update" (Du) #
  2469. # operands. #
  2470. # Next, call the external routine _real_lock_page() so that the #
  2471. # operating system can keep this page from being paged out while we're #
  2472. # in this routine. If this call fails, jump to _cas_terminate2(). #
  2473. # The routine then branches to _real_cas(). This external routine #
  2474. # that actually emulates cas can be supplied by the external os or #
  2475. # made to point directly back into the 060ISP which has a routine for #
  2476. # this purpose. #
  2477. # #
  2478. # _isp_cas_finish(): #
  2479. # Either way, after emulation, the package is re-entered at #
  2480. # _isp_cas_finish(). This routine re-compares the operands in order to #
  2481. # set the condition codes. Finally, these routines will call #
  2482. # _real_unlock_page() in order to unlock the pages that were previously #
  2483. # locked. #
  2484. # #
  2485. # _isp_cas_restart(): #
  2486. # This routine can be entered from an access error handler where #
  2487. # the emulation sequence should be re-started from the beginning. #
  2488. # #
  2489. # _isp_cas_terminate(): #
  2490. # This routine can be entered from an access error handler where #
  2491. # an emulation operand access failed and the operating system would #
  2492. # like an access error stack frame created instead of the current #
  2493. # unimplemented integer instruction frame. #
  2494. # Also, the package enters here if a call to _real_lock_page() #
  2495. # fails. #
  2496. # #
  2497. # _isp_cas_inrange(): #
  2498. # Checks to see whether the instruction address passed to it in #
  2499. # a0 is within the software package cas/cas2 emulation routines. This #
  2500. # can be helpful for an operating system to determine whether an access #
  2501. # error during emulation was due to a cas/cas2 emulation access. #
  2502. # #
  2503. #########################################################################
  2504. set DC, EXC_TEMP+0x8
  2505. set ADDR, EXC_TEMP+0x4
  2506. global _compandset
  2507. _compandset:
  2508. btst &0x1,EXC_OPWORD(%a6) # word or long operation?
  2509. bne.b compandsetl # long
  2510. compandsetw:
  2511. movq.l &0x2,%d0 # size = 2 bytes
  2512. bsr.l _calc_ea # a0 = calculated <ea>
  2513. mov.l %a0,ADDR(%a6) # save <ea> for possible restart
  2514. sf %d7 # clear d7 for word size
  2515. bra.b compandsetfetch
  2516. compandsetl:
  2517. movq.l &0x4,%d0 # size = 4 bytes
  2518. bsr.l _calc_ea # a0 = calculated <ea>
  2519. mov.l %a0,ADDR(%a6) # save <ea> for possible restart
  2520. st %d7 # set d7 for longword size
  2521. compandsetfetch:
  2522. mov.w EXC_EXTWORD(%a6),%d0 # fetch cas extension word
  2523. mov.l %d0,%d1 # make a copy
  2524. lsr.w &0x6,%d0
  2525. andi.w &0x7,%d0 # extract Du
  2526. mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
  2527. andi.w &0x7,%d1 # extract Dc
  2528. mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
  2529. mov.w %d1,DC(%a6) # save Dc
  2530. btst &0x5,EXC_ISR(%a6) # which mode for exception?
  2531. sne %d6 # set on supervisor mode
  2532. mov.l %a0,%a2 # save temporarily
  2533. mov.l %d7,%d1 # pass size
  2534. mov.l %d6,%d0 # pass mode
  2535. bsr.l _real_lock_page # lock page
  2536. tst.l %d0 # did error occur?
  2537. bne.w _cas_terminate2 # yes, clean up the mess
  2538. mov.l %a2,%a0 # pass addr in a0
  2539. bra.l _real_cas
  2540. ########
  2541. global _isp_cas_finish
  2542. _isp_cas_finish:
  2543. btst &0x1,EXC_OPWORD(%a6)
  2544. bne.b cas_finish_l
  2545. # just do the compare again since it's faster than saving the ccodes
  2546. # from the locked routine...
  2547. cas_finish_w:
  2548. mov.w EXC_CC(%a6),%cc # restore cc
  2549. cmp.w %d0,%d4 # do word compare
  2550. mov.w %cc,EXC_CC(%a6) # save cc
  2551. tst.b %d1 # update compare reg?
  2552. bne.b cas_finish_w_done # no
  2553. mov.w DC(%a6),%d3
  2554. mov.w %d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
  2555. cas_finish_w_done:
  2556. mov.l ADDR(%a6),%a0 # pass addr
  2557. sf %d1 # pass size
  2558. btst &0x5,EXC_ISR(%a6)
  2559. sne %d0 # pass mode
  2560. bsr.l _real_unlock_page # unlock page
  2561. rts
  2562. # just do the compare again since it's faster than saving the ccodes
  2563. # from the locked routine...
  2564. cas_finish_l:
  2565. mov.w EXC_CC(%a6),%cc # restore cc
  2566. cmp.l %d0,%d4 # do longword compare
  2567. mov.w %cc,EXC_CC(%a6) # save cc
  2568. tst.b %d1 # update compare reg?
  2569. bne.b cas_finish_l_done # no
  2570. mov.w DC(%a6),%d3
  2571. mov.l %d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
  2572. cas_finish_l_done:
  2573. mov.l ADDR(%a6),%a0 # pass addr
  2574. st %d1 # pass size
  2575. btst &0x5,EXC_ISR(%a6)
  2576. sne %d0 # pass mode
  2577. bsr.l _real_unlock_page # unlock page
  2578. rts
  2579. ########
  2580. global _isp_cas_restart
  2581. _isp_cas_restart:
  2582. mov.l %d6,%sfc # restore previous sfc
  2583. mov.l %d6,%dfc # restore previous dfc
  2584. cmpi.b EXC_OPWORD+1(%a6),&0xfc # cas or cas2?
  2585. beq.l cr_cas2 # cas2
  2586. cr_cas:
  2587. mov.l ADDR(%a6),%a0 # load <ea>
  2588. btst &0x1,EXC_OPWORD(%a6) # word or long operation?
  2589. sne %d7 # set d7 accordingly
  2590. bra.w compandsetfetch
  2591. ########
  2592. # At this stage, it would be nice if d0 held the FSLW.
  2593. global _isp_cas_terminate
  2594. _isp_cas_terminate:
  2595. mov.l %d6,%sfc # restore previous sfc
  2596. mov.l %d6,%dfc # restore previous dfc
  2597. global _cas_terminate2
  2598. _cas_terminate2:
  2599. mov.l %a0,%a2 # copy failing addr to a2
  2600. mov.l %d0,-(%sp)
  2601. bsr.l isp_restore # restore An (if ()+ or -())
  2602. mov.l (%sp)+,%d0
  2603. addq.l &0x4,%sp # remove sub return addr
  2604. subq.l &0x8,%sp # make room for bigger stack
  2605. subq.l &0x8,%a6 # shift frame ptr down, too
  2606. mov.l &26,%d1 # want to move 51 longwords
  2607. lea 0x8(%sp),%a0 # get address of old stack
  2608. lea 0x0(%sp),%a1 # get address of new stack
  2609. cas_term_cont:
  2610. mov.l (%a0)+,(%a1)+ # move a longword
  2611. dbra.w %d1,cas_term_cont # keep going
  2612. mov.w &0x4008,EXC_IVOFF(%a6) # put new stk fmt, voff
  2613. mov.l %a2,EXC_IVOFF+0x2(%a6) # put faulting addr on stack
  2614. mov.l %d0,EXC_IVOFF+0x6(%a6) # put FSLW on stack
  2615. movm.l EXC_DREGS(%a6),&0x3fff # restore user regs
  2616. unlk %a6 # unlink stack frame
  2617. bra.l _real_access
  2618. ########
  2619. global _isp_cas_inrange
  2620. _isp_cas_inrange:
  2621. clr.l %d0 # clear return result
  2622. lea _CASHI(%pc),%a1 # load end of CAS core code
  2623. cmp.l %a1,%a0 # is PC in range?
  2624. blt.b cin_no # no
  2625. lea _CASLO(%pc),%a1 # load begin of CAS core code
  2626. cmp.l %a0,%a1 # is PC in range?
  2627. blt.b cin_no # no
  2628. rts # yes; return d0 = 0
  2629. cin_no:
  2630. mov.l &-0x1,%d0 # out of range; return d0 = -1
  2631. rts
  2632. #################################################################
  2633. #################################################################
  2634. #################################################################
  2635. # This is the start of the cas and cas2 "core" emulation code. #
  2636. # This is the section that may need to be replaced by the host #
  2637. # OS if it is too operating system-specific. #
  2638. # Please refer to the package documentation to see how to #
  2639. # "replace" this section, if necessary. #
  2640. #################################################################
  2641. #################################################################
  2642. #################################################################
  2643. # ###### ## ###### ####
  2644. # # # # # # #
  2645. # # ###### ###### #
  2646. # # # # # #
  2647. # ###### # # ###### ######
  2648. #########################################################################
  2649. # XDEF **************************************************************** #
  2650. # _isp_cas2(): "core" emulation code for the cas2 instruction #
  2651. # #
  2652. # XREF **************************************************************** #
  2653. # _isp_cas2_finish() - only exit point for this emulation code; #
  2654. # do clean-up; calculate ccodes; store #
  2655. # Compare Ops if appropriate. #
  2656. # #
  2657. # INPUT *************************************************************** #
  2658. # *see chart below* #
  2659. # #
  2660. # OUTPUT ************************************************************** #
  2661. # *see chart below* #
  2662. # #
  2663. # ALGORITHM *********************************************************** #
  2664. # (1) Make several copies of the effective address. #
  2665. # (2) Save current SR; Then mask off all maskable interrupts. #
  2666. # (3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set #
  2667. # according to whether exception occurred in user or #
  2668. # supervisor mode. #
  2669. # (4) Use "plpaw" instruction to pre-load ATC with effective #
  2670. # address pages(s). THIS SHOULD NOT FAULT!!! The relevant #
  2671. # page(s) should have already been made resident prior to #
  2672. # entering this routine. #
  2673. # (5) Push the operand lines from the cache w/ "cpushl". #
  2674. # In the 68040, this was done within the locked region. In #
  2675. # the 68060, it is done outside of the locked region. #
  2676. # (6) Use "plpar" instruction to do a re-load of ATC entries for #
  2677. # ADDR1 since ADDR2 entries may have pushed ADDR1 out of the #
  2678. # ATC. #
  2679. # (7) Pre-fetch the core emulation instructions by executing #
  2680. # one branch within each physical line (16 bytes) of the code #
  2681. # before actually executing the code. #
  2682. # (8) Load the BUSCR w/ the bus lock value. #
  2683. # (9) Fetch the source operands using "moves". #
  2684. # (10)Do the compares. If both equal, go to step (13). #
  2685. # (11)Unequal. No update occurs. But, we do write the DST1 op #
  2686. # back to itself (as w/ the '040) so we can gracefully unlock #
  2687. # the bus (and assert LOCKE*) using BUSCR and the final move. #
  2688. # (12)Exit. #
  2689. # (13)Write update operand to the DST locations. Use BUSCR to #
  2690. # assert LOCKE* for the final write operation. #
  2691. # (14)Exit. #
  2692. # #
  2693. # The algorithm is actually implemented slightly differently #
  2694. # depending on the size of the operation and the misalignment of the #
  2695. # operands. A misaligned operand must be written in aligned chunks or #
  2696. # else the BUSCR register control gets confused. #
  2697. # #
  2698. #########################################################################
  2699. #################################################################
  2700. # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON #
  2701. # ENTERING _isp_cas2(). #
  2702. # #
  2703. # D0 = xxxxxxxx #
  2704. # D1 = xxxxxxxx #
  2705. # D2 = cmp operand 1 #
  2706. # D3 = cmp operand 2 #
  2707. # D4 = update oper 1 #
  2708. # D5 = update oper 2 #
  2709. # D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode #
  2710. # D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word #
  2711. # A0 = ADDR1 #
  2712. # A1 = ADDR2 #
  2713. # A2 = xxxxxxxx #
  2714. # A3 = xxxxxxxx #
  2715. # A4 = xxxxxxxx #
  2716. # A5 = xxxxxxxx #
  2717. # A6 = frame pointer #
  2718. # A7 = stack pointer #
  2719. #################################################################
  2720. # align 0x1000
  2721. # beginning label used by _isp_cas_inrange()
  2722. global _CASLO
  2723. _CASLO:
  2724. global _isp_cas2
  2725. _isp_cas2:
  2726. tst.b %d6 # user or supervisor mode?
  2727. bne.b cas2_supervisor # supervisor
  2728. cas2_user:
  2729. movq.l &0x1,%d0 # load user data fc
  2730. bra.b cas2_cont
  2731. cas2_supervisor:
  2732. movq.l &0x5,%d0 # load supervisor data fc
  2733. cas2_cont:
  2734. tst.b %d7 # word or longword?
  2735. beq.w cas2w # word
  2736. ####
  2737. cas2l:
  2738. mov.l %a0,%a2 # copy ADDR1
  2739. mov.l %a1,%a3 # copy ADDR2
  2740. mov.l %a0,%a4 # copy ADDR1
  2741. mov.l %a1,%a5 # copy ADDR2
  2742. addq.l &0x3,%a4 # ADDR1+3
  2743. addq.l &0x3,%a5 # ADDR2+3
  2744. mov.l %a2,%d1 # ADDR1
  2745. # mask interrupts levels 0-6. save old mask value.
  2746. mov.w %sr,%d7 # save current SR
  2747. ori.w &0x0700,%sr # inhibit interrupts
  2748. # load the SFC and DFC with the appropriate mode.
  2749. movc %sfc,%d6 # save old SFC/DFC
  2750. movc %d0,%sfc # store new SFC
  2751. movc %d0,%dfc # store new DFC
  2752. # pre-load the operand ATC. no page faults should occur here because
  2753. # _real_lock_page() should have taken care of this.
  2754. plpaw (%a2) # load atc for ADDR1
  2755. plpaw (%a4) # load atc for ADDR1+3
  2756. plpaw (%a3) # load atc for ADDR2
  2757. plpaw (%a5) # load atc for ADDR2+3
  2758. # push the operand lines from the cache if they exist.
  2759. cpushl %dc,(%a2) # push line for ADDR1
  2760. cpushl %dc,(%a4) # push line for ADDR1+3
  2761. cpushl %dc,(%a3) # push line for ADDR2
  2762. cpushl %dc,(%a5) # push line for ADDR2+2
  2763. mov.l %d1,%a2 # ADDR1
  2764. addq.l &0x3,%d1
  2765. mov.l %d1,%a4 # ADDR1+3
  2766. # if ADDR1 was ATC resident before the above "plpaw" and was executed
  2767. # and it was the next entry scheduled for replacement and ADDR2
  2768. # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
  2769. # entries from the ATC. so, we do a second set of "plpa"s.
  2770. plpar (%a2) # load atc for ADDR1
  2771. plpar (%a4) # load atc for ADDR1+3
  2772. # load the BUSCR values.
  2773. mov.l &0x80000000,%a2 # assert LOCK* buscr value
  2774. mov.l &0xa0000000,%a3 # assert LOCKE* buscr value
  2775. mov.l &0x00000000,%a4 # buscr unlock value
  2776. # there are three possible mis-aligned cases for longword cas. they
  2777. # are separated because the final write which asserts LOCKE* must
  2778. # be aligned.
  2779. mov.l %a0,%d0 # is ADDR1 misaligned?
  2780. andi.b &0x3,%d0
  2781. beq.b CAS2L_ENTER # no
  2782. cmpi.b %d0,&0x2
  2783. beq.w CAS2L2_ENTER # yes; word misaligned
  2784. bra.w CAS2L3_ENTER # yes; byte misaligned
  2785. #
  2786. # D0 = dst operand 1 <-
  2787. # D1 = dst operand 2 <-
  2788. # D2 = cmp operand 1
  2789. # D3 = cmp operand 2
  2790. # D4 = update oper 1
  2791. # D5 = update oper 2
  2792. # D6 = old SFC/DFC
  2793. # D7 = old SR
  2794. # A0 = ADDR1
  2795. # A1 = ADDR2
  2796. # A2 = bus LOCK* value
  2797. # A3 = bus LOCKE* value
  2798. # A4 = bus unlock value
  2799. # A5 = xxxxxxxx
  2800. #
  2801. align 0x10
  2802. CAS2L_START:
  2803. movc %a2,%buscr # assert LOCK*
  2804. movs.l (%a1),%d1 # fetch Dest2[31:0]
  2805. movs.l (%a0),%d0 # fetch Dest1[31:0]
  2806. bra.b CAS2L_CONT
  2807. CAS2L_ENTER:
  2808. bra.b ~+16
  2809. CAS2L_CONT:
  2810. cmp.l %d0,%d2 # Dest1 - Compare1
  2811. bne.b CAS2L_NOUPDATE
  2812. cmp.l %d1,%d3 # Dest2 - Compare2
  2813. bne.b CAS2L_NOUPDATE
  2814. movs.l %d5,(%a1) # Update2[31:0] -> DEST2
  2815. bra.b CAS2L_UPDATE
  2816. bra.b ~+16
  2817. CAS2L_UPDATE:
  2818. movc %a3,%buscr # assert LOCKE*
  2819. movs.l %d4,(%a0) # Update1[31:0] -> DEST1
  2820. movc %a4,%buscr # unlock the bus
  2821. bra.b cas2l_update_done
  2822. bra.b ~+16
  2823. CAS2L_NOUPDATE:
  2824. movc %a3,%buscr # assert LOCKE*
  2825. movs.l %d0,(%a0) # Dest1[31:0] -> DEST1
  2826. movc %a4,%buscr # unlock the bus
  2827. bra.b cas2l_noupdate_done
  2828. bra.b ~+16
  2829. CAS2L_FILLER:
  2830. nop
  2831. nop
  2832. nop
  2833. nop
  2834. nop
  2835. nop
  2836. nop
  2837. bra.b CAS2L_START
  2838. ####
  2839. #################################################################
  2840. # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
  2841. # ENTERING _isp_cas2(). #
  2842. # #
  2843. # D0 = destination[31:0] operand 1 #
  2844. # D1 = destination[31:0] operand 2 #
  2845. # D2 = cmp[31:0] operand 1 #
  2846. # D3 = cmp[31:0] operand 2 #
  2847. # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
  2848. # D5 = xxxxxxxx #
  2849. # D6 = xxxxxxxx #
  2850. # D7 = xxxxxxxx #
  2851. # A0 = xxxxxxxx #
  2852. # A1 = xxxxxxxx #
  2853. # A2 = xxxxxxxx #
  2854. # A3 = xxxxxxxx #
  2855. # A4 = xxxxxxxx #
  2856. # A5 = xxxxxxxx #
  2857. # A6 = frame pointer #
  2858. # A7 = stack pointer #
  2859. #################################################################
  2860. cas2l_noupdate_done:
  2861. # restore previous SFC/DFC value.
  2862. movc %d6,%sfc # restore old SFC
  2863. movc %d6,%dfc # restore old DFC
  2864. # restore previous interrupt mask level.
  2865. mov.w %d7,%sr # restore old SR
  2866. sf %d4 # indicate no update was done
  2867. bra.l _isp_cas2_finish
  2868. cas2l_update_done:
  2869. # restore previous SFC/DFC value.
  2870. movc %d6,%sfc # restore old SFC
  2871. movc %d6,%dfc # restore old DFC
  2872. # restore previous interrupt mask level.
  2873. mov.w %d7,%sr # restore old SR
  2874. st %d4 # indicate update was done
  2875. bra.l _isp_cas2_finish
  2876. ####
  2877. align 0x10
  2878. CAS2L2_START:
  2879. movc %a2,%buscr # assert LOCK*
  2880. movs.l (%a1),%d1 # fetch Dest2[31:0]
  2881. movs.l (%a0),%d0 # fetch Dest1[31:0]
  2882. bra.b CAS2L2_CONT
  2883. CAS2L2_ENTER:
  2884. bra.b ~+16
  2885. CAS2L2_CONT:
  2886. cmp.l %d0,%d2 # Dest1 - Compare1
  2887. bne.b CAS2L2_NOUPDATE
  2888. cmp.l %d1,%d3 # Dest2 - Compare2
  2889. bne.b CAS2L2_NOUPDATE
  2890. movs.l %d5,(%a1) # Update2[31:0] -> Dest2
  2891. bra.b CAS2L2_UPDATE
  2892. bra.b ~+16
  2893. CAS2L2_UPDATE:
  2894. swap %d4 # get Update1[31:16]
  2895. movs.w %d4,(%a0)+ # Update1[31:16] -> DEST1
  2896. movc %a3,%buscr # assert LOCKE*
  2897. swap %d4 # get Update1[15:0]
  2898. bra.b CAS2L2_UPDATE2
  2899. bra.b ~+16
  2900. CAS2L2_UPDATE2:
  2901. movs.w %d4,(%a0) # Update1[15:0] -> DEST1+0x2
  2902. movc %a4,%buscr # unlock the bus
  2903. bra.w cas2l_update_done
  2904. nop
  2905. bra.b ~+16
  2906. CAS2L2_NOUPDATE:
  2907. swap %d0 # get Dest1[31:16]
  2908. movs.w %d0,(%a0)+ # Dest1[31:16] -> DEST1
  2909. movc %a3,%buscr # assert LOCKE*
  2910. swap %d0 # get Dest1[15:0]
  2911. bra.b CAS2L2_NOUPDATE2
  2912. bra.b ~+16
  2913. CAS2L2_NOUPDATE2:
  2914. movs.w %d0,(%a0) # Dest1[15:0] -> DEST1+0x2
  2915. movc %a4,%buscr # unlock the bus
  2916. bra.w cas2l_noupdate_done
  2917. nop
  2918. bra.b ~+16
  2919. CAS2L2_FILLER:
  2920. nop
  2921. nop
  2922. nop
  2923. nop
  2924. nop
  2925. nop
  2926. nop
  2927. bra.b CAS2L2_START
  2928. #################################
  2929. align 0x10
  2930. CAS2L3_START:
  2931. movc %a2,%buscr # assert LOCK*
  2932. movs.l (%a1),%d1 # fetch Dest2[31:0]
  2933. movs.l (%a0),%d0 # fetch Dest1[31:0]
  2934. bra.b CAS2L3_CONT
  2935. CAS2L3_ENTER:
  2936. bra.b ~+16
  2937. CAS2L3_CONT:
  2938. cmp.l %d0,%d2 # Dest1 - Compare1
  2939. bne.b CAS2L3_NOUPDATE
  2940. cmp.l %d1,%d3 # Dest2 - Compare2
  2941. bne.b CAS2L3_NOUPDATE
  2942. movs.l %d5,(%a1) # Update2[31:0] -> DEST2
  2943. bra.b CAS2L3_UPDATE
  2944. bra.b ~+16
  2945. CAS2L3_UPDATE:
  2946. rol.l &0x8,%d4 # get Update1[31:24]
  2947. movs.b %d4,(%a0)+ # Update1[31:24] -> DEST1
  2948. swap %d4 # get Update1[23:8]
  2949. movs.w %d4,(%a0)+ # Update1[23:8] -> DEST1+0x1
  2950. bra.b CAS2L3_UPDATE2
  2951. bra.b ~+16
  2952. CAS2L3_UPDATE2:
  2953. rol.l &0x8,%d4 # get Update1[7:0]
  2954. movc %a3,%buscr # assert LOCKE*
  2955. movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x3
  2956. bra.b CAS2L3_UPDATE3
  2957. nop
  2958. bra.b ~+16
  2959. CAS2L3_UPDATE3:
  2960. movc %a4,%buscr # unlock the bus
  2961. bra.w cas2l_update_done
  2962. nop
  2963. nop
  2964. nop
  2965. bra.b ~+16
  2966. CAS2L3_NOUPDATE:
  2967. rol.l &0x8,%d0 # get Dest1[31:24]
  2968. movs.b %d0,(%a0)+ # Dest1[31:24] -> DEST1
  2969. swap %d0 # get Dest1[23:8]
  2970. movs.w %d0,(%a0)+ # Dest1[23:8] -> DEST1+0x1
  2971. bra.b CAS2L3_NOUPDATE2
  2972. bra.b ~+16
  2973. CAS2L3_NOUPDATE2:
  2974. rol.l &0x8,%d0 # get Dest1[7:0]
  2975. movc %a3,%buscr # assert LOCKE*
  2976. movs.b %d0,(%a0) # Update1[7:0] -> DEST1+0x3
  2977. bra.b CAS2L3_NOUPDATE3
  2978. nop
  2979. bra.b ~+16
  2980. CAS2L3_NOUPDATE3:
  2981. movc %a4,%buscr # unlock the bus
  2982. bra.w cas2l_noupdate_done
  2983. nop
  2984. nop
  2985. nop
  2986. bra.b ~+14
  2987. CAS2L3_FILLER:
  2988. nop
  2989. nop
  2990. nop
  2991. nop
  2992. nop
  2993. nop
  2994. bra.w CAS2L3_START
  2995. #############################################################
  2996. #############################################################
  2997. cas2w:
  2998. mov.l %a0,%a2 # copy ADDR1
  2999. mov.l %a1,%a3 # copy ADDR2
  3000. mov.l %a0,%a4 # copy ADDR1
  3001. mov.l %a1,%a5 # copy ADDR2
  3002. addq.l &0x1,%a4 # ADDR1+1
  3003. addq.l &0x1,%a5 # ADDR2+1
  3004. mov.l %a2,%d1 # ADDR1
  3005. # mask interrupt levels 0-6. save old mask value.
  3006. mov.w %sr,%d7 # save current SR
  3007. ori.w &0x0700,%sr # inhibit interrupts
  3008. # load the SFC and DFC with the appropriate mode.
  3009. movc %sfc,%d6 # save old SFC/DFC
  3010. movc %d0,%sfc # store new SFC
  3011. movc %d0,%dfc # store new DFC
  3012. # pre-load the operand ATC. no page faults should occur because
  3013. # _real_lock_page() should have taken care of this.
  3014. plpaw (%a2) # load atc for ADDR1
  3015. plpaw (%a4) # load atc for ADDR1+1
  3016. plpaw (%a3) # load atc for ADDR2
  3017. plpaw (%a5) # load atc for ADDR2+1
  3018. # push the operand cache lines from the cache if they exist.
  3019. cpushl %dc,(%a2) # push line for ADDR1
  3020. cpushl %dc,(%a4) # push line for ADDR1+1
  3021. cpushl %dc,(%a3) # push line for ADDR2
  3022. cpushl %dc,(%a5) # push line for ADDR2+1
  3023. mov.l %d1,%a2 # ADDR1
  3024. addq.l &0x3,%d1
  3025. mov.l %d1,%a4 # ADDR1+3
  3026. # if ADDR1 was ATC resident before the above "plpaw" and was executed
  3027. # and it was the next entry scheduled for replacement and ADDR2
  3028. # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
  3029. # entries from the ATC. so, we do a second set of "plpa"s.
  3030. plpar (%a2) # load atc for ADDR1
  3031. plpar (%a4) # load atc for ADDR1+3
  3032. # load the BUSCR values.
  3033. mov.l &0x80000000,%a2 # assert LOCK* buscr value
  3034. mov.l &0xa0000000,%a3 # assert LOCKE* buscr value
  3035. mov.l &0x00000000,%a4 # buscr unlock value
  3036. # there are two possible mis-aligned cases for word cas. they
  3037. # are separated because the final write which asserts LOCKE* must
  3038. # be aligned.
  3039. mov.l %a0,%d0 # is ADDR1 misaligned?
  3040. btst &0x0,%d0
  3041. bne.w CAS2W2_ENTER # yes
  3042. bra.b CAS2W_ENTER # no
  3043. #
  3044. # D0 = dst operand 1 <-
  3045. # D1 = dst operand 2 <-
  3046. # D2 = cmp operand 1
  3047. # D3 = cmp operand 2
  3048. # D4 = update oper 1
  3049. # D5 = update oper 2
  3050. # D6 = old SFC/DFC
  3051. # D7 = old SR
  3052. # A0 = ADDR1
  3053. # A1 = ADDR2
  3054. # A2 = bus LOCK* value
  3055. # A3 = bus LOCKE* value
  3056. # A4 = bus unlock value
  3057. # A5 = xxxxxxxx
  3058. #
  3059. align 0x10
  3060. CAS2W_START:
  3061. movc %a2,%buscr # assert LOCK*
  3062. movs.w (%a1),%d1 # fetch Dest2[15:0]
  3063. movs.w (%a0),%d0 # fetch Dest1[15:0]
  3064. bra.b CAS2W_CONT2
  3065. CAS2W_ENTER:
  3066. bra.b ~+16
  3067. CAS2W_CONT2:
  3068. cmp.w %d0,%d2 # Dest1 - Compare1
  3069. bne.b CAS2W_NOUPDATE
  3070. cmp.w %d1,%d3 # Dest2 - Compare2
  3071. bne.b CAS2W_NOUPDATE
  3072. movs.w %d5,(%a1) # Update2[15:0] -> DEST2
  3073. bra.b CAS2W_UPDATE
  3074. bra.b ~+16
  3075. CAS2W_UPDATE:
  3076. movc %a3,%buscr # assert LOCKE*
  3077. movs.w %d4,(%a0) # Update1[15:0] -> DEST1
  3078. movc %a4,%buscr # unlock the bus
  3079. bra.b cas2w_update_done
  3080. bra.b ~+16
  3081. CAS2W_NOUPDATE:
  3082. movc %a3,%buscr # assert LOCKE*
  3083. movs.w %d0,(%a0) # Dest1[15:0] -> DEST1
  3084. movc %a4,%buscr # unlock the bus
  3085. bra.b cas2w_noupdate_done
  3086. bra.b ~+16
  3087. CAS2W_FILLER:
  3088. nop
  3089. nop
  3090. nop
  3091. nop
  3092. nop
  3093. nop
  3094. nop
  3095. bra.b CAS2W_START
  3096. ####
  3097. #################################################################
  3098. # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
  3099. # ENTERING _isp_cas2(). #
  3100. # #
  3101. # D0 = destination[15:0] operand 1 #
  3102. # D1 = destination[15:0] operand 2 #
  3103. # D2 = cmp[15:0] operand 1 #
  3104. # D3 = cmp[15:0] operand 2 #
  3105. # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
  3106. # D5 = xxxxxxxx #
  3107. # D6 = xxxxxxxx #
  3108. # D7 = xxxxxxxx #
  3109. # A0 = xxxxxxxx #
  3110. # A1 = xxxxxxxx #
  3111. # A2 = xxxxxxxx #
  3112. # A3 = xxxxxxxx #
  3113. # A4 = xxxxxxxx #
  3114. # A5 = xxxxxxxx #
  3115. # A6 = frame pointer #
  3116. # A7 = stack pointer #
  3117. #################################################################
  3118. cas2w_noupdate_done:
  3119. # restore previous SFC/DFC value.
  3120. movc %d6,%sfc # restore old SFC
  3121. movc %d6,%dfc # restore old DFC
  3122. # restore previous interrupt mask level.
  3123. mov.w %d7,%sr # restore old SR
  3124. sf %d4 # indicate no update was done
  3125. bra.l _isp_cas2_finish
  3126. cas2w_update_done:
  3127. # restore previous SFC/DFC value.
  3128. movc %d6,%sfc # restore old SFC
  3129. movc %d6,%dfc # restore old DFC
  3130. # restore previous interrupt mask level.
  3131. mov.w %d7,%sr # restore old SR
  3132. st %d4 # indicate update was done
  3133. bra.l _isp_cas2_finish
  3134. ####
  3135. align 0x10
  3136. CAS2W2_START:
  3137. movc %a2,%buscr # assert LOCK*
  3138. movs.w (%a1),%d1 # fetch Dest2[15:0]
  3139. movs.w (%a0),%d0 # fetch Dest1[15:0]
  3140. bra.b CAS2W2_CONT2
  3141. CAS2W2_ENTER:
  3142. bra.b ~+16
  3143. CAS2W2_CONT2:
  3144. cmp.w %d0,%d2 # Dest1 - Compare1
  3145. bne.b CAS2W2_NOUPDATE
  3146. cmp.w %d1,%d3 # Dest2 - Compare2
  3147. bne.b CAS2W2_NOUPDATE
  3148. movs.w %d5,(%a1) # Update2[15:0] -> DEST2
  3149. bra.b CAS2W2_UPDATE
  3150. bra.b ~+16
  3151. CAS2W2_UPDATE:
  3152. ror.l &0x8,%d4 # get Update1[15:8]
  3153. movs.b %d4,(%a0)+ # Update1[15:8] -> DEST1
  3154. movc %a3,%buscr # assert LOCKE*
  3155. rol.l &0x8,%d4 # get Update1[7:0]
  3156. bra.b CAS2W2_UPDATE2
  3157. bra.b ~+16
  3158. CAS2W2_UPDATE2:
  3159. movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x1
  3160. movc %a4,%buscr # unlock the bus
  3161. bra.w cas2w_update_done
  3162. nop
  3163. bra.b ~+16
  3164. CAS2W2_NOUPDATE:
  3165. ror.l &0x8,%d0 # get Dest1[15:8]
  3166. movs.b %d0,(%a0)+ # Dest1[15:8] -> DEST1
  3167. movc %a3,%buscr # assert LOCKE*
  3168. rol.l &0x8,%d0 # get Dest1[7:0]
  3169. bra.b CAS2W2_NOUPDATE2
  3170. bra.b ~+16
  3171. CAS2W2_NOUPDATE2:
  3172. movs.b %d0,(%a0) # Dest1[7:0] -> DEST1+0x1
  3173. movc %a4,%buscr # unlock the bus
  3174. bra.w cas2w_noupdate_done
  3175. nop
  3176. bra.b ~+16
  3177. CAS2W2_FILLER:
  3178. nop
  3179. nop
  3180. nop
  3181. nop
  3182. nop
  3183. nop
  3184. nop
  3185. bra.b CAS2W2_START
  3186. # ###### ## ######
  3187. # # # # #
  3188. # # ###### ######
  3189. # # # # #
  3190. # ###### # # ######
  3191. #########################################################################
  3192. # XDEF **************************************************************** #
  3193. # _isp_cas(): "core" emulation code for the cas instruction #
  3194. # #
  3195. # XREF **************************************************************** #
  3196. # _isp_cas_finish() - only exit point for this emulation code; #
  3197. # do clean-up #
  3198. # #
  3199. # INPUT *************************************************************** #
  3200. # *see entry chart below* #
  3201. # #
  3202. # OUTPUT ************************************************************** #
  3203. # *see exit chart below* #
  3204. # #
  3205. # ALGORITHM *********************************************************** #
  3206. # (1) Make several copies of the effective address. #
  3207. # (2) Save current SR; Then mask off all maskable interrupts. #
  3208. # (3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set #
  3209. # SFC/DFC according to whether exception occurred in user or #
  3210. # supervisor mode. #
  3211. # (4) Use "plpaw" instruction to pre-load ATC with efective #
  3212. # address page(s). THIS SHOULD NOT FAULT!!! The relevant #
  3213. # page(s) should have been made resident prior to entering #
  3214. # this routine. #
  3215. # (5) Push the operand lines from the cache w/ "cpushl". #
  3216. # In the 68040, this was done within the locked region. In #
  3217. # the 68060, it is done outside of the locked region. #
  3218. # (6) Pre-fetch the core emulation instructions by executing one #
  3219. # branch within each physical line (16 bytes) of the code #
  3220. # before actually executing the code. #
  3221. # (7) Load the BUSCR with the bus lock value. #
  3222. # (8) Fetch the source operand. #
  3223. # (9) Do the compare. If equal, go to step (12). #
  3224. # (10)Unequal. No update occurs. But, we do write the DST op back #
  3225. # to itself (as w/ the '040) so we can gracefully unlock #
  3226. # the bus (and assert LOCKE*) using BUSCR and the final move. #
  3227. # (11)Exit. #
  3228. # (12)Write update operand to the DST location. Use BUSCR to #
  3229. # assert LOCKE* for the final write operation. #
  3230. # (13)Exit. #
  3231. # #
  3232. # The algorithm is actually implemented slightly differently #
  3233. # depending on the size of the operation and the misalignment of the #
  3234. # operand. A misaligned operand must be written in aligned chunks or #
  3235. # else the BUSCR register control gets confused. #
  3236. # #
  3237. #########################################################################
  3238. #########################################################
  3239. # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON #
  3240. # ENTERING _isp_cas(). #
  3241. # #
  3242. # D0 = xxxxxxxx #
  3243. # D1 = xxxxxxxx #
  3244. # D2 = update operand #
  3245. # D3 = xxxxxxxx #
  3246. # D4 = compare operand #
  3247. # D5 = xxxxxxxx #
  3248. # D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00) #
  3249. # D7 = longword ('xxxxxxff) or word size ('xxxxxx00) #
  3250. # A0 = ADDR #
  3251. # A1 = xxxxxxxx #
  3252. # A2 = xxxxxxxx #
  3253. # A3 = xxxxxxxx #
  3254. # A4 = xxxxxxxx #
  3255. # A5 = xxxxxxxx #
  3256. # A6 = frame pointer #
  3257. # A7 = stack pointer #
  3258. #########################################################
  3259. global _isp_cas
  3260. _isp_cas:
  3261. tst.b %d6 # user or supervisor mode?
  3262. bne.b cas_super # supervisor
  3263. cas_user:
  3264. movq.l &0x1,%d0 # load user data fc
  3265. bra.b cas_cont
  3266. cas_super:
  3267. movq.l &0x5,%d0 # load supervisor data fc
  3268. cas_cont:
  3269. tst.b %d7 # word or longword?
  3270. bne.w casl # longword
  3271. ####
  3272. casw:
  3273. mov.l %a0,%a1 # make copy for plpaw1
  3274. mov.l %a0,%a2 # make copy for plpaw2
  3275. addq.l &0x1,%a2 # plpaw2 points to end of word
  3276. mov.l %d2,%d3 # d3 = update[7:0]
  3277. lsr.w &0x8,%d2 # d2 = update[15:8]
  3278. # mask interrupt levels 0-6. save old mask value.
  3279. mov.w %sr,%d7 # save current SR
  3280. ori.w &0x0700,%sr # inhibit interrupts
  3281. # load the SFC and DFC with the appropriate mode.
  3282. movc %sfc,%d6 # save old SFC/DFC
  3283. movc %d0,%sfc # load new sfc
  3284. movc %d0,%dfc # load new dfc
  3285. # pre-load the operand ATC. no page faults should occur here because
  3286. # _real_lock_page() should have taken care of this.
  3287. plpaw (%a1) # load atc for ADDR
  3288. plpaw (%a2) # load atc for ADDR+1
  3289. # push the operand lines from the cache if they exist.
  3290. cpushl %dc,(%a1) # push dirty data
  3291. cpushl %dc,(%a2) # push dirty data
  3292. # load the BUSCR values.
  3293. mov.l &0x80000000,%a1 # assert LOCK* buscr value
  3294. mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
  3295. mov.l &0x00000000,%a3 # buscr unlock value
  3296. # pre-load the instruction cache for the following algorithm.
  3297. # this will minimize the number of cycles that LOCK* will be asserted.
  3298. bra.b CASW_ENTER # start pre-loading icache
  3299. #
  3300. # D0 = dst operand <-
  3301. # D1 = update[15:8] operand
  3302. # D2 = update[7:0] operand
  3303. # D3 = xxxxxxxx
  3304. # D4 = compare[15:0] operand
  3305. # D5 = xxxxxxxx
  3306. # D6 = old SFC/DFC
  3307. # D7 = old SR
  3308. # A0 = ADDR
  3309. # A1 = bus LOCK* value
  3310. # A2 = bus LOCKE* value
  3311. # A3 = bus unlock value
  3312. # A4 = xxxxxxxx
  3313. # A5 = xxxxxxxx
  3314. #
  3315. align 0x10
  3316. CASW_START:
  3317. movc %a1,%buscr # assert LOCK*
  3318. movs.w (%a0),%d0 # fetch Dest[15:0]
  3319. cmp.w %d0,%d4 # Dest - Compare
  3320. bne.b CASW_NOUPDATE
  3321. bra.b CASW_UPDATE
  3322. CASW_ENTER:
  3323. bra.b ~+16
  3324. CASW_UPDATE:
  3325. movs.b %d2,(%a0)+ # Update[15:8] -> DEST
  3326. movc %a2,%buscr # assert LOCKE*
  3327. movs.b %d3,(%a0) # Update[7:0] -> DEST+0x1
  3328. bra.b CASW_UPDATE2
  3329. bra.b ~+16
  3330. CASW_UPDATE2:
  3331. movc %a3,%buscr # unlock the bus
  3332. bra.b casw_update_done
  3333. nop
  3334. nop
  3335. nop
  3336. nop
  3337. bra.b ~+16
  3338. CASW_NOUPDATE:
  3339. ror.l &0x8,%d0 # get Dest[15:8]
  3340. movs.b %d0,(%a0)+ # Dest[15:8] -> DEST
  3341. movc %a2,%buscr # assert LOCKE*
  3342. rol.l &0x8,%d0 # get Dest[7:0]
  3343. bra.b CASW_NOUPDATE2
  3344. bra.b ~+16
  3345. CASW_NOUPDATE2:
  3346. movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x1
  3347. movc %a3,%buscr # unlock the bus
  3348. bra.b casw_noupdate_done
  3349. nop
  3350. nop
  3351. bra.b ~+16
  3352. CASW_FILLER:
  3353. nop
  3354. nop
  3355. nop
  3356. nop
  3357. nop
  3358. nop
  3359. nop
  3360. bra.b CASW_START
  3361. #################################################################
  3362. # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
  3363. # CALLING _isp_cas_finish(). #
  3364. # #
  3365. # D0 = destination[15:0] operand #
  3366. # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
  3367. # D2 = xxxxxxxx #
  3368. # D3 = xxxxxxxx #
  3369. # D4 = compare[15:0] operand #
  3370. # D5 = xxxxxxxx #
  3371. # D6 = xxxxxxxx #
  3372. # D7 = xxxxxxxx #
  3373. # A0 = xxxxxxxx #
  3374. # A1 = xxxxxxxx #
  3375. # A2 = xxxxxxxx #
  3376. # A3 = xxxxxxxx #
  3377. # A4 = xxxxxxxx #
  3378. # A5 = xxxxxxxx #
  3379. # A6 = frame pointer #
  3380. # A7 = stack pointer #
  3381. #################################################################
  3382. casw_noupdate_done:
  3383. # restore previous SFC/DFC value.
  3384. movc %d6,%sfc # restore old SFC
  3385. movc %d6,%dfc # restore old DFC
  3386. # restore previous interrupt mask level.
  3387. mov.w %d7,%sr # restore old SR
  3388. sf %d1 # indicate no update was done
  3389. bra.l _isp_cas_finish
  3390. casw_update_done:
  3391. # restore previous SFC/DFC value.
  3392. movc %d6,%sfc # restore old SFC
  3393. movc %d6,%dfc # restore old DFC
  3394. # restore previous interrupt mask level.
  3395. mov.w %d7,%sr # restore old SR
  3396. st %d1 # indicate update was done
  3397. bra.l _isp_cas_finish
  3398. ################
  3399. # there are two possible mis-aligned cases for longword cas. they
  3400. # are separated because the final write which asserts LOCKE* must
  3401. # be an aligned write.
  3402. casl:
  3403. mov.l %a0,%a1 # make copy for plpaw1
  3404. mov.l %a0,%a2 # make copy for plpaw2
  3405. addq.l &0x3,%a2 # plpaw2 points to end of longword
  3406. mov.l %a0,%d1 # byte or word misaligned?
  3407. btst &0x0,%d1
  3408. bne.w casl2 # byte misaligned
  3409. mov.l %d2,%d3 # d3 = update[15:0]
  3410. swap %d2 # d2 = update[31:16]
  3411. # mask interrupts levels 0-6. save old mask value.
  3412. mov.w %sr,%d7 # save current SR
  3413. ori.w &0x0700,%sr # inhibit interrupts
  3414. # load the SFC and DFC with the appropriate mode.
  3415. movc %sfc,%d6 # save old SFC/DFC
  3416. movc %d0,%sfc # load new sfc
  3417. movc %d0,%dfc # load new dfc
  3418. # pre-load the operand ATC. no page faults should occur here because
  3419. # _real_lock_page() should have taken care of this.
  3420. plpaw (%a1) # load atc for ADDR
  3421. plpaw (%a2) # load atc for ADDR+3
  3422. # push the operand lines from the cache if they exist.
  3423. cpushl %dc,(%a1) # push dirty data
  3424. cpushl %dc,(%a2) # push dirty data
  3425. # load the BUSCR values.
  3426. mov.l &0x80000000,%a1 # assert LOCK* buscr value
  3427. mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
  3428. mov.l &0x00000000,%a3 # buscr unlock value
  3429. bra.b CASL_ENTER # start pre-loading icache
  3430. #
  3431. # D0 = dst operand <-
  3432. # D1 = xxxxxxxx
  3433. # D2 = update[31:16] operand
  3434. # D3 = update[15:0] operand
  3435. # D4 = compare[31:0] operand
  3436. # D5 = xxxxxxxx
  3437. # D6 = old SFC/DFC
  3438. # D7 = old SR
  3439. # A0 = ADDR
  3440. # A1 = bus LOCK* value
  3441. # A2 = bus LOCKE* value
  3442. # A3 = bus unlock value
  3443. # A4 = xxxxxxxx
  3444. # A5 = xxxxxxxx
  3445. #
  3446. align 0x10
  3447. CASL_START:
  3448. movc %a1,%buscr # assert LOCK*
  3449. movs.l (%a0),%d0 # fetch Dest[31:0]
  3450. cmp.l %d0,%d4 # Dest - Compare
  3451. bne.b CASL_NOUPDATE
  3452. bra.b CASL_UPDATE
  3453. CASL_ENTER:
  3454. bra.b ~+16
  3455. CASL_UPDATE:
  3456. movs.w %d2,(%a0)+ # Update[31:16] -> DEST
  3457. movc %a2,%buscr # assert LOCKE*
  3458. movs.w %d3,(%a0) # Update[15:0] -> DEST+0x2
  3459. bra.b CASL_UPDATE2
  3460. bra.b ~+16
  3461. CASL_UPDATE2:
  3462. movc %a3,%buscr # unlock the bus
  3463. bra.b casl_update_done
  3464. nop
  3465. nop
  3466. nop
  3467. nop
  3468. bra.b ~+16
  3469. CASL_NOUPDATE:
  3470. swap %d0 # get Dest[31:16]
  3471. movs.w %d0,(%a0)+ # Dest[31:16] -> DEST
  3472. swap %d0 # get Dest[15:0]
  3473. movc %a2,%buscr # assert LOCKE*
  3474. bra.b CASL_NOUPDATE2
  3475. bra.b ~+16
  3476. CASL_NOUPDATE2:
  3477. movs.w %d0,(%a0) # Dest[15:0] -> DEST+0x2
  3478. movc %a3,%buscr # unlock the bus
  3479. bra.b casl_noupdate_done
  3480. nop
  3481. nop
  3482. bra.b ~+16
  3483. CASL_FILLER:
  3484. nop
  3485. nop
  3486. nop
  3487. nop
  3488. nop
  3489. nop
  3490. nop
  3491. bra.b CASL_START
  3492. #################################################################
  3493. # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
  3494. # CALLING _isp_cas_finish(). #
  3495. # #
  3496. # D0 = destination[31:0] operand #
  3497. # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
  3498. # D2 = xxxxxxxx #
  3499. # D3 = xxxxxxxx #
  3500. # D4 = compare[31:0] operand #
  3501. # D5 = xxxxxxxx #
  3502. # D6 = xxxxxxxx #
  3503. # D7 = xxxxxxxx #
  3504. # A0 = xxxxxxxx #
  3505. # A1 = xxxxxxxx #
  3506. # A2 = xxxxxxxx #
  3507. # A3 = xxxxxxxx #
  3508. # A4 = xxxxxxxx #
  3509. # A5 = xxxxxxxx #
  3510. # A6 = frame pointer #
  3511. # A7 = stack pointer #
  3512. #################################################################
  3513. casl_noupdate_done:
  3514. # restore previous SFC/DFC value.
  3515. movc %d6,%sfc # restore old SFC
  3516. movc %d6,%dfc # restore old DFC
  3517. # restore previous interrupt mask level.
  3518. mov.w %d7,%sr # restore old SR
  3519. sf %d1 # indicate no update was done
  3520. bra.l _isp_cas_finish
  3521. casl_update_done:
  3522. # restore previous SFC/DFC value.
  3523. movc %d6,%sfc # restore old SFC
  3524. movc %d6,%dfc # restore old DFC
  3525. # restore previous interrupts mask level.
  3526. mov.w %d7,%sr # restore old SR
  3527. st %d1 # indicate update was done
  3528. bra.l _isp_cas_finish
  3529. #######################################
  3530. casl2:
  3531. mov.l %d2,%d5 # d5 = Update[7:0]
  3532. lsr.l &0x8,%d2
  3533. mov.l %d2,%d3 # d3 = Update[23:8]
  3534. swap %d2 # d2 = Update[31:24]
  3535. # mask interrupts levels 0-6. save old mask value.
  3536. mov.w %sr,%d7 # save current SR
  3537. ori.w &0x0700,%sr # inhibit interrupts
  3538. # load the SFC and DFC with the appropriate mode.
  3539. movc %sfc,%d6 # save old SFC/DFC
  3540. movc %d0,%sfc # load new sfc
  3541. movc %d0,%dfc # load new dfc
  3542. # pre-load the operand ATC. no page faults should occur here because
  3543. # _real_lock_page() should have taken care of this already.
  3544. plpaw (%a1) # load atc for ADDR
  3545. plpaw (%a2) # load atc for ADDR+3
  3546. # puch the operand lines from the cache if they exist.
  3547. cpushl %dc,(%a1) # push dirty data
  3548. cpushl %dc,(%a2) # push dirty data
  3549. # load the BUSCR values.
  3550. mov.l &0x80000000,%a1 # assert LOCK* buscr value
  3551. mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
  3552. mov.l &0x00000000,%a3 # buscr unlock value
  3553. # pre-load the instruction cache for the following algorithm.
  3554. # this will minimize the number of cycles that LOCK* will be asserted.
  3555. bra.b CASL2_ENTER # start pre-loading icache
  3556. #
  3557. # D0 = dst operand <-
  3558. # D1 = xxxxxxxx
  3559. # D2 = update[31:24] operand
  3560. # D3 = update[23:8] operand
  3561. # D4 = compare[31:0] operand
  3562. # D5 = update[7:0] operand
  3563. # D6 = old SFC/DFC
  3564. # D7 = old SR
  3565. # A0 = ADDR
  3566. # A1 = bus LOCK* value
  3567. # A2 = bus LOCKE* value
  3568. # A3 = bus unlock value
  3569. # A4 = xxxxxxxx
  3570. # A5 = xxxxxxxx
  3571. #
  3572. align 0x10
  3573. CASL2_START:
  3574. movc %a1,%buscr # assert LOCK*
  3575. movs.l (%a0),%d0 # fetch Dest[31:0]
  3576. cmp.l %d0,%d4 # Dest - Compare
  3577. bne.b CASL2_NOUPDATE
  3578. bra.b CASL2_UPDATE
  3579. CASL2_ENTER:
  3580. bra.b ~+16
  3581. CASL2_UPDATE:
  3582. movs.b %d2,(%a0)+ # Update[31:24] -> DEST
  3583. movs.w %d3,(%a0)+ # Update[23:8] -> DEST+0x1
  3584. movc %a2,%buscr # assert LOCKE*
  3585. bra.b CASL2_UPDATE2
  3586. bra.b ~+16
  3587. CASL2_UPDATE2:
  3588. movs.b %d5,(%a0) # Update[7:0] -> DEST+0x3
  3589. movc %a3,%buscr # unlock the bus
  3590. bra.w casl_update_done
  3591. nop
  3592. bra.b ~+16
  3593. CASL2_NOUPDATE:
  3594. rol.l &0x8,%d0 # get Dest[31:24]
  3595. movs.b %d0,(%a0)+ # Dest[31:24] -> DEST
  3596. swap %d0 # get Dest[23:8]
  3597. movs.w %d0,(%a0)+ # Dest[23:8] -> DEST+0x1
  3598. bra.b CASL2_NOUPDATE2
  3599. bra.b ~+16
  3600. CASL2_NOUPDATE2:
  3601. rol.l &0x8,%d0 # get Dest[7:0]
  3602. movc %a2,%buscr # assert LOCKE*
  3603. movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x3
  3604. bra.b CASL2_NOUPDATE3
  3605. nop
  3606. bra.b ~+16
  3607. CASL2_NOUPDATE3:
  3608. movc %a3,%buscr # unlock the bus
  3609. bra.w casl_noupdate_done
  3610. nop
  3611. nop
  3612. nop
  3613. bra.b ~+16
  3614. CASL2_FILLER:
  3615. nop
  3616. nop
  3617. nop
  3618. nop
  3619. nop
  3620. nop
  3621. nop
  3622. bra.b CASL2_START
  3623. ####
  3624. ####
  3625. # end label used by _isp_cas_inrange()
  3626. global _CASHI
  3627. _CASHI: