bytes1.c 154 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591
  1. /*
  2. * bytes1.c Copyright (C) 1991-99, Codemist Ltd
  3. *
  4. *
  5. * Bytecode interpreter for Lisp
  6. */
  7. /* Signature: 66175282 07-Mar-2000 */
  8. #include <stdarg.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #ifdef __WATCOMC__
  12. #include <float.h>
  13. #endif
  14. #include "machine.h"
  15. #include "tags.h"
  16. #include "cslerror.h"
  17. #include "externs.h"
  18. #include "arith.h"
  19. #include "entries.h"
  20. #ifdef TIMEOUT
  21. #include "timeout.h"
  22. #endif
  23. #if defined DEMO_MODE || defined DEMO_BUILD
  24. #include "demobyte.h" /* Alternate bytecode mapping used by demo version */
  25. #else
  26. #include "bytes.h"
  27. #endif
  28. /*
  29. * I put all the code that handles property lists in this file since then
  30. * I can arrange that the option that allows me to count the number of byte
  31. * opcodes that are executed also lets me collect statistics on which
  32. * indicators are most heavily used with PUT and GET.
  33. */
  34. #ifdef RECORD_GET
  35. void record_get(Lisp_Object tag, CSLbool found)
  36. {
  37. Lisp_Object nil = C_nil;
  38. Lisp_Object w;
  39. push(tag);
  40. w = Lget_hash_2(nil, tag, get_counts);
  41. pop(tag);
  42. errexitv();
  43. if (w == nil)
  44. { w = cons_no_gc(fixnum_of_int(0), fixnum_of_int(0));
  45. push(w);
  46. Lput_hash(nil, 3, tag, get_counts, w);
  47. pop(w);
  48. errexitv();
  49. }
  50. if (found) qcar(w) += 0x10;
  51. else qcdr(w) += 0x10;
  52. }
  53. #endif
  54. /*
  55. * Here is a short essay on the interaction between flags and properties.
  56. * It is written because the issue appears to be delicate, especially in the
  57. * face of a scheme that I use to speed things up.
  58. * (a) If you use FLAG, REMFLAG and FLAGP with some indicator then that
  59. * indicator is known as a flag.
  60. * (b) If you use PUT, REMPROP and GET with an indicator then what you
  61. * have is a property.
  62. * (c) Providing the names of flags and properties are disjoint no difficulty
  63. * whatever should arise.
  64. * (d) If you use PLIST to gain direct access to a property list then flags
  65. * are visible as pairs (tag . t) and properties as (tag . value).
  66. * (e) Using RPLACx operations on the result of PLIST may cause system
  67. * damage. It is to be considered illegal. Also changes made that
  68. * way may not be matched in any accelarating caches that I keep.
  69. * (f) After (FLAG '(id) 'tag) [when id did not previously have any flags
  70. * or properties] a call (GET 'id 'tag) will return t.
  71. * (g) After (PUT 'id 'tag 'anything) a call (FLAGP 'id 'tag) will return t
  72. * whatever the value of "anything". A call (GET 'id 'tag) will return
  73. * the saved value (which might be nil). Thus FLAGP can be thought of
  74. * as a function that tests if a given property is attached to a
  75. * symbol.
  76. * (h) As a consequence of (g) REMPROP and REMFLAG are really the same
  77. * operation.
  78. */
  79. #ifndef COMMON
  80. Lisp_Object get(Lisp_Object a, Lisp_Object b)
  81. {
  82. Lisp_Object pl, prev, w, nil = C_nil;
  83. int n;
  84. /*
  85. * In CSL mode plists are structured like association lists, and
  86. * NOT as lists with alternate tags and values. There is also
  87. * a bitmap that can provide a fast test for the presence of a
  88. * property...
  89. */
  90. if (!symbolp(a))
  91. {
  92. #ifdef RECORD_GET
  93. record_get(b, NO);
  94. errexit();
  95. #endif
  96. return onevalue(nil);
  97. }
  98. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  99. { if ((w = qfastgets(a)) == nil)
  100. {
  101. #ifdef RECORD_GET
  102. record_get(b, NO);
  103. errexit();
  104. #endif
  105. return onevalue(nil);
  106. }
  107. w = elt(w, n-1);
  108. if (w == SPID_NOPROP) w = nil;
  109. #ifdef RECORD_GET
  110. push(w);
  111. record_get(b, w != nil);
  112. pop(w);
  113. errexit();
  114. #endif
  115. return onevalue(w);
  116. }
  117. pl = qplist(a);
  118. if (pl == nil)
  119. {
  120. #ifdef RECORD_GET
  121. record_get(b, NO);
  122. errexit();
  123. #endif
  124. return onevalue(nil);
  125. }
  126. w = qcar(pl);
  127. if (qcar(w) == b)
  128. {
  129. #ifdef RECORD_GET
  130. push(w);
  131. record_get(b, YES);
  132. pop(w);
  133. errexit();
  134. #endif
  135. return onevalue(qcdr(w));
  136. }
  137. pl = qcdr(pl);
  138. if (pl == nil)
  139. {
  140. #ifdef RECORD_GET
  141. record_get(b, NO);
  142. errexit();
  143. #endif
  144. return onevalue(nil);
  145. }
  146. w = qcar(pl);
  147. if (qcar(w) == b)
  148. {
  149. #ifdef RECORD_GET
  150. push(w);
  151. record_get(b, YES);
  152. pop(w);
  153. errexit();
  154. #endif
  155. return onevalue(qcdr(w));
  156. }
  157. prev = pl;
  158. pl = qcdr(pl);
  159. if (pl == nil)
  160. {
  161. #ifdef RECORD_GET
  162. record_get(b, NO);
  163. errexit();
  164. #endif
  165. return onevalue(nil);
  166. }
  167. while (YES)
  168. { w = qcar(pl);
  169. /*
  170. * If I find the item anywhere beyond the first two places in the plist I
  171. * migrate it up to the front so that next time will be faster
  172. */
  173. if (qcar(w) == b)
  174. { qcdr(prev) = qcdr(pl);
  175. qcdr(pl) = qplist(a);
  176. qplist(a) = pl;
  177. #ifdef RECORD_GET
  178. push(w);
  179. record_get(b, YES);
  180. pop(w);
  181. errexit();
  182. #endif
  183. return onevalue(qcdr(w));
  184. }
  185. prev = pl;
  186. pl = qcdr(pl);
  187. if (pl == nil)
  188. {
  189. #ifdef RECORD_GET
  190. record_get(b, NO);
  191. errexit();
  192. #endif
  193. return onevalue(nil);
  194. }
  195. }
  196. }
  197. Lisp_Object putprop(Lisp_Object a, Lisp_Object b, Lisp_Object c)
  198. {
  199. Lisp_Object nil = C_nil;
  200. Lisp_Object pl;
  201. int n;
  202. if (!symbolp(a)) return c;
  203. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  204. { pl = qfastgets(a);
  205. if (pl == nil)
  206. { push3(a, b, c);
  207. pl = getvector_init(4*fastget_size+4, SPID_NOPROP);
  208. pop3(c, b, a);
  209. errexit();
  210. qfastgets(a) = pl;
  211. }
  212. elt(pl, n-1) = c;
  213. return c; /* NB the property is NOT on the plist */
  214. }
  215. pl = qplist(a);
  216. while (pl != nil)
  217. { Lisp_Object w = qcar(pl);
  218. if (qcar(w) == b)
  219. { qcdr(w) = c;
  220. return c;
  221. }
  222. else pl = qcdr(pl);
  223. }
  224. stackcheck3(0, a, b, c);
  225. nil = C_nil;
  226. push2(a, c);
  227. b = acons(b, c, qplist(a));
  228. pop2(c, a);
  229. errexit();
  230. qplist(a) = b;
  231. return c;
  232. }
  233. static Lisp_Object remprop(Lisp_Object a, Lisp_Object b)
  234. {
  235. Lisp_Object pl, prevp;
  236. Lisp_Object nil = C_nil;
  237. int n;
  238. if (!symbolp(a)) return nil;
  239. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  240. { pl = qfastgets(a);
  241. if (pl != nil) elt(pl, n-1) = SPID_NOPROP;
  242. return nil;
  243. }
  244. prevp = nil;
  245. pl = qplist(a);
  246. while (pl != nil)
  247. { Lisp_Object w = qcar(pl);
  248. if (qcar(w) == b)
  249. { pl = qcdr(pl);
  250. if (prevp == nil) qplist(a) = pl;
  251. else qcdr(prevp) = pl;
  252. return qcdr(w);
  253. }
  254. prevp = pl;
  255. pl = qcdr(prevp);
  256. }
  257. return nil;
  258. }
  259. #else /* in a COMMON world I have to use flat plists */
  260. Lisp_Object get(Lisp_Object a, Lisp_Object b, Lisp_Object c)
  261. {
  262. Lisp_Object nil = C_nil;
  263. Lisp_Object pl;
  264. int n;
  265. if (!symbolp(a))
  266. {
  267. #ifdef RECORD_GET
  268. record_get(b, NO);
  269. errexit();
  270. #endif
  271. return c;
  272. }
  273. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  274. { if ((pl = qfastgets(a)) == nil)
  275. {
  276. #ifdef RECORD_GET
  277. push(c);
  278. record_get(b, NO);
  279. pop(c);
  280. errexit();
  281. #endif
  282. return onevalue(c);
  283. }
  284. pl = elt(pl, n-1);
  285. if (pl == SPID_NOPROP)
  286. {
  287. #ifdef RECORD_GET
  288. push(c);
  289. record_get(b, NO);
  290. pop(c);
  291. errexit();
  292. #endif
  293. return onevalue(c);
  294. }
  295. #ifdef RECORD_GET
  296. push(pl);
  297. record_get(b, YES);
  298. pop(pl);
  299. errexit();
  300. #endif
  301. return onevalue(pl);
  302. }
  303. pl = qplist(a);
  304. while (pl != nil)
  305. { if (qcar(pl) == b)
  306. {
  307. #ifdef RECORD_GET
  308. push(pl);
  309. record_get(b, YES);
  310. pop(pl);
  311. errexit();
  312. #endif
  313. return qcar(qcdr(pl));
  314. }
  315. else pl = qcdr(qcdr(pl));
  316. }
  317. #ifdef RECORD_GET
  318. record_get(b, NO);
  319. errexit();
  320. #endif
  321. return c;
  322. }
  323. Lisp_Object putprop(Lisp_Object a, Lisp_Object b, Lisp_Object c)
  324. {
  325. Lisp_Object nil = C_nil;
  326. Lisp_Object pl;
  327. int n;
  328. if (!symbolp(a)) return c;
  329. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  330. { pl = qfastgets(a);
  331. if (pl == nil)
  332. { push3(a, b, c);
  333. pl = getvector_init(4*fastget_size+4, SPID_NOPROP);
  334. pop3(c, b, a);
  335. errexit();
  336. qfastgets(a) = pl;
  337. }
  338. elt(pl, n-1) = c;
  339. return c; /* NB the property is NOT on the plist */
  340. }
  341. pl = qplist(a);
  342. while (pl != nil)
  343. { if (qcar(pl) == b)
  344. { pl = qcdr(pl);
  345. qcar(pl) = c;
  346. return c;
  347. }
  348. else pl = qcdr(qcdr(pl));
  349. }
  350. stackcheck3(0, a, b, c);
  351. nil = C_nil;
  352. push2(a, c);
  353. b = list2star(b, c, qplist(a));
  354. pop2(c, a);
  355. errexit();
  356. qplist(a) = b;
  357. return c;
  358. }
  359. static Lisp_Object remprop(Lisp_Object a, Lisp_Object b)
  360. {
  361. Lisp_Object nil = C_nil;
  362. Lisp_Object pl, prevp = nil;
  363. int n;
  364. if (!symbolp(a)) return nil;
  365. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  366. { pl = qfastgets(a);
  367. if (pl != nil) elt(pl, n-1) = SPID_NOPROP;
  368. return nil;
  369. }
  370. pl = qplist(a);
  371. while (pl != nil)
  372. { if (qcar(pl) == b)
  373. { Lisp_Object v = qcdr(pl);
  374. pl = qcdr(v);
  375. if (prevp == nil) qplist(a) = pl;
  376. else qcdr(prevp) = pl;
  377. return lisp_true;
  378. }
  379. prevp = qcdr(pl);
  380. pl = qcdr(prevp);
  381. }
  382. return nil;
  383. }
  384. #endif /* end of property list stuff */
  385. #ifndef COMMON
  386. Lisp_Object Lget(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  387. {
  388. Lisp_Object pl, prev, w;
  389. int n;
  390. /*
  391. * In CSL mode plists are structured like association lists, and
  392. * NOT as lists with alternate tags and values. There is also
  393. * a bitmap that can provide a fast test for the presence of a
  394. * property...
  395. */
  396. if (!symbolp(a))
  397. {
  398. #ifdef RECORD_GET
  399. record_get(b, NO);
  400. errexit();
  401. #endif
  402. return onevalue(nil);
  403. }
  404. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  405. { if ((w = qfastgets(a)) == nil)
  406. {
  407. #ifdef RECORD_GET
  408. record_get(b, NO);
  409. errexit();
  410. #endif
  411. return onevalue(nil);
  412. }
  413. w = elt(w, n-1);
  414. if (w == SPID_NOPROP) w = nil;
  415. #ifdef RECORD_GET
  416. push(w);
  417. record_get(b, w != nil);
  418. pop(w);
  419. errexit();
  420. #endif
  421. return onevalue(w);
  422. }
  423. pl = qplist(a);
  424. if (pl == nil)
  425. {
  426. #ifdef RECORD_GET
  427. record_get(b, NO);
  428. errexit();
  429. #endif
  430. return onevalue(nil);
  431. }
  432. w = qcar(pl);
  433. if (qcar(w) == b)
  434. {
  435. #ifdef RECORD_GET
  436. push(w);
  437. record_get(b, YES);
  438. pop(w);
  439. errexit();
  440. #endif
  441. return onevalue(qcdr(w));
  442. }
  443. pl = qcdr(pl);
  444. if (pl == nil)
  445. {
  446. #ifdef RECORD_GET
  447. record_get(b, NO);
  448. errexit();
  449. #endif
  450. return onevalue(nil);
  451. }
  452. w = qcar(pl);
  453. if (qcar(w) == b)
  454. {
  455. #ifdef RECORD_GET
  456. push(w);
  457. record_get(b, YES);
  458. pop(w);
  459. errexit();
  460. #endif
  461. return onevalue(qcdr(w));
  462. }
  463. prev = pl;
  464. pl = qcdr(pl);
  465. if (pl == nil)
  466. {
  467. #ifdef RECORD_GET
  468. record_get(b, NO);
  469. errexit();
  470. #endif
  471. return onevalue(nil);
  472. }
  473. while (YES)
  474. { w = qcar(pl);
  475. /*
  476. * If I find the item anywhere beyond the first two places in the plist I
  477. * migrate it up to the front so that next time will be faster
  478. */
  479. if (qcar(w) == b)
  480. { qcdr(prev) = qcdr(pl);
  481. qcdr(pl) = qplist(a);
  482. qplist(a) = pl;
  483. #ifdef RECORD_GET
  484. push(w);
  485. record_get(b, YES);
  486. pop(w);
  487. errexit();
  488. #endif
  489. return onevalue(qcdr(w));
  490. }
  491. prev = pl;
  492. pl = qcdr(pl);
  493. if (pl == nil)
  494. {
  495. #ifdef RECORD_GET
  496. record_get(b, NO);
  497. errexit();
  498. #endif
  499. return onevalue(nil);
  500. }
  501. }
  502. }
  503. #else
  504. Lisp_Object MS_CDECL Lget_3(Lisp_Object nil, int nargs, ...)
  505. {
  506. va_list aa;
  507. Lisp_Object a, b, c;
  508. CSL_IGNORE(nil);
  509. if (nargs != 3) return aerror("get");
  510. va_start(aa, nargs);
  511. a = va_arg(aa, Lisp_Object);
  512. b = va_arg(aa, Lisp_Object);
  513. c = va_arg(aa, Lisp_Object);
  514. va_end(aa);
  515. return onevalue(get(a, b, c));
  516. }
  517. Lisp_Object Lget(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  518. {
  519. return onevalue(get(a, b, nil));
  520. }
  521. #endif
  522. Lisp_Object MS_CDECL Lputprop(Lisp_Object nil, int nargs, ...)
  523. {
  524. va_list aa;
  525. Lisp_Object a, b, c;
  526. argcheck(nargs, 3, "put");
  527. CSL_IGNORE(nil);
  528. va_start(aa, nargs);
  529. a = va_arg(aa, Lisp_Object);
  530. b = va_arg(aa, Lisp_Object);
  531. c = va_arg(aa, Lisp_Object);
  532. va_end(aa);
  533. a = putprop(a, b, c);
  534. errexit();
  535. return onevalue(a);
  536. }
  537. #ifdef COMMON
  538. Lisp_Object Lflagp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  539. {
  540. a = get(a, b, unset_var);
  541. errexit();
  542. return onevalue(a == unset_var ? nil : lisp_true);
  543. }
  544. Lisp_Object Lflagpcar(Lisp_Object nil,
  545. Lisp_Object a, Lisp_Object b)
  546. {
  547. /* Fairly heavily used by Reduce test file - hence in here */
  548. if (!consp(a)) return onevalue(nil);
  549. a = qcar(a);
  550. a = get(a, b, unset_var);
  551. errexit();
  552. return onevalue(a == unset_var ? nil : lisp_true);
  553. }
  554. Lisp_Object Lflag(Lisp_Object nil,
  555. Lisp_Object a, Lisp_Object b)
  556. {
  557. while (consp(a))
  558. { Lisp_Object v = qcar(a);
  559. a = qcdr(a);
  560. if (!symbolp(v)) continue;
  561. push2(a, b);
  562. putprop(v, b, lisp_true);
  563. pop2(b, a);
  564. errexit();
  565. }
  566. return onevalue(nil);
  567. }
  568. Lisp_Object Lremflag(Lisp_Object nil,
  569. Lisp_Object a, Lisp_Object b)
  570. {
  571. while (consp(a))
  572. { Lisp_Object v = qcar(a);
  573. a = qcdr(a);
  574. if (!symbolp(v)) continue;
  575. push2(a, b);
  576. remprop(v, b);
  577. pop2(b, a);
  578. errexit();
  579. }
  580. return onevalue(nil);
  581. }
  582. #else
  583. Lisp_Object Lflagp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  584. {
  585. Lisp_Object pl, prev, w;
  586. int n;
  587. if (!symbolp(a))
  588. {
  589. #ifdef RECORD_GET
  590. record_get(b, NO);
  591. errexit();
  592. #endif
  593. return onevalue(nil);
  594. }
  595. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  596. { if ((w = qfastgets(a)) == nil)
  597. {
  598. #ifdef RECORD_GET
  599. record_get(b, NO);
  600. errexit();
  601. #endif
  602. return onevalue(nil);
  603. }
  604. w = elt(w, n-1);
  605. if (w == SPID_NOPROP)
  606. {
  607. #ifdef RECORD_GET
  608. record_get(b, NO);
  609. errexit();
  610. #endif
  611. return onevalue(nil);
  612. }
  613. #ifdef RECORD_GET
  614. record_get(b, YES);
  615. errexit();
  616. #endif
  617. return onevalue(lisp_true);
  618. }
  619. pl = qplist(a);
  620. if (pl == nil)
  621. {
  622. #ifdef RECORD_GET
  623. record_get(b, NO);
  624. errexit();
  625. #endif
  626. return onevalue(nil);
  627. }
  628. w = qcar(pl);
  629. if (qcar(w) == b)
  630. {
  631. #ifdef RECORD_GET
  632. record_get(b, YES);
  633. errexit();
  634. #endif
  635. return onevalue(lisp_true);
  636. }
  637. pl = qcdr(pl);
  638. if (pl == nil)
  639. {
  640. #ifdef RECORD_GET
  641. record_get(b, NO);
  642. errexit();
  643. #endif
  644. return onevalue(nil);
  645. }
  646. w = qcar(pl);
  647. if (qcar(w) == b)
  648. {
  649. #ifdef RECORD_GET
  650. record_get(b, YES);
  651. errexit();
  652. #endif
  653. return onevalue(lisp_true);
  654. }
  655. prev = pl;
  656. pl = qcdr(pl);
  657. if (pl == nil)
  658. {
  659. #ifdef RECORD_GET
  660. record_get(b, NO);
  661. errexit();
  662. #endif
  663. return onevalue(nil);
  664. }
  665. while (YES)
  666. { w = qcar(pl);
  667. /*
  668. * If I find the item anywhere beyond the first two places in the plist I
  669. * migrate it up to the front so that next time will be faster
  670. */
  671. if (qcar(w) == b)
  672. { qcdr(prev) = qcdr(pl);
  673. qcdr(pl) = qplist(a);
  674. qplist(a) = pl;
  675. #ifdef RECORD_GET
  676. record_get(b, YES);
  677. errexit();
  678. #endif
  679. return onevalue(lisp_true);
  680. }
  681. prev = pl;
  682. pl = qcdr(pl);
  683. if (pl == nil)
  684. {
  685. #ifdef RECORD_GET
  686. record_get(b, NO);
  687. errexit();
  688. #endif
  689. return onevalue(nil);
  690. }
  691. }
  692. }
  693. Lisp_Object Lflagpcar(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  694. {
  695. Lisp_Object pl, prev, w;
  696. int n;
  697. /* Fairly heavily used by Reduce test file - hence in here */
  698. if (a != nil)
  699. { if (!consp(a))
  700. {
  701. #ifdef RECORD_GET
  702. record_get(b, NO);
  703. errexit();
  704. #endif
  705. return onevalue(nil);
  706. }
  707. a = qcar(a);
  708. if (!symbolp(a))
  709. {
  710. #ifdef RECORD_GET
  711. record_get(b, NO);
  712. errexit();
  713. #endif
  714. return onevalue(nil);
  715. }
  716. }
  717. if (symbolp(b) && (n = header_fastget(qheader(b))) != 0)
  718. { if ((w = qfastgets(a)) == nil)
  719. {
  720. #ifdef RECORD_GET
  721. record_get(b, NO);
  722. errexit();
  723. #endif
  724. return onevalue(nil);
  725. }
  726. w = elt(w, n-1);
  727. if (w == SPID_NOPROP)
  728. {
  729. #ifdef RECORD_GET
  730. record_get(b, NO);
  731. errexit();
  732. #endif
  733. return onevalue(nil);
  734. }
  735. #ifdef RECORD_GET
  736. record_get(b, YES);
  737. errexit();
  738. #endif
  739. return onevalue(lisp_true);
  740. }
  741. pl = qplist(a);
  742. if (pl == nil)
  743. {
  744. #ifdef RECORD_GET
  745. record_get(b, NO);
  746. errexit();
  747. #endif
  748. return onevalue(nil);
  749. }
  750. w = qcar(pl);
  751. if (qcar(w) == b)
  752. {
  753. #ifdef RECORD_GET
  754. record_get(b, YES);
  755. errexit();
  756. #endif
  757. return onevalue(lisp_true);
  758. }
  759. pl = qcdr(pl);
  760. if (pl == nil)
  761. {
  762. #ifdef RECORD_GET
  763. record_get(b, NO);
  764. errexit();
  765. #endif
  766. return onevalue(nil);
  767. }
  768. w = qcar(pl);
  769. if (qcar(w) == b)
  770. {
  771. #ifdef RECORD_GET
  772. record_get(b, YES);
  773. errexit();
  774. #endif
  775. return onevalue(lisp_true);
  776. }
  777. prev = pl;
  778. pl = qcdr(pl);
  779. if (pl == nil)
  780. {
  781. #ifdef RECORD_GET
  782. record_get(b, NO);
  783. errexit();
  784. #endif
  785. return onevalue(nil);
  786. }
  787. while (YES)
  788. { w = qcar(pl);
  789. /*
  790. * If I find the item anywhere beyond the first two places in the plist I
  791. * migrate it up to the front so that next time will be faster
  792. */
  793. if (qcar(w) == b)
  794. { qcdr(prev) = qcdr(pl);
  795. qcdr(pl) = qplist(a);
  796. qplist(a) = pl;
  797. #ifdef RECORD_GET
  798. record_get(b, YES);
  799. errexit();
  800. #endif
  801. return onevalue(lisp_true);
  802. }
  803. prev = pl;
  804. pl = qcdr(pl);
  805. if (pl == nil)
  806. {
  807. #ifdef RECORD_GET
  808. record_get(b, NO);
  809. errexit();
  810. #endif
  811. return onevalue(nil);
  812. }
  813. }
  814. }
  815. Lisp_Object Lflag(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  816. {
  817. int n = 0;
  818. if (symbolp(b)) n = header_fastget(qheader(b));
  819. while (consp(a))
  820. { Lisp_Object v = qcar(a), pl;
  821. a = qcdr(a);
  822. if (!symbolp(v)) continue;
  823. /*
  824. * I store FLAGS just as if they were PROPERTIES that have the value
  825. * T, so after (flag '(a b c) 'd) if anybody goes (get 'a 'd) they get back
  826. * the value T.
  827. */
  828. if (n)
  829. { pl = qfastgets(v);
  830. if (pl == nil)
  831. { push2(v, b);
  832. pl = getvector_init(4*fastget_size+4, SPID_NOPROP);
  833. pop2(b, v);
  834. errexit();
  835. qfastgets(v) = pl;
  836. }
  837. elt(pl, n-1) = lisp_true;
  838. continue;
  839. }
  840. push2(a, b);
  841. pl = qplist(v);
  842. while (pl != nil)
  843. { Lisp_Object w = qcar(pl);
  844. if (qcar(w) == b)
  845. { qcdr(w) = lisp_true;
  846. goto already_flagged;
  847. }
  848. else pl = qcdr(pl);
  849. }
  850. push(v);
  851. b = acons(b, lisp_true, qplist(v));
  852. errexitn(3);
  853. pop(v);
  854. qplist(v) = b;
  855. already_flagged:
  856. pop2(b, a);
  857. }
  858. return onevalue(nil);
  859. }
  860. Lisp_Object Lremflag(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  861. {
  862. int n = 0;
  863. if (symbolp(b)) n = header_fastget(qheader(b));
  864. while (consp(a))
  865. { Lisp_Object pl, prevp, v = qcar(a);
  866. a = qcdr(a);
  867. if (!symbolp(v)) continue;
  868. if (n)
  869. { pl = qfastgets(v);
  870. if (pl != nil) elt(pl, n-1) = SPID_NOPROP;
  871. continue;
  872. }
  873. prevp = nil;
  874. pl = qplist(v);
  875. while (pl != nil)
  876. { Lisp_Object w = qcar(pl);
  877. if (qcar(w) == b)
  878. { pl = qcdr(pl);
  879. if (prevp == nil) qplist(v) = pl;
  880. else qcdr(prevp) = pl;
  881. break;
  882. }
  883. prevp = pl;
  884. pl = qcdr(prevp);
  885. }
  886. }
  887. return onevalue(nil);
  888. }
  889. #endif
  890. Lisp_Object Lremprop(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  891. {
  892. CSL_IGNORE(nil);
  893. return onevalue(remprop(a, b));
  894. }
  895. Lisp_Object Lplist(Lisp_Object nil, Lisp_Object a)
  896. {
  897. Lisp_Object r;
  898. int i;
  899. CSL_IGNORE(nil);
  900. if (!symbolp(a)) return aerror1("plist", a);
  901. r = qplist(a);
  902. a = qfastgets(a);
  903. if (a == nil) return onevalue(r);
  904. for (i=0; i<fastget_size; i++)
  905. { Lisp_Object w = elt(a, i);
  906. if (w != SPID_NOPROP)
  907. { push(a);
  908. #ifdef COMMON
  909. r = list2star(elt(fastget_names, i), w, r);
  910. #else
  911. r = acons(elt(fastget_names, i), w, r);
  912. #endif
  913. pop(a);
  914. errexit();
  915. }
  916. }
  917. return onevalue(r);
  918. }
  919. #ifndef NO_BYTECOUNT
  920. /*
  921. * Unless NO_BYTECOUNT is set I keep two sorts of counts - first
  922. * ones that show how many bytecodes are executed in each separate
  923. * piece of code that the user runs. These can be inspected by
  924. * calling MAPSTORE. Then ones that show (overall) which particular
  925. * byte opcodes are most heavily used. This information is displayed
  926. * when you call BYTECOUNTS.
  927. */
  928. #ifndef DEMO_MODE
  929. #include "opnames.c"
  930. #endif
  931. static int32 total = 0, frequencies[256];
  932. #endif
  933. Lisp_Object MS_CDECL bytecounts(Lisp_Object nil, int nargs, ...)
  934. {
  935. int32 i;
  936. #ifdef RECORD_GET
  937. int32 size;
  938. Lisp_Object v;
  939. double tot;
  940. #endif
  941. argcheck(nargs, 0, "bytecounts");
  942. #ifdef NO_BYTECOUNT
  943. i = 0;
  944. trace_printf("bytecode statistics not available\n");
  945. #else
  946. #ifdef DEMO_MODE
  947. i = 0;
  948. trace_printf("bytecode statistics not available in demo version\n");
  949. #else
  950. trace_printf("\nFrequencies of each bytecode (%ld total)", total);
  951. if (total == 0) total = 1;
  952. for (i=0; i<256; i++)
  953. { if ((i & 3) == 0) trace_printf("\n");
  954. trace_printf("%-9.9s%7.4f ",
  955. opnames[i],
  956. 100.0*(double)frequencies[i]/(double)total);
  957. }
  958. trace_printf("\n");
  959. #endif
  960. #endif
  961. #ifdef RECORD_GET
  962. v = elt(get_counts, 4);
  963. if (v == nil) return onevalue(nil);
  964. size = length_of_header(vechdr(v));
  965. size = (size - 4) >>2;
  966. term_printf("\n %%SCORE TOTAL NOTFOUND INDICATOR-NAME\n");
  967. tot = 0.0;
  968. for (i=1; i<size; i+=2)
  969. { Lisp_Object key = elt(v, i), val = elt(v, i+1);
  970. int32 yes, no;
  971. if (key == SPID_HASH0 || key == SPID_HASH1) continue;
  972. yes = no = 0;
  973. if (consp(val)) yes = int_of_fixnum(qcar(val)),
  974. no = int_of_fixnum(qcdr(val));
  975. tot += (double)(yes+2*no);
  976. }
  977. tot /= 100.0;
  978. for (i=1; i<size; i+=2)
  979. { Lisp_Object key = elt(v, i), val = elt(v, i+1);
  980. int32 yes, no;
  981. if (key == SPID_HASH0 || key == SPID_HASH1) continue;
  982. yes = no = 0;
  983. if (consp(val)) yes = int_of_fixnum(qcar(val)),
  984. no = int_of_fixnum(qcdr(val));
  985. trace_printf("%7.2f %10d %10d ", (double)(yes+2*no)/tot, yes+no, no);
  986. errexit();
  987. loop_print_trace(key);
  988. trace_printf("\n");
  989. }
  990. v = Lmkhash(nil, 3, fixnum_of_int(5), fixnum_of_int(0), nil);
  991. errexit();
  992. get_counts = v;
  993. #endif
  994. return onevalue(nil);
  995. }
  996. #ifdef __CC_NORCROFT
  997. /*
  998. * I want to write all the code out in-line to save time
  999. * even at the cost of using extra space, so I disable crossjump
  1000. * optimisation here. It is quite probable that other C compilers
  1001. * support similar control over optimisation strategy, and since the
  1002. * code in this file is performance critical it may be worth trying
  1003. * out various possibilities.
  1004. */
  1005. # pragma no_optimise_crossjump
  1006. #endif
  1007. Lisp_Object *C_stack;
  1008. /*
  1009. * Throughout most of the system I use the name "stack" as a synonym for
  1010. * the external variable "C_stack", but in the main byte-code interpreter
  1011. * loop I disable that mapping and use a register variable as stack
  1012. * pointer, updating the extern value from time to time as necessary.
  1013. */
  1014. #undef stack
  1015. static int errcode;
  1016. static Lisp_Object *do_freebind(Lisp_Object bvec, Lisp_Object *stack)
  1017. {
  1018. int32 n, k;
  1019. n = length_of_header(vechdr(bvec));
  1020. for (k=4; k<n; k+=4)
  1021. { Lisp_Object v = *(Lisp_Object *)((int32)bvec + k - TAG_VECTOR);
  1022. push(qvalue(v));
  1023. qvalue(v) = C_nil;
  1024. }
  1025. /*
  1026. * TAG_FBIND is a value that can NEVER occur elsewhere in the Lisp system,
  1027. * and so it unambiguously marks a block of fluid bindings on that stack.
  1028. */
  1029. push2(bvec, (Lisp_Object)SPID_FBIND);
  1030. return stack;
  1031. }
  1032. static Lisp_Object *do_freerstr(Lisp_Object *stack)
  1033. {
  1034. Lisp_Object bv;
  1035. int32 n;
  1036. popv(1);
  1037. pop(bv);
  1038. n = length_of_header(vechdr(bv));
  1039. while (n>4)
  1040. { Lisp_Object v = *(Lisp_Object *)((int32)bv + n - (4 + TAG_VECTOR));
  1041. n -= 4;
  1042. pop(qvalue(v));
  1043. }
  1044. return stack;
  1045. }
  1046. /*
  1047. * If OUT_OF_LINE is defined than various fragments of code are written
  1048. * as subroutines called from the main body of bytestream_interpret.
  1049. * This may hurt speed a little, but reduces the size of the one huge
  1050. * function in this file, and may be useful either when memory is at
  1051. * a huge premium (ugh) or [more plausibly] when C compilers get very
  1052. * unhappy with the bulk of the code when all written out in place.
  1053. * The default case I leave (with OUT_OF_LINE undefined) is the one that
  1054. * prefers a few percent speed-up to a fraction of a percent space
  1055. * saving.
  1056. */
  1057. #ifdef OUT_OF_LINE
  1058. static Lisp_Object poll_jump_back(Lisp_Object *stack, Lisp_Object A_reg)
  1059. {
  1060. Lisp_Object nil = C_nil;
  1061. #ifdef SOFTWARE_TICKS
  1062. if (--countdown < 0) deal_with_tick();
  1063. #endif
  1064. C_stack = stack;
  1065. if (stack >= stacklimit)
  1066. { A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  1067. nil = C_nil;
  1068. if (exception_pending()) return SPID_ERROR;
  1069. }
  1070. return A_reg;
  1071. }
  1072. #endif
  1073. #ifdef COMMON
  1074. static Lisp_Object *do_pvbind(Lisp_Object vals, Lisp_Object vars,
  1075. Lisp_Object *stack)
  1076. {
  1077. Lisp_Object val, var, nil = C_nil;
  1078. push4(nil, SPID_PVBIND, vars, vals);
  1079. while (consp(vars))
  1080. { var = qcar(vars);
  1081. vars = qcdr(vars);
  1082. if (!symbolp(var) || var == nil) continue;
  1083. push(vars);
  1084. C_stack = stack;
  1085. var = acons(var, qvalue(var), stack[-4]);
  1086. stack = C_stack;
  1087. nil = C_nil;
  1088. if (exception_pending()) { popv(2); return stack; }
  1089. stack[-4] = var;
  1090. pop(vars);
  1091. }
  1092. pop2(vals, vars);
  1093. while (consp(vars))
  1094. { if (consp(vals)) val = qcar(vals), vals = qcdr(vals);
  1095. else val = unset_var;
  1096. var = qcar(vars);
  1097. if (symbolp(var) && var != nil) qvalue(var) = val;
  1098. vars = qcdr(vars);
  1099. }
  1100. return stack;
  1101. }
  1102. static Lisp_Object *do_pvrestore(Lisp_Object *stack)
  1103. {
  1104. Lisp_Object w, nil = C_nil;
  1105. popv(1);
  1106. pop(w);
  1107. while (w != nil)
  1108. { Lisp_Object q = qcar(w);
  1109. qvalue(qcar(q)) = qcdr(q);
  1110. w = qcdr(w);
  1111. }
  1112. return stack;
  1113. }
  1114. #endif
  1115. static Lisp_Object encapsulate_sp(Lisp_Object *sp)
  1116. /*
  1117. * Creates a boxed up representation of a pointer into the stack.
  1118. */
  1119. { Lisp_Object w = getvector(TAG_VECTOR, TYPE_SP, 8);
  1120. Lisp_Object nil;
  1121. errexit();
  1122. elt(w, 0) = (Lisp_Object)sp;
  1123. return w;
  1124. }
  1125. static void trace_print_0(Lisp_Object name, Lisp_Object *stack)
  1126. {
  1127. freshline_trace();
  1128. trace_printf("Tail calling ");
  1129. loop_print_trace(name);
  1130. trace_printf(" (no args) from ");
  1131. loop_print_trace(*stack);
  1132. trace_printf("\n");
  1133. }
  1134. static void trace_print_1(Lisp_Object name, Lisp_Object *stack)
  1135. {
  1136. freshline_trace();
  1137. trace_printf("Tail calling ");
  1138. loop_print_trace(name);
  1139. trace_printf(" (1 arg) from ");
  1140. loop_print_trace(*stack);
  1141. trace_printf("\n");
  1142. trace_printf("Arg1: ");
  1143. loop_print_trace(stack[-3]);
  1144. trace_printf("\n");
  1145. }
  1146. static void trace_print_2(Lisp_Object name, Lisp_Object *stack)
  1147. {
  1148. freshline_trace();
  1149. trace_printf("Tail calling ");
  1150. loop_print_trace(name);
  1151. trace_printf(" (2 args) from ");
  1152. loop_print_trace(*stack);
  1153. trace_printf("\n");
  1154. trace_printf("Arg1: "); loop_print_trace(stack[-4]);
  1155. trace_printf("\nArg2: "); loop_print_trace(stack[-3]);
  1156. trace_printf("\n");
  1157. }
  1158. static void trace_print_3(Lisp_Object name, Lisp_Object *stack)
  1159. {
  1160. freshline_trace();
  1161. trace_printf("Tail calling ");
  1162. loop_print_trace(name);
  1163. trace_printf(" (3 args) from ");
  1164. loop_print_trace(*stack);
  1165. trace_printf("\n");
  1166. trace_printf("Arg1: "); loop_print_trace(stack[-5]);
  1167. trace_printf("\nArg2: "); loop_print_trace(stack[-4]);
  1168. trace_printf("\nArg3: "); loop_print_trace(stack[-3]);
  1169. trace_printf("\n");
  1170. }
  1171. #define save_pc() pc = (unsigned int)(ppc - \
  1172. (unsigned char *)data_of_bps(codevec))
  1173. #define restore_pc() ppc = (unsigned char *)data_of_bps(codevec) + pc
  1174. #ifdef MEMORY_TRACE
  1175. #define next_byte (cmemory_reference((int32)ppc), *ppc++)
  1176. #else
  1177. #define next_byte *ppc++
  1178. #endif
  1179. #ifdef __powerc
  1180. /* If you have trouble compiling this just comment it out, please */
  1181. #pragma options(!global_optimizer)
  1182. #endif
  1183. Lisp_Object bytestream_interpret(Lisp_Object code, Lisp_Object lit,
  1184. Lisp_Object *entry_stack)
  1185. {
  1186. register unsigned char *ppc;
  1187. register Lisp_Object A_reg;
  1188. Lisp_Object nil = C_nil;
  1189. Lisp_Object *stack = C_stack;
  1190. /*
  1191. * The variables above this line are by a significant margin the
  1192. * most important ones for this code. It may be useful to use
  1193. * 'register' declarations even with good optimising compilers, since
  1194. * the structure of a bytestream interpreter can draw too much attention to
  1195. * individual cases and not enough to the full outer loop. Here the most
  1196. * common paths are the "switch (*ppc++)" and various of the very short
  1197. * and simple opcodes that are dispatched to.
  1198. */
  1199. Lisp_Object r1, r2, r3;
  1200. one_args *f1;
  1201. two_args *f2;
  1202. n_args *f345;
  1203. unsigned int fname, pc, w;
  1204. int32 n, k;
  1205. unsigned char *xppc;
  1206. /*
  1207. * I declare all the other variables I need here up at the top of the function
  1208. * since at least on some C compilers putting the declarations more locally
  1209. * seems to be unexpectedly costly. In some cases moving the stack pointer
  1210. * may be a pain, in others code like
  1211. * { int x; ...} { int x; ... } { int x; ... }
  1212. * end up allocating three stack locations (one for each instance of x) and
  1213. * hence makes this function overall have much to big a stack frame.
  1214. */
  1215. #ifndef NO_BYTECOUNT
  1216. int32 opcodes = 30; /* Attribute 30-bytecode overhead to entry sequence */
  1217. #endif
  1218. #ifdef DEBUG
  1219. /*
  1220. * ffname will (at least until a garbage collection occurs) point to the
  1221. * (C) string that is the name of the function being interpreted. This is
  1222. * jolly useful if one is in a debugger trying to understand what has
  1223. * been going on!
  1224. */
  1225. char *ffname = &celt(qpname(elt(lit, 0)), 0); /* DEBUG */
  1226. CSL_IGNORE(ffname);
  1227. #endif
  1228. /*
  1229. * The byte-stream interpreter here uses the lisp stack and two
  1230. * special registers, called A, and B which act as a mini stack.
  1231. */
  1232. #ifdef STACK_CHECK
  1233. if (check_stack(__FILE__,__LINE__)) return aerror("stack overflow");
  1234. #endif
  1235. litvec = lit;
  1236. /*
  1237. * The next lines are used to allow for functions with > 3 args, and for
  1238. * &optional and &rest cases. Some of these need one or two bytes at the
  1239. * start of the code-vector to indicate just how many arguments are
  1240. * expected. In such cases the byte program-counter must start off
  1241. * positioned just beyond these extra bytes. The way that a code pointer
  1242. * is packed in CSL means that for garbage collection a code-pointer is
  1243. * stored with bottom 4 bits '0010', and it can address to a resolution of
  1244. * one word (4 bytes). However, the actual argument passed into this code
  1245. * does not have to be garbage-collector safe until there is the first
  1246. * chance of a garbage collection, and I exploit that to allow for 0, 1
  1247. * 2 or 3 initial information bytes. The ((code & ~3) + 2) restores
  1248. * proper tagging, and (code & 3) holds an offset.
  1249. */
  1250. ppc = (unsigned char *)data_of_bps(code);
  1251. ppc = ppc + ((int32)code & 3);
  1252. codevec = (Lisp_Object)(((int32)code & ~3) + 2);
  1253. /*
  1254. * I am careful to reload stack from C_stack after any
  1255. * function call, to allow that the garbage collector may relocate the
  1256. * whole stack region. But at present I do not protect entry_stack in
  1257. * this way, so if the garbage collector moves my stack and subsequently
  1258. * I take an error exit I will get in a big mess. At present the garbage
  1259. * collector is not that enthusiastic, so the problem will not arise. If
  1260. * I was sure it NEVER would I could avoid a few cases of "stack = C_stack"
  1261. * here and speed things up by some utterly insignificant amount.
  1262. */
  1263. A_reg = nil;
  1264. for (;;)
  1265. {
  1266. #ifndef NO_BYTECOUNT
  1267. opcodes++;
  1268. total++;
  1269. frequencies[*ppc]++;
  1270. #endif
  1271. #ifdef __APOLLO__
  1272. /*
  1273. * On an Apollo a version of this code that just went switch (*++ppc) went
  1274. * amazingly slowly as a result of clumsy compilation when the value that was
  1275. * switched upon was a char not an int. The cast written here appears to
  1276. * work around the difficulty. Also the same compiler was made very unhappy
  1277. * by having regular labels inside the block just after "switch". I have moved
  1278. * all such labels to be outside the scope of the switch. Note that I have now
  1279. * altered the code to read "switch (*ppc++)", which may or may not make a
  1280. * difference.
  1281. */
  1282. switch ((unsigned int)next_byte)
  1283. #else
  1284. /*
  1285. * With at least some compilers (eg Watcom) if I cast the value obtained here
  1286. * to something other than unsigned char I get worse code, because the fact
  1287. * that the switch range is exactly 0-255 and my control value must be in that
  1288. * range gets lost.
  1289. */
  1290. switch (next_byte)
  1291. #endif
  1292. {
  1293. /*
  1294. * I give labels for all 256 possible cases here so that a sufficiently
  1295. * clever compiler can understand that there is no "default" that can possibly
  1296. * be activated.
  1297. */
  1298. case OP_SPARE1:
  1299. case OP_SPARE2:
  1300. default:
  1301. /*
  1302. * Here I have an unrecognised opcode - the result of a compiler error
  1303. */
  1304. err_printf("\nUnrecognized opcode byte %x\n", *(ppc-1));
  1305. aerror("compiler failure");
  1306. nil = C_nil;
  1307. C_stack = stack;
  1308. goto error_exit;
  1309. case OP_LOC0EXIT:
  1310. A_reg = stack[0];
  1311. #ifdef COMMON
  1312. /*
  1313. * At a load of places here I set exit_count to 1 so that if I then return
  1314. * it will be clear how many values are involved. As currently organized
  1315. * this FAILS to set the number of values in cases like
  1316. * (setq a (values 1 2 3))
  1317. * and
  1318. * (cond
  1319. * ((values 1 2 3)))
  1320. * where in each case the 3 values shown will be (improperly) preserved.
  1321. * I suspect that hardly anybody minds if too many values are occasionally
  1322. * returned, and so will NOT put the overhead of extra reference to
  1323. * exit_count after STORE instructions or conditional branches.
  1324. */
  1325. exit_count = 1;
  1326. #endif
  1327. #ifndef NO_BYTECOUNT
  1328. qcount(elt(litvec, 0)) += opcodes;
  1329. #endif
  1330. C_stack = entry_stack;
  1331. return A_reg;
  1332. case OP_LOC1EXIT:
  1333. A_reg = stack[-1];
  1334. #ifdef COMMON
  1335. exit_count = 1;
  1336. #endif
  1337. #ifndef NO_BYTECOUNT
  1338. qcount(elt(litvec, 0)) += opcodes;
  1339. #endif
  1340. C_stack = entry_stack;
  1341. return A_reg;
  1342. case OP_LOC2EXIT:
  1343. A_reg = stack[-2];
  1344. #ifdef COMMON
  1345. exit_count = 1;
  1346. #endif
  1347. #ifndef NO_BYTECOUNT
  1348. qcount(elt(litvec, 0)) += opcodes;
  1349. #endif
  1350. C_stack = entry_stack;
  1351. return A_reg;
  1352. case OP_NILEXIT:
  1353. #ifndef NO_BYTECOUNT
  1354. qcount(elt(litvec, 0)) += opcodes;
  1355. #endif
  1356. C_stack = entry_stack;
  1357. return onevalue(nil);
  1358. case OP_FREEBIND:
  1359. stack = do_freebind(elt(litvec, next_byte), stack);
  1360. continue;
  1361. case OP_FREERSTR:
  1362. stack = do_freerstr(stack);
  1363. continue;
  1364. #ifdef COMMON
  1365. case OP_PVBIND:
  1366. save_pc();
  1367. stack = do_pvbind(A_reg, B_reg, stack);
  1368. nil = C_nil;
  1369. if (exception_pending()) goto error_exit;
  1370. restore_pc();
  1371. continue;
  1372. case OP_PVRESTORE:
  1373. stack = do_pvrestore(stack);
  1374. continue;
  1375. #endif
  1376. case OP_STOREFREE:
  1377. qvalue(elt(litvec, next_byte)) = A_reg; /* store into special var */
  1378. continue;
  1379. case OP_STOREFREE1:
  1380. qvalue(elt(litvec, 1)) = A_reg;
  1381. continue;
  1382. case OP_STOREFREE2:
  1383. qvalue(elt(litvec, 2)) = A_reg;
  1384. continue;
  1385. case OP_STOREFREE3:
  1386. qvalue(elt(litvec, 3)) = A_reg;
  1387. continue;
  1388. case OP_PUSHNILS:
  1389. n = next_byte;
  1390. for (k=0; k<n; k++) push(nil);
  1391. continue;
  1392. case OP_VNIL:
  1393. B_reg = A_reg;
  1394. A_reg = nil;
  1395. #ifdef COMMON
  1396. exit_count = 1;
  1397. #endif
  1398. continue;
  1399. case OP_SWOP:
  1400. r1 = B_reg;
  1401. B_reg = A_reg;
  1402. A_reg = r1;
  1403. #ifdef COMMON
  1404. exit_count = 1;
  1405. #endif
  1406. continue;
  1407. #ifdef OP_LABEL
  1408. case OP_LABEL: /* Just useful to keep statistics straight */
  1409. continue;
  1410. #endif
  1411. case OP_NCONS: /* A_reg = cons(A_reg, nil); */
  1412. #ifndef OUT_OF_LINE
  1413. /* NB preserves B register */
  1414. r1 = (Lisp_Object)((char *)fringe - sizeof(Cons_Cell));
  1415. qcar(r1) = A_reg;
  1416. qcdr(r1) = nil;
  1417. fringe = r1;
  1418. if ((char *)r1 <= (char *)heaplimit)
  1419. { push(B_reg);
  1420. save_pc();
  1421. C_stack = stack;
  1422. A_reg = reclaim((Lisp_Object)((char *)r1 + TAG_CONS),
  1423. "bytecoded ncons", GC_CONS, 0);
  1424. nil = C_nil;
  1425. if (exception_pending()) goto error_exit;
  1426. stack = C_stack; /* may have been changed by GC */
  1427. restore_pc();
  1428. pop(B_reg);
  1429. }
  1430. else A_reg = (Lisp_Object)((char *)r1 + TAG_CONS);
  1431. #else
  1432. /*
  1433. * What this example shows is that IN_LINE is not always such a bad deal.
  1434. * Making everything safe across the potential garbage collection here
  1435. * is a big mess!
  1436. */
  1437. push(B_reg);
  1438. save_pc();
  1439. C_stack = stack;
  1440. A_reg = ncons(A_reg);
  1441. nil = C_nil;
  1442. if (exception_pending()) goto error_exit;
  1443. stack = C_stack; /* may have been changed by GC */
  1444. restore_pc();
  1445. pop(B_reg);
  1446. #endif
  1447. #ifdef COMMON
  1448. exit_count = 1;
  1449. #endif
  1450. continue;
  1451. case OP_XCONS: /* A_reg = cons(A_reg, B_reg); */
  1452. #ifndef OUT_OF_LINE
  1453. r1 = (Lisp_Object)((char *)fringe - sizeof(Cons_Cell));
  1454. qcar(r1) = A_reg;
  1455. qcdr(r1) = B_reg;
  1456. fringe = r1;
  1457. if ((char *)r1 <= (char *)heaplimit)
  1458. { save_pc();
  1459. C_stack = stack;
  1460. A_reg = reclaim((Lisp_Object)((char *)r1 + TAG_CONS),
  1461. "bytecoded xcons", GC_CONS, 0);
  1462. nil = C_nil;
  1463. if (exception_pending()) goto error_exit;
  1464. stack = C_stack; /* may have been changed by GC */
  1465. restore_pc();
  1466. }
  1467. else A_reg = (Lisp_Object)((char *)r1 + TAG_CONS);
  1468. #else
  1469. save_pc();
  1470. C_stack = stack;
  1471. A_reg = cons(A_reg, B_reg);
  1472. nil = C_nil;
  1473. if (exception_pending()) goto error_exit;
  1474. stack = C_stack; /* may have been changed by GC */
  1475. restore_pc();
  1476. #endif
  1477. #ifdef COMMON
  1478. exit_count = 1;
  1479. #endif
  1480. continue;
  1481. case OP_LIST2: /* A_reg = cons(B_reg, cons(A_reg, nil)); */
  1482. #ifndef OUT_OF_LINE
  1483. r1 = (Lisp_Object)((char *)fringe - 2*sizeof(Cons_Cell));
  1484. qcar(r1) = B_reg;
  1485. qcdr(r1) = (Lisp_Object)((char *)r1 +
  1486. sizeof(Cons_Cell) + TAG_CONS);
  1487. qcar((Lisp_Object)((char *)r1+sizeof(Cons_Cell))) = A_reg;
  1488. qcdr((Lisp_Object)((char *)r1+sizeof(Cons_Cell))) = nil;
  1489. fringe = r1;
  1490. if ((char *)r1 <= (char *)heaplimit)
  1491. { save_pc();
  1492. C_stack = stack;
  1493. A_reg = reclaim((Lisp_Object)((char *)r1 + TAG_CONS),
  1494. "bytecoded list2", GC_CONS, 0);
  1495. nil = C_nil;
  1496. if (exception_pending()) goto error_exit;
  1497. stack = C_stack;
  1498. restore_pc();
  1499. }
  1500. else A_reg = (Lisp_Object)((char *)r1 + TAG_CONS);
  1501. #else
  1502. save_pc();
  1503. C_stack = stack;
  1504. A_reg = list2(B_reg, A_reg);
  1505. nil = C_nil;
  1506. if (exception_pending()) goto error_exit;
  1507. stack = C_stack; /* may have been changed by GC */
  1508. restore_pc();
  1509. #endif
  1510. #ifdef COMMON
  1511. exit_count = 1;
  1512. #endif
  1513. continue;
  1514. case OP_ACONS: /* A_reg = acons(pop(), B_reg, A_reg); */
  1515. /* = (pop() . B) . A */
  1516. #ifndef OUT_OF_LINE
  1517. r1 = (Lisp_Object)((char *)fringe - 2*sizeof(Cons_Cell));
  1518. qcar(r1) = (Lisp_Object)((char *)r1 +
  1519. sizeof(Cons_Cell) + TAG_CONS);
  1520. qcdr(r1) = A_reg;
  1521. pop(qcar((Lisp_Object)((char *)r1+sizeof(Cons_Cell))));
  1522. qcdr((Lisp_Object)((char *)r1+sizeof(Cons_Cell))) = B_reg;
  1523. fringe = r1;
  1524. if ((char *)r1 <= (char *)heaplimit)
  1525. { save_pc();
  1526. C_stack = stack;
  1527. A_reg = reclaim((Lisp_Object)((char *)r1 + TAG_CONS),
  1528. "bytecoded acons", GC_CONS, 0);
  1529. nil = C_nil;
  1530. if (exception_pending()) goto error_exit;
  1531. stack = C_stack;
  1532. restore_pc();
  1533. }
  1534. else A_reg = (Lisp_Object)((char *)r1 + TAG_CONS);
  1535. #else
  1536. pop(r1);
  1537. save_pc();
  1538. C_stack = stack;
  1539. A_reg = acons(r1, B_reg, A_reg);
  1540. nil = C_nil;
  1541. if (exception_pending()) goto error_exit;
  1542. stack = C_stack; /* may have been changed by GC */
  1543. restore_pc();
  1544. #endif
  1545. #ifdef COMMON
  1546. exit_count = 1;
  1547. #endif
  1548. continue;
  1549. /*
  1550. * For the next two opcodes the first argument to the current function
  1551. * must have been an environment pointer as set up with CLOSURE.
  1552. */
  1553. case OP_LOADLEX:
  1554. r1 = elt(stack[1-(int)next_byte], 0);
  1555. B_reg = A_reg;
  1556. w = next_byte; /* Number of levels to chain */
  1557. while (w != 0) r1 = ((Lisp_Object *)r1)[1], w--;
  1558. A_reg = ((Lisp_Object *)r1)[next_byte];
  1559. #ifdef COMMON
  1560. exit_count = 1;
  1561. #endif
  1562. continue;
  1563. case OP_STORELEX:
  1564. r1 = elt(stack[1-(int)next_byte], 0);
  1565. w = next_byte; /* Number of levels to chain */
  1566. while (w != 0) r1 = ((Lisp_Object *)r1)[1], w--;
  1567. ((Lisp_Object *)r1)[next_byte] = A_reg;
  1568. continue;
  1569. case OP_CLOSURE:
  1570. push2(B_reg, A_reg);
  1571. /*
  1572. * This will be the address where the first arg of this function lives on
  1573. * the stack. It provides a hook for the called function to access lexical
  1574. * variables.
  1575. */
  1576. w = next_byte;
  1577. goto create_closure;
  1578. case OP_BIGSTACK: /* LOADLOC, STORELOC, CLOSURE etc */
  1579. /*
  1580. * This opcode allows me to support functions that use up to
  1581. * 2047-deep stack frames using LOADLEX and STORELEX, or
  1582. * up to 4095 deep if just using LOADLOC and STORELOC. I hope
  1583. * that such cases are very uncommon, but examples have been
  1584. * shown to me where my previous limit of 256-item frames was
  1585. * inadequate. The BIGSTACK opcode is followed by a byte that
  1586. * contains a few bits selecting which operation is to be
  1587. * performed, plus an extension to the address byte that follows.
  1588. */
  1589. w = next_byte; /* contains sub-opcode */
  1590. switch (w & 0xc0)
  1591. {
  1592. case 0x00: /* LOADLOC extended */
  1593. B_reg = A_reg;
  1594. w = (w & 0x3f) << 8;
  1595. A_reg = stack[-(int)(w + next_byte)];
  1596. #ifdef COMMON
  1597. exit_count = 1;
  1598. #endif
  1599. continue;
  1600. case 0x40: /* STORELOC extended */
  1601. w = (w & 0x3f) << 8;
  1602. stack[-(int)(w + next_byte)] = A_reg;
  1603. continue;
  1604. case 0x80: /* CLOSURE extended */
  1605. push2(B_reg, A_reg);
  1606. w = ((w & 0x3f) << 8) + next_byte;
  1607. goto create_closure;
  1608. case 0xc0: /* LOADLEX, STORELEX extended */
  1609. n = next_byte;
  1610. k = next_byte;
  1611. n = (n << 4) | (k >> 4);
  1612. k = ((k & 0xf) << 8) | next_byte;
  1613. r1 = elt(stack[1-n], 0);
  1614. B_reg = A_reg;
  1615. n = w & 0x1f;
  1616. while (n != 0) r1 = ((Lisp_Object *)r1)[1], n--;
  1617. if ((w & 0x20) == 0)
  1618. { A_reg = ((Lisp_Object *)r1)[k];
  1619. #ifdef COMMON
  1620. exit_count = 1;
  1621. #endif
  1622. }
  1623. else ((Lisp_Object *)r1)[k] = A_reg;
  1624. continue;
  1625. }
  1626. case OP_LIST2STAR: /* A_reg = list2!*(pop(), B_reg, A_reg); */
  1627. /* = pop() . (B . A) */
  1628. #ifndef OUT_OF_LINE
  1629. r1 = (Lisp_Object)((char *)fringe - 2*sizeof(Cons_Cell));
  1630. pop(qcar(r1));
  1631. qcdr(r1) = (Lisp_Object)((char *)r1 +
  1632. sizeof(Cons_Cell) + TAG_CONS);
  1633. qcar((Lisp_Object)((char *)r1+sizeof(Cons_Cell))) = B_reg;
  1634. qcdr((Lisp_Object)((char *)r1+sizeof(Cons_Cell))) = A_reg;
  1635. fringe = r1;
  1636. if ((char *)r1 <= (char *)heaplimit)
  1637. { save_pc();
  1638. C_stack = stack;
  1639. A_reg = reclaim((Lisp_Object)((char *)r1 + TAG_CONS),
  1640. "bytecoded list2*", GC_CONS, 0);
  1641. nil = C_nil;
  1642. if (exception_pending()) goto error_exit;
  1643. stack = C_stack;
  1644. restore_pc();
  1645. }
  1646. else A_reg = (Lisp_Object)((char *)r1 + TAG_CONS);
  1647. #else
  1648. pop(r1);
  1649. save_pc();
  1650. C_stack = stack;
  1651. A_reg = list2star(r1, B_reg, A_reg);
  1652. nil = C_nil;
  1653. if (exception_pending()) goto error_exit;
  1654. stack = C_stack; /* may have been changed by GC */
  1655. restore_pc();
  1656. #endif
  1657. #ifdef COMMON
  1658. exit_count = 1;
  1659. #endif
  1660. continue;
  1661. case OP_LIST3: /* A_reg = list3(pop(), B_reg, A_reg); */
  1662. /* = pop() . (B . (A . nil)) */
  1663. #ifndef OUT_OF_LINE
  1664. r1 = (Lisp_Object)((char *)fringe - 3*sizeof(Cons_Cell));
  1665. pop(qcar(r1));
  1666. qcdr(r1) = (Lisp_Object)((char *)r1 +
  1667. sizeof(Cons_Cell) + TAG_CONS);
  1668. qcar((Lisp_Object)((char *)r1+sizeof(Cons_Cell))) = B_reg;
  1669. qcdr((Lisp_Object)((char *)r1+sizeof(Cons_Cell))) =
  1670. (Lisp_Object)((char *)r1 +
  1671. 2*sizeof(Cons_Cell) + TAG_CONS);
  1672. qcar((Lisp_Object)((char *)r1+2*sizeof(Cons_Cell))) = A_reg;
  1673. qcdr((Lisp_Object)((char *)r1+2*sizeof(Cons_Cell))) = nil;
  1674. fringe = r1;
  1675. if ((char *)r1 <= (char *)heaplimit)
  1676. { save_pc();
  1677. C_stack = stack;
  1678. A_reg = reclaim((Lisp_Object)((char *)r1 + TAG_CONS),
  1679. "bytecoded list3", GC_CONS, 0);
  1680. nil = C_nil;
  1681. if (exception_pending()) goto error_exit;
  1682. stack = C_stack;
  1683. restore_pc();
  1684. }
  1685. else A_reg = (Lisp_Object)((char *)r1 + TAG_CONS);
  1686. #else
  1687. pop(r1);
  1688. save_pc();
  1689. C_stack = stack;
  1690. A_reg = list3(r1, B_reg, A_reg);
  1691. nil = C_nil;
  1692. if (exception_pending()) goto error_exit;
  1693. stack = C_stack; /* may have been changed by GC */
  1694. restore_pc();
  1695. #endif
  1696. #ifdef COMMON
  1697. exit_count = 1;
  1698. #endif
  1699. continue;
  1700. case OP_ADD1:
  1701. if (is_fixnum(A_reg) && A_reg != fixnum_of_int(0x07ffffff))
  1702. {
  1703. A_reg += 0x10;
  1704. #ifdef COMMON
  1705. exit_count = 1;
  1706. #endif
  1707. continue;
  1708. }
  1709. /*
  1710. * I drop through in the case of floating, bignum or error arithmetic.
  1711. */
  1712. save_pc();
  1713. C_stack = stack;
  1714. A_reg = plus2(A_reg, fixnum_of_int(1));
  1715. nil = C_nil;
  1716. if (exception_pending()) goto error_exit;
  1717. stack = C_stack;
  1718. restore_pc();
  1719. #ifdef COMMON
  1720. exit_count = 1;
  1721. #endif
  1722. continue;
  1723. case OP_PLUS2:
  1724. if (is_fixnum(A_reg) && is_fixnum(B_reg))
  1725. { n = int_of_fixnum(A_reg) + int_of_fixnum(B_reg);
  1726. k = n & fix_mask;
  1727. if (k == 0 || k == fix_mask)
  1728. { A_reg = fixnum_of_int(n);
  1729. #ifdef COMMON
  1730. exit_count = 1;
  1731. #endif
  1732. continue;
  1733. }
  1734. }
  1735. /*
  1736. * I drop through in the case of floating, bignum or error arithmetic.
  1737. */
  1738. save_pc();
  1739. C_stack = stack;
  1740. A_reg = plus2(B_reg, A_reg);
  1741. nil = C_nil;
  1742. if (exception_pending()) goto error_exit;
  1743. stack = C_stack;
  1744. restore_pc();
  1745. #ifdef COMMON
  1746. exit_count = 1;
  1747. #endif
  1748. continue;
  1749. case OP_SUB1:
  1750. if (is_fixnum(A_reg) && A_reg != fixnum_of_int(~0x07ffffff))
  1751. {
  1752. A_reg -= 0x10;
  1753. #ifdef COMMON
  1754. exit_count = 1;
  1755. #endif
  1756. continue;
  1757. }
  1758. /*
  1759. * I drop through in the case of floating, bignum or error arithmetic.
  1760. */
  1761. save_pc();
  1762. C_stack = stack;
  1763. A_reg = plus2(A_reg, fixnum_of_int(-1));
  1764. nil = C_nil;
  1765. if (exception_pending()) goto error_exit;
  1766. stack = C_stack;
  1767. restore_pc();
  1768. #ifdef COMMON
  1769. exit_count = 1;
  1770. #endif
  1771. continue;
  1772. case OP_DIFFERENCE:
  1773. if (is_fixnum(A_reg) && is_fixnum(B_reg))
  1774. { n = int_of_fixnum(B_reg) - int_of_fixnum(A_reg);
  1775. k = n & fix_mask;
  1776. if (k == 0 || k == fix_mask)
  1777. { A_reg = fixnum_of_int(n);
  1778. #ifdef COMMON
  1779. exit_count = 1;
  1780. #endif
  1781. continue;
  1782. }
  1783. }
  1784. /*
  1785. * Although computing A-B as A+(-B) is a bit clumsy here, it is only
  1786. * done when there is a bignum or float involved - the important case
  1787. * where everything is a small integer is handled directly in-line.
  1788. */
  1789. save_pc();
  1790. push(B_reg);
  1791. C_stack = stack;
  1792. A_reg = negate(A_reg);
  1793. stack = C_stack;
  1794. pop(B_reg);
  1795. C_stack = stack;
  1796. nil = C_nil;
  1797. if (exception_pending()) goto error_exit;
  1798. A_reg = plus2(B_reg, A_reg);
  1799. nil = C_nil;
  1800. if (exception_pending()) goto error_exit;
  1801. stack = C_stack;
  1802. restore_pc();
  1803. #ifdef COMMON
  1804. exit_count = 1;
  1805. #endif
  1806. continue;
  1807. case OP_TIMES2:
  1808. /*
  1809. * I do not in-line even the integer case here, since overflow checking
  1810. * is a slight mess.
  1811. */
  1812. save_pc();
  1813. C_stack = stack;
  1814. A_reg = times2(B_reg, A_reg);
  1815. nil = C_nil;
  1816. if (exception_pending()) goto error_exit;
  1817. stack = C_stack;
  1818. restore_pc();
  1819. #ifdef COMMON
  1820. exit_count = 1;
  1821. #endif
  1822. continue;
  1823. case OP_LESSP:
  1824. if (is_fixnum(B_reg) && is_fixnum(A_reg)) w = B_reg < A_reg;
  1825. else
  1826. { save_pc();
  1827. C_stack = stack;
  1828. w = lessp2(B_reg, A_reg);
  1829. nil = C_nil;
  1830. if (exception_pending()) goto error_exit;
  1831. stack = C_stack;
  1832. restore_pc();
  1833. }
  1834. A_reg = Lispify_predicate(w);
  1835. #ifdef COMMON
  1836. exit_count = 1;
  1837. #endif
  1838. continue;
  1839. case OP_GREATERP:
  1840. if (is_fixnum(B_reg) && is_fixnum(A_reg)) w = B_reg > A_reg;
  1841. else
  1842. { save_pc();
  1843. C_stack = stack;
  1844. w = lessp2(A_reg, B_reg);
  1845. nil = C_nil;
  1846. if (exception_pending()) goto error_exit;
  1847. stack = C_stack;
  1848. restore_pc();
  1849. }
  1850. A_reg = Lispify_predicate(w);
  1851. #ifdef COMMON
  1852. exit_count = 1;
  1853. #endif
  1854. continue;
  1855. case OP_FLAGP: /* A = flagp(B, A) */
  1856. #ifdef COMMON
  1857. save_pc(); C_stack = stack;
  1858. A_reg = get(B_reg, A_reg, unset_var);
  1859. nil = C_nil;
  1860. if (exception_pending()) goto error_exit;
  1861. stack = C_stack; restore_pc();
  1862. if (A_reg == unset_var) A_reg = nil;
  1863. else A_reg = lisp_true;
  1864. exit_count = 1;
  1865. continue;
  1866. #else
  1867. #ifndef OUT_OF_LINE
  1868. if (!symbolp(B_reg))
  1869. {
  1870. #ifdef RECORD_GET
  1871. save_pc(); C_stack = stack;
  1872. record_get(A_reg, NO);
  1873. nil = C_nil;
  1874. if (exception_pending()) goto error_exit;
  1875. stack = C_stack; restore_pc();
  1876. #endif
  1877. A_reg = nil;
  1878. continue;
  1879. }
  1880. else if (symbolp(A_reg) &&
  1881. (n = header_fastget(qheader(A_reg))) != 0)
  1882. { r1 = qfastgets(B_reg);
  1883. if (r1 == nil)
  1884. {
  1885. #ifdef RECORD_GET
  1886. save_pc(); C_stack = stack;
  1887. record_get(A_reg, NO);
  1888. nil = C_nil;
  1889. if (exception_pending()) goto error_exit;
  1890. stack = C_stack; restore_pc();
  1891. #endif
  1892. continue;
  1893. }
  1894. r1 = elt(r1, n-1);
  1895. #ifdef RECORD_GET
  1896. push(r1);
  1897. save_pc(); C_stack = stack;
  1898. record_get(A_reg, r1 != SPID_NOPROP);
  1899. nil = C_nil;
  1900. if (exception_pending()) goto error_exit;
  1901. stack = C_stack; restore_pc();
  1902. pop(r1);
  1903. #endif
  1904. if (r1 == SPID_NOPROP) A_reg = nil; else A_reg = lisp_true;
  1905. continue;
  1906. }
  1907. else
  1908. { r1 = qplist(B_reg);
  1909. if (r1 == nil)
  1910. {
  1911. #ifdef RECORD_GET
  1912. save_pc(); C_stack = stack;
  1913. record_get(A_reg, NO);
  1914. nil = C_nil;
  1915. if (exception_pending()) goto error_exit;
  1916. stack = C_stack; restore_pc();
  1917. #endif
  1918. A_reg = nil;
  1919. continue;
  1920. }
  1921. r3 = qcar(r1);
  1922. if (qcar(r3) == A_reg)
  1923. {
  1924. #ifdef RECORD_GET
  1925. save_pc(); C_stack = stack;
  1926. record_get(A_reg, YES);
  1927. nil = C_nil;
  1928. if (exception_pending()) goto error_exit;
  1929. stack = C_stack; restore_pc();
  1930. #endif
  1931. A_reg = lisp_true;
  1932. continue;
  1933. }
  1934. r1 = qcdr(r1);
  1935. if (r1 == nil)
  1936. {
  1937. #ifdef RECORD_GET
  1938. save_pc(); C_stack = stack;
  1939. record_get(A_reg, NO);
  1940. nil = C_nil;
  1941. if (exception_pending()) goto error_exit;
  1942. stack = C_stack; restore_pc();
  1943. #endif
  1944. A_reg = nil;
  1945. continue;
  1946. }
  1947. r3 = qcar(r1);
  1948. if (qcar(r3) == A_reg)
  1949. {
  1950. #ifdef RECORD_GET
  1951. save_pc(); C_stack = stack;
  1952. record_get(A_reg, YES);
  1953. nil = C_nil;
  1954. if (exception_pending()) goto error_exit;
  1955. stack = C_stack; restore_pc();
  1956. #endif
  1957. A_reg = lisp_true;
  1958. continue;
  1959. }
  1960. r2 = r1;
  1961. r1 = qcdr(r1);
  1962. if (r1 == nil)
  1963. {
  1964. #ifdef RECORD_GET
  1965. save_pc(); C_stack = stack;
  1966. record_get(A_reg, NO);
  1967. nil = C_nil;
  1968. if (exception_pending()) goto error_exit;
  1969. stack = C_stack; restore_pc();
  1970. #endif
  1971. A_reg = nil;
  1972. continue;
  1973. }
  1974. for (;;)
  1975. { r3 = qcar(r1);
  1976. if (qcar(r3) == A_reg)
  1977. { qcdr(r2) = qcdr(r1);
  1978. qcdr(r1) = qplist(B_reg);
  1979. qplist(B_reg) = r1;
  1980. #ifdef RECORD_GET
  1981. save_pc(); C_stack = stack;
  1982. record_get(A_reg, NO);
  1983. nil = C_nil;
  1984. if (exception_pending()) goto error_exit;
  1985. stack = C_stack; restore_pc();
  1986. #endif
  1987. A_reg = lisp_true;
  1988. break;
  1989. }
  1990. r2 = r1;
  1991. r1 = qcdr(r1);
  1992. if (r1 == nil)
  1993. {
  1994. #ifdef RECORD_GET
  1995. save_pc(); C_stack = stack;
  1996. record_get(A_reg, NO);
  1997. nil = C_nil;
  1998. if (exception_pending()) goto error_exit;
  1999. stack = C_stack; restore_pc();
  2000. #endif
  2001. A_reg = nil;
  2002. break;
  2003. }
  2004. }
  2005. }
  2006. continue;
  2007. #else
  2008. A_reg = Lflagp(nil, B_reg, A_reg);
  2009. nil = C_nil;
  2010. if (exception_pending()) goto error_exit;
  2011. exit_count = 1;
  2012. continue;
  2013. #endif
  2014. #endif
  2015. case OP_APPLY1:
  2016. save_pc();
  2017. if (is_symbol(B_reg)) /* can optimise this case, I guess */
  2018. { f1 = qfn1(B_reg);
  2019. #ifdef DEBUG
  2020. if (f1 == NULL)
  2021. { term_printf("Illegal function\n");
  2022. my_exit(EXIT_FAILURE);
  2023. }
  2024. #endif
  2025. push(B_reg);
  2026. C_stack = stack;
  2027. A_reg = f1(qenv(B_reg), A_reg);
  2028. nil = C_nil;
  2029. if (exception_pending()) goto stack_apply_error;
  2030. stack = C_stack;
  2031. popv(1);
  2032. restore_pc();
  2033. continue;
  2034. }
  2035. push(A_reg);
  2036. C_stack = stack;
  2037. A_reg = apply(B_reg, 1, nil, B_reg);
  2038. nil = C_nil;
  2039. if (exception_pending()) goto apply_error;
  2040. stack = C_stack;
  2041. restore_pc();
  2042. continue;
  2043. case OP_APPLY2:
  2044. save_pc();
  2045. r2 = *stack;
  2046. if (is_symbol(r2)) /* can optimise this case, I guess */
  2047. { f2 = qfn2(r2);
  2048. #ifdef DEBUG
  2049. if (f2 == NULL)
  2050. { term_printf("Illegal function\n");
  2051. my_exit(EXIT_FAILURE);
  2052. }
  2053. #endif
  2054. C_stack = stack;
  2055. A_reg = f2(qenv(r2), B_reg, A_reg);
  2056. nil = C_nil;
  2057. if (exception_pending()) goto stack_apply_error;
  2058. stack = C_stack;
  2059. popv(1);
  2060. restore_pc();
  2061. continue;
  2062. }
  2063. *stack = B_reg;
  2064. push(A_reg);
  2065. C_stack = stack;
  2066. A_reg = apply(r2, 2, nil, r2);
  2067. nil = C_nil;
  2068. if (exception_pending()) goto apply_error;
  2069. stack = C_stack;
  2070. restore_pc();
  2071. continue;
  2072. case OP_APPLY3:
  2073. save_pc();
  2074. pop(r1);
  2075. r2 = *stack;
  2076. if (is_symbol(r2)) /* can optimise this case, I guess */
  2077. { f345 = qfnn(r2);
  2078. #ifdef DEBUG
  2079. if (f345 == NULL)
  2080. { term_printf("Illegal function\n");
  2081. my_exit(EXIT_FAILURE);
  2082. }
  2083. #endif
  2084. C_stack = stack;
  2085. A_reg = f345(qenv(r2), 3, r1, B_reg, A_reg);
  2086. nil = C_nil;
  2087. if (exception_pending()) goto stack_apply_error;
  2088. stack = C_stack;
  2089. popv(1);
  2090. restore_pc();
  2091. continue;
  2092. }
  2093. *stack = r1;
  2094. push2(B_reg, A_reg);
  2095. C_stack = stack;
  2096. A_reg = apply(r2, 3, nil, r2);
  2097. nil = C_nil;
  2098. if (exception_pending()) goto apply_error;
  2099. stack = C_stack;
  2100. restore_pc();
  2101. continue;
  2102. case OP_APPLY4:
  2103. /*
  2104. * It is not yet clear that APPLY4 is important enough to justify the
  2105. * mess it would involve here...
  2106. */
  2107. err_printf("\nAPPLY4 not implemented yet\n");
  2108. aerror("unfinished work in bytes1.c");
  2109. nil = C_nil;
  2110. C_stack = stack;
  2111. goto error_exit;
  2112. #ifdef COMMON
  2113. #define EQUAL cl_equal
  2114. #else
  2115. #define EQUAL equal
  2116. #endif
  2117. case OP_EQUAL: /* A = equal(B, A) */
  2118. A_reg = EQUAL(B_reg, A_reg) ? lisp_true : nil;
  2119. nil = C_nil;
  2120. if (exception_pending()) goto error_exit;
  2121. #ifdef COMMON
  2122. exit_count = 1;
  2123. #endif
  2124. continue;
  2125. case OP_EQ: /* A = eq(B, A) */
  2126. if (A_reg == B_reg) A_reg = lisp_true;
  2127. else A_reg = nil;
  2128. #ifdef COMMON
  2129. exit_count = 1;
  2130. #endif
  2131. continue;
  2132. case OP_NUMBERP: /* A = numberp(A) */
  2133. A_reg = Lispify_predicate(is_number(A_reg));
  2134. #ifdef COMMON
  2135. exit_count = 1;
  2136. #endif
  2137. continue;
  2138. case OP_QGETV: /* A_reg = getv(B_reg, A_reg) */
  2139. /*
  2140. * Note - this is an UNCHECKED vector access, used when carcheck(nil) has
  2141. * been selected because the user prefers speed to security. This is in
  2142. * here because the Reduce factoriser test uses getv VERY heavily indeed
  2143. * and both use of a special opcode here and removal of the checking make
  2144. * noticable differences to performance. The next line has (A_reg>>2)
  2145. * which is there to convert from a fixnum into a word offset - notionally
  2146. * it means 4*int_of_fixnum(A_reg).
  2147. */
  2148. A_reg = *(Lisp_Object *)(
  2149. (char *)B_reg + (4L - TAG_VECTOR) + ((int32)A_reg>>2));
  2150. #ifdef COMMON
  2151. exit_count = 1;
  2152. #endif
  2153. continue;
  2154. case OP_GETV: /* A_reg = getv(B_reg, A_reg) */
  2155. #ifndef OUT_OF_LINE
  2156. if (!(is_vector(B_reg)) ||
  2157. vector_holds_binary(k = vechdr(B_reg)))
  2158. { aerror1("getv", B_reg);
  2159. nil = C_nil;
  2160. goto error_exit;
  2161. }
  2162. else if (!is_fixnum(A_reg))
  2163. { aerror1("getv offset not fixnum", A_reg);
  2164. nil = C_nil;
  2165. goto error_exit;
  2166. }
  2167. k = (length_of_header(k) - 4) >> 2;
  2168. n = int_of_fixnum(A_reg);
  2169. if (n < 0 || n >= k)
  2170. { aerror1("getv index range", A_reg);
  2171. nil = C_nil;
  2172. goto error_exit;
  2173. }
  2174. A_reg = *(Lisp_Object *)(
  2175. (char *)B_reg + (4L - TAG_VECTOR) + ((int32)A_reg>>2));
  2176. #else
  2177. save_pc();
  2178. C_stack = stack;
  2179. A_reg = Lgetv(nil, B_reg, A_reg);
  2180. nil = C_nil;
  2181. if (exception_pending()) goto error_exit;
  2182. stack = C_stack; /* may have been changed by GC */
  2183. restore_pc();
  2184. #endif
  2185. #ifdef COMMON
  2186. exit_count = 1;
  2187. #endif
  2188. continue;
  2189. case OP_QGETVN: /* A_reg = getv(A_reg, n) */
  2190. /*
  2191. * Note - this is an UNCHECKED vector access, and only applicable to simple
  2192. * vectors that hold general Lisp data. The offset is passed in the
  2193. * byte stream. It is expected that it will help with code that passes
  2194. * around vectors of guff and use (getv vvv 0) etc (aka svref) to
  2195. * grab stuff out.
  2196. */
  2197. A_reg = *(Lisp_Object *)(
  2198. (char *)A_reg + (4L - TAG_VECTOR) + ((next_byte)<<2));
  2199. #ifdef COMMON
  2200. exit_count = 1;
  2201. #endif
  2202. continue;
  2203. case OP_EQCAR:
  2204. if (car_legal(B_reg) && A_reg == qcar(B_reg)) A_reg = lisp_true;
  2205. else A_reg = nil;
  2206. #ifdef COMMON
  2207. exit_count = 1;
  2208. #endif
  2209. continue;
  2210. case OP_LENGTH:
  2211. save_pc();
  2212. C_stack = stack;
  2213. A_reg = Llength(nil, A_reg);
  2214. nil = C_nil;
  2215. if (exception_pending()) goto error_exit;
  2216. stack = C_stack;
  2217. restore_pc();
  2218. #ifdef COMMON
  2219. exit_count = 1;
  2220. #endif
  2221. continue;
  2222. /*
  2223. * The following combinations feel a little odd, but ONE of them showed up
  2224. * very clearly in REDUCE tests, and adding the other few seems liable
  2225. * (on sentiment, not measurement!) to make reasonable sense.
  2226. */
  2227. case OP_LOC0LOC1:
  2228. B_reg = stack[-0];
  2229. A_reg = stack[-1];
  2230. #ifdef COMMON
  2231. exit_count = 1;
  2232. #endif
  2233. continue;
  2234. case OP_LOC1LOC2:
  2235. B_reg = stack[-1];
  2236. A_reg = stack[-2];
  2237. #ifdef COMMON
  2238. exit_count = 1;
  2239. #endif
  2240. continue;
  2241. case OP_LOC2LOC3:
  2242. B_reg = stack[-2];
  2243. A_reg = stack[-3];
  2244. #ifdef COMMON
  2245. exit_count = 1;
  2246. #endif
  2247. continue;
  2248. case OP_LOC1LOC0:
  2249. B_reg = stack[-1];
  2250. A_reg = stack[-0];
  2251. #ifdef COMMON
  2252. exit_count = 1;
  2253. #endif
  2254. continue;
  2255. case OP_LOC2LOC1:
  2256. B_reg = stack[-2];
  2257. A_reg = stack[-1];
  2258. #ifdef COMMON
  2259. exit_count = 1;
  2260. #endif
  2261. continue;
  2262. case OP_LOC3LOC2:
  2263. B_reg = stack[-3];
  2264. A_reg = stack[-2];
  2265. #ifdef COMMON
  2266. exit_count = 1;
  2267. #endif
  2268. continue;
  2269. case OP_CDRLOC0:
  2270. B_reg = A_reg;
  2271. A_reg = stack[-0];
  2272. if (car_legal(A_reg))
  2273. { A_reg = qcdr(A_reg);
  2274. #ifdef COMMON
  2275. exit_count = 1;
  2276. #endif
  2277. continue;
  2278. }
  2279. errcode = err_bad_cdr;
  2280. C_stack = stack;
  2281. goto error_1_A;
  2282. case OP_CDRLOC1:
  2283. B_reg = A_reg;
  2284. A_reg = stack[-1];
  2285. if (car_legal(A_reg))
  2286. { A_reg = qcdr(A_reg);
  2287. #ifdef COMMON
  2288. exit_count = 1;
  2289. #endif
  2290. continue;
  2291. }
  2292. errcode = err_bad_cdr;
  2293. C_stack = stack;
  2294. goto error_1_A;
  2295. case OP_CDRLOC2:
  2296. B_reg = A_reg;
  2297. A_reg = stack[-2];
  2298. if (car_legal(A_reg))
  2299. { A_reg = qcdr(A_reg);
  2300. #ifdef COMMON
  2301. exit_count = 1;
  2302. #endif
  2303. continue;
  2304. }
  2305. errcode = err_bad_cdr;
  2306. C_stack = stack;
  2307. goto error_1_A;
  2308. case OP_CDRLOC3:
  2309. B_reg = A_reg;
  2310. A_reg = stack[-3];
  2311. if (car_legal(A_reg))
  2312. { A_reg = qcdr(A_reg);
  2313. #ifdef COMMON
  2314. exit_count = 1;
  2315. #endif
  2316. continue;
  2317. }
  2318. errcode = err_bad_cdr;
  2319. C_stack = stack;
  2320. goto error_1_A;
  2321. case OP_CDRLOC4:
  2322. B_reg = A_reg;
  2323. A_reg = stack[-4];
  2324. if (car_legal(A_reg))
  2325. { A_reg = qcdr(A_reg);
  2326. #ifdef COMMON
  2327. exit_count = 1;
  2328. #endif
  2329. continue;
  2330. }
  2331. errcode = err_bad_cdr;
  2332. C_stack = stack;
  2333. goto error_1_A;
  2334. case OP_CDRLOC5:
  2335. B_reg = A_reg;
  2336. A_reg = stack[-5];
  2337. if (car_legal(A_reg))
  2338. { A_reg = qcdr(A_reg);
  2339. #ifdef COMMON
  2340. exit_count = 1;
  2341. #endif
  2342. continue;
  2343. }
  2344. errcode = err_bad_cdr;
  2345. C_stack = stack;
  2346. goto error_1_A;
  2347. case OP_CAARLOC0:
  2348. B_reg = A_reg;
  2349. A_reg = stack[-0];
  2350. goto caar;
  2351. case OP_CAARLOC1:
  2352. B_reg = A_reg;
  2353. A_reg = stack[-1];
  2354. goto caar;
  2355. case OP_CAARLOC2:
  2356. B_reg = A_reg;
  2357. A_reg = stack[-2];
  2358. goto caar;
  2359. case OP_CAARLOC3:
  2360. B_reg = A_reg;
  2361. A_reg = stack[-3];
  2362. goto caar;
  2363. case OP_CAAR:
  2364. goto caar;
  2365. case OP_CADR:
  2366. if (car_legal(A_reg)) A_reg = qcdr(A_reg);
  2367. else
  2368. { errcode = err_bad_cdr;
  2369. C_stack = stack;
  2370. goto error_1_A;
  2371. }
  2372. if (car_legal(A_reg))
  2373. { A_reg = qcar(A_reg);
  2374. #ifdef COMMON
  2375. exit_count = 1;
  2376. #endif
  2377. continue;
  2378. }
  2379. errcode = err_bad_car;
  2380. C_stack = stack;
  2381. goto error_1_A;
  2382. case OP_CDAR:
  2383. if (car_legal(A_reg)) A_reg = qcar(A_reg);
  2384. else
  2385. { errcode = err_bad_car;
  2386. C_stack = stack;
  2387. goto error_1_A;
  2388. }
  2389. if (car_legal(A_reg))
  2390. { A_reg = qcdr(A_reg);
  2391. #ifdef COMMON
  2392. exit_count = 1;
  2393. #endif
  2394. continue;
  2395. }
  2396. errcode = err_bad_cdr;
  2397. C_stack = stack;
  2398. goto error_1_A;
  2399. case OP_CDDR:
  2400. if (car_legal(A_reg)) A_reg = qcdr(A_reg);
  2401. else
  2402. { errcode = err_bad_cdr;
  2403. C_stack = stack;
  2404. goto error_1_A;
  2405. }
  2406. if (car_legal(A_reg))
  2407. { A_reg = qcdr(A_reg);
  2408. #ifdef COMMON
  2409. exit_count = 1;
  2410. #endif
  2411. continue;
  2412. }
  2413. errcode = err_bad_cdr;
  2414. C_stack = stack;
  2415. goto error_1_A;
  2416. /*
  2417. * The ICASE opcode is followed by a byte (n say) that indicates the number
  2418. * of cases that follow, followed by n+1 double-byte label values.
  2419. * If these addresses are called L<dflt>, L<0>, L<1>, ... L<n-1> then if the
  2420. * A register contains an integer in the range 0 <= k < n then control is
  2421. * transferred to L<k>, while if the A register does not hold an integer or
  2422. * if its value is out of range then control goes to L<dflt>.
  2423. */
  2424. case OP_ICASE:
  2425. w = next_byte;
  2426. if (is_fixnum(A_reg) &&
  2427. (n = int_of_fixnum(A_reg)) >= 0 &&
  2428. n < (int)w) ppc += 2*n + 2;
  2429. w = next_byte;
  2430. /*
  2431. * I support backwards jumps here by setting their top bit. At present I do
  2432. * poll for interrupts on a backwards case-branch. And the encoding used means
  2433. * that case branches can not reach quite as far as regular jumps.
  2434. */
  2435. if (w & 0x80) ppc = ppc - (((w & 0x7f) << 8) + *ppc);
  2436. else ppc = ppc + (w << 8) + *ppc;
  2437. continue;
  2438. /*
  2439. * There are a bunch of special-case jumps here - they are only
  2440. * provided with the variants that jump forwards by small offsets,
  2441. * but are expected to pick up a useful number of cases (for both speed and
  2442. * compactness) all the same.
  2443. */
  2444. case OP_JUMPL0NIL:
  2445. xppc = ppc;
  2446. ppc++;
  2447. if (stack[0] == nil) ppc = ppc + *xppc;
  2448. continue;
  2449. case OP_JUMPL0T:
  2450. xppc = ppc;
  2451. ppc++;
  2452. if (stack[0] != nil) ppc = ppc + *xppc;
  2453. continue;
  2454. case OP_JUMPL1NIL:
  2455. xppc = ppc;
  2456. ppc++;
  2457. if (stack[-1] == nil) ppc = ppc + *xppc;
  2458. continue;
  2459. case OP_JUMPL1T:
  2460. xppc = ppc;
  2461. ppc++;
  2462. if (stack[-1] != nil) ppc = ppc + *xppc;
  2463. continue;
  2464. case OP_JUMPL2NIL:
  2465. xppc = ppc;
  2466. ppc++;
  2467. if (stack[-2] == nil) ppc = ppc + *xppc;
  2468. continue;
  2469. case OP_JUMPL2T:
  2470. xppc = ppc;
  2471. ppc++;
  2472. if (stack[-2] != nil) ppc = ppc + *xppc;
  2473. continue;
  2474. case OP_JUMPL3NIL:
  2475. xppc = ppc;
  2476. ppc++;
  2477. if (stack[-3] == nil) ppc = ppc + *xppc;
  2478. continue;
  2479. case OP_JUMPL3T:
  2480. xppc = ppc;
  2481. ppc++;
  2482. if (stack[-3] != nil) ppc = ppc + *xppc;
  2483. continue;
  2484. case OP_JUMPL4NIL:
  2485. xppc = ppc;
  2486. ppc++;
  2487. if (stack[-4] == nil) ppc = ppc + *xppc;
  2488. continue;
  2489. case OP_JUMPL4T:
  2490. xppc = ppc;
  2491. ppc++;
  2492. if (stack[-4] != nil) ppc = ppc + *xppc;
  2493. continue;
  2494. case OP_JUMPL0ATOM:
  2495. xppc = ppc;
  2496. ppc++;
  2497. if (!consp(stack[0])) ppc = ppc + *xppc;
  2498. continue;
  2499. case OP_JUMPL0NATOM:
  2500. xppc = ppc;
  2501. ppc++;
  2502. if (consp(stack[0])) ppc = ppc + *xppc;
  2503. continue;
  2504. case OP_JUMPL1ATOM:
  2505. xppc = ppc;
  2506. ppc++;
  2507. if (!consp(stack[-1])) ppc = ppc + *xppc;
  2508. continue;
  2509. case OP_JUMPL1NATOM:
  2510. xppc = ppc;
  2511. ppc++;
  2512. if (consp(stack[-1])) ppc = ppc + *xppc;
  2513. continue;
  2514. case OP_JUMPL2ATOM:
  2515. xppc = ppc;
  2516. ppc++;
  2517. if (!consp(stack[-2])) ppc = ppc + *xppc;
  2518. continue;
  2519. case OP_JUMPL2NATOM:
  2520. xppc = ppc;
  2521. ppc++;
  2522. if (consp(stack[-2])) ppc = ppc + *xppc;
  2523. continue;
  2524. case OP_JUMPL3ATOM:
  2525. xppc = ppc;
  2526. ppc++;
  2527. if (!consp(stack[-3])) ppc = ppc + *xppc;
  2528. continue;
  2529. case OP_JUMPL3NATOM:
  2530. xppc = ppc;
  2531. ppc++;
  2532. if (consp(stack[-3])) ppc = ppc + *xppc;
  2533. continue;
  2534. case OP_JUMPST0NIL:
  2535. xppc = ppc;
  2536. ppc++;
  2537. if ((stack[0] = A_reg) == nil) ppc = ppc + *xppc;
  2538. continue;
  2539. case OP_JUMPST0T:
  2540. xppc = ppc;
  2541. ppc++;
  2542. if ((stack[0] = A_reg) != nil) ppc = ppc + *xppc;
  2543. continue;
  2544. case OP_JUMPST1NIL:
  2545. xppc = ppc;
  2546. ppc++;
  2547. if ((stack[-1] = A_reg) == nil) ppc = ppc + *xppc;
  2548. continue;
  2549. case OP_JUMPST1T:
  2550. xppc = ppc;
  2551. ppc++;
  2552. if ((stack[-1] = A_reg) != nil) ppc = ppc + *xppc;
  2553. continue;
  2554. case OP_JUMPST2NIL:
  2555. xppc = ppc;
  2556. ppc++;
  2557. if ((stack[-2] = A_reg) == nil) ppc = ppc + *xppc;
  2558. continue;
  2559. case OP_JUMPST2T:
  2560. xppc = ppc;
  2561. ppc++;
  2562. if ((stack[-2] = A_reg) != nil) ppc = ppc + *xppc;
  2563. continue;
  2564. case OP_JUMPFREE1NIL:
  2565. xppc = ppc;
  2566. ppc++;
  2567. if (qvalue(elt(litvec, 1)) == nil) ppc = ppc + *xppc;
  2568. continue;
  2569. case OP_JUMPFREE1T:
  2570. xppc = ppc;
  2571. ppc++;
  2572. if (qvalue(elt(litvec, 1)) != nil) ppc = ppc + *xppc;
  2573. continue;
  2574. case OP_JUMPFREE2NIL:
  2575. xppc = ppc;
  2576. ppc++;
  2577. if (qvalue(elt(litvec, 2)) == nil) ppc = ppc + *xppc;
  2578. continue;
  2579. case OP_JUMPFREE2T:
  2580. xppc = ppc;
  2581. ppc++;
  2582. if (qvalue(elt(litvec, 2)) != nil) ppc = ppc + *xppc;
  2583. continue;
  2584. case OP_JUMPFREE3NIL:
  2585. xppc = ppc;
  2586. ppc++;
  2587. if (qvalue(elt(litvec, 3)) == nil) ppc = ppc + *xppc;
  2588. continue;
  2589. case OP_JUMPFREE3T:
  2590. xppc = ppc;
  2591. ppc++;
  2592. if (qvalue(elt(litvec, 3)) != nil) ppc = ppc + *xppc;
  2593. continue;
  2594. case OP_JUMPFREE4NIL:
  2595. xppc = ppc;
  2596. ppc++;
  2597. if (qvalue(elt(litvec, 4)) == nil) ppc = ppc + *xppc;
  2598. continue;
  2599. case OP_JUMPFREE4T:
  2600. xppc = ppc;
  2601. ppc++;
  2602. if (qvalue(elt(litvec, 4)) != nil) ppc = ppc + *xppc;
  2603. continue;
  2604. case OP_JUMPLIT1EQ:
  2605. xppc = ppc;
  2606. ppc++;
  2607. if (elt(litvec, 1) == A_reg) ppc = ppc + *xppc;
  2608. continue;
  2609. case OP_JUMPLIT1NE:
  2610. xppc = ppc;
  2611. ppc++;
  2612. if (elt(litvec, 1) != A_reg) ppc = ppc + *xppc;
  2613. continue;
  2614. case OP_JUMPLIT2EQ:
  2615. xppc = ppc;
  2616. ppc++;
  2617. if (elt(litvec, 2) == A_reg) ppc = ppc + *xppc;
  2618. continue;
  2619. case OP_JUMPLIT2NE:
  2620. xppc = ppc;
  2621. ppc++;
  2622. if (elt(litvec, 2) != A_reg) ppc = ppc + *xppc;
  2623. continue;
  2624. case OP_JUMPLIT3EQ:
  2625. xppc = ppc;
  2626. ppc++;
  2627. if (elt(litvec, 3) == A_reg) ppc = ppc + *xppc;
  2628. continue;
  2629. case OP_JUMPLIT3NE:
  2630. xppc = ppc;
  2631. ppc++;
  2632. if (elt(litvec, 3) != A_reg) ppc = ppc + *xppc;
  2633. continue;
  2634. case OP_JUMPLIT4EQ:
  2635. xppc = ppc;
  2636. ppc++;
  2637. if (elt(litvec, 4) == A_reg) ppc = ppc + *xppc;
  2638. continue;
  2639. case OP_JUMPLIT4NE:
  2640. xppc = ppc;
  2641. ppc++;
  2642. if (elt(litvec, 4) != A_reg) ppc = ppc + *xppc;
  2643. continue;
  2644. case OP_JUMPFREENIL:
  2645. w = next_byte;
  2646. xppc = ppc;
  2647. ppc++;
  2648. if (qvalue(elt(litvec, w)) == nil) ppc = ppc + *xppc;
  2649. continue;
  2650. case OP_JUMPFREET:
  2651. w = next_byte;
  2652. xppc = ppc;
  2653. ppc++;
  2654. if (qvalue(elt(litvec, w)) != nil) ppc = ppc + *xppc;
  2655. continue;
  2656. case OP_JUMPLITEQ:
  2657. w = next_byte;
  2658. xppc = ppc;
  2659. ppc++;
  2660. if (elt(litvec, w) == A_reg) ppc = ppc + *xppc;
  2661. continue;
  2662. case OP_JUMPLITNE:
  2663. w = next_byte;
  2664. xppc = ppc;
  2665. ppc++;
  2666. if (elt(litvec, w) != A_reg) ppc = ppc + *xppc;
  2667. continue;
  2668. case OP_JUMPB1NIL:
  2669. f1 = one_arg_functions[next_byte];
  2670. save_pc();
  2671. C_stack = stack;
  2672. A_reg = f1(nil, A_reg);
  2673. nil = C_nil;
  2674. if (exception_pending()) goto call_error_exit;
  2675. stack = C_stack;
  2676. restore_pc();
  2677. xppc = ppc;
  2678. ppc++;
  2679. if (A_reg == nil) ppc = ppc + *xppc;
  2680. continue;
  2681. case OP_JUMPB1T:
  2682. f1 = one_arg_functions[next_byte];
  2683. save_pc();
  2684. C_stack = stack;
  2685. A_reg = f1(nil, A_reg);
  2686. nil = C_nil;
  2687. if (exception_pending()) goto call_error_exit;
  2688. stack = C_stack;
  2689. restore_pc();
  2690. xppc = ppc;
  2691. ppc++;
  2692. if (A_reg != nil) ppc = ppc + *xppc;
  2693. continue;
  2694. case OP_JUMPB2NIL:
  2695. f2 = two_arg_functions[next_byte];
  2696. save_pc();
  2697. C_stack = stack;
  2698. A_reg = f2(nil, B_reg, A_reg);
  2699. nil = C_nil;
  2700. if (exception_pending()) goto error_exit;
  2701. stack = C_stack;
  2702. restore_pc();
  2703. xppc = ppc;
  2704. ppc++;
  2705. if (A_reg == nil) ppc = ppc + *xppc;
  2706. continue;
  2707. case OP_JUMPB2T:
  2708. f2 = two_arg_functions[next_byte];
  2709. save_pc();
  2710. C_stack = stack;
  2711. A_reg = f2(nil, B_reg, A_reg);
  2712. nil = C_nil;
  2713. if (exception_pending()) goto error_exit;
  2714. stack = C_stack;
  2715. restore_pc();
  2716. xppc = ppc;
  2717. ppc++;
  2718. if (A_reg != nil) ppc = ppc + *xppc;
  2719. continue;
  2720. case OP_JUMPEQCAR: /* jump if eqcar(A, <some literal>) */
  2721. w = next_byte;
  2722. xppc = ppc;
  2723. ppc++;
  2724. if (car_legal(A_reg) &&
  2725. elt(litvec, w) == qcar(A_reg)) ppc = ppc + *xppc;
  2726. continue;
  2727. case OP_JUMPNEQCAR:
  2728. w = next_byte;
  2729. xppc = ppc;
  2730. ppc++;
  2731. if (!car_legal(A_reg) ||
  2732. elt(litvec, w) != qcar(A_reg)) ppc = ppc + *xppc;
  2733. continue;
  2734. case OP_JUMPFLAGP:
  2735. w = next_byte;
  2736. xppc = ppc;
  2737. ppc++;
  2738. if (!symbolp(A_reg)) continue;
  2739. else
  2740. #ifdef COMMON
  2741. { save_pc(); C_stack = stack;
  2742. r1 = get(A_reg, elt(litvec, w), unset_var);
  2743. nil = C_nil;
  2744. if (exception_pending()) goto error_exit;
  2745. stack = C_stack; restore_pc();
  2746. if (r1 != unset_var) ppc = ppc + *xppc;
  2747. continue;
  2748. }
  2749. #else
  2750. #ifndef OUT_OF_LINE
  2751. B_reg = elt(litvec, w);
  2752. if (symbolp(B_reg) &&
  2753. (n = header_fastget(qheader(B_reg))) != 0)
  2754. { r1 = qfastgets(A_reg);
  2755. if (r1 == nil)
  2756. {
  2757. #ifdef RECORD_GET
  2758. save_pc(); C_stack = stack;
  2759. record_get(B_reg, NO);
  2760. nil = C_nil;
  2761. if (exception_pending()) goto error_exit;
  2762. stack = C_stack; restore_pc();
  2763. #endif
  2764. continue;
  2765. }
  2766. r1 = elt(r1, n-1);
  2767. #ifdef RECORD_GET
  2768. push(r1);
  2769. save_pc(); C_stack = stack;
  2770. record_get(B_reg, r1 != SPID_NOPROP);
  2771. nil = C_nil;
  2772. if (exception_pending()) goto error_exit;
  2773. stack = C_stack; restore_pc();
  2774. pop(r1);
  2775. #endif
  2776. if (r1 != SPID_NOPROP) ppc = ppc + *xppc;
  2777. continue;
  2778. }
  2779. r1 = qplist(A_reg);
  2780. if (r1 == nil)
  2781. {
  2782. #ifdef RECORD_GET
  2783. save_pc(); C_stack = stack;
  2784. record_get(B_reg, NO);
  2785. nil = C_nil;
  2786. if (exception_pending()) goto error_exit;
  2787. stack = C_stack; restore_pc();
  2788. #endif
  2789. continue;
  2790. }
  2791. r3 = qcar(r1);
  2792. if (qcar(r3) == B_reg)
  2793. { ppc = ppc + *xppc;
  2794. #ifdef RECORD_GET
  2795. save_pc(); C_stack = stack;
  2796. record_get(B_reg, YES);
  2797. nil = C_nil;
  2798. if (exception_pending()) goto error_exit;
  2799. stack = C_stack; restore_pc();
  2800. #endif
  2801. continue;
  2802. }
  2803. r1 = qcdr(r1);
  2804. if (r1 == nil)
  2805. {
  2806. #ifdef RECORD_GET
  2807. save_pc(); C_stack = stack;
  2808. record_get(B_reg, NO);
  2809. nil = C_nil;
  2810. if (exception_pending()) goto error_exit;
  2811. stack = C_stack; restore_pc();
  2812. #endif
  2813. continue;
  2814. }
  2815. r3 = qcar(r1);
  2816. if (qcar(r3) == B_reg)
  2817. { ppc = ppc + *xppc;
  2818. #ifdef RECORD_GET
  2819. save_pc(); C_stack = stack;
  2820. record_get(B_reg, YES);
  2821. nil = C_nil;
  2822. if (exception_pending()) goto error_exit;
  2823. stack = C_stack; restore_pc();
  2824. #endif
  2825. continue;
  2826. }
  2827. r2 = r1;
  2828. r1 = qcdr(r1);
  2829. if (r1 == nil)
  2830. {
  2831. #ifdef RECORD_GET
  2832. save_pc(); C_stack = stack;
  2833. record_get(B_reg, NO);
  2834. nil = C_nil;
  2835. if (exception_pending()) goto error_exit;
  2836. stack = C_stack; restore_pc();
  2837. #endif
  2838. continue;
  2839. }
  2840. for (;;)
  2841. { r3 = qcar(r1);
  2842. if (qcar(r3) == B_reg)
  2843. { qcdr(r2) = qcdr(r1);
  2844. qcdr(r1) = qplist(A_reg);
  2845. qplist(A_reg) = r1;
  2846. ppc = ppc + *xppc;
  2847. #ifdef RECORD_GET
  2848. save_pc(); C_stack = stack;
  2849. record_get(B_reg, YES);
  2850. nil = C_nil;
  2851. if (exception_pending()) goto error_exit;
  2852. stack = C_stack; restore_pc();
  2853. #endif
  2854. break;
  2855. }
  2856. r2 = r1;
  2857. r1 = qcdr(r1);
  2858. if (r1 == nil)
  2859. {
  2860. #ifdef RECORD_GET
  2861. save_pc(); C_stack = stack;
  2862. record_get(B_reg, NO);
  2863. nil = C_nil;
  2864. if (exception_pending()) goto error_exit;
  2865. stack = C_stack; restore_pc();
  2866. #endif
  2867. break;
  2868. }
  2869. }
  2870. continue;
  2871. #else
  2872. r1 = Lflagp(nil, A_reg, elt(litvec, w));
  2873. nil = C_nil;
  2874. if (exception_pending()) goto error_exit;
  2875. if (r1 != nil) ppc = ppc + *xppc;
  2876. continue;
  2877. #endif
  2878. #endif
  2879. case OP_JUMPNFLAGP:
  2880. w = next_byte;
  2881. xppc = ppc;
  2882. ppc++;
  2883. if (!symbolp(A_reg))
  2884. { ppc = ppc + *xppc;
  2885. continue;
  2886. }
  2887. else
  2888. #ifdef COMMON
  2889. { save_pc(); C_stack = stack;
  2890. r1 = get(A_reg, elt(litvec, w), unset_var);
  2891. nil = C_nil;
  2892. if (exception_pending()) goto error_exit;
  2893. stack = C_stack; restore_pc();
  2894. if (r1 == unset_var) ppc = ppc + *xppc;
  2895. continue;
  2896. }
  2897. #else
  2898. #ifndef OUT_OF_LINE
  2899. B_reg = elt(litvec, w);
  2900. if (symbolp(B_reg) &&
  2901. (n = header_fastget(qheader(B_reg))) != 0)
  2902. { r1 = qfastgets(A_reg);
  2903. if (r1 == nil)
  2904. {
  2905. #ifdef RECORD_GET
  2906. save_pc(); C_stack = stack;
  2907. record_get(B_reg, NO);
  2908. nil = C_nil;
  2909. if (exception_pending()) goto error_exit;
  2910. stack = C_stack; restore_pc();
  2911. #endif
  2912. ppc = ppc + *xppc;
  2913. continue;
  2914. }
  2915. r1 = elt(r1, n-1);
  2916. #ifdef RECORD_GET
  2917. push(r1);
  2918. save_pc(); C_stack = stack;
  2919. record_get(B_reg, r1 != SPID_NOPROP);
  2920. nil = C_nil;
  2921. if (exception_pending()) goto error_exit;
  2922. stack = C_stack; restore_pc();
  2923. pop(r1);
  2924. #endif
  2925. if (r1 == SPID_NOPROP) ppc = ppc + *xppc;
  2926. continue;
  2927. }
  2928. r1 = qplist(A_reg);
  2929. if (r1 == nil)
  2930. { ppc = ppc + *xppc;
  2931. #ifdef RECORD_GET
  2932. save_pc(); C_stack = stack;
  2933. record_get(B_reg, NO);
  2934. nil = C_nil;
  2935. if (exception_pending()) goto error_exit;
  2936. stack = C_stack; restore_pc();
  2937. #endif
  2938. continue;
  2939. }
  2940. r3 = qcar(r1);
  2941. if (qcar(r3) == B_reg)
  2942. {
  2943. #ifdef RECORD_GET
  2944. save_pc(); C_stack = stack;
  2945. record_get(B_reg, YES);
  2946. nil = C_nil;
  2947. if (exception_pending()) goto error_exit;
  2948. stack = C_stack; restore_pc();
  2949. #endif
  2950. continue;
  2951. }
  2952. r1 = qcdr(r1);
  2953. if (r1 == nil)
  2954. { ppc = ppc + *xppc;
  2955. #ifdef RECORD_GET
  2956. save_pc(); C_stack = stack;
  2957. record_get(B_reg, NO);
  2958. nil = C_nil;
  2959. if (exception_pending()) goto error_exit;
  2960. stack = C_stack; restore_pc();
  2961. #endif
  2962. continue;
  2963. }
  2964. r3 = qcar(r1);
  2965. if (qcar(r3) == B_reg)
  2966. {
  2967. #ifdef RECORD_GET
  2968. save_pc(); C_stack = stack;
  2969. record_get(B_reg, YES);
  2970. nil = C_nil;
  2971. if (exception_pending()) goto error_exit;
  2972. stack = C_stack; restore_pc();
  2973. #endif
  2974. continue;
  2975. }
  2976. r2 = r1;
  2977. r1 = qcdr(r1);
  2978. if (r1 == nil)
  2979. { ppc = ppc + *xppc;
  2980. #ifdef RECORD_GET
  2981. save_pc(); C_stack = stack;
  2982. record_get(B_reg, NO);
  2983. nil = C_nil;
  2984. if (exception_pending()) goto error_exit;
  2985. stack = C_stack; restore_pc();
  2986. #endif
  2987. continue;
  2988. }
  2989. for (;;)
  2990. { r3 = qcar(r1);
  2991. if (qcar(r3) == B_reg)
  2992. { qcdr(r2) = qcdr(r1);
  2993. qcdr(r1) = qplist(A_reg);
  2994. qplist(A_reg) = r1;
  2995. #ifdef RECORD_GET
  2996. save_pc(); C_stack = stack;
  2997. record_get(B_reg, YES);
  2998. nil = C_nil;
  2999. if (exception_pending()) goto error_exit;
  3000. stack = C_stack; restore_pc();
  3001. #endif
  3002. break;
  3003. }
  3004. r2 = r1;
  3005. r1 = qcdr(r1);
  3006. if (r1 == nil)
  3007. { ppc = ppc + *xppc;
  3008. #ifdef RECORD_GET
  3009. save_pc(); C_stack = stack;
  3010. record_get(B_reg, NO);
  3011. nil = C_nil;
  3012. if (exception_pending()) goto error_exit;
  3013. stack = C_stack; restore_pc();
  3014. #endif
  3015. break;
  3016. }
  3017. }
  3018. continue;
  3019. #else
  3020. r1 = Lflagp(nil, A_reg, elt(litvec, w));
  3021. nil = C_nil;
  3022. if (exception_pending()) goto error_exit;
  3023. if (r1 == nil) ppc = ppc + *xppc;
  3024. continue;
  3025. #endif
  3026. #endif
  3027. /*
  3028. * Now the general jumps. Each has four variants - forwards and backwards
  3029. * and long and short offsets. Backwards jumps poll for interrupts so that
  3030. * all loops will be interruptible.
  3031. */
  3032. case OP_JUMPATOM:
  3033. xppc = ppc;
  3034. ppc++;
  3035. if (!consp(A_reg)) ppc = ppc + *xppc;
  3036. continue;
  3037. case OP_JUMPATOM_B:
  3038. xppc = ppc;
  3039. ppc++;
  3040. if (!consp(A_reg))
  3041. { ppc = ppc - *xppc;
  3042. #ifndef OUT_OF_LINE
  3043. #ifdef SOFTWARE_TICKS
  3044. if (--countdown < 0) deal_with_tick();
  3045. #endif
  3046. if (stack >= stacklimit)
  3047. { C_stack = stack;
  3048. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3049. nil = C_nil;
  3050. if (exception_pending()) goto error_exit;
  3051. stack = C_stack; /* may have been changed by GC */
  3052. }
  3053. #else
  3054. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3055. goto error_exit;
  3056. stack = C_stack;
  3057. #endif
  3058. }
  3059. continue;
  3060. case OP_JUMPNATOM:
  3061. xppc = ppc;
  3062. ppc++;
  3063. if (consp(A_reg)) ppc = ppc + *xppc;
  3064. continue;
  3065. case OP_JUMPNATOM_B:
  3066. xppc = ppc;
  3067. ppc++;
  3068. if (consp(A_reg))
  3069. { ppc = ppc - *xppc;
  3070. #ifndef OUT_OF_LINE
  3071. #ifdef SOFTWARE_TICKS
  3072. if (--countdown < 0) deal_with_tick();
  3073. #endif
  3074. if (stack >= stacklimit)
  3075. { C_stack = stack;
  3076. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3077. nil = C_nil;
  3078. if (exception_pending()) goto error_exit;
  3079. stack = C_stack; /* may have been changed by GC */
  3080. }
  3081. #else
  3082. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3083. goto error_exit;
  3084. stack = C_stack;
  3085. #endif
  3086. }
  3087. continue;
  3088. case OP_JUMPEQ:
  3089. xppc = ppc;
  3090. ppc++;
  3091. if (A_reg == B_reg) ppc = ppc + *xppc;
  3092. continue;
  3093. case OP_JUMPEQ_B:
  3094. xppc = ppc;
  3095. ppc++;
  3096. if (A_reg == B_reg)
  3097. { ppc = ppc - *xppc;
  3098. #ifndef OUT_OF_LINE
  3099. #ifdef SOFTWARE_TICKS
  3100. if (--countdown < 0) deal_with_tick();
  3101. #endif
  3102. if (stack >= stacklimit)
  3103. { C_stack = stack;
  3104. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3105. nil = C_nil;
  3106. if (exception_pending()) goto error_exit;
  3107. stack = C_stack; /* may have been changed by GC */
  3108. }
  3109. #else
  3110. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3111. goto error_exit;
  3112. stack = C_stack;
  3113. #endif
  3114. }
  3115. continue;
  3116. case OP_JUMPNE:
  3117. xppc = ppc;
  3118. ppc++;
  3119. if (A_reg != B_reg) ppc = ppc + *xppc;
  3120. continue;
  3121. case OP_JUMPNE_B:
  3122. xppc = ppc;
  3123. ppc++;
  3124. if (A_reg != B_reg)
  3125. { ppc = ppc - *xppc;
  3126. #ifndef OUT_OF_LINE
  3127. #ifdef SOFTWARE_TICKS
  3128. if (--countdown < 0) deal_with_tick();
  3129. #endif
  3130. if (stack >= stacklimit)
  3131. { C_stack = stack;
  3132. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3133. nil = C_nil;
  3134. if (exception_pending()) goto error_exit;
  3135. stack = C_stack; /* may have been changed by GC */
  3136. }
  3137. #else
  3138. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3139. goto error_exit;
  3140. stack = C_stack;
  3141. #endif
  3142. }
  3143. continue;
  3144. case OP_JUMPEQUAL:
  3145. xppc = ppc;
  3146. ppc++;
  3147. if (EQUAL(A_reg, B_reg)) ppc = ppc + *xppc;
  3148. continue;
  3149. case OP_JUMPEQUAL_B:
  3150. xppc = ppc;
  3151. ppc++;
  3152. if (EQUAL(A_reg, B_reg))
  3153. { ppc = ppc - *xppc;
  3154. #ifndef OUT_OF_LINE
  3155. #ifdef SOFTWARE_TICKS
  3156. if (--countdown < 0) deal_with_tick();
  3157. #endif
  3158. if (stack >= stacklimit)
  3159. { C_stack = stack;
  3160. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3161. nil = C_nil;
  3162. if (exception_pending()) goto error_exit;
  3163. stack = C_stack; /* may have been changed by GC */
  3164. }
  3165. #else
  3166. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3167. goto error_exit;
  3168. stack = C_stack;
  3169. #endif
  3170. }
  3171. continue;
  3172. case OP_JUMPNEQUAL:
  3173. xppc = ppc;
  3174. ppc++;
  3175. if (!EQUAL(A_reg, B_reg)) ppc = ppc + *xppc;
  3176. continue;
  3177. case OP_JUMPNEQUAL_B:
  3178. xppc = ppc;
  3179. ppc++;
  3180. if (!EQUAL(A_reg, B_reg))
  3181. { ppc = ppc - *xppc;
  3182. #ifndef OUT_OF_LINE
  3183. #ifdef SOFTWARE_TICKS
  3184. if (--countdown < 0) deal_with_tick();
  3185. #endif
  3186. if (stack >= stacklimit)
  3187. { C_stack = stack;
  3188. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3189. nil = C_nil;
  3190. if (exception_pending()) goto error_exit;
  3191. stack = C_stack; /* may have been changed by GC */
  3192. }
  3193. #else
  3194. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3195. goto error_exit;
  3196. stack = C_stack;
  3197. #endif
  3198. }
  3199. continue;
  3200. case OP_JUMP:
  3201. ppc = ppc + *ppc + 1;
  3202. continue;
  3203. case OP_JUMP_B:
  3204. ppc = ppc - *ppc + 1;
  3205. #ifndef OUT_OF_LINE
  3206. #ifdef SOFTWARE_TICKS
  3207. if (--countdown < 0) deal_with_tick();
  3208. #endif
  3209. if (stack >= stacklimit)
  3210. { C_stack = stack;
  3211. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3212. nil = C_nil;
  3213. if (exception_pending()) goto error_exit;
  3214. stack = C_stack; /* may have been changed by GC */
  3215. }
  3216. #else
  3217. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3218. goto error_exit;
  3219. stack = C_stack;
  3220. #endif
  3221. continue;
  3222. case OP_JUMPATOM_L:
  3223. w = next_byte;
  3224. xppc = ppc;
  3225. ppc++;
  3226. if (!consp(A_reg)) ppc = ppc + ((w << 8) + *xppc);
  3227. continue;
  3228. case OP_JUMPATOM_BL:
  3229. w = next_byte;
  3230. xppc = ppc;
  3231. ppc++;
  3232. if (!consp(A_reg))
  3233. { ppc = ppc - ((w << 8) + *xppc);
  3234. #ifndef OUT_OF_LINE
  3235. #ifdef SOFTWARE_TICKS
  3236. if (--countdown < 0) deal_with_tick();
  3237. #endif
  3238. if (stack >= stacklimit)
  3239. { C_stack = stack;
  3240. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3241. nil = C_nil;
  3242. if (exception_pending()) goto error_exit;
  3243. stack = C_stack; /* may have been changed by GC */
  3244. }
  3245. #else
  3246. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3247. goto error_exit;
  3248. stack = C_stack;
  3249. #endif
  3250. }
  3251. continue;
  3252. case OP_JUMPNATOM_L:
  3253. w = next_byte;
  3254. xppc = ppc;
  3255. ppc++;
  3256. if (consp(A_reg)) ppc = ppc + ((w << 8) + *xppc);
  3257. continue;
  3258. case OP_JUMPNATOM_BL:
  3259. w = next_byte;
  3260. xppc = ppc;
  3261. ppc++;
  3262. if (consp(A_reg))
  3263. { ppc = ppc - ((w << 8) + *xppc);
  3264. #ifndef OUT_OF_LINE
  3265. #ifdef SOFTWARE_TICKS
  3266. if (--countdown < 0) deal_with_tick();
  3267. #endif
  3268. if (stack >= stacklimit)
  3269. { C_stack = stack;
  3270. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3271. nil = C_nil;
  3272. if (exception_pending()) goto error_exit;
  3273. stack = C_stack; /* may have been changed by GC */
  3274. }
  3275. #else
  3276. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3277. goto error_exit;
  3278. stack = C_stack;
  3279. #endif
  3280. }
  3281. continue;
  3282. case OP_JUMPEQ_L:
  3283. w = next_byte;
  3284. xppc = ppc;
  3285. ppc++;
  3286. if (A_reg == B_reg) ppc = ppc + ((w << 8) + *xppc);
  3287. continue;
  3288. case OP_JUMPEQ_BL:
  3289. w = next_byte;
  3290. xppc = ppc;
  3291. ppc++;
  3292. if (A_reg == B_reg)
  3293. { ppc = ppc - ((w << 8) + *xppc);
  3294. #ifndef OUT_OF_LINE
  3295. #ifdef SOFTWARE_TICKS
  3296. if (--countdown < 0) deal_with_tick();
  3297. #endif
  3298. if (stack >= stacklimit)
  3299. { C_stack = stack;
  3300. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3301. nil = C_nil;
  3302. if (exception_pending()) goto error_exit;
  3303. stack = C_stack; /* may have been changed by GC */
  3304. }
  3305. #else
  3306. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3307. goto error_exit;
  3308. stack = C_stack;
  3309. #endif
  3310. }
  3311. continue;
  3312. case OP_JUMPNE_L:
  3313. w = next_byte;
  3314. xppc = ppc;
  3315. ppc++;
  3316. if (A_reg != B_reg) ppc = ppc + ((w << 8) + *xppc);
  3317. continue;
  3318. case OP_JUMPNE_BL:
  3319. w = next_byte;
  3320. xppc = ppc;
  3321. ppc++;
  3322. if (A_reg != B_reg)
  3323. { ppc = ppc - ((w << 8) + *xppc);
  3324. #ifndef OUT_OF_LINE
  3325. #ifdef SOFTWARE_TICKS
  3326. if (--countdown < 0) deal_with_tick();
  3327. #endif
  3328. if (stack >= stacklimit)
  3329. { C_stack = stack;
  3330. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3331. nil = C_nil;
  3332. if (exception_pending()) goto error_exit;
  3333. stack = C_stack; /* may have been changed by GC */
  3334. }
  3335. #else
  3336. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3337. goto error_exit;
  3338. stack = C_stack;
  3339. #endif
  3340. }
  3341. continue;
  3342. case OP_JUMPEQUAL_L:
  3343. w = next_byte;
  3344. xppc = ppc;
  3345. ppc++;
  3346. if (EQUAL(A_reg, B_reg))
  3347. ppc = ppc + ((w << 8) + *xppc);
  3348. continue;
  3349. case OP_JUMPEQUAL_BL:
  3350. w = next_byte;
  3351. xppc = ppc;
  3352. ppc++;
  3353. if (EQUAL(A_reg, B_reg))
  3354. { ppc = ppc - ((w << 8) + *xppc);
  3355. #ifndef OUT_OF_LINE
  3356. #ifdef SOFTWARE_TICKS
  3357. if (--countdown < 0) deal_with_tick();
  3358. #endif
  3359. if (stack >= stacklimit)
  3360. { C_stack = stack;
  3361. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3362. nil = C_nil;
  3363. if (exception_pending()) goto error_exit;
  3364. stack = C_stack; /* may have been changed by GC */
  3365. }
  3366. #else
  3367. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3368. goto error_exit;
  3369. stack = C_stack;
  3370. #endif
  3371. }
  3372. continue;
  3373. case OP_JUMPNEQUAL_L:
  3374. w = next_byte;
  3375. xppc = ppc;
  3376. ppc++;
  3377. if (!EQUAL(A_reg, B_reg))
  3378. ppc = ppc + ((w << 8) + *xppc);
  3379. continue;
  3380. case OP_JUMPNEQUAL_BL:
  3381. w = next_byte;
  3382. xppc = ppc;
  3383. ppc++;
  3384. if (!EQUAL(A_reg, B_reg))
  3385. { ppc = ppc - ((w << 8) + *xppc);
  3386. #ifndef OUT_OF_LINE
  3387. #ifdef SOFTWARE_TICKS
  3388. if (--countdown < 0) deal_with_tick();
  3389. #endif
  3390. if (stack >= stacklimit)
  3391. { C_stack = stack;
  3392. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3393. nil = C_nil;
  3394. if (exception_pending()) goto error_exit;
  3395. stack = C_stack; /* may have been changed by GC */
  3396. }
  3397. #else
  3398. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3399. goto error_exit;
  3400. stack = C_stack;
  3401. #endif
  3402. }
  3403. continue;
  3404. case OP_JUMP_L:
  3405. w = next_byte;
  3406. ppc = ppc + ((w << 8) + *ppc) + 1;
  3407. continue;
  3408. case OP_JUMP_BL:
  3409. w = next_byte;
  3410. ppc = ppc - ((w << 8) + *ppc) + 1;
  3411. #ifndef OUT_OF_LINE
  3412. #ifdef SOFTWARE_TICKS
  3413. if (--countdown < 0) deal_with_tick();
  3414. #endif
  3415. if (stack >= stacklimit)
  3416. { C_stack = stack;
  3417. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  3418. nil = C_nil;
  3419. if (exception_pending()) goto error_exit;
  3420. stack = C_stack; /* may have been changed by GC */
  3421. }
  3422. #else
  3423. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  3424. goto error_exit;
  3425. stack = C_stack;
  3426. #endif
  3427. continue;
  3428. case OP_CATCH:
  3429. w = (unsigned int)((ppc + *ppc) -
  3430. (unsigned char *)data_of_bps(codevec));
  3431. ppc++;
  3432. goto catcher;
  3433. case OP_CATCH_B:
  3434. w = (unsigned int)((ppc - *ppc) -
  3435. (unsigned char *)data_of_bps(codevec));
  3436. ppc++;
  3437. goto catcher;
  3438. case OP_CATCH_L:
  3439. w = next_byte;
  3440. w = (unsigned int)((ppc + (w << 8) + *ppc) -
  3441. (unsigned char *)data_of_bps(codevec));
  3442. ppc++;
  3443. goto catcher;
  3444. case OP_CATCH_BL:
  3445. w = next_byte;
  3446. w = (unsigned int)((ppc - ((w << 8) + *ppc)) -
  3447. (unsigned char *)data_of_bps(codevec));
  3448. ppc++;
  3449. goto catcher;
  3450. case OP_UNCATCH:
  3451. popv(1); pop(r1); popv(1);
  3452. catch_tags = qcdr(r1);
  3453. qcar(r1) = r1; qcdr(r1) = nil;
  3454. continue;
  3455. case OP_PROTECT:
  3456. /*
  3457. * This is used to support UNWIND-PROTECT.
  3458. * This needs to save A_reg, all the multiple-result registers,
  3459. * and the exit_count. Also something to indicate that there had not been
  3460. * an error.
  3461. */
  3462. popv(3);
  3463. #ifdef COMMON
  3464. A_reg = Lmv_list(nil, A_reg);
  3465. nil = C_nil;
  3466. if (exception_pending()) goto error_exit;
  3467. #endif
  3468. push3(nil, fixnum_of_int(UNWIND_NULL), A_reg);
  3469. continue;
  3470. case OP_UNPROTECT:
  3471. /*
  3472. * This must restore all the results (including exit_count). If the
  3473. * PROTECT had been done by an unwinding then exit_reason and exit_tag
  3474. * must also be restored, and the unwind condition must be re-instated.
  3475. */
  3476. pop3(A_reg, B_reg, exit_tag);
  3477. exit_reason = int_of_fixnum(B_reg);
  3478. #ifdef COMMON
  3479. /*
  3480. * Here I have multiple values to restore.
  3481. */
  3482. exit_count = 0;
  3483. B_reg = A_reg;
  3484. A_reg = nil;
  3485. if (consp(B_reg))
  3486. { A_reg = qcar(B_reg);
  3487. B_reg = qcdr(B_reg);
  3488. exit_count++;
  3489. while (consp(B_reg))
  3490. { (&mv_1)[exit_count++] = qcar(B_reg);
  3491. B_reg = qcdr(B_reg);
  3492. }
  3493. }
  3494. #endif
  3495. exit_value = A_reg;
  3496. if (exit_reason != UNWIND_NULL) goto pop_stack_and_exit;
  3497. continue;
  3498. case OP_THROW:
  3499. pop(r1); /* the tag to throw to */
  3500. for (r2 = catch_tags; r2!=nil; r2=qcdr(r2))
  3501. if (r1 == qcar(r2)) break;
  3502. if (r2==nil)
  3503. { aerror1("throw: tag not found", r1);
  3504. nil = C_nil;
  3505. goto error_exit;
  3506. }
  3507. catch_tags = qcdr(r2);
  3508. exit_tag = r2;
  3509. exit_value = A_reg;
  3510. exit_reason = UNWIND_THROW;
  3511. flip_exception();
  3512. /*
  3513. * NOTE WELL: this means that at error_exit (after all the possible cases
  3514. * where something I call returns with NIL marked) it is essential to check
  3515. * for THROW as well as just error returns.
  3516. */
  3517. goto error_exit;
  3518. /*
  3519. * I expect that calling functions with 0, 1, 2 or 3 arguments will
  3520. * be enormously important for Lisp, and so separate opcodes are provided
  3521. * for these cases. The operand in each case selects the function to be
  3522. * called, which MUST be a symbol (loaded from the literal vector),
  3523. * and arguments are taken from A and B as necessary. If several
  3524. * arguments are needed the first argument will be loaded first, and thus
  3525. * it is the LAST argument that end up in the A register.
  3526. */
  3527. case OP_CALL0_0: /* Calling myself... */
  3528. fname = 0;
  3529. goto call0;
  3530. case OP_CALL0_1:
  3531. fname = 1;
  3532. goto call0;
  3533. case OP_CALL0_2:
  3534. fname = 2;
  3535. goto call0;
  3536. case OP_CALL0_3:
  3537. fname = 3;
  3538. goto call0;
  3539. case OP_CALL0:
  3540. fname = next_byte;
  3541. goto call0;
  3542. case OP_JCALL:
  3543. /*
  3544. * This version has the number of args and the target packed into a
  3545. * single operand byte. JCALLN is functionally similar but allows
  3546. * for more extreme cases by using one byte to specify the target
  3547. * and another to give the number of arguments being passed.
  3548. */
  3549. w = next_byte;
  3550. fname = w & 0x1f;
  3551. w = (w >> 5) & 0x7;
  3552. switch (w)
  3553. {
  3554. case 0: goto jcall0;
  3555. case 1: goto jcall1;
  3556. case 2: goto jcall2;
  3557. case 3: goto jcall3;
  3558. default:goto jcalln;
  3559. }
  3560. case OP_JCALLN:
  3561. fname = next_byte;
  3562. w = next_byte;
  3563. switch (w)
  3564. {
  3565. case 0: goto jcall0;
  3566. case 1: goto jcall1;
  3567. case 2: goto jcall2;
  3568. case 3: goto jcall3;
  3569. default:goto jcalln;
  3570. }
  3571. case OP_BIGCALL:
  3572. /*
  3573. * This provides for calls (and a few other operations!) where the literal
  3574. * to be referenced is beyond position 256 in the literal vector. The
  3575. * encoding is that BIGCALL is followed by two bytes. The top half of the
  3576. * first of these is a sub opcode, while the remaining 12 bits provide
  3577. * support for literal vectors with up to 4096 elements. At present I
  3578. * will just not support code bigger than that. Note that if I were feeling
  3579. * keen here I could easily arrange that the 12-bit offset here started at
  3580. * 256 and went on upwards. But for simplicity in a first version I will
  3581. * leave a bit of redundancy.
  3582. */
  3583. w = next_byte;
  3584. fname = next_byte + ((w & 0xf) << 8);
  3585. switch (w >> 4)
  3586. {
  3587. case 0: goto call0;
  3588. case 1: goto call1;
  3589. case 2: goto call2;
  3590. case 3: goto call3;
  3591. case 4:
  3592. /*
  3593. * Here I write out a variant on the CALLN code.
  3594. */
  3595. push2(B_reg, A_reg);
  3596. save_pc();
  3597. C_stack = stack;
  3598. A_reg = elt(litvec, fname);
  3599. A_reg = apply(A_reg, (int)(*ppc), nil, A_reg);
  3600. nil = C_nil;
  3601. if (exception_pending()) goto ncall_error_exit;
  3602. stack = C_stack; /* args were popped by apply */
  3603. restore_pc();
  3604. ppc++;
  3605. continue;
  3606. case 5: goto call2r;
  3607. /*
  3608. * sub-opcodes 6 and 7 are use for LOADFREE and STOREFREE - this is a bit
  3609. * odd but fits the required operations tightly into the opcode map.
  3610. */
  3611. case 6:
  3612. B_reg = A_reg;
  3613. A_reg = qvalue(elt(litvec, fname));
  3614. #ifdef COMMON
  3615. exit_count = 1;
  3616. #endif
  3617. continue;
  3618. case 7:
  3619. qvalue(elt(litvec, fname)) = A_reg; /* store into special var */
  3620. continue;
  3621. case 8: goto jcall0;
  3622. case 9: goto jcall1;
  3623. case 10:goto jcall2;
  3624. case 11:goto jcall3;
  3625. /* The codes for big JCALLs take a further byte that give the number of args */
  3626. case 12:w = next_byte; goto jcalln;
  3627. /*
  3628. * Codes 13 and 14 do FREEBIND and LITGET, which completes the list of
  3629. * byte operations that access big literals.
  3630. */
  3631. case 13:stack = do_freebind(elt(litvec, fname), stack);
  3632. continue;
  3633. case 14:B_reg = A_reg;
  3634. A_reg = elt(litvec, fname);
  3635. goto perform_get;
  3636. /*
  3637. * Code 15 is LOADLIT with a long offset, which may be used as an alternative
  3638. * to the LOADLIT/QGETVN mechanism that I otherwise support.
  3639. */
  3640. case 15:B_reg = A_reg;
  3641. A_reg = elt(litvec, fname);
  3642. #ifdef COMMON
  3643. exit_count = 1;
  3644. #endif
  3645. continue;
  3646. }
  3647. case OP_CALL1_0:
  3648. /*
  3649. * Note that this is spotted and treated as a direct call to the
  3650. * current function (because offset zero in the literal vector is reserved
  3651. * for the name of the function). I can NOT avoid the overhead of stacking
  3652. * and restoring codevec and litvec here, even the values used in the called
  3653. * function are the same as the present ones, because the lower level call
  3654. * might itself do a JCALL and corrupt them! Also I know that the current
  3655. * function is bytecoded, so I avoid the overhead of (re-)discovering that.
  3656. */
  3657. push3(codevec, litvec, A_reg); /* the argument */
  3658. save_pc();
  3659. C_stack = stack;
  3660. #ifdef SOFTWARE_TICKS
  3661. if (--countdown < 0) deal_with_tick();
  3662. #endif
  3663. if (stack >= stacklimit)
  3664. { reclaim(nil, "stack", GC_STACK, 0);
  3665. nil = C_nil;
  3666. if (exception_pending()) goto callself_error_exit;
  3667. }
  3668. A_reg = bytestream_interpret(codevec-2, litvec, stack-1);
  3669. nil = C_nil;
  3670. if (exception_pending()) goto callself_error_exit;
  3671. stack = C_stack;
  3672. pop2(litvec, codevec);
  3673. restore_pc();
  3674. continue;
  3675. case OP_CALL1_1:
  3676. fname = 1;
  3677. goto call1;
  3678. case OP_CALL1_2:
  3679. fname = 2;
  3680. goto call1;
  3681. case OP_CALL1_3:
  3682. fname = 3;
  3683. goto call1;
  3684. case OP_CALL1_4:
  3685. fname = 4;
  3686. goto call1;
  3687. case OP_CALL1_5:
  3688. fname = 5;
  3689. goto call1;
  3690. case OP_CALL1:
  3691. fname = next_byte;
  3692. goto call1;
  3693. case OP_CALL2_0:
  3694. push4(codevec, litvec, B_reg, A_reg);
  3695. save_pc();
  3696. C_stack = stack;
  3697. #ifdef SOFTWARE_TICKS
  3698. if (--countdown < 0) deal_with_tick();
  3699. #endif
  3700. if (stack >= stacklimit)
  3701. { reclaim(nil, "stack", GC_STACK, 0);
  3702. nil = C_nil;
  3703. if (exception_pending()) goto callself_error_exit;
  3704. }
  3705. A_reg = bytestream_interpret(codevec-2, litvec, stack-2);
  3706. nil = C_nil;
  3707. if (exception_pending()) goto callself_error_exit;
  3708. stack = C_stack;
  3709. pop2(litvec, codevec);
  3710. restore_pc();
  3711. continue;
  3712. case OP_CALL2_1:
  3713. fname = 1;
  3714. goto call2;
  3715. case OP_CALL2_2:
  3716. fname = 2;
  3717. goto call2;
  3718. case OP_CALL2_3:
  3719. fname = 3;
  3720. goto call2;
  3721. case OP_CALL2_4:
  3722. fname = 4;
  3723. goto call2;
  3724. case OP_CALL2:
  3725. fname = next_byte;
  3726. goto call2;
  3727. case OP_CALL2R:
  3728. fname = next_byte;
  3729. goto call2r;
  3730. case OP_CALL3:
  3731. fname = next_byte;
  3732. goto call3;
  3733. case OP_CALLN:
  3734. /*
  3735. * Here the first post-byte indicates the function to be called,
  3736. * and the second is the number of args (>= 4) to be passed. All but the
  3737. * last two args have been pushed onto the stack already. The last two are
  3738. * in A and B.
  3739. */
  3740. push2(B_reg, A_reg);
  3741. save_pc();
  3742. C_stack = stack;
  3743. A_reg = elt(litvec, *ppc);
  3744. /*
  3745. * Note that I never need to call something with 0, 1, 2 or 3 args here.
  3746. */
  3747. A_reg = apply(A_reg, (int)(*(ppc+1)), nil, A_reg);
  3748. nil = C_nil;
  3749. if (exception_pending()) goto ncall_error_exit;
  3750. stack = C_stack; /* args were popped by apply */
  3751. restore_pc();
  3752. ppc = ppc + 2;
  3753. continue;
  3754. case OP_BUILTIN0:
  3755. f345 = zero_arg_functions[next_byte];
  3756. /* BUILTIN0: A=fn() */
  3757. save_pc();
  3758. C_stack = stack;
  3759. A_reg = f345(nil, 0);
  3760. nil = C_nil;
  3761. if (exception_pending()) goto error_exit;
  3762. stack = C_stack;
  3763. restore_pc();
  3764. continue;
  3765. case OP_BUILTIN2R:
  3766. f2 = two_arg_functions[next_byte];
  3767. /* BUILTIN2R: A=fn(A,B); NOTE arg order reversed */
  3768. save_pc();
  3769. C_stack = stack;
  3770. A_reg = f2(nil, A_reg, B_reg);
  3771. nil = C_nil;
  3772. if (exception_pending()) goto error_exit;
  3773. stack = C_stack;
  3774. restore_pc();
  3775. continue;
  3776. case OP_BUILTIN3:
  3777. f345 = three_arg_functions[next_byte];
  3778. /* CALL3: A=fn(pop(),B,A); */
  3779. save_pc();
  3780. pop(r1);
  3781. C_stack = stack;
  3782. A_reg = f345(nil, 3, r1, B_reg, A_reg);
  3783. nil = C_nil;
  3784. if (exception_pending()) goto error_exit;
  3785. stack = C_stack;
  3786. restore_pc();
  3787. continue;
  3788. /*
  3789. * Now here in a neat block I will have the cases that seem to occur most
  3790. * frequently, at least when I tested things running REDUCE. By collecting
  3791. * these together I hope to (slightly) improve the cache locality behaviour
  3792. * for this code - maybe...
  3793. */
  3794. case OP_LOADLOC:
  3795. B_reg = A_reg;
  3796. A_reg = stack[-(int)next_byte];
  3797. #ifdef COMMON
  3798. exit_count = 1;
  3799. #endif
  3800. continue;
  3801. case OP_LOADLOC0:
  3802. B_reg = A_reg;
  3803. A_reg = stack[-0];
  3804. #ifdef COMMON
  3805. exit_count = 1;
  3806. #endif
  3807. continue;
  3808. case OP_LOADLOC1:
  3809. B_reg = A_reg;
  3810. A_reg = stack[-1];
  3811. #ifdef COMMON
  3812. exit_count = 1;
  3813. #endif
  3814. continue;
  3815. case OP_LOADLOC2:
  3816. B_reg = A_reg;
  3817. A_reg = stack[-2];
  3818. #ifdef COMMON
  3819. exit_count = 1;
  3820. #endif
  3821. continue;
  3822. case OP_LOADLOC3:
  3823. B_reg = A_reg;
  3824. A_reg = stack[-3];
  3825. #ifdef COMMON
  3826. exit_count = 1;
  3827. #endif
  3828. continue;
  3829. case OP_LOADLOC4:
  3830. B_reg = A_reg;
  3831. A_reg = stack[-4];
  3832. #ifdef COMMON
  3833. exit_count = 1;
  3834. #endif
  3835. continue;
  3836. case OP_LOADLOC5:
  3837. B_reg = A_reg;
  3838. A_reg = stack[-5];
  3839. #ifdef COMMON
  3840. exit_count = 1;
  3841. #endif
  3842. continue;
  3843. case OP_LOADLOC6:
  3844. B_reg = A_reg;
  3845. A_reg = stack[-6];
  3846. #ifdef COMMON
  3847. exit_count = 1;
  3848. #endif
  3849. continue;
  3850. case OP_LOADLOC7:
  3851. B_reg = A_reg;
  3852. A_reg = stack[-7];
  3853. #ifdef COMMON
  3854. exit_count = 1;
  3855. #endif
  3856. continue;
  3857. case OP_LOADLOC8:
  3858. B_reg = A_reg;
  3859. A_reg = stack[-8];
  3860. #ifdef COMMON
  3861. exit_count = 1;
  3862. #endif
  3863. continue;
  3864. case OP_LOADLOC9:
  3865. B_reg = A_reg;
  3866. A_reg = stack[-9];
  3867. #ifdef COMMON
  3868. exit_count = 1;
  3869. #endif
  3870. continue;
  3871. case OP_LOADLOC10:
  3872. B_reg = A_reg;
  3873. A_reg = stack[-10];
  3874. #ifdef COMMON
  3875. exit_count = 1;
  3876. #endif
  3877. continue;
  3878. case OP_LOADLOC11:
  3879. B_reg = A_reg;
  3880. A_reg = stack[-11];
  3881. #ifdef COMMON
  3882. exit_count = 1;
  3883. #endif
  3884. continue;
  3885. case OP_CAR:
  3886. if (car_legal(A_reg))
  3887. { A_reg = qcar(A_reg);
  3888. #ifdef COMMON
  3889. exit_count = 1;
  3890. #endif
  3891. continue;
  3892. }
  3893. errcode = err_bad_car;
  3894. C_stack = stack;
  3895. goto error_1_A;
  3896. case OP_CARLOC0:
  3897. B_reg = A_reg;
  3898. A_reg = stack[-0];
  3899. if (car_legal(A_reg))
  3900. { A_reg = qcar(A_reg);
  3901. #ifdef COMMON
  3902. exit_count = 1;
  3903. #endif
  3904. continue;
  3905. }
  3906. errcode = err_bad_car;
  3907. C_stack = stack;
  3908. goto error_1_A;
  3909. case OP_CARLOC1:
  3910. B_reg = A_reg;
  3911. A_reg = stack[-1];
  3912. if (car_legal(A_reg))
  3913. { A_reg = qcar(A_reg);
  3914. #ifdef COMMON
  3915. exit_count = 1;
  3916. #endif
  3917. continue;
  3918. }
  3919. errcode = err_bad_car;
  3920. C_stack = stack;
  3921. goto error_1_A;
  3922. case OP_CARLOC2:
  3923. B_reg = A_reg;
  3924. A_reg = stack[-2];
  3925. if (car_legal(A_reg))
  3926. { A_reg = qcar(A_reg);
  3927. #ifdef COMMON
  3928. exit_count = 1;
  3929. #endif
  3930. continue;
  3931. }
  3932. errcode = err_bad_car;
  3933. C_stack = stack;
  3934. goto error_1_A;
  3935. case OP_CARLOC3:
  3936. B_reg = A_reg;
  3937. A_reg = stack[-3];
  3938. if (car_legal(A_reg))
  3939. { A_reg = qcar(A_reg);
  3940. #ifdef COMMON
  3941. exit_count = 1;
  3942. #endif
  3943. continue;
  3944. }
  3945. errcode = err_bad_car;
  3946. C_stack = stack;
  3947. goto error_1_A;
  3948. case OP_CARLOC4:
  3949. B_reg = A_reg;
  3950. A_reg = stack[-4];
  3951. if (car_legal(A_reg))
  3952. { A_reg = qcar(A_reg);
  3953. #ifdef COMMON
  3954. exit_count = 1;
  3955. #endif
  3956. continue;
  3957. }
  3958. errcode = err_bad_car;
  3959. C_stack = stack;
  3960. goto error_1_A;
  3961. case OP_CARLOC5:
  3962. B_reg = A_reg;
  3963. A_reg = stack[-5];
  3964. if (car_legal(A_reg))
  3965. { A_reg = qcar(A_reg);
  3966. #ifdef COMMON
  3967. exit_count = 1;
  3968. #endif
  3969. continue;
  3970. }
  3971. errcode = err_bad_car;
  3972. C_stack = stack;
  3973. goto error_1_A;
  3974. case OP_CARLOC6:
  3975. B_reg = A_reg;
  3976. A_reg = stack[-6];
  3977. if (car_legal(A_reg))
  3978. { A_reg = qcar(A_reg);
  3979. #ifdef COMMON
  3980. exit_count = 1;
  3981. #endif
  3982. continue;
  3983. }
  3984. errcode = err_bad_car;
  3985. C_stack = stack;
  3986. goto error_1_A;
  3987. case OP_CARLOC7:
  3988. B_reg = A_reg;
  3989. A_reg = stack[-7];
  3990. if (car_legal(A_reg))
  3991. { A_reg = qcar(A_reg);
  3992. #ifdef COMMON
  3993. exit_count = 1;
  3994. #endif
  3995. continue;
  3996. }
  3997. errcode = err_bad_car;
  3998. C_stack = stack;
  3999. goto error_1_A;
  4000. case OP_CARLOC8:
  4001. B_reg = A_reg;
  4002. A_reg = stack[-8];
  4003. if (car_legal(A_reg))
  4004. { A_reg = qcar(A_reg);
  4005. #ifdef COMMON
  4006. exit_count = 1;
  4007. #endif
  4008. continue;
  4009. }
  4010. errcode = err_bad_car;
  4011. C_stack = stack;
  4012. goto error_1_A;
  4013. case OP_CARLOC9:
  4014. B_reg = A_reg;
  4015. A_reg = stack[-9];
  4016. if (car_legal(A_reg))
  4017. { A_reg = qcar(A_reg);
  4018. #ifdef COMMON
  4019. exit_count = 1;
  4020. #endif
  4021. continue;
  4022. }
  4023. errcode = err_bad_car;
  4024. C_stack = stack;
  4025. goto error_1_A;
  4026. case OP_CARLOC10:
  4027. B_reg = A_reg;
  4028. A_reg = stack[-10];
  4029. if (car_legal(A_reg))
  4030. { A_reg = qcar(A_reg);
  4031. #ifdef COMMON
  4032. exit_count = 1;
  4033. #endif
  4034. continue;
  4035. }
  4036. errcode = err_bad_car;
  4037. C_stack = stack;
  4038. goto error_1_A;
  4039. case OP_CARLOC11:
  4040. B_reg = A_reg;
  4041. A_reg = stack[-11];
  4042. if (car_legal(A_reg))
  4043. { A_reg = qcar(A_reg);
  4044. #ifdef COMMON
  4045. exit_count = 1;
  4046. #endif
  4047. continue;
  4048. }
  4049. errcode = err_bad_car;
  4050. C_stack = stack;
  4051. goto error_1_A;
  4052. case OP_CDR:
  4053. if (car_legal(A_reg))
  4054. { A_reg = qcdr(A_reg);
  4055. #ifdef COMMON
  4056. exit_count = 1;
  4057. #endif
  4058. continue;
  4059. }
  4060. errcode = err_bad_cdr;
  4061. C_stack = stack;
  4062. goto error_1_A;
  4063. case OP_STORELOC:
  4064. stack[-(int)next_byte] = A_reg;
  4065. /* NB this opcode does not pop the A/B stack */
  4066. continue;
  4067. case OP_STORELOC0:
  4068. stack[-0] = A_reg;
  4069. continue;
  4070. case OP_STORELOC1:
  4071. stack[-1] = A_reg;
  4072. continue;
  4073. case OP_STORELOC2:
  4074. stack[-2] = A_reg;
  4075. continue;
  4076. case OP_STORELOC3:
  4077. stack[-3] = A_reg;
  4078. continue;
  4079. case OP_STORELOC4:
  4080. stack[-4] = A_reg;
  4081. continue;
  4082. case OP_STORELOC5:
  4083. stack[-5] = A_reg;
  4084. continue;
  4085. case OP_STORELOC6:
  4086. stack[-6] = A_reg;
  4087. continue;
  4088. case OP_STORELOC7:
  4089. stack[-7] = A_reg;
  4090. continue;
  4091. case OP_LOADLIT:
  4092. /*
  4093. * Associated with each body of byte-codes there is a literal vector,
  4094. * and this opcode loads values from same. The literal vector has a
  4095. * header word and is tagged as a Lisp vector.
  4096. */
  4097. B_reg = A_reg;
  4098. A_reg = elt(litvec, next_byte);
  4099. #ifdef COMMON
  4100. exit_count = 1;
  4101. #endif
  4102. continue;
  4103. case OP_LOADLIT1:
  4104. B_reg = A_reg;
  4105. A_reg = elt(litvec, 1);
  4106. #ifdef COMMON
  4107. exit_count = 1;
  4108. #endif
  4109. continue;
  4110. case OP_LOADLIT2:
  4111. B_reg = A_reg;
  4112. A_reg = elt(litvec, 2);
  4113. #ifdef COMMON
  4114. exit_count = 1;
  4115. #endif
  4116. continue;
  4117. case OP_LOADLIT3:
  4118. B_reg = A_reg;
  4119. A_reg = elt(litvec, 3);
  4120. #ifdef COMMON
  4121. exit_count = 1;
  4122. #endif
  4123. continue;
  4124. case OP_LOADLIT4:
  4125. B_reg = A_reg;
  4126. A_reg = elt(litvec, 4);
  4127. #ifdef COMMON
  4128. exit_count = 1;
  4129. #endif
  4130. continue;
  4131. case OP_LOADLIT5:
  4132. B_reg = A_reg;
  4133. A_reg = elt(litvec, 5);
  4134. #ifdef COMMON
  4135. exit_count = 1;
  4136. #endif
  4137. continue;
  4138. case OP_LOADLIT6:
  4139. B_reg = A_reg;
  4140. A_reg = elt(litvec, 6);
  4141. #ifdef COMMON
  4142. exit_count = 1;
  4143. #endif
  4144. continue;
  4145. case OP_LOADLIT7:
  4146. B_reg = A_reg;
  4147. A_reg = elt(litvec, 7);
  4148. #ifdef COMMON
  4149. exit_count = 1;
  4150. #endif
  4151. continue;
  4152. case OP_LOADFREE:
  4153. /*
  4154. * Load the value of a free (GLOBAL, SPECIAL, FLUID) variable
  4155. */
  4156. B_reg = A_reg;
  4157. A_reg = qvalue(elt(litvec, next_byte));
  4158. #ifdef COMMON
  4159. exit_count = 1;
  4160. #endif
  4161. continue;
  4162. case OP_LOADFREE1:
  4163. B_reg = A_reg;
  4164. A_reg = qvalue(elt(litvec, 1));
  4165. #ifdef COMMON
  4166. exit_count = 1;
  4167. #endif
  4168. continue;
  4169. case OP_LOADFREE2:
  4170. B_reg = A_reg;
  4171. A_reg = qvalue(elt(litvec, 2));
  4172. #ifdef COMMON
  4173. exit_count = 1;
  4174. #endif
  4175. continue;
  4176. case OP_LOADFREE3:
  4177. B_reg = A_reg;
  4178. A_reg = qvalue(elt(litvec, 3));
  4179. #ifdef COMMON
  4180. exit_count = 1;
  4181. #endif
  4182. continue;
  4183. case OP_LOADFREE4:
  4184. B_reg = A_reg;
  4185. A_reg = qvalue(elt(litvec, 4));
  4186. #ifdef COMMON
  4187. exit_count = 1;
  4188. #endif
  4189. continue;
  4190. case OP_JUMPNIL:
  4191. xppc = ppc;
  4192. ppc++;
  4193. if (A_reg == nil) ppc = ppc + *xppc;
  4194. continue;
  4195. case OP_JUMPNIL_B:
  4196. xppc = ppc;
  4197. ppc++;
  4198. if (A_reg == nil)
  4199. { ppc = ppc - *xppc;
  4200. /*
  4201. * To ensure that all code is interruptable I poll on every backwards
  4202. * jump. The SIGINT event simulates a stack overflow, and the
  4203. * consequent entry to the garbage collector then handles the event.
  4204. */
  4205. #ifndef OUT_OF_LINE
  4206. #ifdef SOFTWARE_TICKS
  4207. if (--countdown < 0) deal_with_tick();
  4208. #endif
  4209. if (stack >= stacklimit)
  4210. { C_stack = stack;
  4211. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4212. nil = C_nil;
  4213. if (exception_pending()) goto error_exit;
  4214. stack = C_stack; /* may have been changed by GC */
  4215. }
  4216. #else
  4217. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4218. goto error_exit;
  4219. stack = C_stack;
  4220. #endif
  4221. }
  4222. continue;
  4223. case OP_JUMPT:
  4224. xppc = ppc;
  4225. ppc++;
  4226. if (A_reg != nil) ppc = ppc + *xppc;
  4227. continue;
  4228. case OP_JUMPT_B:
  4229. xppc = ppc;
  4230. ppc++;
  4231. if (A_reg != nil)
  4232. { ppc = ppc - *xppc;
  4233. #ifndef OUT_OF_LINE
  4234. #ifdef SOFTWARE_TICKS
  4235. if (--countdown < 0) deal_with_tick();
  4236. #endif
  4237. if (stack >= stacklimit)
  4238. { C_stack = stack;
  4239. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4240. nil = C_nil;
  4241. if (exception_pending()) goto error_exit;
  4242. stack = C_stack; /* may have been changed by GC */
  4243. }
  4244. #else
  4245. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4246. goto error_exit;
  4247. stack = C_stack;
  4248. #endif
  4249. }
  4250. continue;
  4251. case OP_JUMPNIL_L:
  4252. w = next_byte;
  4253. xppc = ppc;
  4254. ppc++;
  4255. if (A_reg == nil) ppc = ppc + ((w << 8) + *xppc);
  4256. continue;
  4257. case OP_JUMPNIL_BL:
  4258. w = next_byte;
  4259. xppc = ppc;
  4260. ppc++;
  4261. if (A_reg == nil)
  4262. { ppc = ppc - ((w << 8) + *xppc);
  4263. #ifndef OUT_OF_LINE
  4264. #ifdef SOFTWARE_TICKS
  4265. if (--countdown < 0) deal_with_tick();
  4266. #endif
  4267. if (stack >= stacklimit)
  4268. { C_stack = stack;
  4269. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4270. nil = C_nil;
  4271. if (exception_pending()) goto error_exit;
  4272. stack = C_stack; /* may have been changed by GC */
  4273. }
  4274. #else
  4275. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4276. goto error_exit;
  4277. stack = C_stack;
  4278. #endif
  4279. }
  4280. continue;
  4281. case OP_JUMPT_L:
  4282. w = next_byte;
  4283. xppc = ppc;
  4284. ppc++;
  4285. if (A_reg != nil) ppc = ppc + ((w << 8) + *xppc);
  4286. continue;
  4287. case OP_JUMPT_BL:
  4288. w = next_byte;
  4289. xppc = ppc;
  4290. ppc++;
  4291. if (A_reg != nil)
  4292. { ppc = ppc - ((w << 8) + *xppc);
  4293. #ifndef OUT_OF_LINE
  4294. #ifdef SOFTWARE_TICKS
  4295. if (--countdown < 0) deal_with_tick();
  4296. #endif
  4297. if (stack >= stacklimit)
  4298. { C_stack = stack;
  4299. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4300. nil = C_nil;
  4301. if (exception_pending()) goto error_exit;
  4302. stack = C_stack; /* may have been changed by GC */
  4303. }
  4304. #else
  4305. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4306. goto error_exit;
  4307. stack = C_stack;
  4308. #endif
  4309. }
  4310. continue;
  4311. case OP_BUILTIN1:
  4312. f1 = one_arg_functions[next_byte];
  4313. /* BUILTIN1: A=fn(A); */
  4314. save_pc();
  4315. C_stack = stack;
  4316. A_reg = f1(nil, A_reg);
  4317. nil = C_nil;
  4318. if (exception_pending()) goto error_exit;
  4319. stack = C_stack;
  4320. restore_pc();
  4321. continue;
  4322. case OP_BUILTIN2:
  4323. f2 = two_arg_functions[next_byte];
  4324. /* BUILTIN2: A=fn(B,A); */
  4325. save_pc();
  4326. C_stack = stack;
  4327. A_reg = f2(nil, B_reg, A_reg);
  4328. nil = C_nil;
  4329. if (exception_pending()) goto error_exit;
  4330. stack = C_stack;
  4331. restore_pc();
  4332. continue;
  4333. case OP_EXIT:
  4334. /*
  4335. * Here I assume that exit_count has been set up already. Note also that
  4336. * there is no need to do any LOSE operations just before an EXIT since the
  4337. * stack gets reset automatically here.
  4338. */
  4339. #ifndef NO_BYTECOUNT
  4340. qcount(elt(litvec, 0)) += opcodes;
  4341. #endif
  4342. C_stack = entry_stack;
  4343. return A_reg;
  4344. case OP_PUSH:
  4345. push(A_reg);
  4346. continue;
  4347. case OP_PUSHNIL:
  4348. push(nil);
  4349. continue;
  4350. case OP_PUSHNIL2:
  4351. push2(nil, nil);
  4352. continue;
  4353. case OP_PUSHNIL3:
  4354. push3(nil, nil, nil);
  4355. continue;
  4356. case OP_POP:
  4357. B_reg = A_reg;
  4358. pop(A_reg);
  4359. #ifdef COMMON
  4360. exit_count = 1;
  4361. #endif
  4362. continue;
  4363. case OP_LOSE:
  4364. popv(1);
  4365. continue;
  4366. case OP_LOSE2:
  4367. popv(2);
  4368. continue;
  4369. case OP_LOSE3:
  4370. popv(3);
  4371. continue;
  4372. case OP_LOSES:
  4373. popv(next_byte);
  4374. continue;
  4375. case OP_CONS: /* A_reg = cons(B_reg, A_reg); */
  4376. #ifndef OUT_OF_LINE
  4377. r1 = (Lisp_Object)((char *)fringe - sizeof(Cons_Cell));
  4378. qcar(r1) = B_reg;
  4379. qcdr(r1) = A_reg;
  4380. fringe = r1;
  4381. if ((char *)r1 <= (char *)heaplimit)
  4382. { save_pc();
  4383. C_stack = stack;
  4384. A_reg = reclaim((Lisp_Object)((char *)r1 + TAG_CONS),
  4385. "bytecoded cons", GC_CONS, 0);
  4386. nil = C_nil;
  4387. if (exception_pending()) goto error_exit;
  4388. stack = C_stack; /* may have been changed by GC */
  4389. restore_pc();
  4390. }
  4391. else A_reg = (Lisp_Object)((char *)r1 + TAG_CONS);
  4392. #else
  4393. save_pc();
  4394. C_stack = stack;
  4395. A_reg = cons(B_reg, A_reg);
  4396. nil = C_nil;
  4397. if (exception_pending()) goto error_exit;
  4398. stack = C_stack; /* may have been changed by GC */
  4399. restore_pc();
  4400. #endif
  4401. #ifdef COMMON
  4402. exit_count = 1;
  4403. #endif
  4404. continue;
  4405. /*
  4406. * FASTGET n
  4407. * 0 <= n < 64 (GET A_reg property_n)
  4408. * 64 <= n < 128 (GET A_reg property_n B_reg)
  4409. * 128 <= n < 192 (FLAGP A_reg property_n)
  4410. */
  4411. case OP_FASTGET:
  4412. w = next_byte;
  4413. #ifdef RECORD_GET
  4414. n = 0;
  4415. #endif
  4416. if (symbolp(A_reg))
  4417. { r1 = qfastgets(A_reg);
  4418. if (r1 == nil)
  4419. { if (w & 0x40) A_reg = B_reg;
  4420. else A_reg = nil;
  4421. }
  4422. else
  4423. { A_reg = elt(r1, w & 0x7f);
  4424. if (A_reg == SPID_NOPROP)
  4425. { if (w & 0x40) A_reg = B_reg;
  4426. else A_reg = nil;
  4427. #ifdef RECORD_GET
  4428. n = 1;
  4429. #endif
  4430. }
  4431. else if (w & 0x80) A_reg = lisp_true;
  4432. }
  4433. }
  4434. else A_reg = nil;
  4435. #ifdef RECORD_GET
  4436. save_pc(); C_stack = stack;
  4437. record_get(elt(fastget_names, w & 0x7f), n);
  4438. nil = C_nil;
  4439. if (exception_pending()) goto error_exit;
  4440. stack = C_stack; restore_pc();
  4441. #endif
  4442. continue;
  4443. case OP_LITGET:
  4444. B_reg = A_reg;
  4445. A_reg = elt(litvec, next_byte);
  4446. goto perform_get;
  4447. case OP_GET: /* A = get(B, A) */
  4448. goto perform_get;
  4449. }
  4450. /*
  4451. * Now various code-fragments that want to be inside the "for (;;)" loop
  4452. * but outside the "switch".
  4453. */
  4454. perform_get:
  4455. #ifdef COMMON
  4456. /*
  4457. * This direct byte code supports the 2-argument version of GET. The
  4458. * 3-arg version should be done as a regular general call.
  4459. */
  4460. save_pc(); C_stack = stack;
  4461. A_reg = get(B_reg, A_reg, nil);
  4462. nil = C_nil;
  4463. if (exception_pending()) goto error_exit;
  4464. stack = C_stack; restore_pc();
  4465. exit_count = 1;
  4466. continue;
  4467. #else
  4468. #ifndef OUT_OF_LINE
  4469. /*
  4470. * Get is very heavily used - so I have in-lined it here since it is fairly
  4471. * short code and ought not to overload register allocation. See "fns1.c"
  4472. * for the regular version of this code.
  4473. */
  4474. if (!symbolp(B_reg))
  4475. {
  4476. #ifdef RECORD_GET
  4477. save_pc(); C_stack = stack;
  4478. record_get(A_reg, NO);
  4479. nil = C_nil;
  4480. if (exception_pending()) goto error_exit;
  4481. stack = C_stack; restore_pc();
  4482. #endif
  4483. A_reg = nil;
  4484. continue;
  4485. }
  4486. else
  4487. { if (symbolp(A_reg) &&
  4488. (n = header_fastget(qheader(A_reg))) != 0)
  4489. { if ((r1 = qfastgets(B_reg)) == nil)
  4490. {
  4491. #ifdef RECORD_GET
  4492. save_pc(); C_stack = stack;
  4493. record_get(A_reg, NO);
  4494. nil = C_nil;
  4495. if (exception_pending()) goto error_exit;
  4496. stack = C_stack; restore_pc();
  4497. #endif
  4498. continue;
  4499. }
  4500. #ifdef RECORD_GET
  4501. push(r1);
  4502. save_pc(); C_stack = stack;
  4503. record_get(A_reg, elt(r1, n-1) != nil);
  4504. nil = C_nil;
  4505. if (exception_pending()) goto error_exit;
  4506. stack = C_stack; restore_pc();
  4507. pop(r1);
  4508. #endif
  4509. A_reg = elt(r1, n-1);
  4510. if (A_reg == SPID_NOPROP) A_reg = nil;
  4511. continue;
  4512. }
  4513. /*
  4514. * I write out the check on the first two items in the property list
  4515. * longhand, expecting that a match will most often occur there. If
  4516. * I get a match later on I will migrate the entry to the front of the list.
  4517. */
  4518. r1 = qplist(B_reg);
  4519. if (r1 == nil)
  4520. {
  4521. #ifdef RECORD_GET
  4522. save_pc(); C_stack = stack;
  4523. record_get(A_reg, NO);
  4524. nil = C_nil;
  4525. if (exception_pending()) goto error_exit;
  4526. stack = C_stack; restore_pc();
  4527. #endif
  4528. A_reg = nil;
  4529. continue;
  4530. }
  4531. r3 = qcar(r1);
  4532. if (qcar(r3) == A_reg)
  4533. {
  4534. #ifdef RECORD_GET
  4535. save_pc(); C_stack = stack;
  4536. record_get(A_reg, YES);
  4537. nil = C_nil;
  4538. if (exception_pending()) goto error_exit;
  4539. stack = C_stack; restore_pc();
  4540. #endif
  4541. A_reg = qcdr(r3);
  4542. continue;
  4543. }
  4544. r1 = qcdr(r1);
  4545. if (r1 == nil)
  4546. {
  4547. #ifdef RECORD_GET
  4548. save_pc(); C_stack = stack;
  4549. record_get(A_reg, NO);
  4550. nil = C_nil;
  4551. if (exception_pending()) goto error_exit;
  4552. stack = C_stack; restore_pc();
  4553. #endif
  4554. A_reg = nil;
  4555. continue;
  4556. }
  4557. r3 = qcar(r1);
  4558. if (qcar(r3) == A_reg)
  4559. {
  4560. #ifdef RECORD_GET
  4561. save_pc(); C_stack = stack;
  4562. record_get(A_reg, YES);
  4563. nil = C_nil;
  4564. if (exception_pending()) goto error_exit;
  4565. stack = C_stack; restore_pc();
  4566. #endif
  4567. A_reg = qcdr(r3);
  4568. continue;
  4569. }
  4570. r2 = r1;
  4571. r1 = qcdr(r1);
  4572. if (r1 == nil)
  4573. {
  4574. #ifdef RECORD_GET
  4575. save_pc(); C_stack = stack;
  4576. record_get(A_reg, NO);
  4577. nil = C_nil;
  4578. if (exception_pending()) goto error_exit;
  4579. stack = C_stack; restore_pc();
  4580. #endif
  4581. A_reg = nil;
  4582. continue;
  4583. }
  4584. for (;;)
  4585. { r3 = qcar(r1);
  4586. if (qcar(r3) == A_reg)
  4587. { qcdr(r2) = qcdr(r1);
  4588. qcdr(r1) = qplist(B_reg);
  4589. qplist(B_reg) = r1;
  4590. #ifdef RECORD_GET
  4591. save_pc(); C_stack = stack;
  4592. record_get(A_reg, YES);
  4593. nil = C_nil;
  4594. if (exception_pending()) goto error_exit;
  4595. stack = C_stack; restore_pc();
  4596. #endif
  4597. A_reg = qcdr(r3);
  4598. break;
  4599. }
  4600. r2 = r1;
  4601. r1 = qcdr(r1);
  4602. if (r1 == nil)
  4603. {
  4604. #ifdef RECORD_GET
  4605. save_pc(); C_stack = stack;
  4606. record_get(A_reg, NO);
  4607. nil = C_nil;
  4608. if (exception_pending()) goto error_exit;
  4609. stack = C_stack; restore_pc();
  4610. #endif
  4611. A_reg = nil;
  4612. break;
  4613. }
  4614. }
  4615. }
  4616. continue;
  4617. #else
  4618. save_pc(); C_stack = stack;
  4619. A_reg = get(B_reg, A_reg);
  4620. nil = C_nil;
  4621. if (exception_pending()) goto error_exit;
  4622. stack = C_stack; restore_pc();
  4623. exit_count = 1;
  4624. continue;
  4625. #endif
  4626. #endif
  4627. caar:
  4628. if (car_legal(A_reg)) A_reg = qcar(A_reg);
  4629. else
  4630. { errcode = err_bad_car;
  4631. C_stack = stack;
  4632. goto error_1_A;
  4633. }
  4634. if (car_legal(A_reg))
  4635. { A_reg = qcar(A_reg);
  4636. #ifdef COMMON
  4637. exit_count = 1;
  4638. #endif
  4639. continue;
  4640. }
  4641. errcode = err_bad_car;
  4642. C_stack = stack;
  4643. goto error_1_A;
  4644. catcher:
  4645. A_reg = cons(A_reg, catch_tags);
  4646. nil = C_nil;
  4647. if (exception_pending()) goto error_exit;
  4648. catch_tags = A_reg;
  4649. push3(fixnum_of_int(w+1), catch_tags, SPID_CATCH);
  4650. continue;
  4651. call0: r1 = elt(litvec, fname);
  4652. /*
  4653. * NB I set fname to be the literal-vector offset in the line above so that
  4654. * it will be possible to find the name of the function that was called
  4655. * if I have to display a backtrace.
  4656. */
  4657. f345 = qfnn(r1);
  4658. /* CALL0: A=fn() */
  4659. #ifdef DEBUG
  4660. if (f345 == NULL)
  4661. { term_printf("Illegal function\n");
  4662. my_exit(EXIT_FAILURE);
  4663. }
  4664. #endif
  4665. save_pc();
  4666. C_stack = stack;
  4667. A_reg = f345(qenv(r1), 0);
  4668. nil = C_nil;
  4669. if (exception_pending()) goto call_error_exit;
  4670. stack = C_stack;
  4671. restore_pc();
  4672. continue;
  4673. jcall0: r1 = elt(litvec, fname);
  4674. f345 = qfnn(r1);
  4675. #ifdef DEBUG
  4676. if (f345 == NULL)
  4677. { term_printf("Illegal function\n");
  4678. my_exit(EXIT_FAILURE);
  4679. }
  4680. #endif
  4681. #ifndef NO_BYTECOUNT
  4682. qcount(elt(litvec, 0)) += opcodes;
  4683. opcodes = 30;
  4684. #endif
  4685. #ifndef DO_NOT_BOTHER_TO_POLL_ON_TAILCALL
  4686. /*
  4687. * The issue here is cases such as
  4688. * (de f1 (x) (f2 x))
  4689. * (de f2 (x) (f1 x))
  4690. * where the bodies of the functions so not do enough work that polling
  4691. * for interrupts or for window-system updates will happen. Thus it seems
  4692. * I need to perform a polling operation as part of the tail-call sequence.
  4693. * I leave a (long-winded) option to disable this and thereby save a really
  4694. * minor amount of time and space at the loss of a fairly minor amount of
  4695. * safety.
  4696. */
  4697. #ifndef OUT_OF_LINE
  4698. #ifdef SOFTWARE_TICKS
  4699. if (--countdown < 0) deal_with_tick();
  4700. #endif
  4701. if (stack >= stacklimit)
  4702. { C_stack = stack;
  4703. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4704. nil = C_nil;
  4705. if (exception_pending()) goto error_exit;
  4706. stack = C_stack; /* may have been changed by GC */
  4707. }
  4708. #else
  4709. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4710. goto error_exit;
  4711. stack = C_stack;
  4712. #endif
  4713. #endif
  4714. if (f345 == bytecoded0)
  4715. { lit = qenv(r1);
  4716. codevec = qcar(lit);
  4717. litvec = qcdr(lit);
  4718. stack = entry_stack;
  4719. ppc = (unsigned char *)data_of_bps(codevec);
  4720. continue;
  4721. }
  4722. else if (f345 == tracebytecoded0)
  4723. { r2 = elt(litvec, 0);
  4724. lit = qenv(r1);
  4725. codevec = qcar(lit);
  4726. litvec = qcdr(lit);
  4727. /*
  4728. * I make TRACECODED a special case, in effect writing it out in-line
  4729. * here, to avoid some ugly confusion with backtraces following tail calls.
  4730. */
  4731. stack = entry_stack;
  4732. push3(litvec, codevec, r2);
  4733. C_stack = stack;
  4734. trace_print_0(elt(litvec, 0), stack);
  4735. nil = C_nil;
  4736. if (exception_pending()) goto error_exit;
  4737. popv(1);
  4738. pop2(codevec, litvec);
  4739. ppc = (unsigned char *)data_of_bps(codevec);
  4740. continue;
  4741. }
  4742. C_stack = entry_stack;
  4743. return f345(qenv(r1), 0);
  4744. call1: r1 = elt(litvec, fname);
  4745. f1 = qfn1(r1);
  4746. #ifdef DEBUG
  4747. if (f1 == NULL)
  4748. { term_printf("Illegal function\n");
  4749. my_exit(EXIT_FAILURE);
  4750. }
  4751. #endif
  4752. /* CALL1: A=fn(A); */
  4753. save_pc();
  4754. C_stack = stack;
  4755. A_reg = f1(qenv(r1), A_reg);
  4756. nil = C_nil;
  4757. if (exception_pending()) goto call_error_exit;
  4758. stack = C_stack;
  4759. restore_pc();
  4760. continue;
  4761. jcall1: r1 = elt(litvec, fname);
  4762. f1 = qfn1(r1);
  4763. #ifdef DEBUG
  4764. if (f1 == NULL)
  4765. { term_printf("Illegal function\n");
  4766. my_exit(EXIT_FAILURE);
  4767. }
  4768. #endif
  4769. #ifndef NO_BYTECOUNT
  4770. qcount(elt(litvec, 0)) += opcodes;
  4771. opcodes = 30;
  4772. #endif
  4773. #ifndef DO_NOT_BOTHER_TO_POLL_ON_TAILCALL
  4774. /*
  4775. * The issue here is cases such as
  4776. * (de f1 (x) (f2 x))
  4777. * (de f2 (x) (f1 x))
  4778. * where the bodies of the functions so not do enough work that polling
  4779. * for interrupts or for window-system updates will happen. Thus it seems
  4780. * I need to perform a polling operation as part of the tail-call sequence.
  4781. * I leave a (long-winded) option to disable this and thereby save a really
  4782. * minor amount of time and space at the loss of a fairly minor amount of
  4783. * safety.
  4784. */
  4785. #ifndef OUT_OF_LINE
  4786. #ifdef SOFTWARE_TICKS
  4787. if (--countdown < 0) deal_with_tick();
  4788. #endif
  4789. if (stack >= stacklimit)
  4790. { C_stack = stack;
  4791. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4792. nil = C_nil;
  4793. if (exception_pending()) goto error_exit;
  4794. stack = C_stack; /* may have been changed by GC */
  4795. }
  4796. #else
  4797. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4798. goto error_exit;
  4799. stack = C_stack;
  4800. #endif
  4801. #endif
  4802. if (f1 == bytecoded1)
  4803. { lit = qenv(r1);
  4804. codevec = qcar(lit);
  4805. litvec = qcdr(lit);
  4806. stack = entry_stack;
  4807. push(A_reg);
  4808. ppc = (unsigned char *)data_of_bps(codevec);
  4809. continue;
  4810. }
  4811. else if (f1 == tracebytecoded1)
  4812. { r2 = elt(litvec, 0);
  4813. lit = qenv(r1);
  4814. codevec = qcar(lit);
  4815. litvec = qcdr(lit);
  4816. stack = entry_stack;
  4817. push(A_reg);
  4818. push3(litvec, codevec, r2);
  4819. C_stack = stack;
  4820. trace_print_1(elt(litvec, 0), stack);
  4821. nil = C_nil;
  4822. if (exception_pending()) goto error_exit;
  4823. popv(1);
  4824. pop2(codevec, litvec);
  4825. ppc = (unsigned char *)data_of_bps(codevec);
  4826. continue;
  4827. }
  4828. C_stack = entry_stack;
  4829. return f1(qenv(r1), A_reg);
  4830. call2: r1 = elt(litvec, fname);
  4831. f2 = qfn2(r1);
  4832. #ifdef DEBUG
  4833. if (f2 == NULL)
  4834. { term_printf("Illegal function\n");
  4835. my_exit(EXIT_FAILURE);
  4836. }
  4837. #endif
  4838. /* CALL2: A=fn(B,A); */
  4839. save_pc();
  4840. C_stack = stack;
  4841. A_reg = f2(qenv(r1), B_reg, A_reg);
  4842. nil = C_nil;
  4843. if (exception_pending()) goto call_error_exit;
  4844. stack = C_stack;
  4845. restore_pc();
  4846. continue;
  4847. call2r: r1 = elt(litvec, fname);
  4848. f2 = qfn2(r1);
  4849. #ifdef DEBUG
  4850. if (f2 == NULL)
  4851. { term_printf("Illegal function\n");
  4852. my_exit(EXIT_FAILURE);
  4853. }
  4854. #endif
  4855. /* CALL2R: A=fn(A,B); NOTE arg order reversed */
  4856. save_pc();
  4857. C_stack = stack;
  4858. A_reg = f2(qenv(r1), A_reg, B_reg);
  4859. nil = C_nil;
  4860. if (exception_pending()) goto call_error_exit;
  4861. stack = C_stack;
  4862. restore_pc();
  4863. continue;
  4864. jcall2: r1 = elt(litvec, fname);
  4865. f2 = qfn2(r1);
  4866. #ifdef DEBUG
  4867. if (f2 == NULL)
  4868. { term_printf("Illegal function\n");
  4869. my_exit(EXIT_FAILURE);
  4870. }
  4871. #endif
  4872. #ifndef NO_BYTECOUNT
  4873. qcount(elt(litvec, 0)) += opcodes;
  4874. opcodes = 30;
  4875. #endif
  4876. #ifndef DO_NOT_BOTHER_TO_POLL_ON_TAILCALL
  4877. /*
  4878. * The issue here is cases such as
  4879. * (de f1 (x) (f2 x))
  4880. * (de f2 (x) (f1 x))
  4881. * where the bodies of the functions so not do enough work that polling
  4882. * for interrupts or for window-system updates will happen. Thus it seems
  4883. * I need to perform a polling operation as part of the tail-call sequence.
  4884. * I leave a (long-winded) option to disable this and thereby save a really
  4885. * minor amount of time and space at the loss of a fairly minor amount of
  4886. * safety.
  4887. */
  4888. #ifndef OUT_OF_LINE
  4889. #ifdef SOFTWARE_TICKS
  4890. if (--countdown < 0) deal_with_tick();
  4891. #endif
  4892. if (stack >= stacklimit)
  4893. { C_stack = stack;
  4894. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4895. nil = C_nil;
  4896. if (exception_pending()) goto error_exit;
  4897. stack = C_stack; /* may have been changed by GC */
  4898. }
  4899. #else
  4900. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4901. goto error_exit;
  4902. stack = C_stack;
  4903. #endif
  4904. #endif
  4905. if (f2 == bytecoded2)
  4906. { lit = qenv(r1);
  4907. codevec = qcar(lit);
  4908. litvec = qcdr(lit);
  4909. stack = entry_stack;
  4910. push2(B_reg, A_reg);
  4911. ppc = (unsigned char *)data_of_bps(codevec);
  4912. continue;
  4913. }
  4914. else if (f2 == tracebytecoded2)
  4915. { r2 = elt(litvec, 0);
  4916. lit = qenv(r1);
  4917. codevec = qcar(lit);
  4918. litvec = qcdr(lit);
  4919. stack = entry_stack;
  4920. push2(B_reg, A_reg);
  4921. push3(litvec, codevec, r2);
  4922. C_stack = stack;
  4923. trace_print_2(elt(litvec, 0), stack);
  4924. nil = C_nil;
  4925. if (exception_pending()) goto error_exit;
  4926. popv(1);
  4927. pop2(codevec, litvec);
  4928. ppc = (unsigned char *)data_of_bps(codevec);
  4929. continue;
  4930. }
  4931. C_stack = entry_stack;
  4932. return f2(qenv(r1), B_reg, A_reg);
  4933. call3: r1 = elt(litvec, fname);
  4934. f345 = qfnn(r1);
  4935. #ifdef DEBUG
  4936. if (f345 == NULL)
  4937. { term_printf("Illegal function\n");
  4938. my_exit(EXIT_FAILURE);
  4939. }
  4940. #endif
  4941. /* CALL3: A=fn(pop(),B,A); */
  4942. save_pc();
  4943. pop(r2);
  4944. C_stack = stack;
  4945. A_reg = f345(qenv(r1), 3, r2, B_reg, A_reg);
  4946. nil = C_nil;
  4947. if (exception_pending()) goto call_error_exit;
  4948. stack = C_stack;
  4949. restore_pc();
  4950. continue;
  4951. jcall3: r1 = elt(litvec, fname);
  4952. f345 = qfnn(r1);
  4953. #ifdef DEBUG
  4954. if (f345 == NULL)
  4955. { term_printf("Illegal function\n");
  4956. my_exit(EXIT_FAILURE);
  4957. }
  4958. #endif
  4959. pop(r2);
  4960. #ifndef NO_BYTECOUNT
  4961. qcount(elt(litvec, 0)) += opcodes;
  4962. opcodes = 30;
  4963. #endif
  4964. #ifndef DO_NOT_BOTHER_TO_POLL_ON_TAILCALL
  4965. /*
  4966. * The issue here is cases such as
  4967. * (de f1 (x) (f2 x))
  4968. * (de f2 (x) (f1 x))
  4969. * where the bodies of the functions so not do enough work that polling
  4970. * for interrupts or for window-system updates will happen. Thus it seems
  4971. * I need to perform a polling operation as part of the tail-call sequence.
  4972. * I leave a (long-winded) option to disable this and thereby save a really
  4973. * minor amount of time and space at the loss of a fairly minor amount of
  4974. * safety.
  4975. */
  4976. #ifndef OUT_OF_LINE
  4977. #ifdef SOFTWARE_TICKS
  4978. if (--countdown < 0) deal_with_tick();
  4979. #endif
  4980. if (stack >= stacklimit)
  4981. { C_stack = stack;
  4982. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  4983. nil = C_nil;
  4984. if (exception_pending()) goto error_exit;
  4985. stack = C_stack; /* may have been changed by GC */
  4986. }
  4987. #else
  4988. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  4989. goto error_exit;
  4990. stack = C_stack;
  4991. #endif
  4992. #endif
  4993. if (f345 == bytecoded3)
  4994. { lit = qenv(r1);
  4995. codevec = qcar(lit);
  4996. litvec = qcdr(lit);
  4997. stack = entry_stack;
  4998. push3(r2, B_reg, A_reg);
  4999. ppc = (unsigned char *)data_of_bps(codevec);
  5000. continue;
  5001. }
  5002. else if (f345 == tracebytecoded3)
  5003. { r3 = elt(litvec, 0);
  5004. lit = qenv(r1);
  5005. codevec = qcar(lit);
  5006. litvec = qcdr(lit);
  5007. stack = entry_stack;
  5008. push3(r2, B_reg, A_reg);
  5009. push3(litvec, codevec, r3);
  5010. C_stack = stack;
  5011. trace_print_3(elt(litvec, 0), stack);
  5012. nil = C_nil;
  5013. if (exception_pending()) goto error_exit;
  5014. popv(1);
  5015. pop2(codevec, litvec);
  5016. ppc = (unsigned char *)data_of_bps(codevec);
  5017. continue;
  5018. }
  5019. C_stack = entry_stack;
  5020. return f345(qenv(r1), 3, r2, B_reg, A_reg);
  5021. jcalln:
  5022. #ifndef NO_BYTECOUNT
  5023. qcount(elt(litvec, 0)) += opcodes;
  5024. opcodes = 30;
  5025. #endif
  5026. #ifndef DO_NOT_BOTHER_TO_POLL_ON_TAILCALL
  5027. /*
  5028. * The issue here is cases such as
  5029. * (de f1 (x) (f2 x))
  5030. * (de f2 (x) (f1 x))
  5031. * where the bodies of the functions so not do enough work that polling
  5032. * for interrupts or for window-system updates will happen. Thus it seems
  5033. * I need to perform a polling operation as part of the tail-call sequence.
  5034. * I leave a (long-winded) option to disable this and thereby save a really
  5035. * minor amount of time and space at the loss of a fairly minor amount of
  5036. * safety.
  5037. */
  5038. #ifndef OUT_OF_LINE
  5039. #ifdef SOFTWARE_TICKS
  5040. if (--countdown < 0) deal_with_tick();
  5041. #endif
  5042. if (stack >= stacklimit)
  5043. { C_stack = stack;
  5044. A_reg = reclaim(A_reg, "stack", GC_STACK, 0);
  5045. nil = C_nil;
  5046. if (exception_pending()) goto error_exit;
  5047. stack = C_stack; /* may have been changed by GC */
  5048. }
  5049. #else
  5050. if ((A_reg = poll_jump_back(stack, A_reg)) == SPID_ERROR)
  5051. goto error_exit;
  5052. stack = C_stack;
  5053. #endif
  5054. #endif
  5055. /*
  5056. * here I could shuffle the stack down quite a lot...
  5057. */
  5058. push2(B_reg, A_reg);
  5059. C_stack = stack;
  5060. A_reg = elt(litvec, fname);
  5061. /*
  5062. * Also if the function is byte-coded I can enter it more directly.
  5063. * It is strongly desirable that I do so so that backtraces will work
  5064. * better.
  5065. */
  5066. A_reg = apply(A_reg, (int)w, nil, A_reg);
  5067. nil = C_nil;
  5068. if (exception_pending()) goto ncall_error_exit;
  5069. #ifndef NO_BYTECOUNT
  5070. qcount(elt(litvec, 0)) += opcodes;
  5071. #endif
  5072. C_stack = entry_stack;
  5073. return A_reg;
  5074. create_closure:
  5075. save_pc();
  5076. A_reg = encapsulate_sp(&stack[-2-(int)w]);
  5077. nil = C_nil;
  5078. if (exception_pending()) goto error_exit;
  5079. pop(B_reg);
  5080. C_stack = stack;
  5081. A_reg = list2star(cfunarg, B_reg, A_reg);
  5082. nil = C_nil;
  5083. if (exception_pending()) goto error_exit;
  5084. stack = C_stack; /* may have been changed by GC */
  5085. restore_pc();
  5086. pop(B_reg);
  5087. continue;
  5088. /*****************************************************************************/
  5089. call_error_exit:
  5090. flip_exception();
  5091. /*
  5092. * I suspect that the next few lines are UNHELPFUL now, so maybe I should
  5093. * get rid of them...
  5094. */
  5095. C_stack = stack;
  5096. if ((exit_reason & UNWIND_ERROR) != 0)
  5097. { A_reg = elt(litvec, fname);
  5098. err_printf("Calling: ");
  5099. loop_print_error(A_reg);
  5100. err_printf("\n");
  5101. nil = C_nil;
  5102. if (exception_pending()) flip_exception();
  5103. }
  5104. goto pop_stack_and_exit;
  5105. ncall_error_exit:
  5106. flip_exception();
  5107. goto pop_stack_and_exit;
  5108. callself_error_exit:
  5109. flip_exception();
  5110. goto pop_stack_and_exit;
  5111. stack_apply_error:
  5112. { flip_exception();
  5113. stack = C_stack;
  5114. pop(r1);
  5115. C_stack = stack;
  5116. /*
  5117. * I suspect that the next few lines are UNHELPFUL now, so maybe I should
  5118. * get rid of them...
  5119. */
  5120. if ((exit_reason & UNWIND_ERROR) != 0)
  5121. { err_printf("apply: ");
  5122. loop_print_error(r1);
  5123. err_printf("\n");
  5124. nil = C_nil;
  5125. if (exception_pending()) flip_exception();
  5126. }
  5127. }
  5128. goto pop_stack_and_exit;
  5129. apply_error:
  5130. flip_exception();
  5131. C_stack = stack;
  5132. /*
  5133. * I suspect that the next few lines are UNHELPFUL now, so maybe I should
  5134. * get rid of them...
  5135. */
  5136. if ((exit_reason & UNWIND_ERROR) != 0)
  5137. { err_printf("apply: ");
  5138. loop_print_error(A_reg);
  5139. err_printf("\n");
  5140. nil = C_nil;
  5141. if (exception_pending()) flip_exception();
  5142. }
  5143. goto pop_stack_and_exit;
  5144. error_exit:
  5145. flip_exception();
  5146. goto pop_stack_and_exit;
  5147. error_1_A:
  5148. C_stack = stack;
  5149. error(1, errcode, A_reg);
  5150. nil = C_nil;
  5151. flip_exception();
  5152. goto pop_stack_and_exit;
  5153. pop_stack_and_exit:
  5154. stack = C_stack;
  5155. /*
  5156. * What follows is my current guess for a good diagnostic...
  5157. */
  5158. if ((exit_reason & UNWIND_ERROR) != 0)
  5159. { err_printf("Inside: ");
  5160. loop_print_error(elt(litvec, 0));
  5161. err_printf("\n");
  5162. nil = C_nil;
  5163. if (exception_pending()) flip_exception();
  5164. }
  5165. /*
  5166. * Here I need to scan down the current stack-frame looking for either a
  5167. * CATCH or an UNWIND-PROTECT marker.
  5168. */
  5169. for (;;)
  5170. { unwind_stack(entry_stack, YES);
  5171. if (C_stack == entry_stack)
  5172. { w = 0;
  5173. break;
  5174. }
  5175. /* Here I have a CATCH/UNWIND record within the current function */
  5176. stack = C_stack;
  5177. pop2(r1, r2);
  5178. C_stack = stack;
  5179. /*
  5180. * If the tag matches exit_tag then I must reset pc based on offset (r2)
  5181. * and continue. NB need to restore A_reg from exit_value.
  5182. */
  5183. w = int_of_fixnum(r2);
  5184. if (qcar(r1) == SPID_PROTECT)
  5185. { /* This is an UNWIND catcher */
  5186. push2(exit_tag, fixnum_of_int(exit_reason));
  5187. #ifdef COMMON
  5188. C_stack = stack;
  5189. A_reg = Lmv_list(nil, exit_value);
  5190. nil = C_nil;
  5191. if (exception_pending()) goto error_exit;
  5192. #endif
  5193. push(A_reg);
  5194. ppc = (unsigned char *)data_of_bps(codevec) + w;
  5195. w = 1;
  5196. break;
  5197. }
  5198. else if (exit_reason == UNWIND_THROW && r1 == exit_tag)
  5199. { ppc = (unsigned char *)data_of_bps(codevec) + w;
  5200. w = 1;
  5201. break;
  5202. }
  5203. }
  5204. if (w)
  5205. { A_reg = exit_value;
  5206. continue;
  5207. }
  5208. #ifndef NO_BYTECOUNT
  5209. qcount(elt(litvec, 0)) += opcodes;
  5210. #endif
  5211. C_stack = entry_stack;
  5212. flip_exception();
  5213. return nil;
  5214. }
  5215. }
  5216. #ifdef __powerc
  5217. /* If you have trouble compiling this just comment it out, please */
  5218. #pragma options(global_optimizer)
  5219. #endif
  5220. /* end of bytes1.c */