cc_x86.s 139 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395
  1. ; Copyright (C) 2016 Jeremiah Orians
  2. ; This file is part of stage0.
  3. ;
  4. ; stage0 is free software: you can redistribute it and/or modify
  5. ; it under the terms of the GNU General Public License as published by
  6. ; the Free Software Foundation, either version 3 of the License, or
  7. ; (at your option) any later version.
  8. ;
  9. ; stage0 is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License
  15. ; along with stage0. If not, see <http://www.gnu.org/licenses/>.
  16. ;; A Minimal C Compiler
  17. ;; type Cells are in the following form:
  18. ;; NEXT (0), SIZE (4), OFFSET (8), INDIRECT (12), MEMBERS (16), TYPE (20), NAME (24)
  19. ;; token_list Cells are in the following form:
  20. ;; NEXT (0), LOCALS/PREV (4), S (8), TYPE/FILENAME (12), ARGUMENTS/DEPTH/LINENUMBER (16)
  21. ;; Each being the length of a register [32bits]
  22. ;;
  23. ;; STACK space: End of program -> 512KB (0x80000) [Could be reduced]
  24. ;; HEAP space: 512KB -> End of Memory
  25. ;; R15 is the STACK pointer
  26. ;; R14 is the HEAP pointer
  27. :start
  28. ;; Prep TAPE_02
  29. LOADUI R0 0x1101
  30. FOPEN_WRITE
  31. ;; Prep TAPE_01
  32. LOADUI R0 0x1100
  33. FOPEN_READ
  34. :main
  35. LOADUI R0 0x1100 ; Pass Tape_01 for reading
  36. LOADR32 R14 @HEAP ; Setup Initial HEAP
  37. LOADUI R15 $STACK ; Setup Initial STACK
  38. CALLI R15 @read_all_tokens ; Read all Tokens in Tape_01
  39. CALLI R15 @reverse_list ; Fix Token Order
  40. ; CALLI R15 @debug_list ; Lets try to debug token errors
  41. MOVE R13 R0 ; Set global_token for future reading
  42. FALSE R12 ; Set struct token_list* out to NULL
  43. FALSE R11 ; Set struct token_list* list_strings to NULL
  44. FALSE R10 ; Set struct token_list* globals_list to NULL
  45. CALLI R15 @program ; Build our output
  46. LOADUI R0 $header_string1 ; Using our first header string
  47. LOADUI R1 0x1101 ; Using Tape_02
  48. CALLI R15 @file_print ; Write string
  49. MOVE R0 R12 ; using Contents of output_list
  50. CALLI R15 @recursive_output ; Recursively write
  51. LOADUI R0 $header_string2 ; Using our second header string
  52. CALLI R15 @file_print ; Write string
  53. MOVE R0 R10 ; using Contents of globals_list
  54. CALLI R15 @recursive_output ; Recursively write
  55. LOADUI R0 $header_string3 ; Using our third header string
  56. CALLI R15 @file_print ; Write string
  57. MOVE R0 R11 ; using Contents of strings_list
  58. CALLI R15 @recursive_output ; Recursively write
  59. HALT ; We have completed compiling our input
  60. ;; Symbol lists
  61. :global_constant_list
  62. NOP
  63. :global_symbol_list
  64. NOP
  65. :global_function_list
  66. NOP
  67. ;; Pointer to initial HEAP ADDRESS
  68. :HEAP
  69. '00080000'
  70. ;; Output strings
  71. :header_string1
  72. "
  73. # Core program
  74. "
  75. :header_string2
  76. "
  77. :ELF_data
  78. # Program global variables
  79. "
  80. :header_string3
  81. "
  82. # Program strings
  83. "
  84. ;; clearWhiteSpace function
  85. ;; Receives a character in R0 and FILE* in R1 and line_num in R11
  86. ;; Returns first non-whitespace character in R0
  87. :clearWhiteSpace
  88. CMPSKIPI.NE R0 32 ; Check for a Space
  89. JUMP @clearWhiteSpace_reset ; Looks like we need to remove a space
  90. CMPSKIPI.NE R0 9 ; Check for a tab
  91. JUMP @clearWhiteSpace_reset ; Looks like we need to remove a tab
  92. CMPSKIPI.E R0 10 ; Check for a newline
  93. RET R15 ; Looks we found a non-whitespace
  94. ADDUI R11 R11 1 ; Increment line number
  95. ;; Fall through to iterate to next char
  96. :clearWhiteSpace_reset
  97. FGETC ; Get next char
  98. JUMP @clearWhiteSpace ; Iterate
  99. ;; consume_byte function
  100. ;; Receives a char in R0, FILE* in R1 and index in R13
  101. ;; Returns next char in R0
  102. :consume_byte
  103. STOREX8 R0 R14 R13 ; Put char onto HEAP
  104. ADDUI R13 R13 1 ; Increment index
  105. FGETC ; Get next char
  106. RET R15
  107. ;; consume_word function
  108. ;; Receives a char in R0, FILE* in R1, FREQUENT in R2 and index in R13
  109. ;; Returns next char in R0
  110. :consume_word
  111. PUSHR R3 R15 ; Protect R3
  112. FALSE R3 ; ESCAPE is FALSE
  113. :consume_word_reset
  114. JUMP.NZ R3 @consume_word_iter1
  115. CMPSKIPI.NE R0 92 ; If \
  116. TRUE R3 ; Looks like we are in an escape
  117. JUMP @consume_word_iter2
  118. :consume_word_iter1
  119. FALSE R3 ; Looks like we are no longer in an escape
  120. :consume_word_iter2
  121. CALLI R15 @consume_byte ; Store the char
  122. JUMP.NZ R3 @consume_word_reset ; If escape loop
  123. CMPJUMPI.NE R0 R2 @consume_word_reset ; if not matching frequent loop
  124. FGETC ; Get a new char to return
  125. POPR R3 R15 ; Restore R3
  126. RET R15
  127. ;; fixup_label function
  128. ;; Receives nothing (But uses R14 as HEAP pointer)
  129. ;; Returns 32 in R0 and no other registers altered
  130. :fixup_label
  131. PUSHR R1 R15 ; Protect R1 from change
  132. PUSHR R2 R15 ; Protect R2 from change
  133. LOADUI R0 58 ; Set HOLD to :
  134. FALSE R2 ; Set I to 0
  135. :fixup_label_reset
  136. MOVE R1 R0 ; Set PREV = HOLD
  137. LOADXU8 R0 R14 R2 ; Read hold_string[I] into HOLD
  138. STOREX8 R1 R14 R2 ; Set hold_string[I] = PREV
  139. ADDUI R2 R2 1 ; increment I
  140. JUMP.NZ R0 @fixup_label_reset ; Loop until we hit a NULL
  141. ;; clean up
  142. ADDUI R2 R2 1 ; increment I
  143. LOADUI R0 32 ; Put 32 in R0
  144. POPR R2 R15 ; Restore R2
  145. POPR R1 R15 ; Restore R1
  146. RET R15
  147. ;; in_set2 function
  148. ;; Receives a Char in R0, FILE* in R1, char* in R2 and index in R13
  149. ;; Return result in R2
  150. :in_set2
  151. PUSHR R3 R15 ; Protect R3 from changes
  152. :in_set2_reset
  153. LOADU8 R3 R2 0 ; Get char from list
  154. JUMP.Z R3 @in_set2_fail ; Stop when 0 == s[0]
  155. CMPJUMPI.E R0 R3 @in_set2_done ; We found a match
  156. ADDUI R2 R2 1 ; Increment to next char
  157. JUMP.NZ R3 @in_set2_reset ; Iterate if not NULL
  158. :in_set2_fail
  159. ;; Looks like not found
  160. FALSE R2 ; Return FALSE
  161. :in_set2_done
  162. CMPSKIPI.E R2 0 ; Provided not FALSE
  163. TRUE R2 ; The result is true
  164. POPR R3 R15 ; Restore R3
  165. RET R15
  166. ;; in_set function
  167. ;; Receives a Char in R0, char* in R1
  168. ;; Return result in R0
  169. :in_set
  170. PUSHR R2 R15 ; Protect R3 from changes
  171. :in_set_reset
  172. LOADU8 R2 R1 0 ; Get char from list
  173. JUMP.Z R2 @in_set_fail ; Stop when 0 == s[0]
  174. CMPJUMPI.E R0 R2 @in_set_done ; We found a match
  175. ADDUI R1 R1 1 ; Increment to next char
  176. JUMP.NZ R2 @in_set_reset ; Iterate if not NULL
  177. :in_set_fail
  178. ;; Looks like not found
  179. FALSE R1 ; Return FALSE
  180. :in_set_done
  181. CMPSKIPI.E R1 0 ; Provided not FALSE
  182. TRUE R2 ; The result is true
  183. MOVE R0 R2 ; Put result in correct place
  184. POPR R2 R15 ; Restore R3
  185. RET R15
  186. ;; Common in_set strings of interest
  187. ;; As Raw strings (") is forbidden and ' has some restrictions
  188. :nice_chars
  189. "
  190. !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
  191. :keyword_chars
  192. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
  193. :variable_chars
  194. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
  195. :symbol_chars
  196. "<=>|&!-"
  197. :hex_chars
  198. "0123456789ABCDEF"
  199. :digit_chars
  200. "0123456789"
  201. :whitespace_chars
  202. "
  203. "
  204. ;; preserve_keyword function
  205. ;; Receives a Char in R0, FILE* in R1 and index in R13
  206. ;; Overwrites R2
  207. ;; Returns next CHAR
  208. :preserve_keyword
  209. LOADUI R2 $keyword_chars ; Using keyword list of chars
  210. CALLI R15 @in_set2 ; Check if in list
  211. JUMP.Z R2 @preserve_keyword_label ; if not in set, stop iterating
  212. :preserve_keyword_reset
  213. CALLI R15 @consume_byte ; Consume another byte
  214. JUMP @preserve_keyword ; Iterate
  215. :preserve_keyword_label
  216. CMPSKIPI.NE R0 58 ; Check for label (:)
  217. CALLI R15 @fixup_label ; Looks like we found one
  218. RET R15
  219. ;; preserve_symbol function
  220. ;; Receives a Char in R0, FILE* in R1 and index in R13
  221. ;; Overwrites R2
  222. ;; Returns next CHAR
  223. :preserve_symbol
  224. LOADUI R2 $symbol_chars ; Using symbol list of chars
  225. CALLI R15 @in_set2 ; Check if in list
  226. JUMP.NZ R2 @preserve_symbol_reset
  227. ;; Looks we didn't find anything we wanted to preserve
  228. RET R15
  229. :preserve_symbol_reset
  230. CALLI R15 @consume_byte ; Consume another byte
  231. JUMP @preserve_symbol ; Iterate
  232. ;; purge_macro function
  233. ;; Receives a Char in R0, FILE* in R1 and index in R13
  234. ;; Returns next CHAR via jumping to get_token_reset
  235. :purge_macro
  236. CMPSKIPI.NE R0 10 ; Check for Line Feed
  237. JUMP @get_token_reset ; Looks like we found it, call it done
  238. FGETC ; Looks like we need another CHAR
  239. JUMP @purge_macro ; Keep looping
  240. ;; get_token function
  241. ;; Receives a Char in R0, FILE* in R1, line_num in R11 and TOKEN in R10
  242. ;; sets index in R13 and current in R12
  243. ;; Overwrites R2
  244. ;; Returns next CHAR
  245. :get_token
  246. PUSHR R12 R15 ; Preserve R12
  247. PUSHR R13 R15 ; Preserve R13
  248. COPY R12 R14 ; Save CURRENT's Address
  249. ADDUI R14 R14 20 ; Update Malloc to free space for string
  250. :get_token_reset
  251. FALSE R13 ; Reset string_index to 0
  252. CALLI R15 @clearWhiteSpace ; Clear any leading whitespace
  253. CMPSKIPI.NE R0 35 ; Deal with # line macros
  254. JUMP @purge_macro ; Returns at get_token_reset
  255. ;; Check for keywords
  256. LOADUI R2 $keyword_chars ; Using keyword list
  257. CALLI R15 @in_set2 ; Check if keyword
  258. JUMP.Z R2 @get_token_symbol ; if not a keyword
  259. CALLI R15 @preserve_keyword ; Yep its a keyword
  260. JUMP @get_token_done ; Be done with token
  261. ;; Check for symbols
  262. :get_token_symbol
  263. LOADUI R2 $symbol_chars ; Using symbol list
  264. CALLI R15 @in_set2 ; Check if symbol
  265. JUMP.Z R2 @get_token_char ; If not a symbol
  266. CALLI R15 @preserve_symbol ; Yep its a symbol
  267. JUMP @get_token_done ; Be done with token
  268. ;; Check for char
  269. :get_token_char
  270. CMPSKIPI.E R0 39 ; Check if '
  271. JUMP @get_token_string ; Not a '
  272. COPY R2 R0 ; Prepare for consume_word
  273. CALLI R15 @consume_word ; Call it
  274. JUMP @get_token_done ; Be done with token
  275. ;; Check for string
  276. :get_token_string
  277. CMPSKIPI.E R0 34 ; Check if "
  278. JUMP @get_token_EOF ; Not a "
  279. COPY R2 R0 ; Prepare for consume_word
  280. CALLI R15 @consume_word ; Call it
  281. JUMP @get_token_done ; Be done with token
  282. ;; Check for EOF
  283. :get_token_EOF
  284. CMPSKIPI.L R0 0 ; If c < 0
  285. JUMP @get_token_comment ; If not EOF
  286. POPR R13 R15 ; Restore R13
  287. POPR R12 R15 ; Restore R12
  288. RET R15 ; Otherwise just return the EOF
  289. ;; Check for C comments
  290. :get_token_comment
  291. CMPSKIPI.E R0 47 ; Deal with non-comments
  292. JUMP @get_token_else ; immediately
  293. CALLI R15 @consume_byte ; Deal with another byte
  294. CMPSKIPI.NE R0 42 ; if * make it a block comment
  295. JUMP @get_token_comment_block ; and purge it all
  296. CMPSKIPI.E R0 47 ; Check if not //
  297. JUMP @get_token_done ; Finish off the token
  298. ;; Looks like it was //
  299. FGETC ; Get next char
  300. JUMP @get_token_reset ; Try again
  301. ;; Deal with the mess that is C block comments
  302. :get_token_comment_block
  303. FGETC ; Get next char
  304. :get_token_comment_block_outer
  305. CMPSKIPI.NE R0 47 ; Check for closing /
  306. JUMP @get_token_comment_block_outer_done ; Yep has closing /
  307. :get_token_comment_block_inner
  308. CMPSKIPI.NE R0 42 ; Check for preclosing *
  309. JUMP @get_token_comment_block_inner_done ; Yep has *
  310. ;; Otherwise we are just consuming
  311. FGETC ; Remove another CHAR
  312. CMPSKIPI.NE R0 10 ; Check for Line Feed
  313. ADDUI R11 R11 1 ; Found one, updating line number
  314. JUMP @get_token_comment_block_inner
  315. :get_token_comment_block_inner_done
  316. FGETC ; Remove another CHAR
  317. CMPSKIPI.NE R0 10 ; Check for Line Feed
  318. ADDUI R11 R11 1 ; Found one, updating line number
  319. JUMP @get_token_comment_block_outer
  320. :get_token_comment_block_outer_done
  321. FGETC ; Remove another CHAR
  322. JUMP @get_token_reset ; And Try again
  323. ;; Deal with default case
  324. :get_token_else
  325. CALLI R15 @consume_byte ; Consume the byte and be done
  326. :get_token_done
  327. ADDUI R13 R13 2 ; Pad with NULL the string
  328. STORE32 R14 R12 8 ; Set CURRENT->S to String
  329. ADD R14 R14 R13 ; Add string length to HEAP
  330. STORE32 R10 R12 0 ; CURRENT->NEXT = TOKEN
  331. STORE32 R10 R12 4 ; CURRENT->PREV = TOKE
  332. STORE32 R11 R12 16 ; CURRENT->LINENUM = LINE_NUM
  333. MOVE R10 R12 ; SET TOKEN to CURRENT
  334. POPR R13 R15 ; Restore R13
  335. POPR R12 R15 ; Restore R12
  336. RET R15
  337. ;; reverse_list function
  338. ;; Receives a Token_list in R0
  339. ;; Returns List in Reverse order in R0
  340. :reverse_list
  341. PUSHR R1 R15 ; Protect R1
  342. PUSHR R2 R15 ; Protect R2
  343. FALSE R1 ; Set ROOT to NULL
  344. CMPJUMPI.E R0 R1 @reverse_list_done ; ABORT if given a NULL
  345. :reverse_list_reset
  346. LOAD32 R2 R0 0 ; SET next to HEAD->NEXT
  347. STORE32 R1 R0 0 ; SET HEAD->NEXT to ROOT
  348. MOVE R1 R0 ; SET ROOT to HEAD
  349. MOVE R0 R2 ; SET HEAD to NEXT
  350. JUMP.NZ R0 @reverse_list_reset ; Iterate if HEAD not NULL
  351. :reverse_list_done
  352. MOVE R0 R1 ; SET Result to ROOT
  353. POPR R2 R15 ; Restore R2
  354. POPR R1 R15 ; Restore R1
  355. RET R15
  356. ;; read_all_tokens function
  357. ;; Receives a FILE* in R0
  358. ;; sets line_num in R11 and TOKEN in R10
  359. ;; Overwrites R2
  360. ;; Returns struct token_list* in R0
  361. :read_all_tokens
  362. PUSHR R1 R15 ; Protect R1
  363. PUSHR R2 R15 ; Protect R2
  364. PUSHR R10 R15 ; Protect R10
  365. PUSHR R11 R15 ; Protect R11
  366. MOVE R1 R0 ; Set R1 as FILE*
  367. FGETC ; Read our first CHAR
  368. LOADUI R11 1 ; Start line_num at 1
  369. FALSE R10 ; First token is NULL
  370. :read_all_tokens_reset
  371. JUMP.NP R0 @read_all_tokens_done
  372. CALLI R15 @get_token
  373. JUMP @read_all_tokens_reset
  374. :read_all_tokens_done
  375. MOVE R0 R10 ; Return the Token
  376. POPR R11 R15 ; Restore R11
  377. POPR R10 R15 ; Restore R10
  378. POPR R2 R15 ; Restore R2
  379. POPR R1 R15 ; Restore R1
  380. RET R15
  381. ;; parse_string function
  382. ;; Receives char* string in R0
  383. ;; R14 is HEAP Pointer
  384. ;; Returns char* in R0
  385. :parse_string
  386. PUSHR R1 R15 ; Protect R1
  387. COPY R1 R0 ; Make a copy of STRING
  388. CALLI R15 @weird ; Check if string is weird
  389. SWAP R0 R1
  390. JUMP.Z R1 @parse_string_regular ; Deal with regular strings
  391. ;; Looks like we have a weirdo
  392. CALLI R15 @collect_weird_string ; Create our weird string
  393. JUMP @parse_string_done ; Simply return what was created
  394. :parse_string_regular
  395. CALLI R15 @collect_regular_string
  396. :parse_string_done
  397. POPR R1 R15 ; Restore R1
  398. RET R15
  399. ;; weird function
  400. ;; Analyze string to determine if it's output would be weird for mescc-tools
  401. ;; Receives char* in R0
  402. ;; Returns BOOL in R0
  403. :weird
  404. PUSHR R1 R15 ; Protect R1
  405. PUSHR R2 R15 ; Protect R2
  406. PUSHR R3 R15 ; Protect R3
  407. PUSHR R4 R15 ; Protect R4
  408. FALSE R2 ; Assume FALSE
  409. ADDUI R3 R0 1 ; STRING = STRING + 1
  410. :weird_iter
  411. JUMP.NZ R2 @weird_done ; Stop if TRUE
  412. LOADU8 R4 R3 0 ; C = STRING[0]
  413. JUMP.Z R4 @weird_done ; Be done at NULL Termination
  414. CMPSKIPI.E R4 92 ; If not '\\'
  415. JUMP @weird_post_escape ; Looks like no escape analysis
  416. ;; Deal with the mess
  417. COPY R0 R3 ; Using STRING
  418. CALLI R15 @escape_lookup ; Get our CHAR
  419. MOVE R4 R0 ; C = ESCAPE_LOOKUP(STRING)
  420. LOADU8 R0 R3 1 ; STRING[1]
  421. CMPSKIPI.NE R0 120 ; if 'x' == STRING[1]
  422. ADDUI R3 R3 2 ; STRING = STRING + 2
  423. ADDUI R3 R3 1 ; STRING = STRING + 1
  424. :weird_post_escape
  425. LOADUI R1 $nice_chars ; using list of nice CHARS
  426. COPY R0 R4 ; using copy of C
  427. CALLI R15 @in_set ; Use in_set
  428. CMPSKIPI.NE R0 0 ; IF TRUE
  429. TRUE R2 ; Return TRUE
  430. ADDUI R3 R3 1 ; STRING = STRING + 1
  431. LOADUI R1 $whitespace_chars ; Check Whitespace Chars
  432. COPY R0 R4 ; Using copy of C
  433. CALLI R15 @in_set ; Use in_set
  434. JUMP.Z R0 @weird_iter ; If False simply loop
  435. LOADU8 R0 R3 0 ; STRING[1]
  436. CMPSKIPI.NE R0 58 ; If ':' == STRING[1]
  437. TRUE R2 ; Flip flag
  438. JUMP @weird_iter ; Keep trying to find an answer
  439. :weird_done
  440. MOVE R0 R2 ; Whatever is in R2 is the answer
  441. POPR R4 R15 ; Restore R4
  442. POPR R3 R15 ; Restore R3
  443. POPR R2 R15 ; Restore R2
  444. POPR R1 R15 ; Restore R1
  445. RET R15
  446. ;; collect_weird_string function
  447. ;; Converts weird string into a form mescc-tools can handle cleanly
  448. ;; Receives char* in R0
  449. ;; R14 is HEAP Pointer and $hex_chars as the table
  450. ;; Returns char* in R0
  451. :collect_weird_string
  452. PUSHR R1 R15 ; Protect R1
  453. PUSHR R2 R15 ; Protect R2
  454. PUSHR R3 R15 ; Protect R3
  455. PUSHR R4 R15 ; Protect R4
  456. LOADUI R4 $hex_chars ; Pointer to TABLE
  457. COPY R3 R14 ; Get HOLD
  458. MOVE R2 R0 ; Put STRING in Place
  459. LOADUI R0 39 ; Prefix with '
  460. PUSH8 R0 R3 ; HOLD[0] = '\'' && HOLD = HOLD + 1
  461. :collect_weird_string_iter
  462. ADDUI R2 R2 1 ; STRING = STRING + 1
  463. LOADUI R0 32 ; Insert ' '
  464. PUSH8 R0 R3 ; HOLD[0] = ' ' && HOLD = HOLD + 1
  465. COPY R0 R2 ; copy STRING
  466. CALLI R15 @escape_lookup ; Get char value
  467. ANDI R1 R0 0x0F ; Save Bottom out of the way
  468. SR0I R0 4 ; Isolate Top
  469. LOADXU8 R0 R4 R0 ; Using Table
  470. LOADXU8 R1 R4 R1 ; Using Table
  471. PUSH8 R0 R3 ; HOLD[0] = TABLE[(TEMP >> 4)] && HOLD = HOLD + 1
  472. PUSH8 R1 R3 ; HOLD[0] = TABLE[(TEMP & 15)] && HOLD = HOLD + 1
  473. LOADU8 R0 R2 0 ; STRING[0]
  474. JUMP.Z R0 @collect_weird_string_done ; Stop if NULL
  475. CMPSKIPI.E R0 92 ; IF STRING[0] != '\\'
  476. JUMP @collect_weird_string_check ; Deal with iteration
  477. LOADU8 R0 R2 1 ; STRING[1]
  478. CMPSKIPI.NE R0 120 ; If STRING[1] == 'x'
  479. ADDUI R2 R2 2 ; STRING = STRING + 2
  480. ADDUI R2 R2 1 ; STRING = STRING + 1
  481. :collect_weird_string_check
  482. LOADU8 R0 R2 1 ; STRING[1]
  483. JUMP.NZ R0 @collect_weird_string_iter
  484. :collect_weird_string_done
  485. LOADUI R0 32 ; Insert ' '
  486. PUSH8 R0 R3 ; HOLD[0] = ' ' && HOLD = HOLD + 1
  487. LOADUI R0 48 ; Insert '0'
  488. PUSH8 R0 R3 ; HOLD[0] = '0' && HOLD = HOLD + 1
  489. PUSH8 R0 R3 ; HOLD[0] = '0' && HOLD = HOLD + 1
  490. LOADUI R0 39 ; Insert '\''
  491. PUSH8 R0 R3 ; HOLD[0] = '\'' && HOLD = HOLD + 1
  492. LOADUI R0 10 ; Insert '\n'
  493. PUSH8 R0 R3 ; HOLD[0] = '\n' && HOLD = HOLD + 1
  494. ADDUI R3 R3 1 ; NULL Terminate
  495. SWAP R3 R14 ; CALLOC HOLD
  496. MOVE R0 R3 ; Return HOLD
  497. POPR R4 R15 ; Restore R4
  498. POPR R3 R15 ; Restore R3
  499. POPR R2 R15 ; Restore R2
  500. POPR R1 R15 ; Restore R1
  501. RET R15
  502. ;; hex function
  503. ;; Receives Char in R0
  504. ;; Return Int in R0
  505. :hex
  506. SUBUI R0 R0 48 ; First shift
  507. CMPSKIPI.GE R0 10 ; If 0-9
  508. RET R15 ; Be done
  509. ;; Deal with A-F
  510. ANDI R0 R0 0xDF ; Unset high bit
  511. SUBUI R0 R0 7 ; Shift them down
  512. CMPSKIPI.GE R0 10 ; if between 9 and A
  513. JUMP @hex_error ; Throw an error
  514. CMPSKIPI.L R0 16 ; if > F
  515. JUMP @hex_error ; Throw an error
  516. RET R15
  517. :hex_error
  518. LOADUI R0 $hex_error_message ; Our message
  519. FALSE R1 ; For human
  520. CALLI R15 @file_print ; write it
  521. CALLI R15 @line_error ; More info
  522. HALT
  523. :hex_error_message
  524. "Tried to print non-hex number
  525. "
  526. ;; escape_lookup function
  527. ;; Receives char* in R0
  528. ;; Returns char in R0
  529. :escape_lookup
  530. PUSHR R1 R15 ; Protect R1
  531. PUSHR R2 R15 ; Protect R2
  532. MOVE R1 R0 ; Put C in the right spot
  533. FALSE R2 ; Our flag for done
  534. LOADU8 R0 R1 0 ; c[0]
  535. CMPSKIPI.E R0 92 ; If C[0] != '\\'
  536. JUMP @escape_lookup_none ; Deal with none case
  537. LOADU8 R0 R1 1 ; c[1]
  538. CMPSKIPI.NE R0 120 ; if \x??
  539. JUMP @escape_lookup_hex
  540. ;; Deal with \? escapes
  541. CMPSKIPI.NE R0 110 ; If \n
  542. LOADUI R2 10 ; return \n
  543. CMPSKIPI.NE R0 116 ; If \t
  544. LOADUI R2 9 ; return \t
  545. CMPSKIPI.NE R0 92 ; If \\
  546. LOADUI R2 92 ; return \\
  547. CMPSKIPI.NE R0 39 ; If \'
  548. LOADUI R2 39 ; return \'
  549. CMPSKIPI.NE R0 34 ; If \"
  550. LOADUI R2 34 ; return \"
  551. CMPSKIPI.NE R0 114 ; If \r
  552. LOADUI R2 13 ; return \r
  553. JUMP.Z R2 @escape_lookup_error ; Looks like we got something weird
  554. JUMP @escape_lookup_done ; Otherwise just use our R2
  555. :escape_lookup_none
  556. MOVE R2 R0 ; We just return the char at C[0]
  557. JUMP @escape_lookup_done ; Be done
  558. :escape_lookup_hex
  559. LOADU8 R0 R1 2 ; c[2]
  560. CALLI R15 @hex ; Get first char
  561. SL0I R0 4 ; Shift our first nybble
  562. MOVE R2 R0 ; Protect our top nybble
  563. LOADU8 R0 R1 3 ; c[3]
  564. CALLI R15 @hex ; Get second char
  565. ADD R2 R2 R0 ; \x?? => ? << 4 + ?
  566. :escape_lookup_done
  567. MOVE R0 R2 ; R2 has our answer
  568. POPR R2 R15 ; Restore R2
  569. POPR R1 R15 ; Restore R1
  570. RET R15
  571. :escape_lookup_error
  572. MOVE R2 R0 ; Protect Char that failed
  573. LOADUI R0 $escape_lookup_string0 ; Load message
  574. FALSE R1 ; We want the User to see
  575. CALLI R15 @file_print ; Write it
  576. MOVE R0 R2 ; Our CHAR
  577. FPUTC ; Write it
  578. LOADUI R0 10 ; '\n'
  579. FPUTC ; Write it
  580. CALLI R15 @line_error ; Provide some debug information
  581. HALT
  582. :escape_lookup_string0
  583. "Received invalid escape \\"
  584. ;; collect_regular_string function
  585. ;; Converts C string into a RAW string for mescc-tools
  586. ;; Receives char* in R0
  587. ;; R14 is HEAP Pointer
  588. ;; Returns char* in R0
  589. :collect_regular_string
  590. PUSHR R1 R15 ; Protect R1
  591. PUSHR R2 R15 ; Protect R2
  592. COPY R2 R14 ; MESSAGE
  593. MOVE R1 R0 ; Put STRING in the right place
  594. :collect_regular_string_iter
  595. LOADU8 R0 R1 0 ; STRING[0]
  596. JUMP.Z R0 @collect_regular_string_done ; End at NULL
  597. CMPSKIPI.NE R0 92 ; if STRING[0] == '\\'
  598. JUMP @collect_regular_string_escape ; deal with escapes
  599. ;; Deal with vannilla chars
  600. STORE8 R0 R2 0 ; MESSAGE[0] = STRING[0]
  601. ADDUI R2 R2 1 ; MESSAGE = MESSAGE + 1
  602. ADDUI R1 R1 1 ; STRING = STRING + 1
  603. JUMP @collect_regular_string_iter ; Loop
  604. :collect_regular_string_escape
  605. COPY R0 R1 ; Prepare for call
  606. CALLI R15 @escape_lookup ; Get what weird char we need
  607. STORE8 R0 R2 0 ; MESSAGE[0] = escape_lookup(string)
  608. ADDUI R2 R2 1 ; MESSAGE = MESSAGE + 1
  609. LOADU8 R0 R1 1 ; STRING[1]
  610. CMPSKIPI.NE R0 120 ; if \x??
  611. ADDUI R1 R1 2 ; STRING = STRING + 2
  612. ADDUI R1 R1 2 ; STRING = STRING + 2
  613. JUMP @collect_regular_string_iter ; Loop
  614. :collect_regular_string_done
  615. LOADUI R0 34 ; Using "
  616. STORE8 R0 R2 0 ; MESSAGE[0] = '"'
  617. LOADUI R0 10 ; Using '\n'
  618. STORE8 R0 R2 1 ; MESSAGE[1] = "\n"
  619. ADDUI R2 R2 3 ; Add extra NULL padding
  620. SWAP R2 R14 ; Update HEAP
  621. MOVE R0 R2 ; Put MESSAGE in the right Spot
  622. POPR R2 R15 ; Restore R2
  623. POPR R1 R15 ; Restore R1
  624. RET R15
  625. ;; unary_expr_sizeof function
  626. ;; Receives nothing
  627. ;; Returns nothing
  628. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  629. :unary_expr_sizeof
  630. PUSHR R0 R15 ; Protect R0
  631. PUSHR R1 R15 ; Protect R1
  632. PUSHR R2 R15 ; Protect R2
  633. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  634. LOADUI R0 $unary_expr_sizeof_string0 ; Our first error message
  635. LOADUI R1 $open_paren ; Using "("
  636. CALLI R15 @require_match ; Ensure a match
  637. CALLI R15 @type_name ; Get type_name
  638. MOVE R2 R0 ; Protect A
  639. LOADUI R0 $unary_expr_sizeof_string1 ; Our final error message
  640. LOADUI R1 $close_paren ; Using ")"
  641. CALLI R15 @require_match ; Ensure a match
  642. LOADUI R0 $unary_expr_sizeof_string2 ; Our header
  643. CALLI R15 @emit_out ; emit it
  644. LOAD32 R0 R2 4 ; A->SIZE
  645. CALLI R15 @numerate_number ; Convert to string
  646. CALLI R15 @emit_out ; emit it
  647. LOADUI R0 $newline ; Using "\n"
  648. CALLI R15 @emit_out ; emit it
  649. POPR R2 R15 ; Restore R2
  650. POPR R1 R15 ; Restore R1
  651. POPR R0 R15 ; Restore R0
  652. RET R15
  653. :unary_expr_sizeof_string0
  654. "ERROR in unary_expr
  655. Missing (
  656. "
  657. :unary_expr_sizeof_string1
  658. "ERROR in unary_expr
  659. Missing )
  660. "
  661. :unary_expr_sizeof_string2
  662. "LOAD_IMMEDIATE_eax %"
  663. ;; constant_load function
  664. ;; Receives struct token_list* a in R0
  665. ;; Returns nothing
  666. :constant_load
  667. PUSHR R0 R15 ; Protect R0
  668. LOADUI R0 $constant_load_string0 ; Our header
  669. CALLI R15 @emit_out ; emit it
  670. POPR R0 R15 ; Restore R0
  671. LOAD32 R0 R0 16 ; A->ARGUMENTS
  672. LOAD32 R0 R0 8 ; A->ARGUMENTS->S
  673. CALLI R15 @emit_out ; emit it
  674. LOADUI R0 $newline ; Using "\n"
  675. CALLI R15 @emit_out ; emit it
  676. RET R15
  677. :constant_load_string0
  678. "LOAD_IMMEDIATE_eax %"
  679. ;; variable_load function
  680. ;; Receives struct token_list* a in R0
  681. ;; and struct token_list* current_target in R8
  682. ;; Returns Nothing
  683. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  684. :variable_load
  685. PUSHR R1 R15 ; Protect R1
  686. PUSHR R2 R15 ; Protect R2
  687. MOVE R2 R0 ; Protect A
  688. ;; Check if function call
  689. LOADUI R0 $type_function_name ; Using "FUNCTION"
  690. LOAD32 R1 R2 12 ; A->TYPE
  691. LOAD32 R1 R1 24 ; A->TYPE->NAME
  692. CALLI R15 @match ; IF "FUNCTION" == A->TYPE->NAME
  693. JUMP.Z R0 @variable_load_regular ; Nope
  694. LOADUI R0 $open_paren ; Using "("
  695. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  696. CALLI R15 @match ; IF "(" == GLOBAL_TOKEN->S
  697. JUMP.Z R0 @variable_load_regular ; Nope
  698. ;; Deal with function call
  699. LOAD32 R0 R2 16 ; A->DEPTH
  700. CALLI R15 @numerate_number ; Convert to string
  701. TRUE R1 ; Passing TRUE
  702. CALLI R15 @function_call ; DO IT
  703. JUMP @variable_load_done ; Be done
  704. :variable_load_regular
  705. LOAD32 R8 R2 12 ; CURRENT_TARGET = A->TYPE
  706. LOADUI R0 $variable_load_string0 ; Our prefix
  707. CALLI R15 @emit_out ; emit it
  708. LOAD32 R0 R2 16 ; A->DEPTH
  709. CALLI R15 @numerate_number ; Convert to string
  710. CALLI R15 @emit_out ; emit it
  711. LOADUI R0 $newline ; Using "\n"
  712. CALLI R15 @emit_out ; emit it
  713. ;; check for special case 1
  714. LOADUI R0 $equal ; Using "="
  715. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  716. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  717. JUMP.NZ R0 @variable_load_done ; Be done
  718. ;; deal with the general case
  719. LOADUI R0 $variable_load_string1 ; Our postfix
  720. CALLI R15 @emit_out ; emit it
  721. :variable_load_done
  722. POPR R2 R15 ; Restore R2
  723. POPR R1 R15 ; Restore R1
  724. RET R15
  725. :variable_load_string0
  726. "LOAD_BASE_ADDRESS_eax %"
  727. :variable_load_string1
  728. "LOAD_INTEGER
  729. "
  730. ;; function_load function
  731. ;; Receives struct token_list* a in R0
  732. ;; Returns nothing
  733. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  734. :function_load
  735. PUSHR R1 R15 ; Protect R1
  736. LOAD32 R0 R0 8 ; A->S
  737. PUSHR R0 R15 ; Protect A->S
  738. LOADUI R0 $open_paren ; Using "("
  739. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  740. CALLI R15 @match ; If GLOBAL_TOKEN->S == "("
  741. JUMP.Z R0 @function_load_regular ; If not do the simple thing
  742. ;; Deal iwth function call
  743. POPR R0 R15 ; Restore A->S
  744. FALSE R1 ; FALSE
  745. CALLI R15 @function_call ; Do the function call
  746. JUMP @function_load_done ; Clean up
  747. :function_load_regular
  748. LOADUI R0 $function_load_string0 ; Using our header string
  749. CALLI R15 @emit_out ; emit it
  750. POPR R0 R15 ; Restore A->S
  751. CALLI R15 @emit_out ; emit it
  752. LOADUI R0 $newline ; Using "\n"
  753. CALLI R15 @emit_out ; emit it
  754. :function_load_done
  755. POPR R1 R15 ; Restore R1
  756. RET R15
  757. :function_load_string0
  758. "LOAD_IMMEDIATE_eax &FUNCTION_"
  759. ;; global_load function
  760. ;; Receives struct token_list* a in R0
  761. ;; and struct token_list* current_target in R8
  762. ;; Returns nothing
  763. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  764. :global_load
  765. PUSHR R0 R15 ; Protect A
  766. LOAD32 R8 R0 12 ; CURRENT_TARGET = A->TYPE
  767. LOADUI R0 $global_load_string0 ; Our header string
  768. CALLI R15 @emit_out ; emit it
  769. POPR R0 R15 ; Restore A
  770. LOAD32 R0 R0 8 ; A->S
  771. CALLI R15 @emit_out ; emit it
  772. LOADUI R0 $newline ; Using "\n"
  773. CALLI R15 @emit_out ; emit it
  774. PUSHR R1 R15 ; Protect R1
  775. LOADUI R0 $equal ; Using "="
  776. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  777. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  778. JUMP.NZ R0 @global_load_done ; Skip the following
  779. ;; Deal with non-assignment
  780. LOADUI R0 $global_load_string1 ; Our footer string
  781. CALLI R15 @emit_out ; emit it
  782. :global_load_done
  783. POPR R1 R15 ; Restore R1
  784. RET R15
  785. :global_load_string0
  786. "LOAD_IMMEDIATE_eax &GLOBAL_"
  787. :global_load_string1
  788. "LOAD_INTEGER
  789. "
  790. ;; primary_expr_failure function
  791. ;; Fails hard and fast
  792. ;; Receives nothing
  793. ;; HALTs and will trash registers
  794. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  795. :primary_expr_failure
  796. LOADUI R0 $primary_expr_failure_string0 ; Our first string
  797. FALSE R1 ; Display to User
  798. CALLI R15 @file_print ; Print it
  799. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  800. CALLI R15 @file_print ; Print it
  801. LOADUI R0 $primary_expr_failure_string1 ; Our last string
  802. CALLI R15 @file_print ; Print it
  803. CALLI R15 @line_error ; Make it a line error message too
  804. HALT
  805. :primary_expr_failure_string0
  806. "Received "
  807. :primary_expr_failure_string1
  808. " in primary_expr
  809. "
  810. ;; primary_expr_string function
  811. ;; Receives struct token_list* global_token in R13,
  812. ;; struct token_list* out in R12,
  813. ;; struct token_list* string_list in R11
  814. ;; struct token_list* global_list in R10
  815. ;; and struct token_list* FUNC in R9
  816. ;; and struct token_list* current_target in R8
  817. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  818. ;; Returns the token_lists modified
  819. :primary_expr_string
  820. PUSHR R0 R15 ; Protect R0
  821. PUSHR R1 R15 ; Protect R1
  822. PUSHR R2 R15 ; Protect R2
  823. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  824. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  825. STORER32 R1 @current_count ; Update CURRENT_COUNT
  826. CALLI R15 @numerate_number ; Convert to string
  827. MOVE R2 R0 ; Put string in safe place
  828. LOADUI R0 $primary_expr_string_string0 ; Our string prefix
  829. CALLI R15 @emit_out ; emit it
  830. LOAD32 R0 R9 8 ; FUNCTION->S
  831. COPY R1 R2 ; NUMBER_STRING
  832. CALLI R15 @uniqueID_out ; Make it unique
  833. ;; The target
  834. LOADUI R0 $primary_expr_string_string1
  835. COPY R1 R11 ; Using STRINGS_LIST
  836. CALLI R15 @emit ; emit it
  837. MOVE R1 R0 ; Put STRINGS_LIST in correct place
  838. LOAD32 R0 R9 8 ; Using FUNCTION->S
  839. CALLI R15 @uniqueID ; Make it unique
  840. MOVE R11 R0 ; Update STRINGS_LIST
  841. ;; Parse the string
  842. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  843. CALLI R15 @parse_string ; Parse it
  844. COPY R1 R11 ; Using STRINGS_LIST
  845. CALLI R15 @emit ; emit it
  846. MOVE R11 R0 ; Update STRINGS_LIST
  847. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  848. POPR R2 R15 ; Restore R2
  849. POPR R1 R15 ; Restore R1
  850. POPR R0 R15 ; Restore R0
  851. RET R15
  852. :primary_expr_string_string0
  853. "LOAD_IMMEDIATE_eax &STRING_"
  854. :primary_expr_string_string1
  855. ":STRING_"
  856. ;; primary_expr_char function
  857. ;; Receives struct token_list* global_token in R13,
  858. ;; struct token_list* out in R12,
  859. ;; struct token_list* string_list in R11
  860. ;; struct token_list* global_list in R10
  861. ;; and struct token_list* FUNC in R9
  862. ;; and struct token_list* current_target in R8
  863. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  864. ;; Returns the token_lists modified
  865. :primary_expr_char
  866. PUSHR R0 R15 ; Protect R0
  867. LOADUI R0 $primary_expr_char_string0 ; Using our header string
  868. CALLI R15 @emit_out ; emit it
  869. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  870. ADDUI R0 R0 1 ; GLOBAL_TOKEN->S + 1
  871. CALLI R15 @escape_lookup ; escape_lookup value
  872. CALLI R15 @numerate_number ; Make it a string
  873. CALLI R15 @emit_out ; emit it
  874. LOADUI R0 $newline ; Using "\n"
  875. CALLI R15 @emit_out ; emit it
  876. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  877. POPR R0 R15 ; Restore R0
  878. RET R15
  879. :primary_expr_char_string0
  880. "LOAD_IMMEDIATE_eax %"
  881. ;; primary_expr_number function
  882. ;; struct token_list* out in R12,
  883. ;; struct token_list* string_list in R11
  884. ;; struct token_list* global_list in R10
  885. ;; and struct token_list* FUNC in R9
  886. ;; and struct token_list* current_target in R8
  887. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  888. ;; Returns the token_lists modified
  889. :primary_expr_number
  890. LOADUI R0 $primary_expr_number_string0 ; Our header
  891. CALLI R15 @emit_out ; emit it
  892. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  893. CALLI R15 @emit_out ; emit it
  894. LOADUI R0 $newline ; Using "\n"
  895. CALLI R15 @emit_out ; emit it
  896. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  897. RET R15
  898. :primary_expr_number_string0
  899. "LOAD_IMMEDIATE_eax %"
  900. ;; primary_expr_variable function
  901. ;; struct token_list* out in R12,
  902. ;; struct token_list* string_list in R11
  903. ;; struct token_list* global_list in R10
  904. ;; and struct token_list* FUNC in R9
  905. ;; and struct token_list* current_target in R8
  906. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  907. ;; Returns the token_lists modified
  908. :primary_expr_variable
  909. PUSHR R0 R15 ; Protect R0
  910. PUSHR R1 R15 ; Protect R1
  911. PUSHR R2 R15 ; Protect R2
  912. LOAD32 R2 R13 8 ; S = GLOBAL_TOKEN->S
  913. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  914. COPY R0 R2 ; Using S
  915. LOADR32 R1 @global_constant_list
  916. CALLI R15 @sym_lookup ; Lookup S in CONSTANTS
  917. JUMP.Z R0 @primary_expr_variable_locals ; try Locals
  918. ;; Deal with Constants
  919. CALLI R15 @constant_load ; A is in R0 already
  920. JUMP @primary_expr_variable_done ; Moving on
  921. :primary_expr_variable_locals
  922. COPY R0 R2 ; Using S
  923. LOAD32 R1 R9 4 ; Using FUNCTION->LOCALS
  924. CALLI R15 @sym_lookup ; Lookup S in Locals
  925. JUMP.Z R0 @primary_expr_variable_arguments ; try arguments
  926. ;; Deal with Locals
  927. CALLI R15 @variable_load ; A is in R0 already
  928. JUMP @primary_expr_variable_done ; Moving on
  929. :primary_expr_variable_arguments
  930. COPY R0 R2 ; Using S
  931. LOAD32 R1 R9 16 ; Using FUNCTION->ARGUMENTS
  932. CALLI R15 @sym_lookup ; Lookup S in arguments
  933. JUMP.Z R0 @primary_expr_variable_function ; try Functions
  934. ;; Deal with argument
  935. CALLI R15 @variable_load ; A is in R0 already
  936. JUMP @primary_expr_variable_done ; Moving on
  937. :primary_expr_variable_function
  938. COPY R0 R2 ; Using S
  939. LOADR32 R1 @global_function_list ; Get current GLOBAL_FUNCTION_LIST
  940. CALLI R15 @sym_lookup ; Lookup S in GLOBAL_FUNCTION_LIST
  941. JUMP.Z R0 @primary_expr_variable_global ; try Globals
  942. ;; Deal with function
  943. CALLI R15 @function_load ; Dothe work
  944. JUMP @primary_expr_variable_done ; Moving on
  945. :primary_expr_variable_global
  946. COPY R0 R2 ; Using S
  947. LOADR32 R1 @global_symbol_list ; Get current GLOBAL_SYMBOL_LIST
  948. CALLI R15 @sym_lookup ; Lookup S in GLOBAL_SYMBOL_LIST
  949. JUMP.Z R0 @primary_expr_variable_failure ; Looks like it isn't anything we know
  950. ;; Deal with a global
  951. CALLI R15 @global_load
  952. :primary_expr_variable_done
  953. POPR R2 R15 ; Restore R2
  954. POPR R1 R15 ; Restore R1
  955. POPR R0 R15 ; Restore R0
  956. RET R15
  957. :primary_expr_variable_failure
  958. MOVE R0 R2 ; Using S
  959. FALSE R1 ; We want the user to see
  960. CALLI R15 @file_print ; Print it
  961. LOADUI R0 $primary_expr_variable_string0 ; Body
  962. CALLI R15 @file_print ; Print it
  963. CALLI R15 @line_error ; Provide useful error info
  964. HALT
  965. :primary_expr_variable_string0
  966. " is not a defined symbol
  967. "
  968. ;; promote_type function
  969. ;; Receives struct type* in R0 and struct type* in R1
  970. ;; Returns first match struct type* in R0
  971. :promote_type
  972. JUMP.Z R1 @promote_type_abort0 ; If B is NULL just abort
  973. PUSHR R1 R15 ; Protect R1
  974. SWAP R0 R1 ; Give A a try
  975. JUMP.Z R1 @promote_type_abort1 ; A is NULL just short abort
  976. ;; Looks like we have a bunch of work to do
  977. PUSHR R2 R15 ; Protect R2
  978. PUSHR R3 R15 ; Protect R3
  979. PUSHR R4 R15 ; Protect R4
  980. PUSHR R5 R15 ; Protect R5
  981. MOVE R5 R1 ; Put A in the right spot
  982. MOVE R4 R0 ; Put B in the right spot
  983. LOADR32 R3 @global_types ; I = GLOBAL_TYPES
  984. :promote_type_iter
  985. LOAD32 R1 R3 24 ; I->NAME
  986. LOAD32 R0 R5 24 ; A->NAME
  987. CMPJUMPI.E R0 R1 @promote_type_done ; break
  988. LOAD32 R0 R4 24 ; B->NAME
  989. CMPJUMPI.E R0 R1 @promote_type_done ; break
  990. LOAD32 R1 R3 12 ; I->INDIRECT
  991. LOAD32 R1 R1 24 ; I->INDIRECT->NAME
  992. LOAD32 R0 R5 24 ; A->NAME
  993. CMPJUMPI.E R0 R1 @promote_type_done ; break
  994. LOAD32 R0 R4 24 ; B->NAME
  995. CMPJUMPI.E R0 R1 @promote_type_done ; break
  996. LOAD32 R3 R3 0 ; I = I->NEXT
  997. JUMP.NZ R3 @promote_type_iter ; Loop if not NULL
  998. :promote_type_done
  999. MOVE R0 R3 ; Return I
  1000. POPR R5 R15 ; Restore R5
  1001. POPR R4 R15 ; Restore R4
  1002. POPR R3 R15 ; Restore R3
  1003. POPR R2 R15 ; Restore R2
  1004. :promote_type_abort1
  1005. POPR R1 R15 ; Restore R1
  1006. :promote_type_abort0
  1007. RET R15
  1008. ;; common_recursion function
  1009. ;; Receives FUNCTION* in R0
  1010. ;; struct token_list* out in R12,
  1011. ;; struct token_list* string_list in R11
  1012. ;; struct token_list* global_list in R10
  1013. ;; and struct token_list* FUNC in R9
  1014. ;; and struct token_list* current_target in R8
  1015. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1016. ;; Returns the token_lists modified
  1017. :common_recursion
  1018. PUSHR R0 R15 ; Protect R0
  1019. PUSHR R1 R15 ; Protect R1
  1020. PUSHR R2 R15 ; Protect R2
  1021. MOVE R2 R0 ; Protect F
  1022. COPY R1 R8 ; LAST_TYPE = CURRENT_TARGET
  1023. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1024. LOADUI R0 $common_recursion_string0 ; Header string
  1025. CALLI R15 @emit_out ; Our header
  1026. CALL R2 R15 ; CALL F()
  1027. COPY R0 R8 ; Using CURRENT_TARGET
  1028. CALLI R15 @promote_type ; Promote type
  1029. MOVE R8 R0 ; update CURRENT_TARGET
  1030. LOADUI R0 $common_recursion_string1 ; Footer string
  1031. CALLI R15 @emit_out ; Our footer
  1032. POPR R2 R15 ; Restore R2
  1033. POPR R1 R15 ; Restore R1
  1034. POPR R0 R15 ; Restore R0
  1035. RET R15
  1036. :common_recursion_string0
  1037. "PUSH_eax #_common_recursion
  1038. "
  1039. :common_recursion_string1
  1040. "POP_ebx # _common_recursion
  1041. "
  1042. ;; general_recursion function
  1043. ;; Receives FUNCTION F in R0, char* s in R1, char* name in R2
  1044. ;; and FUNCTION ITERATE in R3
  1045. ;; struct token_list* out in R12,
  1046. ;; struct token_list* string_list in R11
  1047. ;; struct token_list* global_list in R10
  1048. ;; and struct token_list* FUNC in R9
  1049. ;; and struct token_list* current_target in R8
  1050. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1051. ;; Returns nothing
  1052. :general_recursion
  1053. PUSHR R0 R15 ; Protect R0
  1054. PUSHR R1 R15 ; Protect S
  1055. PUSHR R0 R15 ; Protect F
  1056. COPY R0 R2 ; Using NAME
  1057. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1058. CALLI R15 @match ; IF GLOBAL_TOKEN->S == NAME
  1059. JUMP.Z R0 @general_recursion_done
  1060. ;; deal with case of match
  1061. POPR R0 R15 ; Restore F
  1062. CALLI R15 @common_recursion ; Recurse
  1063. POPR R1 R15 ; Restore S
  1064. COPY R0 R1 ; Put S in correct place
  1065. CALLI R15 @emit_out ; emit it
  1066. CALL R3 R15 ; CALL ITERATE()
  1067. POPR R0 R15 ; Restore R0
  1068. RET R15 ; Don't double pop
  1069. :general_recursion_done
  1070. POPR R0 R15 ; Restore F
  1071. POPR R1 R15 ; Restore S
  1072. POPR R0 R15 ; Restore R0
  1073. RET R15
  1074. ;; ceil_log2 function
  1075. ;; Receives INT A in R0
  1076. ;; Returns LOG2(A) in R0
  1077. :ceil_log2
  1078. PUSHR R1 R15 ; Protect R1
  1079. PUSHR R2 R15 ; Protect R2
  1080. FALSE R2 ; RESULT = 0
  1081. SUBI R1 R0 1 ; A - 1
  1082. AND R1 R1 R0 ; A & (A - 1)
  1083. CMPSKIPI.NE R1 0 ; IF (A & (A - 1)) == 0
  1084. LOADI R2 -1 ; RESULT = -1
  1085. :ceil_log2_iter
  1086. JUMP.Z R0 @ceil_log2_done ; IF A > 0
  1087. ADDI R2 R2 1 ; RESULT = RESULT + 1
  1088. SARI R0 1 ; A = A >> 1
  1089. JUMP @ceil_log2_iter ; Loop
  1090. :ceil_log2_done
  1091. MOVE R0 R2 ; Use RESULT
  1092. POPR R2 R15 ; Restore R2
  1093. POPR R1 R15 ; Restore R1
  1094. RET R15
  1095. ;; postfix_expr_arrow function
  1096. ;; Receives nothing
  1097. ;; struct token_list* out in R12,
  1098. ;; struct token_list* string_list in R11
  1099. ;; struct token_list* global_list in R10
  1100. ;; and struct token_list* FUNC in R9
  1101. ;; and struct token_list* current_target in R8
  1102. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1103. ;; Returns the token_lists modified
  1104. :postfix_expr_arrow
  1105. PUSHR R0 R15 ; Protect R0
  1106. PUSHR R1 R15 ; Protect R1
  1107. PUSHR R2 R15 ; Protect R2
  1108. LOADUI R0 $postfix_expr_arrow_string0 ; Our header string
  1109. CALLI R15 @emit_out ; Emit it
  1110. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1111. COPY R0 R8 ; Passing CURRENT_TARGET
  1112. LOAD32 R1 R13 8 ; Using GLOBAL_TOKEN->S
  1113. CALLI R15 @lookup_member ; Look it up
  1114. LOAD32 R2 R0 4 ; Protect I->SIZE
  1115. LOAD32 R8 R0 20 ; CURRENT_TARGET = I->TYPE
  1116. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1117. LOAD32 R1 R0 8 ; I->OFFSET
  1118. JUMP.Z R1 @postfix_expr_arrow_offset ; If no offset needed skip the work
  1119. ;; Deal with non-zero offsets
  1120. LOADUI R0 $postfix_expr_arrow_string1 ; Our first prefix
  1121. CALLI R15 @emit_out ; Emit it
  1122. LOADUI R0 $postfix_expr_arrow_string2 ; Our second prefix
  1123. CALLI R15 @emit_out ; Emit it
  1124. MOVE R0 R1 ; Put I->OFFSET in the right place
  1125. CALLI R15 @numerate_number ; Convert to string
  1126. CALLI R15 @emit_out ; Emit it
  1127. LOADUI R0 $postfix_expr_arrow_string3 ; Our postfix
  1128. CALLI R15 @emit_out ; Emit it
  1129. :postfix_expr_arrow_offset
  1130. LOADUI R0 $equal ; Using "="
  1131. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1132. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  1133. JUMP.NZ R0 @postfix_expr_arrow_done
  1134. LOADUI R0 4 ; Compare against 4
  1135. CMPJUMPI.L R0 R2 @postfix_expr_arrow_done
  1136. ;; Deal with special case
  1137. LOADUI R0 $postfix_expr_arrow_string4 ; Our final string
  1138. CALLI R15 @emit_out ; Emit it
  1139. :postfix_expr_arrow_done
  1140. POPR R2 R15 ; Restore R2
  1141. POPR R1 R15 ; Restore R1
  1142. POPR R0 R15 ; Restore R0
  1143. RET R15
  1144. :postfix_expr_arrow_string0
  1145. "# looking up offset
  1146. "
  1147. :postfix_expr_arrow_string1
  1148. "# -> offset calculation
  1149. "
  1150. :postfix_expr_arrow_string2
  1151. "LOAD_IMMEDIATE_ebx %"
  1152. :postfix_expr_arrow_string3
  1153. "
  1154. ADD_ebx_to_eax
  1155. "
  1156. :postfix_expr_arrow_string4
  1157. "LOAD_INTEGER
  1158. "
  1159. ;; postfix_expr_array function
  1160. ;; Receives nothing
  1161. ;; struct token_list* out in R12,
  1162. ;; struct token_list* string_list in R11
  1163. ;; struct token_list* global_list in R10
  1164. ;; and struct token_list* FUNC in R9
  1165. ;; and struct token_list* current_target in R8
  1166. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1167. ;; Returns the token_lists modified
  1168. :postfix_expr_array
  1169. PUSHR R0 R15 ; Protect R0
  1170. PUSHR R1 R15 ; Protect R1
  1171. PUSHR R2 R15 ; Protect R2
  1172. COPY R2 R8 ; ARRAY = CURRENT_TARGET
  1173. LOADUI R0 $expression ; Using EXPRESSION
  1174. CALLI R15 @common_recursion ; Recurse
  1175. MOVE R8 R2 ; CURRENT_TARGET = ARRAY
  1176. LOADUI R2 $postfix_expr_array_string0 ; ASSIGN = load integer
  1177. LOADUI R0 $type_char_indirect_name ; Using "char*"
  1178. LOAD32 R1 R8 24 ; CURRENT_TARGET->NAME
  1179. CALLI R15 @match ; IF CURRENT_TARGET->NAME == "char*"
  1180. CMPSKIPI.E R0 0 ; deal with Byte
  1181. LOADUI R2 $postfix_expr_array_string1 ; ASSIGN = load byte
  1182. JUMP.NZ R0 @postfix_expr_array_byte ; Skip if Byte
  1183. ;; Deal with larger than byte
  1184. LOADUI R0 $postfix_expr_array_string2 ; Our shift
  1185. CALLI R15 @emit_out ; emit it
  1186. LOAD32 R0 R8 12 ; CURRENT_TARGET->INDIRECT
  1187. LOAD32 R0 R0 4 ; CURRENT_TARGET->INDIRECT->SIZE
  1188. CALLI R15 @ceil_log2 ; LOG2(CURRENT_TARGET->INDIRECT->SIZE)
  1189. CALLI R15 @numerate_number ; Convert to string
  1190. CALLI R15 @emit_out ; emit it
  1191. LOADUI R0 $newline ; Using "\n"
  1192. CALLI R15 @emit_out ; emit it
  1193. :postfix_expr_array_byte
  1194. LOADUI R0 $postfix_expr_array_string3 ; Add the offset
  1195. CALLI R15 @emit_out ; emit it
  1196. LOADUI R0 $postfix_expr_array_string4 ; Our final error message
  1197. LOADUI R1 $close_bracket ; Using "]"
  1198. CALLI R15 @require_match ; Ensure match
  1199. LOADUI R0 $equal ; Using "="
  1200. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1201. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  1202. CMPSKIPI.E R0 0 ; If match
  1203. LOADUI R2 $postfix_expr_array_string5 ; empty string
  1204. MOVE R0 R2 ; What ever string survived
  1205. CALLI R15 @emit_out ; emit it
  1206. POPR R2 R15 ; Restore R2
  1207. POPR R1 R15 ; Restore R1
  1208. POPR R0 R15 ; Restore R0
  1209. RET R15
  1210. :postfix_expr_array_string0
  1211. "LOAD_INTEGER
  1212. "
  1213. :postfix_expr_array_string1
  1214. "LOAD_BYTE
  1215. "
  1216. :postfix_expr_array_string2
  1217. "SAL_eax_Immediate8 !"
  1218. :postfix_expr_array_string3
  1219. "ADD_ebx_to_eax
  1220. "
  1221. :postfix_expr_array_string4
  1222. "ERROR in postfix_expr
  1223. Missing ]
  1224. "
  1225. :postfix_expr_array_string5
  1226. ""
  1227. ;; postfix_expr_stub function
  1228. ;; Receives nothing
  1229. ;; struct token_list* out in R12,
  1230. ;; struct token_list* string_list in R11
  1231. ;; struct token_list* global_list in R10
  1232. ;; and struct token_list* FUNC in R9
  1233. ;; and struct token_list* current_target in R8
  1234. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1235. ;; Returns the token_lists modified
  1236. :postfix_expr_stub
  1237. PUSHR R0 R15 ; Protect R0
  1238. PUSHR R1 R15 ; Protect R1
  1239. LOADUI R0 $open_bracket ; Using "["
  1240. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1241. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "["
  1242. JUMP.Z R0 @postfix_expr_stub_next
  1243. ;; Deal with "[" case
  1244. CALLI R15 @postfix_expr_array ; process
  1245. CALLI R15 @postfix_expr_stub ; recurse
  1246. :postfix_expr_stub_next
  1247. LOADUI R0 $arrow_string ; Using "->"
  1248. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1249. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "->"
  1250. JUMP.Z R0 @postfix_expr_stub_done ; clean up
  1251. ;; Deal with "->" case
  1252. CALLI R15 @postfix_expr_arrow ; Process
  1253. CALLI R15 @postfix_expr_stub ; recurse
  1254. :postfix_expr_stub_done
  1255. POPR R1 R15 ; Restore R1
  1256. POPR R0 R15 ; Restore R0
  1257. RET R15
  1258. ;; postfix_expr function
  1259. ;; struct token_list* out in R12,
  1260. ;; struct token_list* string_list in R11
  1261. ;; struct token_list* global_list in R10
  1262. ;; and struct token_list* FUNC in R9
  1263. ;; and struct token_list* current_target in R8
  1264. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1265. ;; Returns the token_lists modified
  1266. :postfix_expr
  1267. CALLI R15 @primary_expr ; Walk up the tree
  1268. CALLI R15 @postfix_expr_stub ; Deal with nodes on this level
  1269. RET R15
  1270. ;; additive_expr_stub function
  1271. ;; receives nothing
  1272. ;; returns nothing
  1273. ;; Updates struct token_list*
  1274. :additive_expr_stub
  1275. PUSHR R0 R15 ; Protect R0
  1276. PUSHR R1 R15 ; Protect R1
  1277. PUSHR R2 R15 ; Protect R2
  1278. PUSHR R3 R15 ; Protect R3
  1279. ;; Fixed pieces
  1280. LOADUI R0 $postfix_expr ; Set First argument
  1281. LOADUI R3 $additive_expr_stub
  1282. ;; The + bit
  1283. LOADUI R1 $additive_expr_stub_string0 ; Our first operation
  1284. LOADUI R2 $plus_string ; Using "+"
  1285. CALLI R15 @general_recursion
  1286. ;; The - bit
  1287. LOADUI R1 $additive_expr_stub_string1 ; Our second operation
  1288. LOADUI R2 $minus_string ; Using "-"
  1289. CALLI R15 @general_recursion
  1290. ;; The * bit
  1291. LOADUI R1 $additive_expr_stub_string2 ; Our third operation
  1292. LOADUI R2 $multiply_string ; Using "*"
  1293. CALLI R15 @general_recursion
  1294. ;; The / bit
  1295. LOADUI R1 $additive_expr_stub_string3 ; Our fourth operation
  1296. LOADUI R2 $divide_string ; Using "/"
  1297. CALLI R15 @general_recursion
  1298. ;; The % bit
  1299. LOADUI R1 $additive_expr_stub_string4 ; Our fifth operation
  1300. LOADUI R2 $modulus_string ; Using "%"
  1301. CALLI R15 @general_recursion
  1302. ;; The << bit
  1303. LOADUI R1 $additive_expr_stub_string5 ; Our sixth operation
  1304. LOADUI R2 $left_shift_string ; Using "<<"
  1305. CALLI R15 @general_recursion
  1306. ;; The >> bit
  1307. LOADUI R1 $additive_expr_stub_string6 ; Our final operation
  1308. LOADUI R2 $right_shift_string ; Using ">>"
  1309. CALLI R15 @general_recursion
  1310. POPR R3 R15 ; Restore R3
  1311. POPR R2 R15 ; Restore R2
  1312. POPR R1 R15 ; Restore R1
  1313. POPR R0 R15 ; Restore R0
  1314. RET R15
  1315. :additive_expr_stub_string0
  1316. "ADD_ebx_to_eax
  1317. "
  1318. :additive_expr_stub_string1
  1319. "SUBTRACT_eax_from_ebx_into_ebx
  1320. MOVE_ebx_to_eax
  1321. "
  1322. :additive_expr_stub_string2
  1323. "MULTIPLY_eax_by_ebx_into_eax
  1324. "
  1325. :additive_expr_stub_string3
  1326. "XCHG_eax_ebx
  1327. LOAD_IMMEDIATE_edx %0
  1328. DIVIDE_eax_by_ebx_into_eax
  1329. "
  1330. :additive_expr_stub_string4
  1331. "XCHG_eax_ebx
  1332. LOAD_IMMEDIATE_edx %0
  1333. MODULUS_eax_from_ebx_into_ebx
  1334. MOVE_edx_to_eax
  1335. "
  1336. :additive_expr_stub_string5
  1337. "COPY_eax_to_ecx
  1338. COPY_ebx_to_eax
  1339. SAL_eax_cl
  1340. "
  1341. :additive_expr_stub_string6
  1342. "COPY_eax_to_ecx
  1343. COPY_ebx_to_eax
  1344. SAR_eax_cl
  1345. "
  1346. ;; additive_expr function
  1347. ;; Receives struct token_list* global_token in R13,
  1348. ;; struct token_list* out in R12,
  1349. ;; struct token_list* string_list in R11
  1350. ;; struct token_list* global_list in R10
  1351. ;; and struct token_list* FUNC in R9
  1352. ;; and struct token_list* current_target in R8
  1353. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1354. ;; Returns the token_lists modified
  1355. :additive_expr
  1356. CALLI R15 @postfix_expr ; Walk up the tree
  1357. CALLI R15 @additive_expr_stub ; Deal with nodes at this level
  1358. RET R15
  1359. ;; relational_expr_stub function
  1360. ;; receives nothing
  1361. ;; returns nothing
  1362. ;; Updates struct token_list*
  1363. :relational_expr_stub
  1364. PUSHR R0 R15 ; Protect R0
  1365. PUSHR R1 R15 ; Protect R1
  1366. PUSHR R2 R15 ; Protect R2
  1367. PUSHR R3 R15 ; Protect R3
  1368. ;; Fixed pieces
  1369. LOADUI R0 $additive_expr ; Set First argument
  1370. LOADUI R3 $relational_expr_stub
  1371. ;; The < bit
  1372. LOADUI R1 $relational_expr_stub_string0 ; Our first operation
  1373. LOADUI R2 $less_than_string ; Using "<"
  1374. CALLI R15 @general_recursion
  1375. ;; The <= bit
  1376. LOADUI R1 $relational_expr_stub_string1 ; Our second operation
  1377. LOADUI R2 $less_than_equal_string ; Using "<="
  1378. CALLI R15 @general_recursion
  1379. ;; The >= bit
  1380. LOADUI R1 $relational_expr_stub_string2 ; Our third operation
  1381. LOADUI R2 $greater_than_equal_string ; Using ">="
  1382. CALLI R15 @general_recursion
  1383. ;; The > bit
  1384. LOADUI R1 $relational_expr_stub_string3 ; Our fourth operation
  1385. LOADUI R2 $greater_than_string ; Using ">"
  1386. CALLI R15 @general_recursion
  1387. ;; The == bit
  1388. LOADUI R1 $relational_expr_stub_string4 ; Our fifth operation
  1389. LOADUI R2 $equal_to_string ; Using "=="
  1390. CALLI R15 @general_recursion
  1391. ;; The != bit
  1392. LOADUI R1 $relational_expr_stub_string5 ; Our final operation
  1393. LOADUI R2 $not_equal_string ; Using "!="
  1394. CALLI R15 @general_recursion
  1395. POPR R3 R15 ; Restore R3
  1396. POPR R2 R15 ; Restore R2
  1397. POPR R1 R15 ; Restore R1
  1398. POPR R0 R15 ; Restore R0
  1399. RET R15
  1400. :relational_expr_stub_string0
  1401. "CMP
  1402. SETL
  1403. MOVEZBL
  1404. "
  1405. :relational_expr_stub_string1
  1406. "CMP
  1407. SETLE
  1408. MOVEZBL
  1409. "
  1410. :relational_expr_stub_string2
  1411. "CMP
  1412. SETGE
  1413. MOVEZBL
  1414. "
  1415. :relational_expr_stub_string3
  1416. "CMP
  1417. SETG
  1418. MOVEZBL
  1419. "
  1420. :relational_expr_stub_string4
  1421. "CMP
  1422. SETE
  1423. MOVEZBL
  1424. "
  1425. :relational_expr_stub_string5
  1426. "CMP
  1427. SETNE
  1428. MOVEZBL
  1429. "
  1430. ;; relational_expr function
  1431. ;; Receives struct token_list* global_token in R13,
  1432. ;; struct token_list* out in R12,
  1433. ;; struct token_list* string_list in R11
  1434. ;; struct token_list* global_list in R10
  1435. ;; and struct token_list* FUNC in R9
  1436. ;; and struct token_list* current_target in R8
  1437. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1438. ;; Returns the token_lists modified
  1439. :relational_expr
  1440. CALLI R15 @additive_expr ; Walk up the tree
  1441. CALLI R15 @relational_expr_stub ; Deal with nodes at this level
  1442. RET R15
  1443. ;; relational_expr_stub function
  1444. ;; receives nothing
  1445. ;; returns nothing
  1446. ;; Updates struct token_list*
  1447. :bitwise_expr_stub
  1448. PUSHR R0 R15 ; Protect R0
  1449. PUSHR R1 R15 ; Protect R1
  1450. PUSHR R2 R15 ; Protect R2
  1451. PUSHR R3 R15 ; Protect R3
  1452. ;; Fixed pieces
  1453. LOADUI R0 $relational_expr ; Set First argument
  1454. LOADUI R3 $bitwise_expr_stub
  1455. ;; The & bit
  1456. LOADUI R1 $bitwise_expr_stub_string0 ; Our first operation
  1457. LOADUI R2 $bitwise_and ; Using "&"
  1458. CALLI R15 @general_recursion
  1459. ;; The && bit
  1460. LOADUI R1 $bitwise_expr_stub_string0 ; Our first operation
  1461. LOADUI R2 $logical_and ; Using "&&"
  1462. CALLI R15 @general_recursion
  1463. ;; The | bit
  1464. LOADUI R1 $bitwise_expr_stub_string1 ; Our second operation
  1465. LOADUI R2 $bitwise_or ; Using "|"
  1466. CALLI R15 @general_recursion
  1467. ;; The || bit
  1468. LOADUI R1 $bitwise_expr_stub_string1 ; Our second operation
  1469. LOADUI R2 $logical_or ; Using "||"
  1470. CALLI R15 @general_recursion
  1471. ;; The ^ bit
  1472. LOADUI R1 $bitwise_expr_stub_string2 ; Our second operation
  1473. LOADUI R2 $bitwise_xor ; Using "^"
  1474. CALLI R15 @general_recursion
  1475. POPR R3 R15 ; Restore R3
  1476. POPR R2 R15 ; Restore R2
  1477. POPR R1 R15 ; Restore R1
  1478. POPR R0 R15 ; Restore R0
  1479. RET R15
  1480. :bitwise_expr_stub_string0
  1481. "AND_eax_ebx
  1482. "
  1483. :bitwise_expr_stub_string1
  1484. "OR_eax_ebx
  1485. "
  1486. :bitwise_expr_stub_string2
  1487. "XOR_ebx_eax_into_eax
  1488. "
  1489. ;; bitwise_expr function
  1490. ;; Receives struct token_list* global_token in R13,
  1491. ;; struct token_list* out in R12,
  1492. ;; struct token_list* string_list in R11
  1493. ;; struct token_list* global_list in R10
  1494. ;; and struct token_list* FUNC in R9
  1495. ;; and struct token_list* current_target in R8
  1496. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1497. ;; Returns the token_lists modified
  1498. :bitwise_expr
  1499. CALLI R15 @relational_expr ; Walk up the tree
  1500. CALLI R15 @bitwise_expr_stub ; Deal with nodes at this level
  1501. RET R15
  1502. ;; primary_expr function
  1503. ;; Receives struct token_list* global_token in R13,
  1504. ;; struct token_list* out in R12,
  1505. ;; struct token_list* string_list in R11
  1506. ;; struct token_list* global_list in R10
  1507. ;; and struct token_list* FUNC in R9
  1508. ;; and struct token_list* current_target in R8
  1509. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1510. ;; Returns the token_lists modified
  1511. :primary_expr
  1512. PUSHR R0 R15 ; Protect R0
  1513. PUSHR R1 R15 ; Protect R1
  1514. LOADUI R0 $sizeof_string ; Load "sizeof"
  1515. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1516. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "sizeof"
  1517. JUMP.Z R0 @primary_expr_negate ; Guess not
  1518. ;; Deal with sizeof expression
  1519. CALLI R15 @unary_expr_sizeof ; Do real work
  1520. JUMP @primary_expr_done ; Wrap up
  1521. :primary_expr_negate
  1522. LOADU8 R0 R1 0 ; GLOBAL_TOKEN->S[0]
  1523. CMPSKIPI.E R0 45 ; IF GLOBAL_TOKEN->S[0] == '-'
  1524. JUMP @primary_expr_bang ; If not try '!'
  1525. ;; Deal with -a and -4 expressions
  1526. LOADUI R0 $primary_expr_str0 ; Load HEADER
  1527. CALLI R15 @emit_out ; emit it
  1528. LOADUI R0 $primary_expr ; Using PRIMARY_EXPR
  1529. CALLI R15 @common_recursion ; Recurse
  1530. LOADUI R0 $primary_expr_str1 ; add footer
  1531. CALLI R15 @emit_out ; emit it
  1532. JUMP @primary_expr_done ; Wrap up
  1533. :primary_expr_bang
  1534. CMPSKIPI.E R0 33 ; IF GLOBAL_TOKEN->S[0] == "!"
  1535. JUMP @primary_expr_nested ; If not try '('
  1536. ;; deal with !a expressions
  1537. LOADUI R0 $primary_expr_str2 ; Load HEADER
  1538. CALLI R15 @emit_out ; emit it
  1539. LOADUI R0 $postfix_expr ; Using POSTFIX_EXPR
  1540. CALLI R15 @common_recursion ; Recurse
  1541. LOADUI R0 $primary_expr_str3 ; add footer
  1542. CALLI R15 @emit_out ; emit it
  1543. JUMP @primary_expr_done ; Wrap up
  1544. :primary_expr_nested
  1545. CMPSKIPI.E R0 40 ; IF GLOBAL_TOKEN->S[0] == '('
  1546. JUMP @primary_expr_ch ; If not try 'char'
  1547. ;; Deal with ( expr )
  1548. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1549. CALLI R15 @expression ; Recurse
  1550. LOADUI R0 $primary_expr_str4 ; Using error message
  1551. LOADUI R1 $close_paren ; Using ")"
  1552. CALLI R15 @require_match ; Make sure we have closing match
  1553. JUMP @primary_expr_done ; Wrap up
  1554. :primary_expr_ch
  1555. CMPSKIPI.E R0 39 ; IF GLOBAL_TOKEN->S[0] == '\''
  1556. JUMP @primary_expr_st ; If not try "string"
  1557. ;; Deal with 'char'
  1558. CALLI R15 @primary_expr_char ; Collect char
  1559. JUMP @primary_expr_done ; Wrap up
  1560. :primary_expr_st
  1561. CMPSKIPI.E R0 34 ; IF GLOBAL_TOKEN->S[0] == '"'
  1562. JUMP @primary_expr_var ; If not try variables
  1563. ;; deal with "string"
  1564. CALLI R15 @primary_expr_string ; Collect string
  1565. JUMP @primary_expr_done ; Wrap up
  1566. :primary_expr_var
  1567. LOADUI R1 $variable_chars ; Using a-z+A-Z+_
  1568. CALLI R15 @in_set ; IF GLOBAL_TOKEN->S[0] in a-z+A-Z+_
  1569. JUMP.Z R0 @primary_expr_num
  1570. ;; Deal with foo TODO
  1571. CALLI R15 @primary_expr_variable ; deal with names
  1572. JUMP @primary_expr_done ; Wrap up
  1573. :primary_expr_num
  1574. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  1575. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  1576. LOADUI R1 $digit_chars ; Using 0-9
  1577. CALLI R15 @in_set ; IF GLOBAL_TOKEN->S[0] in 0-9
  1578. JUMP.Z R0 @primary_expr_failure ; Fail HARD
  1579. ;; Deal with 5
  1580. CALLI R15 @primary_expr_number ; deal with number
  1581. :primary_expr_done
  1582. POPR R1 R15 ; Restore R1
  1583. POPR R0 R15 ; Restore R0
  1584. RET R15
  1585. :primary_expr_str0
  1586. "LOAD_IMMEDIATE_eax %0
  1587. "
  1588. :primary_expr_str1
  1589. "SUBTRACT_eax_from_ebx_into_ebx
  1590. MOVE_ebx_to_eax
  1591. "
  1592. :primary_expr_str2
  1593. "LOAD_IMMEDIATE_eax %1
  1594. "
  1595. :primary_expr_str3
  1596. "XOR_ebx_eax_into_eax
  1597. "
  1598. :primary_expr_str4
  1599. "Error in Primary expression
  1600. Didn't get )
  1601. "
  1602. ;; expression function
  1603. ;; Receives struct token_list* global_token in R13,
  1604. ;; struct token_list* out in R12,
  1605. ;; struct token_list* string_list in R11
  1606. ;; struct token_list* global_list in R10
  1607. ;; and struct token_list* FUNC in R9
  1608. ;; and struct token_list* current_target in R8
  1609. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1610. ;; Returns the token_lists modified
  1611. :expression
  1612. PUSHR R0 R15 ; Protect R0
  1613. PUSHR R1 R15 ; Protect R1
  1614. PUSHR R2 R15 ; Protect R2
  1615. PUSHR R3 R15 ; Protect R3
  1616. CALLI R15 @bitwise_expr ; Check for more primitives first
  1617. LOADUI R0 $equal ; Using "="
  1618. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1619. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  1620. JUMP.Z R0 @expression_done ; Be done
  1621. ;; Determine store type
  1622. LOADUI R3 $expression_string1 ; Assuming the default of STORE CHAR
  1623. ;; First possible reason for INT
  1624. LOADUI R0 $close_bracket ; Using "]"
  1625. LOAD32 R1 R13 4 ; GLOBAL_TOKEN->PREV
  1626. LOAD32 R1 R1 8 ; GLOBAL_TOKEN->PREV->S
  1627. CALLI R15 @match ; IF GLOBAL_TOKEN->PREV-> == "]"
  1628. CMPSKIPI.NE R0 0 ; IF FALSE
  1629. LOADUI R3 $expression_string0 ; STORE INTEGER
  1630. ;; Second possible reason for INTeger
  1631. LOADUI R0 $type_char_indirect_name ; Using "char*"
  1632. LOAD32 R1 R8 24 ; CURRENT_TARGET->NAME
  1633. CALLI R15 @match ; IF CURRENT_TARGET->NAME == "char*"
  1634. CMPSKIPI.NE R0 0 ; IF FALSE
  1635. LOADUI R3 $expression_string0 ; STORE INTEGER
  1636. ;; Recurse to evaluate expression being stored
  1637. LOADUI R0 $expression ; Using expression
  1638. CALLI R15 @common_recursion ; Perform common recursion
  1639. ;; Put our string and clean up
  1640. MOVE R0 R3 ; Using our STORED string
  1641. CALLI R15 @emit_out ; emit it
  1642. FALSE R8 ; CURRENT_TARGET = NULL
  1643. :expression_done
  1644. POPR R3 R15 ; Restore R3
  1645. POPR R2 R15 ; Restore R2
  1646. POPR R1 R15 ; Restore R1
  1647. POPR R0 R15 ; Restore R0
  1648. RET R15
  1649. :expression_string0
  1650. "STORE_INTEGER
  1651. "
  1652. :expression_string1
  1653. "STORE_CHAR
  1654. "
  1655. ;; process_if function
  1656. ;; struct token_list* out in R12,
  1657. ;; struct token_list* string_list in R11
  1658. ;; struct token_list* global_list in R10
  1659. ;; and struct token_list* FUNC in R9
  1660. ;; and struct token_list* current_target in R8
  1661. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1662. ;; Returns the token_lists modified
  1663. :process_if
  1664. PUSHR R0 R15 ; Protect R0
  1665. PUSHR R1 R15 ; Protect R1
  1666. PUSHR R2 R15 ; Protect R2
  1667. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  1668. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  1669. STORER32 R1 @current_count ; Update CURRENT_COUNT
  1670. CALLI R15 @numerate_number ; Convert CURRENT_COUNT to string
  1671. MOVE R2 R0 ; Protect our string
  1672. LOADUI R0 $process_if_string0 ; using first string
  1673. CALLI R15 @emit_out ; emit it
  1674. LOAD32 R0 R9 8 ; FUNCTION->S
  1675. COPY R1 R2 ; Using our current count string
  1676. CALLI R15 @uniqueID_out ; Add unique identifier
  1677. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1678. LOADUI R0 $process_if_string1 ; Our first error message
  1679. LOADUI R1 $open_paren ; Using "("
  1680. CALLI R15 @require_match ; Make sure we have what we need
  1681. CALLI R15 @expression ; Recurse to get our boolean expression
  1682. LOADUI R0 $process_if_string2 ; Our test and jump
  1683. CALLI R15 @emit_out ; emit it
  1684. LOAD32 R0 R9 8 ; FUNCTION->S
  1685. COPY R1 R2 ; Using our current count string
  1686. CALLI R15 @uniqueID_out ; Add unique identifier
  1687. LOADUI R0 $process_if_string3 ; Our second error message
  1688. LOADUI R1 $close_paren ; Using ")"
  1689. CALLI R15 @require_match ; Make sure we have what we need
  1690. CALLI R15 @statement ; Collect our if statement
  1691. LOADUI R0 $process_if_string4 ; Our jump over else
  1692. CALLI R15 @emit_out ; emit it
  1693. LOAD32 R0 R9 8 ; FUNCTION->S
  1694. COPY R1 R2 ; Using our current count string
  1695. CALLI R15 @uniqueID_out ; Add unique identifier
  1696. LOADUI R0 $process_if_string5 ; Our else label
  1697. CALLI R15 @emit_out ; emit it
  1698. LOAD32 R0 R9 8 ; FUNCTION->S
  1699. CALLI R15 @uniqueID_out ; Add unique identifier
  1700. LOADUI R0 $else_string ; Using "else"
  1701. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1702. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "else"
  1703. JUMP.Z R0 @process_if_else ; Looks like no else
  1704. ;; Deal with else
  1705. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1706. CALLI R15 @statement ; Grab else statement
  1707. :process_if_else
  1708. LOADUI R0 $process_if_string6 ; Our jump over else
  1709. CALLI R15 @emit_out ; emit it
  1710. LOAD32 R0 R9 8 ; FUNCTION->S
  1711. COPY R1 R2 ; Using our current count string
  1712. CALLI R15 @uniqueID_out ; Add unique identifier
  1713. POPR R2 R15 ; Restore R2
  1714. POPR R1 R15 ; Restore R1
  1715. POPR R0 R15 ; Restore R0
  1716. RET R15
  1717. :process_if_string0
  1718. "# IF_"
  1719. :process_if_string1
  1720. "ERROR in process_if
  1721. MISSING (
  1722. "
  1723. :process_if_string2
  1724. "TEST
  1725. JUMP_EQ %ELSE_"
  1726. :process_if_string3
  1727. "ERROR in process_if
  1728. MISSING )
  1729. "
  1730. :process_if_string4
  1731. "JUMP %_END_IF_"
  1732. :process_if_string5
  1733. ":ELSE_"
  1734. :process_if_string6
  1735. ":_END_IF_"
  1736. ;; save_break_frame microfunction
  1737. ;; Overwrites R0 and R1
  1738. ;; Saves break frame on stack
  1739. ;; Returns to caller
  1740. :save_break_frame
  1741. POPR R1 R15 ; Save return address
  1742. LOADR32 R0 @break_frame ; Obtain BREAK_FRAME
  1743. PUSHR R0 R15 ; Protect BREAK_FRAME
  1744. LOADR32 R0 @break_target_head ; obtain HEAD
  1745. PUSHR R0 R15 ; Protect HEAD
  1746. LOADR32 R0 @break_target_func ; obtain FUNC
  1747. PUSHR R0 R15 ; Protect FUNC
  1748. LOADR32 R0 @break_target_num ; obtain NUM
  1749. PUSHR R0 R15 ; Protect NUM
  1750. PUSHR R1 R15 ; Set where we are returning to
  1751. RET R15
  1752. ;; restore_break_frame microfunction
  1753. ;; Overwrites R0 and R1
  1754. ;; Restores break frame from stack
  1755. ;; Returns to caller
  1756. :restore_break_frame
  1757. POPR R1 R15 ; Save return address
  1758. POPR R0 R15 ; obtain NUM
  1759. STORER32 R0 @break_target_num ; Restore NUM
  1760. POPR R0 R15 ; obtain FUNC
  1761. STORER32 R0 @break_target_func ; Restore FUNC
  1762. POPR R0 R15 ; obtain HEAD
  1763. STORER32 R0 @break_target_head ; Restore HEAD
  1764. POPR R0 R15 ; obtain BREAK_FRAME
  1765. STORER32 R0 @break_frame ; Restore BREAK_FRAME
  1766. PUSHR R1 R15 ; Set where we are returning to
  1767. RET R15
  1768. ;; set_break_frame microfunction
  1769. ;; Receives char* num in R0, char* head in R1
  1770. ;; Overwrites R0
  1771. ;; Sets break frame using
  1772. ;; R9 holding FUNC
  1773. ;; Returns to calling function
  1774. :set_break_frame
  1775. STORER32 R1 @break_target_head ; update BREAK_TARGET_HEAD
  1776. STORER32 R0 @break_target_num ; Update BREAK_TARGET_NUM
  1777. LOAD32 R0 R9 4 ; Using FUNCTION->LOCALS
  1778. STORER32 R0 @break_frame ; update BREAK_FRAME
  1779. LOAD32 R0 R9 8 ; Using FUNCTION->S
  1780. STORER32 R0 @break_target_func ; update BREAK_TARGET_FUNC
  1781. RET R15
  1782. ;; process_for function
  1783. ;; struct token_list* out in R12,
  1784. ;; struct token_list* string_list in R11
  1785. ;; struct token_list* global_list in R10
  1786. ;; and struct token_list* FUNC in R9
  1787. ;; and struct token_list* current_target in R8
  1788. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1789. ;; Returns the token_lists modified
  1790. :process_for
  1791. PUSHR R2 R15 ; Protect R2
  1792. PUSHR R1 R15 ; Protect R1
  1793. PUSHR R0 R15 ; Protect R0
  1794. CALLI R15 @save_break_frame ; Save break frame
  1795. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  1796. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  1797. STORER32 R1 @current_count ; Update CURRENT_COUNT
  1798. CALLI R15 @numerate_number ; Convert to string
  1799. COPY R2 R0 ; Protect NUMBER_STRING
  1800. LOADUI R1 $process_for_string0 ; Get new HEAD
  1801. CALLI R15 @set_break_frame ; Set the break frame values
  1802. LOADUI R0 $process_for_string1 ; Our comment header
  1803. CALLI R15 @emit_out ; emit it
  1804. COPY R1 R2 ; Using NUMBER_STRING
  1805. LOAD32 R0 R9 8 ; FUNCTION->S
  1806. CALLI R15 @uniqueID_out ; emit it
  1807. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1808. LOADUI R0 $process_for_string2 ; Our first error message
  1809. LOADUI R1 $open_paren ; Using "("
  1810. CALLI R15 @require_match ; Verify match
  1811. LOADUI R0 $semicolon ; Using ";"
  1812. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1813. CALLI R15 @match ; IF GLOBAL_TOKEN->S -- ";"
  1814. CMPSKIPI.NE R0 0 ; If GLOBAL_TOKEN->S != ";"
  1815. CALLI R15 @expression ; Skip that step
  1816. LOADUI R0 $process_for_string3 ; Our comment header
  1817. CALLI R15 @emit_out ; emit it
  1818. COPY R1 R2 ; Using NUMBER_STRING
  1819. LOAD32 R0 R9 8 ; FUNCTION->S
  1820. CALLI R15 @uniqueID_out ; emit it
  1821. LOADUI R0 $process_for_string4 ; Our second error message
  1822. LOADUI R1 $semicolon ; Using ";"
  1823. CALLI R15 @require_match ; Verify match
  1824. CALLI R15 @expression ; TEST logic required
  1825. LOADUI R0 $process_for_string5 ; Our comment header
  1826. CALLI R15 @emit_out ; emit it
  1827. COPY R1 R2 ; Using NUMBER_STRING
  1828. LOAD32 R0 R9 8 ; FUNCTION->S
  1829. CALLI R15 @uniqueID_out ; emit it
  1830. LOADUI R0 $process_for_string6 ; Our comment header
  1831. CALLI R15 @emit_out ; emit it
  1832. LOAD32 R0 R9 8 ; FUNCTION->S
  1833. CALLI R15 @uniqueID_out ; emit it
  1834. LOADUI R0 $process_for_string7 ; Our comment header
  1835. CALLI R15 @emit_out ; emit it
  1836. LOAD32 R0 R9 8 ; FUNCTION->S
  1837. CALLI R15 @uniqueID_out ; emit it
  1838. LOADUI R0 $process_for_string8 ; Our third error message
  1839. LOADUI R1 $semicolon ; Using ";"
  1840. CALLI R15 @require_match ; Verify match
  1841. CALLI R15 @expression ; Iterator logic
  1842. LOADUI R0 $process_for_string9 ; Our comment header
  1843. CALLI R15 @emit_out ; emit it
  1844. COPY R1 R2 ; Using NUMBER_STRING
  1845. LOAD32 R0 R9 8 ; FUNCTION->S
  1846. CALLI R15 @uniqueID_out ; emit it
  1847. LOADUI R0 $process_for_string10 ; Our comment header
  1848. CALLI R15 @emit_out ; emit it
  1849. LOAD32 R0 R9 8 ; FUNCTION->S
  1850. CALLI R15 @uniqueID_out ; emit it
  1851. LOADUI R0 $process_for_string11 ; Our final error message
  1852. LOADUI R1 $close_paren ; Using ")"
  1853. CALLI R15 @require_match ; Verify match
  1854. CALLI R15 @statement ; Main body
  1855. LOADUI R0 $process_for_string12 ; Our comment header
  1856. CALLI R15 @emit_out ; emit it
  1857. COPY R1 R2 ; Using NUMBER_STRING
  1858. LOAD32 R0 R9 8 ; FUNCTION->S
  1859. CALLI R15 @uniqueID_out ; emit it
  1860. LOADUI R0 $process_for_string13 ; Our comment header
  1861. CALLI R15 @emit_out ; emit it
  1862. LOAD32 R0 R9 8 ; FUNCTION->S
  1863. CALLI R15 @uniqueID_out ; emit it
  1864. CALLI R15 @restore_break_frame ; Restore break frame
  1865. POPR R0 R15 ; Restore R0
  1866. POPR R1 R15 ; Restore R1
  1867. POPR R2 R15 ; Restore R2
  1868. RET R15
  1869. :process_for_string0
  1870. "FOR_END_"
  1871. :process_for_string1
  1872. "# FOR_initialization_"
  1873. :process_for_string2
  1874. "ERROR in process_for
  1875. MISSING (
  1876. "
  1877. :process_for_string3
  1878. ":FOR_"
  1879. :process_for_string4
  1880. "ERROR in process_for
  1881. MISSING ;1
  1882. "
  1883. :process_for_string5
  1884. "TEST
  1885. JUMP_EQ %FOR_END_"
  1886. :process_for_string6
  1887. "JUMP %FOR_THEN_"
  1888. :process_for_string7
  1889. ":FOR_ITER_"
  1890. :process_for_string8
  1891. "ERROR in process_for
  1892. MISSING ;2
  1893. "
  1894. :process_for_string9
  1895. "JUMP %FOR_"
  1896. :process_for_string10
  1897. ":FOR_THEN_"
  1898. :process_for_string11
  1899. "ERROR in process_for
  1900. MISSING )
  1901. "
  1902. :process_for_string12
  1903. "JUMP %FOR_ITER_"
  1904. :process_for_string13
  1905. ":FOR_END_"
  1906. ;; process_do function
  1907. ;; struct token_list* out in R12,
  1908. ;; struct token_list* string_list in R11
  1909. ;; struct token_list* global_list in R10
  1910. ;; and struct token_list* FUNC in R9
  1911. ;; and struct token_list* current_target in R8
  1912. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1913. ;; Returns the token_lists modified
  1914. :process_do
  1915. PUSHR R2 R15 ; Protect R2
  1916. PUSHR R1 R15 ; Protect R1
  1917. PUSHR R0 R15 ; Protect R0
  1918. CALLI R15 @save_break_frame ; Save break frame
  1919. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  1920. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  1921. STORER32 R1 @current_count ; Update CURRENT_COUNT
  1922. CALLI R15 @numerate_number ; Convert to string
  1923. COPY R2 R0 ; Protect NUMBER_STRING
  1924. LOADUI R1 $process_do_string0 ; Using our desired head
  1925. CALLI R15 @set_break_frame ; Set the break frame values
  1926. LOADUI R0 $process_do_string1 ; Our label
  1927. CALLI R15 @emit_out ; emit it
  1928. COPY R1 R2 ; Using NUMBER_STRING
  1929. LOAD32 R0 R9 8 ; FUNCTION->S
  1930. CALLI R15 @uniqueID_out ; emit it
  1931. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1932. CALLI R15 @statement ; Collect our Do statement
  1933. LOADUI R0 $process_do_string2 ; our first error message
  1934. LOADUI R1 $while_string ; Using "while"
  1935. CALLI R15 @require_match ; Check for match
  1936. LOADUI R0 $process_do_string3 ; our second error message
  1937. LOADUI R1 $open_paren ; Using "("
  1938. CALLI R15 @require_match ; Check for match
  1939. CALLI R15 @expression ; Our logical expression
  1940. LOADUI R0 $process_do_string4 ; our third error message
  1941. LOADUI R1 $close_paren ; Using ")"
  1942. CALLI R15 @require_match ; Check for match
  1943. LOADUI R0 $process_do_string5 ; our final error message
  1944. LOADUI R1 $semicolon ; Using ";"
  1945. CALLI R15 @require_match ; Check for match
  1946. LOADUI R0 $process_do_string6 ; Our test string
  1947. CALLI R15 @emit_out ; emit it
  1948. COPY R1 R2 ; Put NUMBER_STRING in right place
  1949. LOAD32 R0 R9 8 ; FUNCTION->S
  1950. CALLI R15 @uniqueID_out ; emit it
  1951. LOADUI R0 $process_do_string7 ; Our end label string
  1952. CALLI R15 @emit_out ; emit it
  1953. LOAD32 R0 R9 8 ; FUNCTION->S
  1954. CALLI R15 @uniqueID_out ; emit it
  1955. CALLI R15 @restore_break_frame ; Restore break frame
  1956. POPR R0 R15 ; Restore R0
  1957. POPR R1 R15 ; Restore R1
  1958. POPR R2 R15 ; Restore R2
  1959. RET R15
  1960. :process_do_string0
  1961. "DO_END_"
  1962. :process_do_string1
  1963. ":DO_"
  1964. :process_do_string2
  1965. "ERROR in process_do
  1966. MISSING while
  1967. "
  1968. :process_do_string3
  1969. "ERROR in process_do
  1970. MISSING (
  1971. "
  1972. :process_do_string4
  1973. "ERROR in process_do
  1974. MISSING )
  1975. "
  1976. :process_do_string5
  1977. "ERROR in process_do
  1978. MISSING ;
  1979. "
  1980. :process_do_string6
  1981. "TEST
  1982. JUMP_NE %DO_"
  1983. :process_do_string7
  1984. ":DO_END_"
  1985. ;; process_while function
  1986. ;; struct token_list* out in R12,
  1987. ;; struct token_list* string_list in R11
  1988. ;; struct token_list* global_list in R10
  1989. ;; and struct token_list* FUNC in R9
  1990. ;; and struct token_list* current_target in R8
  1991. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1992. ;; Returns the token_lists modified
  1993. :process_while
  1994. PUSHR R2 R15 ; Protect R2
  1995. PUSHR R1 R15 ; Protect R1
  1996. PUSHR R0 R15 ; Protect R0
  1997. CALLI R15 @save_break_frame ; Save break frame
  1998. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  1999. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  2000. STORER32 R1 @current_count ; Update CURRENT_COUNT
  2001. CALLI R15 @numerate_number ; Convert to string
  2002. COPY R2 R0 ; Protect NUMBER_STRING
  2003. LOADUI R1 $process_while_string0 ; Set HEAD
  2004. CALLI R15 @set_break_frame ; Set the break frame values
  2005. LOADUI R0 $process_while_string1 ; Our head label
  2006. CALLI R15 @emit_out ; emit it
  2007. COPY R1 R2 ; Using NUMBER_STRING
  2008. LOAD32 R0 R9 8 ; FUNCTION->S
  2009. CALLI R15 @uniqueID_out ; emit it
  2010. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2011. LOADUI R0 $process_while_string2 ; Our first error message
  2012. LOADUI R1 $open_paren ; Using "("
  2013. CALLI R15 @require_match ; Check for match
  2014. CALLI R15 @expression ; Collect test expression
  2015. LOADUI R0 $process_while_string3 ; Our test and jump
  2016. CALLI R15 @emit_out ; emit it
  2017. COPY R1 R2 ; Using NUMBER_STRING
  2018. LOAD32 R0 R9 8 ; FUNCTION->S
  2019. CALLI R15 @uniqueID_out ; emit it
  2020. LOADUI R0 $process_while_string4 ; Our trailing comment
  2021. CALLI R15 @emit_out ; emit it
  2022. LOAD32 R0 R9 8 ; FUNCTION->S
  2023. CALLI R15 @uniqueID_out ; emit it
  2024. LOADUI R0 $process_while_string5 ; Our first error message
  2025. LOADUI R1 $close_paren ; Using ")"
  2026. CALLI R15 @require_match ; Check for match
  2027. CALLI R15 @statement ; Collect our loop statement
  2028. LOADUI R0 $process_while_string6 ; Our test and jump
  2029. CALLI R15 @emit_out ; emit it
  2030. COPY R1 R2 ; Using NUMBER_STRING
  2031. LOAD32 R0 R9 8 ; FUNCTION->S
  2032. CALLI R15 @uniqueID_out ; emit it
  2033. LOADUI R0 $process_while_string7 ; Our trailing comment
  2034. CALLI R15 @emit_out ; emit it
  2035. LOAD32 R0 R9 8 ; FUNCTION->S
  2036. CALLI R15 @uniqueID_out ; emit it
  2037. CALLI R15 @restore_break_frame ; Restore break frame
  2038. POPR R0 R15 ; Restore R0
  2039. POPR R1 R15 ; Restore R1
  2040. POPR R2 R15 ; Restore R2
  2041. RET R15
  2042. :process_while_string0
  2043. "END_WHILE_"
  2044. :process_while_string1
  2045. ":WHILE_"
  2046. :process_while_string2
  2047. "ERROR in process_while
  2048. MISSING (
  2049. "
  2050. :process_while_string3
  2051. "TEST
  2052. JUMP_EQ %END_WHILE_"
  2053. :process_while_string4
  2054. "# THEN_while_"
  2055. :process_while_string5
  2056. "ERROR in process_while
  2057. MISSING )
  2058. "
  2059. :process_while_string6
  2060. "JUMP %WHILE_"
  2061. :process_while_string7
  2062. ":END_WHILE_"
  2063. ;; return_result function
  2064. ;; Receives nothing
  2065. ;; Returns nothing
  2066. ;; and struct token_list* FUNC in R9
  2067. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2068. :return_result
  2069. PUSHR R0 R15 ; Protect R0
  2070. PUSHR R1 R15 ; Protect R1
  2071. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2072. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2073. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2074. CMPSKIPI.E R0 59 ; IF GLOBAL_TOKEN->S[0] == ';'
  2075. CALLI R15 @expression ; Evaluate expression
  2076. LOADUI R0 $return_result_string0 ; Using or error message
  2077. LOADUI R1 $semicolon ; Using ";"
  2078. CALLI R15 @require_match ; Require a match to ";"
  2079. LOADUI R0 $return_result_string1 ; Our pop command
  2080. LOAD32 R1 R9 4 ; FUNCTION->LOCALS
  2081. :return_result_iter
  2082. JUMP.Z R1 @return_result_done ; Be done when we hit NULL
  2083. CALLI R15 @emit_out ; Put the string every iteration
  2084. LOAD32 R1 R1 0 ; I = I->NEXT
  2085. JUMP @return_result_iter ; Keep looping
  2086. :return_result_done
  2087. LOADUI R0 $return_result_string2 ; Our footer
  2088. CALLI R15 @emit_out ; emit it
  2089. POPR R1 R15 ; Restore R1
  2090. POPR R0 R15 ; Restore R0
  2091. RET R15
  2092. :return_result_string0
  2093. "ERROR in return_result
  2094. MISSING ;
  2095. "
  2096. :return_result_string1
  2097. "POP_ebx # _return_result_locals
  2098. "
  2099. :return_result_string2
  2100. "RETURN
  2101. "
  2102. ;; process_break function
  2103. ;; Receives nothing
  2104. ;; and struct token_list* FUNC in R9
  2105. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2106. ;; Returns the token_lists modified
  2107. :process_break
  2108. PUSHR R0 R15 ; Protect R0
  2109. PUSHR R1 R15 ; Protect R1
  2110. PUSHR R2 R15 ; Protect R2
  2111. LOADR32 R0 @break_target_head ; BREAK_TARGET_HEAD
  2112. JUMP.NZ R0 @process_break_NON_NULL
  2113. ;; Deal with NULL == BREAK_TARGET_HEAD
  2114. LOADUI R0 $process_break_string0 ; Our first error message
  2115. FALSE R1 ; Write for User
  2116. CALLI R15 @file_print ; write it
  2117. CALLI R15 @line_error ; Give useful info
  2118. LOADUI R0 $newline ; Using "\n"
  2119. CALLI R15 @file_print ; Print it
  2120. HALT
  2121. :process_break_NON_NULL
  2122. LOADR32 R2 @break_frame ; BREAK_FRAME
  2123. LOAD32 R1 R9 4 ; I = FUNCTION->LOCALS
  2124. LOADUI R0 $process_break_string1 ; Our pop string
  2125. :process_break_iter
  2126. CMPJUMPI.E R1 R2 @process_break_done ; IF I == BREAK_FRAME
  2127. JUMP.Z R1 @process_break_done ; IF NULL == I break
  2128. CALLI R15 @emit_out ; emit pop
  2129. LOAD32 R1 R1 0 ; I = I->NEXT
  2130. JUMP @process_break_iter ; Loop
  2131. :process_break_done
  2132. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2133. LOADUI R0 $process_break_string2 ; Our jump string
  2134. CALLI R15 @emit_out ; emit it
  2135. LOADR32 R0 @break_target_head ; Our HEAD string
  2136. CALLI R15 @emit_out ; emit it
  2137. LOADR32 R0 @break_target_func ; Our FUNC string
  2138. CALLI R15 @emit_out ; emit it
  2139. LOADUI R0 $underline ; Using "_"
  2140. CALLI R15 @emit_out ; emit it
  2141. LOADR32 R0 @break_target_num ; Our NUM string
  2142. CALLI R15 @emit_out ; emit it
  2143. LOADUI R0 $newline ; Using "\n"
  2144. CALLI R15 @emit_out ; emit it
  2145. LOADUI R0 $process_break_string3 ; Our final error string
  2146. LOADUI R1 $semicolon ; Using ";"
  2147. CALLI R15 @require_match ; Make sure we get that match
  2148. POPR R2 R15 ; Restore R2
  2149. POPR R1 R15 ; Restore R1
  2150. POPR R0 R15 ; Restore R0
  2151. RET R15
  2152. :process_break_string0
  2153. "Not inside of a loop or case statement
  2154. "
  2155. :process_break_string1
  2156. "POP_ebx # break_cleanup_locals
  2157. "
  2158. :process_break_string2
  2159. "JUMP %"
  2160. :process_break_string3
  2161. "ERROR in break statement
  2162. Missing ;
  2163. "
  2164. :break_frame
  2165. NOP
  2166. :break_target_head
  2167. NOP
  2168. :break_target_func
  2169. NOP
  2170. :break_target_num
  2171. NOP
  2172. ;; process_asm function
  2173. ;; Receives struct token_list* global_token in R13,
  2174. ;; struct token_list* out in R12,
  2175. ;; struct token_list* string_list in R11
  2176. ;; struct token_list* global_list in R10
  2177. ;; and struct token_list* FUNC in R9
  2178. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2179. ;; Returns the token_lists modified
  2180. :process_asm
  2181. PUSHR R0 R15 ; Protect R0
  2182. PUSHR R1 R15 ; Protect R1
  2183. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2184. ;; First required match
  2185. LOADUI R0 $process_asm_string0 ; Using our First error message
  2186. LOADUI R1 $open_paren ; Using "("
  2187. CALLI R15 @require_match ; Make sure of our required match
  2188. :process_asm_iter
  2189. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2190. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2191. CMPSKIPI.E R0 34 ; IF GLOBAL_TOKEN->S[0] == '"'
  2192. JUMP @process_asm_done ; Otherwise be done
  2193. ;; Add block of assembly
  2194. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2195. ADDUI R0 R0 1 ; GLOBAL_TOKEN->S + 1
  2196. CALLI R15 @emit_out ; emit it
  2197. LOADUI R0 $newline ; Using "\n"
  2198. CALLI R15 @emit_out ; emit it
  2199. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2200. JUMP @process_asm_iter
  2201. :process_asm_done
  2202. LOADUI R0 $process_asm_string1 ; Using our First error message
  2203. LOADUI R1 $close_paren ; Using ")"
  2204. CALLI R15 @require_match ; Make sure of our required match
  2205. LOADUI R0 $process_asm_string2 ; Using our First error message
  2206. LOADUI R1 $semicolon ; Using ";"
  2207. CALLI R15 @require_match ; Make sure of our required match
  2208. POPR R1 R15 ; Restore R1
  2209. POPR R0 R15 ; Restore R0
  2210. RET R15
  2211. :process_asm_string0
  2212. "ERROR in process_asm
  2213. MISSING (
  2214. "
  2215. :process_asm_string1
  2216. "ERROR in process_asm
  2217. MISSING )
  2218. "
  2219. :process_asm_string2
  2220. "ERROR in process_asm
  2221. MISSING ;
  2222. "
  2223. ;; recursive_statement function
  2224. ;; Receives struct token_list* global_token in R13,
  2225. ;; struct token_list* out in R12,
  2226. ;; struct token_list* string_list in R11
  2227. ;; struct token_list* global_list in R10
  2228. ;; and struct token_list* FUNC in R9
  2229. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2230. ;; Returns the token_lists modified
  2231. :recursive_statement
  2232. PUSHR R0 R15 ; Protect R0
  2233. PUSHR R1 R15 ; Protect R1
  2234. PUSHR R2 R15 ; Protect R2
  2235. PUSHR R3 R15 ; Protect R3
  2236. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2237. LOAD32 R3 R9 4 ; FRAME = FUNCTION->LOCALS
  2238. :recursive_statement_iter
  2239. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2240. LOADUI R0 $close_curly_brace ; '}'
  2241. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "}"
  2242. JUMP.NZ R0 @recursive_statement_cleanup
  2243. ;; Lets collect those statements
  2244. CALLI R15 @statement ; Collect next statement
  2245. JUMP @recursive_statement_iter ; Iterate
  2246. :recursive_statement_cleanup
  2247. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2248. LOAD32 R1 R12 8 ; OUT->S
  2249. LOADUI R0 $recursive_statement_string0 ; "RETURN\n"
  2250. CALLI R15 @match ; IF OUT->S == "RETURN\n"
  2251. JUMP.NZ R0 @recursive_statement_done ; Save some work
  2252. ;; Lets pop them all off
  2253. LOAD32 R2 R9 4 ; FUNC->LOCALS
  2254. LOADUI R0 $recursive_statement_string1 ; Our POP string
  2255. :recursive_statement_pop
  2256. CMPJUMPI.E R2 R3 @recursive_statement_done
  2257. CALLI R15 @emit_out ; emit it
  2258. LOAD32 R2 R2 0 ; I = I->NEXT
  2259. JUMP.NZ R2 @recursive_statement_pop ; Keep looping
  2260. :recursive_statement_done
  2261. STORE32 R3 R9 4 ; FUNC->LOCALS = FRAME
  2262. POPR R3 R15 ; Restore R3
  2263. POPR R2 R15 ; Restore R2
  2264. POPR R1 R15 ; Restore R1
  2265. POPR R0 R15 ; Restore R0
  2266. RET R15
  2267. :recursive_statement_string0
  2268. "RETURN
  2269. "
  2270. :recursive_statement_string1
  2271. "POP_ebx # _recursive_statement_locals
  2272. "
  2273. ;; statement function
  2274. ;; Receives struct token_list* global_token in R13,
  2275. ;; struct token_list* out in R12,
  2276. ;; struct token_list* string_list in R11
  2277. ;; struct token_list* global_list in R10
  2278. ;; and struct token_list* FUNC in R9
  2279. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2280. ;; Returns the token_lists modified
  2281. :statement
  2282. PUSHR R0 R15 ; Protect R0
  2283. PUSHR R1 R15 ; Protect R1
  2284. PUSHR R2 R15 ; Protect R2
  2285. LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
  2286. LOADU8 R0 R2 0 ; GLOBAL_TOKEN->S[0]
  2287. CMPSKIPI.E R0 123 ; If GLOBAL_TOKEN->S[0] != '{'
  2288. JUMP @statement_label ; Try next match
  2289. ;; Deal with { statements }
  2290. CALLI R15 @recursive_statement
  2291. JUMP @statement_done ; All done
  2292. :statement_label
  2293. CMPSKIPI.E R0 58 ; If GLOBAL_TOKEN->S[0] != ':'
  2294. JUMP @statement_collect_local ; Try next match
  2295. ;; Deal with :label
  2296. LOAD32 R0 R13 8 ; Using GLOBAL_TOKEN->S
  2297. CALLI R15 @emit_out ; emit it
  2298. LOADUI R0 $statement_string0 ; Using label string
  2299. CALLI R15 @emit_out ; emit it
  2300. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2301. JUMP @statement_done ; Move on to next thing
  2302. :statement_collect_local
  2303. LOADUI R0 $struct ; Using "struct"
  2304. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2305. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "struct"
  2306. JUMP.NZ R0 @statement_collect_local_0
  2307. ;; Otherwise check if it is a primitive
  2308. LOADUI R0 $prim_types ; Using the Primitive types list
  2309. SWAP R0 R1 ; Put in correct order
  2310. CALLI R15 @lookup_type ; Check if a primitive type
  2311. JUMP.Z R0 @statement_process_if ; If not try the next one
  2312. :statement_collect_local_0
  2313. CALLI R15 @collect_local ; Collect the local
  2314. JUMP @statement_done ; And move on
  2315. :statement_process_if
  2316. LOADUI R0 $if_string ; Using "if"
  2317. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2318. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "if"
  2319. JUMP.Z R0 @statement_process_do
  2320. CALLI R15 @process_if ; Collect that if statement
  2321. JUMP @statement_done ; Move on to next thing
  2322. :statement_process_do
  2323. LOADUI R0 $do_string ; Using "do"
  2324. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2325. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "do"
  2326. JUMP.Z R0 @statement_process_while
  2327. CALLI R15 @process_do ; Collect that do statement
  2328. JUMP @statement_done ; Move on to next thing
  2329. :statement_process_while
  2330. LOADUI R0 $while_string ; Using "while"
  2331. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2332. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "while"
  2333. JUMP.Z R0 @statement_process_for
  2334. CALLI R15 @process_while ; Collect that while statement
  2335. JUMP @statement_done ; Move on to next thing
  2336. :statement_process_for
  2337. LOADUI R0 $for_string ; Using "for"
  2338. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2339. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "for"
  2340. JUMP.Z R0 @statement_process_asm
  2341. CALLI R15 @process_for ; Collect that FOR statement
  2342. JUMP @statement_done ; Move on to next thing
  2343. :statement_process_asm
  2344. LOADUI R0 $asm_string ; Using "asm"
  2345. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2346. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "asm"
  2347. JUMP.Z R0 @statement_goto
  2348. CALLI R15 @process_asm ; Collect that ASM statement
  2349. JUMP @statement_done ; Move on to next thing
  2350. :statement_goto
  2351. LOADUI R0 $goto_string ; Using "goto"
  2352. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2353. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "goto"
  2354. JUMP.Z R0 @statement_return_result
  2355. ;; Deal with goto label:
  2356. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2357. LOADUI R0 $statement_string1 ; Using our JUMP string
  2358. CALLI R15 @emit_out ; emit it
  2359. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2360. CALLI R15 @emit_out ; emit it
  2361. LOADUI R0 $newline ; "\n"
  2362. CALLI R15 @emit_out ; emit it
  2363. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2364. LOADUI R0 $statement_string2 ; Using our error message
  2365. LOADUI R1 $semicolon ; Using ";"
  2366. CALLI R15 @require_match ; Make sure of our required match
  2367. JUMP @statement_done ; Move on
  2368. :statement_return_result
  2369. LOADUI R0 $return_string ; Using "return"
  2370. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2371. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "return"
  2372. JUMP.Z R0 @statement_break
  2373. ;; Deal with return statements in functions
  2374. CALLI R15 @return_result ; Do all of the work
  2375. JUMP @statement_done ; Move on to next
  2376. :statement_break
  2377. LOADUI R0 $break_string ; Using "break"
  2378. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2379. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "break"
  2380. JUMP.Z R0 @statement_continue
  2381. ;; Let break function deal with updating out
  2382. CALLI R15 @process_break ; Do all the work
  2383. JUMP @statement_done ; Move on to next
  2384. :statement_continue
  2385. LOADUI R0 $continue_string ; Using "continue"
  2386. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2387. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "continue"
  2388. JUMP.Z R0 @statement_expression
  2389. ;; Simple Continue compatibility
  2390. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2391. LOADUI R0 $statement_string3 ; Using our continue comment string
  2392. CALLI R15 @emit_out ; emit it
  2393. LOADUI R0 $statement_string2 ; Using our error message
  2394. LOADUI R1 $semicolon ; Using ";"
  2395. CALLI R15 @require_match ; Make sure of our required match
  2396. JUMP @statement_done ; Move on
  2397. :statement_expression
  2398. CALLI R15 @expression ; Do expression evaluation
  2399. LOADUI R0 $statement_string2 ; Load our error message
  2400. LOADUI R1 $semicolon ; use ";"
  2401. CALLI R15 @require_match ; Make sure GLOBAL_TOKEN-> == ";"
  2402. :statement_done
  2403. POPR R2 R15 ; Restore R2
  2404. POPR R1 R15 ; Restore R1
  2405. POPR R0 R15 ; Restore R0
  2406. RET R15
  2407. :statement_string0
  2408. " #C goto label
  2409. "
  2410. :statement_string1
  2411. "JUMP %"
  2412. :statement_string2
  2413. "ERROR in statement
  2414. MISSING ;
  2415. "
  2416. :statement_string3
  2417. "
  2418. #continue statement
  2419. "
  2420. ;; collect_local function
  2421. ;; Receives struct token_list* global_token in R13,
  2422. ;; struct token_list* out in R12,
  2423. ;; struct token_list* string_list in R11
  2424. ;; struct token_list* global_list in R10
  2425. ;; and struct token_list* FUNC in R9
  2426. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2427. ;; Returns the token_lists modified
  2428. :collect_local
  2429. PUSHR R0 R15 ; Protect R0
  2430. PUSHR R1 R15 ; Protect R1
  2431. PUSHR R2 R15 ; Protect R2
  2432. CALLI R15 @type_name ; Get it's type
  2433. MOVE R1 R0 ; Prepare for call
  2434. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2435. LOAD32 R2 R9 4 ; FUNC->LOCALS
  2436. CALLI R15 @sym_declare ; SET A
  2437. MOVE R2 R0 ; Protect A
  2438. ;; Figure out depth
  2439. LOADUI R0 $main_string ; Using "main"
  2440. LOAD32 R1 R9 8 ; FUNC->S
  2441. CALLI R15 @match ; IF FUNC->S == "main"
  2442. JUMP.Z R0 @collect_local_0 ; Try next
  2443. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2444. JUMP.NZ R0 @collect_local_0 ; Try next
  2445. LOADI R0 -20 ; The default depth for main
  2446. STORE32 R0 R2 16 ; A->DEPTH = -20
  2447. JUMP @collect_local_output ; Deal with header
  2448. :collect_local_0
  2449. LOAD32 R0 R9 16 ; FUNC->ARGS
  2450. JUMP.NZ R0 @collect_local_1 ; Try Next
  2451. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2452. JUMP.NZ R0 @collect_local_1 ; Try Next
  2453. LOADI R0 -8 ; The default depth for foo()
  2454. STORE32 R0 R2 16 ; A->DEPTH = -8
  2455. JUMP @collect_local_output ; Deal with header
  2456. :collect_local_1
  2457. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2458. JUMP.NZ R0 @collect_local_2 ; Try Next
  2459. LOAD32 R0 R9 16 ; FUNC->ARGS
  2460. LOAD32 R0 R0 16 ; FUNC->ARGS->DEPTH
  2461. SUBI R0 R0 8 ; DEPTH = FUNC->ARGS->DEPTH - 8
  2462. STORE32 R0 R2 16 ; A->DEPTH = DEPTH
  2463. JUMP @collect_local_output ; Deal with header
  2464. :collect_local_2
  2465. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2466. LOAD32 R0 R0 16 ; FUNC->LOCALS->DEPTH
  2467. SUBI R0 R0 4 ; DEPTH = FUNC->LOCALS->DEPTH - 4
  2468. STORE32 R0 R2 16 ; A->DEPTH = DEPTH
  2469. :collect_local_output
  2470. STORE32 R2 R9 4 ; FUNC->LOCALS = A
  2471. ;; Output header
  2472. LOADUI R0 $collect_local_string0 ; Starting with the comment
  2473. CALLI R15 @emit_out ; emit it
  2474. LOAD32 R0 R2 8 ; A->S
  2475. CALLI R15 @emit_out ; emit it
  2476. LOADUI R0 $newline ; Using "\n"
  2477. CALLI R15 @emit_out ; emit it
  2478. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2479. ;; Deal with possible assignment
  2480. LOADUI R0 $equal ; Using "="
  2481. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2482. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  2483. JUMP.Z R0 @collect_local_nonassign
  2484. ;; Deal with assignment of the local
  2485. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2486. CALLI R15 @expression ; Update OUT with the evaluation of the Expression
  2487. :collect_local_nonassign
  2488. LOADUI R0 $collect_local_string1 ; Our error message
  2489. LOADUI R1 $semicolon ; Using ";"
  2490. CALLI R15 @require_match ; Make sure GLOBAL_TOKEN->S == ";"
  2491. ;; Final Footer
  2492. LOADUI R0 $collect_local_string2 ; Add our PUSH statement
  2493. CALLI R15 @emit_out ; emit it
  2494. LOAD32 R0 R2 8 ; A->S
  2495. CALLI R15 @emit_out ; emit it
  2496. LOADUI R0 $newline ; Using "\n"
  2497. CALLI R15 @emit_out ; emit it
  2498. POPR R2 R15 ; Restore R2
  2499. POPR R1 R15 ; Restore R1
  2500. POPR R0 R15 ; Restore R0
  2501. RET R15
  2502. :collect_local_string0
  2503. "# Defining local "
  2504. :collect_local_string1
  2505. "ERROR in collect_local
  2506. Missing ;
  2507. "
  2508. :collect_local_string2
  2509. "PUSH_eax #"
  2510. ;; collect_arguments function
  2511. ;; Receives struct token_list* global_token in R13,
  2512. ;; struct token_list* out in R12,
  2513. ;; struct token_list* string_list in R11
  2514. ;; struct token_list* global_list in R10
  2515. ;; and struct token_list* FUNC in R9
  2516. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2517. ;; Returns the token_lists modified
  2518. :collect_arguments
  2519. PUSHR R0 R15 ; Protect R0
  2520. PUSHR R1 R15 ; Protect R1
  2521. PUSHR R2 R15 ; Protect R2
  2522. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2523. :collect_arguments_iter
  2524. LOADUI R0 $close_paren ; Using ")"
  2525. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2526. CALLI R15 @match ; IF GLOBAL_TOKEN->S == ")"
  2527. JUMP.NZ R0 @collect_arguments_done ; Be done
  2528. ;; Collect the arguments
  2529. CALLI R15 @type_name ; Get what type we are working with
  2530. MOVE R1 R0 ; Put TYPE where it will be used
  2531. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2532. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2533. CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] == ')'
  2534. JUMP @collect_arguments_iter3 ; foo(int,char,void) doesn't need anything done
  2535. ;; Check for foo(int a,...)
  2536. CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] == ','
  2537. JUMP @collect_arguments_iter3 ; Looks like final case
  2538. ;; Deal with foo(int a, ...)
  2539. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2540. LOAD32 R2 R9 16 ; FUNC->ARGUMENTS
  2541. CALLI R15 @sym_declare ; Get A
  2542. MOVE R2 R0 ; Get A out of the way
  2543. :collect_arguments_func
  2544. LOAD32 R0 R9 16 ; FUNC->ARGS
  2545. CMPSKIPI.E R0 0 ; IF NULL == FUNC->ARGS
  2546. LOAD32 R0 R0 16 ; FUNC->ARGS->DEPTH
  2547. SUBI R0 R0 4 ; FUNC->ARGS->DEPTH - 4 or NULL - 4 (-4)
  2548. STORE32 R0 R2 16 ; A->DEPTH = VALUE
  2549. :collect_arguments_iter2
  2550. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2551. STORE32 R2 R9 16 ; FUNC->ARGUMENTS = A
  2552. :collect_arguments_iter3
  2553. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2554. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2555. CMPSKIPI.NE R0 44 ; IF GLOBAL_TOKEN->S[0] == ','
  2556. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2557. JUMP @collect_arguments_iter ; Keep looping
  2558. :collect_arguments_done
  2559. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2560. POPR R2 R15 ; Restore R2
  2561. POPR R1 R15 ; Restore R1
  2562. POPR R0 R15 ; Restore R0
  2563. RET R15
  2564. ;; declare_function function
  2565. ;; Receives struct token_list* global_token in R13,
  2566. ;; struct token_list* out in R12,
  2567. ;; struct token_list* string_list in R11
  2568. ;; and struct token_list* global_list in R10
  2569. ;; SETS R9 to struct token_list* FUNC
  2570. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2571. ;; Returns the token_lists modified
  2572. :declare_function
  2573. PUSHR R0 R15 ; Protect R0
  2574. PUSHR R1 R15 ; Protect R1
  2575. PUSHR R2 R15 ; Protect R2
  2576. FALSE R0 ; Using Zero
  2577. STORER32 R0 @current_count ; CURRENT_COUNT = 0
  2578. LOAD32 R0 R13 4 ; GLOBAL_TOKEN->PREV
  2579. LOAD32 R0 R0 8 ; GLOBAL_TOKEN->PREV->S
  2580. FALSE R1 ; Passing NULL
  2581. LOADR32 R2 @global_function_list ; where the global function list is located
  2582. CALLI R15 @sym_declare ; declare FUNC
  2583. STORER32 R0 @global_function_list ; GLOBAL_FUNCTION_LIST = FUNC
  2584. MOVE R9 R0 ; SETS FUNC
  2585. CALLI R15 @collect_arguments ; Collect function arguments
  2586. LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
  2587. LOADU8 R0 R2 0 ; GLOBAL_TOKEN->S[0]
  2588. CMPSKIPI.NE R0 59 ; IF GLOBAL_TOKEN->S[0] == ';'
  2589. JUMP @declare_function_prototype ; Don't waste time
  2590. ;; Looks like it is an actual function definition
  2591. LOADUI R0 $declare_function_string0 ; Using first string
  2592. CALLI R15 @emit_out ; emit it
  2593. LOAD32 R0 R9 8 ; Using FUNC->S
  2594. CALLI R15 @emit_out ; emit it
  2595. LOADUI R0 $newline ; Using "\n"
  2596. CALLI R15 @emit_out ; emit it
  2597. LOADUI R0 $declare_function_string1 ; Using second string
  2598. CALLI R15 @emit_out ; emit it
  2599. LOAD32 R0 R9 8 ; Using FUNC->S
  2600. CALLI R15 @emit_out ; emit it
  2601. LOADUI R0 $newline ; Using "\n"
  2602. CALLI R15 @emit_out ; emit it
  2603. :declare_function_nonmain
  2604. FALSE R1 ; Cleaning up before call
  2605. CALLI R15 @statement ; Collect the statement
  2606. ;; Prevent Duplicate Returns
  2607. LOAD32 R1 R12 8 ; OUT->S
  2608. LOADUI R0 $declare_function_string2 ; Our final string
  2609. CALLI R15 @match ; Check for Match
  2610. JUMP.NZ R0 @declare_function_done ; Clean up
  2611. ;; Deal with adding the return
  2612. LOADUI R0 $declare_function_string2 ; Our final string
  2613. CALLI R15 @emit_out ; emit it
  2614. :declare_function_done
  2615. POPR R2 R15 ; Restore R2
  2616. POPR R1 R15 ; Restore R1
  2617. POPR R0 R15 ; Restore R0
  2618. RET R15
  2619. :declare_function_prototype
  2620. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2621. JUMP @declare_function_done ; Clean up
  2622. :declare_function_string0
  2623. "# Defining function "
  2624. :declare_function_string1
  2625. ":FUNCTION_"
  2626. :declare_function_string2
  2627. "RETURN
  2628. "
  2629. :current_count
  2630. NOP
  2631. ;; program function
  2632. ;; Receives struct token_list* global_token in R13,
  2633. ;; struct token_list* out in R12,
  2634. ;; struct token_list* string_list in R11
  2635. ;; and struct token_list* global_list in R10
  2636. ;; and struct token_list* FUNC in R9
  2637. ;; and struct token_list* current_target in R8
  2638. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2639. ;; Returns the token_lists modified
  2640. :program
  2641. PUSHR R0 R15 ; Protect R0
  2642. PUSHR R1 R15 ; Protect R1
  2643. PUSHR R2 R15 ; Protect R2
  2644. PUSHR R3 R15 ; Protect R3
  2645. :program_iter
  2646. JUMP.Z R13 @program_done ; Looks like we read all the tokens
  2647. LOADUI R0 $constant ; Using the constant string
  2648. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2649. CALLI R15 @match ; Check if they match
  2650. JUMP.Z R0 @program_type ; Looks like not
  2651. ;; Deal with CONSTANT case
  2652. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2653. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2654. FALSE R1 ; Set NULL
  2655. LOADR32 R2 @global_constant_list ; GLOBAL_CONSTANTS_LIST
  2656. CALLI R15 @sym_declare ; Declare the global constant
  2657. STORER32 R0 @global_constant_list ; Update global constant
  2658. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2659. STORE32 R13 R0 16 ; GLOBAL_CONSTANT_LIST->ARGUMENTS = GLOBAL_TOKEN
  2660. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2661. JUMP @program_iter ; Loop again
  2662. :program_type
  2663. CALLI R15 @type_name ; Get the type
  2664. JUMP.Z R0 @program_iter ; If newly defined type iterate
  2665. ;; Looks like we got a defined type
  2666. MOVE R1 R0 ; Put the type where it can be used
  2667. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2668. LOADUI R3 $global_symbol_list ; Get address of global symbol list
  2669. LOAD32 R2 R3 0 ; GLOBAL_SYMBOLS_LIST
  2670. CALLI R15 @sym_declare ; Declare that global symbol
  2671. STORE32 R0 R3 0 ; Update global symbol list
  2672. LOAD32 R3 R13 8 ; GLOBAL_TOKEN->S
  2673. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2674. LOADUI R0 $semicolon ; Get semicolon string
  2675. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2676. CALLI R15 @match ; Check if they match
  2677. JUMP.Z R0 @program_function ; If not a match
  2678. ;; Deal with case of TYPE NAME;
  2679. COPY R1 R10 ; Using GLOBALS_LIST
  2680. LOADUI R0 $program_string0 ; Using the GLOBAL_ prefix
  2681. CALLI R15 @emit ; emit it
  2682. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2683. MOVE R0 R3 ; Use GLOBAL_TOKEN->PREV->S
  2684. CALLI R15 @emit ; emit it
  2685. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2686. LOADUI R0 $program_string1 ; Using the NOP postfix
  2687. CALLI R15 @emit ; emit it
  2688. MOVE R10 R0 ; Move new GLOBALS_LIST into Place
  2689. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2690. JUMP @program_iter
  2691. :program_function
  2692. LOADUI R0 $open_paren ; Get open paren string
  2693. CALLI R15 @match ; Check if they match
  2694. JUMP.Z R0 @program_assign ; If not a match
  2695. ;; Deal with case of TYPE NAME(...)
  2696. CALLI R15 @declare_function
  2697. JUMP @program_iter
  2698. :program_assign
  2699. LOADUI R0 $equal ; Get equal string
  2700. CALLI R15 @match ; Check if they match
  2701. JUMP.Z R0 @program_error ; If not a match
  2702. COPY R1 R10 ; Using GLOBALS_LIST
  2703. LOADUI R0 $program_string0 ; Using the GLOBAL_ prefix
  2704. CALLI R15 @emit ; emit it
  2705. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2706. MOVE R0 R3 ; Use GLOBAL_TOKEN->PREV->S
  2707. CALLI R15 @emit ; emit it
  2708. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2709. LOADUI R0 $newline ; Using the Newline postfix
  2710. CALLI R15 @emit ; emit it
  2711. MOVE R10 R0 ; Update GLOBALS_LIST
  2712. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2713. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2714. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2715. LOADUI R1 $digit_chars ; 0-9
  2716. CALLI R15 @in_set ; Figure out if in set
  2717. JUMP.Z R0 @program_assign_string ; If not in sets
  2718. ;; Looks like we have an int
  2719. COPY R1 R10 ; Using GLOBALS_LIST
  2720. LOADUI R0 $percent ; Using percent prefix
  2721. CALLI R15 @emit ; emit it
  2722. MOVE R1 R0 ; Put GLOBALS_LIST into Place
  2723. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2724. CALLI R15 @emit ; emit it
  2725. MOVE R1 R0 ; Put GLOBALS_LIST into Place
  2726. LOADUI R0 $newline ; Using newline postfix
  2727. CALLI R15 @emit ; emit it
  2728. MOVE R10 R0 ; Update GLOBALS_LIST
  2729. JUMP @program_assign_done ; Move on
  2730. :program_assign_string
  2731. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2732. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2733. CMPSKIPI.E R0 34 ; If GLOBAL_TOKEN->S[0] == '"'
  2734. JUMP @program_error ; If not we hit an error
  2735. ;; Looks like we have a string
  2736. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2737. CALLI R15 @parse_string ; Parse it into useful form
  2738. COPY R1 R10 ; GLOBALS_LIST
  2739. CALLI R15 @emit ; emit it
  2740. MOVE R10 R0 ; Update GLOBALS_LIST
  2741. :program_assign_done
  2742. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2743. LOADUI R0 $program_string4 ; Potential error message
  2744. LOADUI R1 $semicolon ; Checking for ;
  2745. CALLI R15 @require_match ; Catch those errors
  2746. JUMP @program_iter
  2747. :program_error
  2748. LOADUI R0 $program_string2 ; message part 1
  2749. FALSE R1 ; Show to user
  2750. CALLI R15 @file_print ; write
  2751. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2752. CALLI R15 @file_print ; write
  2753. LOADUI R0 $program_string3 ; message part 2
  2754. CALLI R15 @file_print ; write
  2755. CALLI R15 @line_error ; Provide a meaningful error message
  2756. HALT
  2757. :program_done
  2758. POPR R3 R15 ; Restore R3
  2759. POPR R2 R15 ; Restore R2
  2760. POPR R1 R15 ; Restore R1
  2761. POPR R0 R15 ; Restore R0
  2762. RET R15
  2763. :program_string0
  2764. ":GLOBAL_"
  2765. :program_string1
  2766. "
  2767. NOP
  2768. "
  2769. :program_string2
  2770. "Received "
  2771. :program_string3
  2772. " in program
  2773. "
  2774. :program_string4
  2775. "ERROR in Program
  2776. Missing ;
  2777. "
  2778. ;; sym_declare function
  2779. ;; Receives char* in R0, struct type* in R1, struct token_list* in R2
  2780. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2781. ;; Returns struct token_list* in R0
  2782. :sym_declare
  2783. STORE32 R2 R14 0 ; A->NEXT = LIST
  2784. STORE32 R0 R14 8 ; A->S = S
  2785. STORE32 R1 R14 12 ; A->TYPE = T
  2786. ADDUI R0 R14 20 ; CALLOC struct token_list
  2787. SWAP R0 R14 ; Prepare for Return
  2788. RET R15
  2789. ;; sym_lookup function
  2790. ;; Receives char* in R0 and struct token_list in R1
  2791. ;; Returns struct token_list* or NULL in R0
  2792. :sym_lookup
  2793. PUSHR R2 R15 ; Protect R2
  2794. MOVE R2 R1 ; Protect I
  2795. MOVE R1 R0 ; Put S in proper place
  2796. :sym_lookup_iter
  2797. JUMP.Z R2 @sym_lookup_done ; Stop if NULL
  2798. LOAD32 R0 R2 8 ; I->S
  2799. CALLI R15 @match ; if I->S == S
  2800. JUMP.NZ R0 @sym_lookup_done ; Stop if match
  2801. LOAD32 R2 R2 0 ; I = I->NEXT
  2802. JUMP @sym_lookup_iter ; Keep looping
  2803. :sym_lookup_done
  2804. MOVE R0 R2 ; Using R2 as our result
  2805. POPR R2 R15 ; Restore R2
  2806. RET R15
  2807. ;; function_call function
  2808. ;; Receives CHAR* S in R0 and INT BOOL in R1
  2809. ;; struct token_list* out in R12,
  2810. ;; struct token_list* string_list in R11
  2811. ;; and struct token_list* global_list in R10
  2812. ;; and struct token_list* FUNC in R9
  2813. ;; and struct token_list* current_target in R8
  2814. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2815. ;; Returns the token_lists modified
  2816. :function_call
  2817. PUSHR R0 R15 ; Protect R0
  2818. PUSHR R1 R15 ; Protect R1
  2819. PUSHR R2 R15 ; Protect R2
  2820. PUSHR R3 R15 ; Protect R3
  2821. PUSHR R4 R15 ; Protect R4
  2822. MOVE R2 R0 ; Protect S
  2823. MOVE R3 R1 ; Protect BOOL
  2824. LOADUI R0 $function_call_string0 ; Our first error message
  2825. LOADUI R1 $open_paren ; Using "("
  2826. CALLI R15 @require_match ; Make sure of a match
  2827. FALSE R4 ; PASSED = 0
  2828. LOADUI R0 $function_call_string1 ; Our first header
  2829. CALLI R15 @emit_out ; emit it
  2830. LOADUI R0 $function_call_string2 ; Our second header
  2831. CALLI R15 @emit_out ; emit it
  2832. LOADUI R0 $function_call_string3 ; Our third header
  2833. CALLI R15 @emit_out ; emit it
  2834. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2835. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2836. CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] != ')'
  2837. JUMP @function_call_collect_done ; looks like function()
  2838. ;; Collect arguments
  2839. CALLI R15 @expression ; Deal with first argument
  2840. LOADUI R0 $function_call_string4 ; Push it onto stack
  2841. CALLI R15 @emit_out ; emit it
  2842. ADDUI R4 R4 1 ; PASSED = 1
  2843. :function_call_collect_iter
  2844. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2845. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2846. CMPSKIPI.E R0 44 ; IF GLOBAL_TOKEN->S[0] != ','
  2847. JUMP @function_call_collect_done ; looks like we are done collecting arguments
  2848. ;; Collect another argument
  2849. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2850. CALLI R15 @expression ; Deal with Nth argument
  2851. LOADUI R0 $function_call_string5 ; Push it onto stack
  2852. CALLI R15 @emit_out ; emit it
  2853. ADDUI R4 R4 1 ; PASSED = PASSED + 1
  2854. JUMP @function_call_collect_iter ; Keep looping
  2855. :function_call_collect_done
  2856. LOADUI R0 $function_call_string6 ; Our second error message
  2857. LOADUI R1 $close_paren ; Using ")"
  2858. CALLI R15 @require_match ; Make sure of a match
  2859. JUMP.Z R3 @function_call_call_false ; if BOOL != TRUE
  2860. ;; Deal with TRUE == BOOL
  2861. LOADUI R0 $function_call_string7 ; Our first prefix
  2862. CALLI R15 @emit_out ; emit it
  2863. MOVE R0 R2 ; Using S
  2864. CALLI R15 @emit_out ; emit it
  2865. LOADUI R0 $function_call_string8 ; Our first postfix
  2866. CALLI R15 @emit_out ; emit it
  2867. LOADUI R0 $function_call_string9 ; Our second postfix
  2868. CALLI R15 @emit_out ; emit it
  2869. LOADUI R0 $function_call_string10 ; Our last postfix
  2870. CALLI R15 @emit_out ; emit it
  2871. JUMP @function_call_call_done ; Move on
  2872. :function_call_call_false
  2873. ;; Deal with FALSE == BOOL
  2874. LOADUI R0 $function_call_string11 ; Our first prefix
  2875. CALLI R15 @emit_out ; emit it
  2876. LOADUI R0 $function_call_string12 ; Our last prefix
  2877. CALLI R15 @emit_out ; emit it
  2878. MOVE R0 R2 ; Using S
  2879. CALLI R15 @emit_out ; emit it
  2880. LOADUI R0 $newline ; Using "\n"
  2881. CALLI R15 @emit_out ; emit it
  2882. :function_call_call_done
  2883. LOADUI R0 $function_call_string13 ; Our POP
  2884. :function_call_pop_iter
  2885. JUMP.Z R4 @function_call_pop_done ; Skip POP if out of args on Stack
  2886. CALLI R15 @emit_out ; emit our POP
  2887. SUBI R4 R4 1 ; PASSED = PASSED - 1
  2888. JUMP @function_call_pop_iter ; Loop
  2889. :function_call_pop_done
  2890. LOADUI R0 $function_call_string14 ; Our first postfix
  2891. CALLI R15 @emit_out ; emit it
  2892. LOADUI R0 $function_call_string15 ; Our final postfix
  2893. CALLI R15 @emit_out ; emit it
  2894. POPR R4 R15 ; Restore R4
  2895. POPR R3 R15 ; Restore R3
  2896. POPR R2 R15 ; Restore R2
  2897. POPR R1 R15 ; Restore R1
  2898. POPR R0 R15 ; Restore R0
  2899. RET R15
  2900. :function_call_string0
  2901. "ERROR in process_expression_list
  2902. No ( was found
  2903. "
  2904. :function_call_string1
  2905. "PUSH_edi # Prevent overwriting in recursion
  2906. "
  2907. :function_call_string2
  2908. "PUSH_ebp # Protect the old base pointer
  2909. "
  2910. :function_call_string3
  2911. "COPY_esp_to_edi # Copy new base pointer
  2912. "
  2913. :function_call_string4
  2914. "PUSH_eax #_process_expression1
  2915. "
  2916. :function_call_string5
  2917. "PUSH_eax #_process_expression2
  2918. "
  2919. :function_call_string6
  2920. "ERROR in process_expression_list
  2921. No ) was found
  2922. "
  2923. :function_call_string7
  2924. "LOAD_BASE_ADDRESS_eax %"
  2925. :function_call_string8
  2926. "
  2927. LOAD_INTEGER
  2928. "
  2929. :function_call_string9
  2930. "COPY_edi_to_ebp
  2931. "
  2932. :function_call_string10
  2933. "CALL_eax
  2934. "
  2935. :function_call_string11
  2936. "COPY_edi_to_ebp
  2937. "
  2938. :function_call_string12
  2939. "CALL_IMMEDIATE %FUNCTION_"
  2940. :function_call_string13
  2941. "POP_ebx # _process_expression_locals
  2942. "
  2943. :function_call_string14
  2944. "POP_ebp # Restore old base pointer
  2945. "
  2946. :function_call_string15
  2947. "POP_edi # Prevent overwrite
  2948. "
  2949. ;; emit function
  2950. ;; Receives char* in R0, struct token_list* in R1
  2951. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2952. ;; Returns struct token_list* in R0
  2953. :emit
  2954. PUSHR R2 R15 ; Protect R2
  2955. COPY R2 R14 ; Pointer to T
  2956. ADDUI R14 R14 20 ; CALLOC struct token_list
  2957. STORE32 R1 R2 0 ; T->NEXT = HEAD
  2958. STORE32 R0 R2 8 ; T->S = S
  2959. MOVE R0 R2 ; Put T in proper spot for return
  2960. POPR R2 R15 ; Restore R2
  2961. RET R15
  2962. ;; emit_out function
  2963. ;; Receives char* in R0
  2964. ;; struct token_list* out in R12,
  2965. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2966. ;; Returns struct token_list* in R0
  2967. :emit_out
  2968. STORE32 R12 R14 0 ; T->NEXT = OUT
  2969. ADDUI R12 R14 20 ; Get T
  2970. SWAP R12 R14 ; CALLOC struct token_list
  2971. STORE32 R0 R12 8 ; T->S = S
  2972. RET R15
  2973. ;; uniqueID function
  2974. ;; Receives char* in R0, struct token_list* in R1 and char* in R2
  2975. ;; Calls emit repeatedly
  2976. ;; Returns struct token_list* in R0
  2977. :uniqueID
  2978. CALLI R15 @emit ; emit S
  2979. MOVE R1 R0 ; Put L in the correct place
  2980. LOADUI R0 $underline ; Using "_"
  2981. CALLI R15 @emit ; emit it
  2982. MOVE R1 R0 ; Put L in the correct place
  2983. COPY R0 R2 ; Put NUM in the correct place
  2984. CALLI R15 @emit ; emit NUM
  2985. MOVE R1 R0 ; Put L in the correct place
  2986. LOADUI R0 $newline ; Using "\n"
  2987. CALLI R15 @emit ; emit it
  2988. RET R15
  2989. ;; uniqueID_out function
  2990. ;; Receives char* in R0, char* in R1
  2991. ;; Calls emit_out repeatedly
  2992. ;; Returns nothing
  2993. :uniqueID_out
  2994. CALLI R15 @emit_out ; emit S
  2995. LOADUI R0 $underline ; Using "_"
  2996. CALLI R15 @emit_out ; emit it
  2997. COPY R0 R1 ; Put NUM in the correct place
  2998. CALLI R15 @emit_out ; emit NUM
  2999. LOADUI R0 $newline ; Using "\n"
  3000. CALLI R15 @emit_out ; emit it
  3001. RET R15
  3002. ;; file_print function
  3003. ;; Receives pointer to string in R0 and FILE* in R1
  3004. ;; Returns nothing
  3005. :file_print
  3006. PUSHR R2 R15 ; Protect R2 from Overwrite
  3007. MOVE R2 R0 ; Put string pointer into place
  3008. :file_print_read
  3009. LOAD8 R0 R2 0 ; Get a char
  3010. JUMP.Z R0 @file_print_done ; If NULL be done
  3011. FPUTC ; Write the Char
  3012. ADDUI R2 R2 1 ; Point at next CHAR
  3013. JUMP @file_print_read ; Loop again
  3014. :file_print_done
  3015. POPR R2 R15 ; Restore R2
  3016. RET R15
  3017. ;; recursive_output function
  3018. ;; Receives token_list in R0 and FILE* in R1
  3019. ;; Returns nothing and alters nothing
  3020. :recursive_output
  3021. JUMP.Z R0 @recursive_output_abort ; Abort if NULL
  3022. PUSHR R2 R15 ; Preserve R2 from recursion
  3023. MOVE R2 R0 ; Preserve R0 from recursion
  3024. LOAD32 R0 R2 0 ; Using I->NEXT
  3025. CALLI R15 @recursive_output ; Recurse
  3026. LOAD32 R0 R2 8 ; Using I->S
  3027. CALLI R15 @file_print ; Write the string
  3028. MOVE R0 R2 ; Put R0 back
  3029. POPR R2 R15 ; Restore R0
  3030. :recursive_output_abort
  3031. RET R15
  3032. ;; match function
  3033. ;; Receives a CHAR* in R0, CHAR* in R1
  3034. ;; Returns Bool in R0 indicating if strings match
  3035. :match
  3036. PUSHR R1 R15 ; Protect R1
  3037. PUSHR R2 R15 ; Protect R2
  3038. PUSHR R3 R15 ; Protect R3
  3039. PUSHR R4 R15 ; Protect R4
  3040. MOVE R2 R0 ; Put First string in place
  3041. MOVE R3 R1 ; Put Second string in place
  3042. LOADUI R4 0 ; Set initial index of 0
  3043. :match_cmpbyte
  3044. LOADXU8 R0 R2 R4 ; Get a byte of our first string
  3045. LOADXU8 R1 R3 R4 ; Get a byte of our second string
  3046. ADDUI R4 R4 1 ; Prep for next loop
  3047. CMPSKIP.NE R1 R0 ; Compare the bytes
  3048. JUMP.NZ R1 @match_cmpbyte ; Loop if bytes are equal
  3049. ;; Done
  3050. FALSE R2 ; Default answer
  3051. CMPSKIP.NE R0 R1 ; If ended loop with everything matching
  3052. TRUE R2 ; Set as TRUE
  3053. MOVE R0 R2 ; Prepare for return
  3054. POPR R4 R15 ; Restore R4
  3055. POPR R3 R15 ; Restore R3
  3056. POPR R2 R15 ; Restore R2
  3057. POPR R1 R15 ; Restore R1
  3058. RET R15
  3059. ;; lookup_type function
  3060. ;; Receives a CHAR* in R0 and struct type* in R1
  3061. ;; Returns struct type* in R0 or NULL if no match
  3062. :lookup_type
  3063. PUSHR R1 R15 ; Protect R1
  3064. PUSHR R2 R15 ; Protect R2
  3065. MOVE R2 R1 ; Put START in correct place
  3066. MOVE R1 R0 ; Put S in correct place
  3067. :lookup_type_iter
  3068. LOAD32 R0 R2 24 ; Get I->NAME
  3069. CALLI R15 @match ; Check if I->NAME == S
  3070. JUMP.NZ R0 @lookup_type_done ; If match found be done
  3071. LOAD32 R2 R2 0 ; I = I->NEXT
  3072. JUMP.NZ R2 @lookup_type_iter ; Otherwise iterate until I == NULL
  3073. :lookup_type_done
  3074. MOVE R0 R2 ; Our answer (I or NULL)
  3075. POPR R2 R15 ; Restore R2
  3076. POPR R1 R15 ; Restore R1
  3077. RET R15
  3078. ;; lookup_member function
  3079. ;; Receives struct type* parent in R0 and char* name in R1
  3080. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3081. ;; Returns struct type* of member in R0 or aborts with error
  3082. :lookup_member
  3083. PUSHR R1 R15 ; Protect R1
  3084. PUSHR R2 R15 ; Protect R2
  3085. PUSHR R3 R15 ; Protect R3
  3086. LOAD32 R3 R0 24 ; PARENT->NAME for error
  3087. MOVE R2 R0 ; I = PARENT
  3088. :lookup_member_iter
  3089. LOAD32 R2 R2 16 ; I = I->MEMBERS
  3090. JUMP.Z R2 @lookup_member_error ; We failed hard
  3091. LOAD32 R0 R2 24 ; I->NAME
  3092. CALLI R15 @match ; IF I->NAME == NAME
  3093. JUMP.Z R0 @lookup_member_iter ; Loop again
  3094. :lookup_member_done
  3095. MOVE R0 R2 ; Put I in the correct place
  3096. POPR R3 R15 ; Restore R3
  3097. POPR R2 R15 ; Restore R2
  3098. POPR R1 R15 ; Restore R1
  3099. RET R15
  3100. :lookup_member_error
  3101. FALSE R1 ; Write to TTY
  3102. LOADUI R0 $lookup_member_string0 ; Our header string
  3103. CALLI R15 @file_print ; Print it
  3104. MOVE R0 R3 ; Using PARENT->NAME
  3105. CALLI R15 @file_print ; Print it
  3106. LOADUI R0 $arrow_string ; Using "->"
  3107. CALLI R15 @file_print ; Print it
  3108. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3109. CALLI R15 @file_print ; Print it
  3110. LOADUI R0 $lookup_member_string1 ; Our footer string
  3111. CALLI R15 @file_print ; Print it
  3112. CALLI R15 @line_error ; Give line info
  3113. LOADUI R0 $newline ; Our final addition
  3114. CALLI R15 @file_print ; Print it
  3115. HALT
  3116. :lookup_member_string0
  3117. "ERROR in lookup_member "
  3118. :lookup_member_string1
  3119. " does not exist
  3120. "
  3121. ;; build_member function
  3122. ;; Receives a struct type* in R0, int in R1 and int in R2
  3123. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3124. ;; Modifies R2 to current member_size
  3125. ;; Returns struct type* in R0
  3126. :build_member
  3127. PUSHR R3 R15 ; Protect R3
  3128. PUSHR R4 R15 ; Protect R4
  3129. PUSHR R5 R15 ; Protect R5
  3130. PUSHR R6 R15 ; Protect R6
  3131. MOVE R6 R1 ; Protect OFFSET
  3132. MOVE R4 R0 ; Protect LAST
  3133. CALLI R15 @type_name ; Get MEMBER_TYPE
  3134. MOVE R5 R0 ; Protect MEMBER_TYPE
  3135. ADDUI R3 R14 28 ; CALLOC struct type
  3136. SWAP R3 R14 ; SET I
  3137. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3138. STORE32 R0 R3 24 ; I->NAME = GLOBAL_TOKEN->S
  3139. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3140. STORE32 R4 R3 16 ; I->MEMBERS = LAST
  3141. LOADUI R0 $open_bracket ; Using "["
  3142. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  3143. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "["
  3144. JUMP.Z R0 @build_member_single
  3145. ;; Deal with type name [ number ] ;
  3146. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3147. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3148. CALLI R15 @numerate_string ; Convert string to int NUMBER
  3149. LOAD32 R1 R5 20 ; MEMBER_TYPE->TYPE
  3150. LOAD32 R1 R1 4 ; MEMBER_TYPE->TYPE->SIZE
  3151. MULU R0 R0 R1 ; MEMBER_TYPE->TYPE->SIZE * NUMBER
  3152. STORE32 R0 R3 4 ; I->SIZE = MEMBER_TYPE->TYPE->SIZE * NUMBER
  3153. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3154. LOADUI R0 $build_member_string0 ; Our error message
  3155. LOADUI R1 $close_bracket ; Using "]"
  3156. CALLI R15 @require_match ; Make sure it is right
  3157. JUMP @build_member_done ; Skip over single steps
  3158. :build_member_single
  3159. LOAD32 R0 R5 4 ; MEMBER_TYPE->SIZE
  3160. STORE32 R0 R3 4 ; I->SIZE = MEMBER_TYPE->SIZE
  3161. :build_member_done
  3162. LOAD32 R2 R3 4 ; MEMBER_SIZE = I->SIZE
  3163. STORE32 R5 R3 20 ; I->TYPE = MEMBER_TYPE
  3164. STORE32 R6 R3 8 ; I->OFFSET = OFFSET
  3165. MOVE R1 R6 ; Restore OFFSET
  3166. MOVE R0 R3 ; RETURN I in R0
  3167. POPR R6 R15 ; Restore R6
  3168. POPR R5 R15 ; Restore R5
  3169. POPR R4 R15 ; Restore R4
  3170. POPR R3 R15 ; Restore R3
  3171. RET R15
  3172. :build_member_string0
  3173. "Struct only supports [num] form
  3174. "
  3175. ;; build_union function
  3176. ;; Receives a struct type* in R0, int in R1 and int in R2
  3177. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3178. ;; Modifies R2 to current member_size
  3179. ;; Returns struct type* in R0
  3180. :build_union
  3181. PUSHR R3 R15 ; Protect R3
  3182. PUSHR R4 R15 ; Protect R4
  3183. PUSHR R5 R15 ; Protect R5
  3184. MOVE R4 R0 ; Protect LAST
  3185. MOVE R3 R1 ; Protect OFFSET
  3186. FALSE R5 ; SIZE = 0
  3187. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3188. LOADUI R0 $build_union_string0 ; ERROR MESSAGE
  3189. LOADUI R1 $open_curly_brace ; OPEN CURLY BRACE
  3190. CALLI R15 @require_match ; Ensure we have that curly brace
  3191. :build_union_iter
  3192. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3193. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  3194. LOADUI R1 125 ; numerical value of }
  3195. CMPJUMPI.E R0 R1 @build_union_done ; No more looping required
  3196. MOVE R0 R4 ; We are passing last to be overwritten
  3197. MOVE R1 R3 ; We are also passing OFFSET
  3198. CALLI R15 @build_member ; To build_member to get new LAST and new member_size
  3199. CMPSKIP.LE R2 R5 ; If MEMBER_SIZE > SIZE
  3200. COPY R5 R2 ; SIZE = MEMMER_SIZE
  3201. MOVE R4 R0 ; Protect LAST
  3202. MOVE R3 R1 ; Protect OFFSET
  3203. LOADUI R0 $build_union_string1 ; ERROR MESSAGE
  3204. LOADUI R1 $semicolon ; SEMICOLON
  3205. CALLI R15 @require_match ; Ensure we have that curly brace
  3206. JUMP @build_union_iter ; Loop until we get that closing curly brace
  3207. :build_union_done
  3208. MOVE R2 R5 ; Setting MEMBER_SIZE = SIZE
  3209. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3210. MOVE R1 R3 ; Restore OFFSET
  3211. MOVE R0 R4 ; Restore LAST as we are turning that
  3212. POPR R5 R15 ; Restore R5
  3213. POPR R4 R15 ; Restore R4
  3214. POPR R3 R15 ; Restore R3
  3215. RET R15
  3216. :build_union_string0
  3217. "ERROR in build_union
  3218. Missing {
  3219. "
  3220. :build_union_string1
  3221. "ERROR in build_union
  3222. Missing ;
  3223. "
  3224. ;; create_struct function
  3225. ;; Receives Nothing
  3226. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3227. ;; Returns Nothing
  3228. :create_struct
  3229. PUSHR R0 R15 ; Protect R0
  3230. PUSHR R1 R15 ; Protect R1
  3231. PUSHR R2 R15 ; Protect R2
  3232. PUSHR R3 R15 ; Protect R3
  3233. PUSHR R4 R15 ; Protect R4
  3234. PUSHR R5 R15 ; Protect R5
  3235. PUSHR R6 R15 ; Protect R6
  3236. FALSE R5 ; OFFSET = 0
  3237. FALSE R2 ; MEMBER_SIZE = 0
  3238. COPY R3 R14 ; SET HEAD
  3239. ADDUI R14 R14 28 ; CALLOC struct type
  3240. COPY R4 R14 ; SET I
  3241. ADDUI R14 R14 28 ; CALLOC struct type
  3242. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3243. STORE32 R0 R3 24 ; HEAD->NAME = GLOBAL_TOKEN->S
  3244. STORE32 R0 R4 24 ; I->NAME = GLOBAL_TOKEN->S
  3245. STORE32 R4 R3 12 ; HEAD->INDIRECT = I
  3246. STORE32 R3 R4 12 ; I->INDIRECT - HEAD
  3247. LOADR32 R0 @global_types ; Get Address of GLOBAL_TYPES
  3248. STORE R0 R3 0 ; HEAD->NEXT = GLOBAL_TYPES
  3249. STORER32 R3 @global_types ; GLOBAL_TYPES = HEAD
  3250. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3251. LOADUI R0 4 ; Standard Pointer SIZE
  3252. STORE32 R0 R4 4 ; I->SIZE = 4
  3253. LOADUI R0 $create_struct_string0 ; ERROR MESSAGE
  3254. LOADUI R1 $open_curly_brace ; OPEN CURLY BRACE
  3255. CALLI R15 @require_match ; Ensure we have that curly brace
  3256. FALSE R6 ; LAST = NULL
  3257. :create_struct_iter
  3258. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3259. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  3260. LOADUI R1 125 ; Numerical value of }
  3261. CMPJUMPI.E R0 R1 @create_struct_done ; Stop looping if match
  3262. LOADUI R1 $union ; Pointer to string UNION
  3263. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3264. CALLI R15 @match ; Check if they Match
  3265. SWAP R0 R6 ; Put LAST in place
  3266. MOVE R1 R5 ; Put OFFSET in place
  3267. JUMP.NZ R6 @create_struct_union ; Deal with union case
  3268. ;; Deal with standard member case
  3269. CALLI R15 @build_member ; Sets new LAST and MEMBER_SIZE
  3270. JUMP @create_struct_iter2 ; reset for loop
  3271. :create_struct_union
  3272. CALLI R15 @build_union
  3273. :create_struct_iter2
  3274. ADD R5 R1 R2 ; OFFSET = OFFSET + MEMBER_SIZE
  3275. SWAP R0 R6 ; Put LAST in place
  3276. LOADUI R0 $create_struct_string1 ; ERROR MESSAGE
  3277. LOADUI R1 $semicolon ; SEMICOLON
  3278. CALLI R15 @require_match ; Ensure we have that semicolon
  3279. JUMP @create_struct_iter ; Keep Looping
  3280. :create_struct_done
  3281. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3282. LOADUI R0 $create_struct_string1 ; ERROR MESSAGE
  3283. LOADUI R1 $semicolon ; SEMICOLON
  3284. CALLI R15 @require_match ; Ensure we have that semicolon
  3285. STORE32 R5 R3 4 ; HEAD->SIZE = OFFSET
  3286. STORE32 R6 R3 16 ; HEAD->MEMBERS = LAST
  3287. STORE32 R6 R4 16 ; I->MEMBERS = LAST
  3288. POPR R6 R15 ; Restore R6
  3289. POPR R5 R15 ; Restore R5
  3290. POPR R4 R15 ; Restore R4
  3291. POPR R3 R15 ; Restore R3
  3292. POPR R2 R15 ; Restore R2
  3293. POPR R1 R15 ; Restore R1
  3294. POPR R0 R15 ; Restore R0
  3295. RET R15
  3296. :create_struct_string0
  3297. "ERROR in create_struct
  3298. Missing {
  3299. "
  3300. :create_struct_string1
  3301. "ERROR in create_struct
  3302. Missing ;
  3303. "
  3304. ;; type_name function
  3305. ;; Receives Nothing
  3306. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3307. ;; Returns struct type* in R0
  3308. :type_name
  3309. PUSHR R1 R15 ; Protect R1
  3310. PUSHR R2 R15 ; Protect R2
  3311. LOADUI R0 $struct ; String for struct for comparison
  3312. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  3313. CALLI R15 @match ; Check if they match
  3314. CMPSKIPI.E R0 0 ; If STRUCTURE
  3315. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3316. LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
  3317. LOADR32 R1 @global_types ; Check using the GLOBAL TYPES LIST
  3318. SWAP R0 R2 ; Put GLOBAL_TOKEN->S in the right place
  3319. CALLI R15 @lookup_type ; RET = lookup_type(GLOBAL_TOKEN->S)
  3320. MOVE R1 R2 ; Put STRUCTURE in the right place
  3321. CMPSKIP.E R0 R1 ; If RET == NULL and !STRUCTURE
  3322. JUMP @type_name_struct ; Guess not
  3323. ;; Exit with useful error message
  3324. FALSE R1 ; We will want to be writing the error message for the Human
  3325. LOADUI R0 $type_name_string0 ; The first string
  3326. CALLI R15 @file_print ; Display it
  3327. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3328. CALLI R15 @file_print ; Display it
  3329. LOADUI R0 $newline ; Terminating linefeed
  3330. CALLI R15 @file_print ; Display it
  3331. CALLI R15 @line_error ; Give useful debug info
  3332. HALT ; Just exit
  3333. :type_name_struct
  3334. JUMP.NZ R0 @type_name_iter ; If was found
  3335. CALLI R15 @create_struct ; Otherwise create it
  3336. JUMP @type_name_done ; and be done
  3337. :type_name_iter
  3338. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3339. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  3340. LOADU8 R1 R1 0 ; GLOBAL_TOKEN->S[0]
  3341. CMPSKIPI.E R1 42 ; if GLOBAL_TOKEN->S[0] == '*'
  3342. JUMP @type_name_done ; Looks like Nope
  3343. LOAD32 R0 R0 12 ; RET = RET->INDIRECT
  3344. JUMP @type_name_iter ; Keep looping
  3345. :type_name_done
  3346. POPR R2 R15 ; Restore R2
  3347. POPR R1 R15 ; Restore R1
  3348. RET R15
  3349. :type_name_string0
  3350. "Unknown type "
  3351. ;; line_error function
  3352. ;; Receives Nothing
  3353. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3354. ;; Returns nothing
  3355. :line_error
  3356. PUSHR R0 R15 ; Protect R0
  3357. PUSHR R1 R15 ; Protect R1
  3358. LOADUI R0 $line_error_string0 ; Our leading string
  3359. FALSE R1 ; We want the user to see
  3360. CALLI R15 @file_print ; Print it
  3361. LOAD32 R0 R13 16 ; GLOBAL_TOKEN->LINENUMBER
  3362. CALLI R15 @numerate_number ; Get a string pointer for number
  3363. CALLI R15 @file_print ; And print it
  3364. POPR R1 R15 ; Restore R1
  3365. POPR R0 R15 ; Restore R0
  3366. RET R15
  3367. :line_error_string0
  3368. "In file: TTY1 On line: "
  3369. ;; require_match function
  3370. ;; Receives char* in R0 and char* in R1
  3371. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3372. ;; Returns Nothing
  3373. :require_match
  3374. PUSHR R0 R15 ; Protect R0
  3375. PUSHR R2 R15 ; Protect R2
  3376. MOVE R2 R0 ; Get MESSAGE out of the way
  3377. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3378. CALLI R15 @match ; Check if GLOBAL_TOKEN->S == REQUIRED
  3379. JUMP.NZ R0 @require_match_done ; Looks like it was a match
  3380. ;; Terminate with an error
  3381. MOVE R0 R2 ; Put MESSAGE in required spot
  3382. FALSE R1 ; We want to write for user
  3383. CALLI R15 @file_print ; Write it
  3384. CALLI R15 @line_error ; And provide some debug info
  3385. HALT ; Then Stop immediately
  3386. :require_match_done
  3387. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3388. POPR R2 R15 ; Restore R2
  3389. POPR R0 R15 ; Restore R0
  3390. RET R15
  3391. ;; numerate_number function
  3392. ;; Receives int in R0
  3393. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3394. ;; Returns pointer to string generated
  3395. :numerate_number
  3396. PUSHR R1 R15 ; Preserve R1
  3397. PUSHR R2 R15 ; Preserve R2
  3398. PUSHR R3 R15 ; Preserve R3
  3399. PUSHR R4 R15 ; Preserve R4
  3400. PUSHR R5 R15 ; Preserve R5
  3401. PUSHR R6 R15 ; Preserve R6
  3402. MOVE R3 R0 ; Move Integer out of the way
  3403. COPY R1 R14 ; Get pointer result
  3404. ADDUI R14 R14 16 ; CALLOC the 16 chars of space
  3405. FALSE R6 ; Set index to 0
  3406. JUMP.Z R3 @numerate_number_ZERO ; Deal with Special case of ZERO
  3407. JUMP.P R3 @numerate_number_Positive
  3408. LOADUI R0 45 ; Using -
  3409. STOREX8 R0 R1 R6 ; write leading -
  3410. ADDUI R6 R6 1 ; Increment by 1
  3411. NOT R3 R3 ; Flip into positive
  3412. ADDUI R3 R3 1 ; Adjust twos
  3413. :numerate_number_Positive
  3414. LOADR R2 @Max_Decimal ; Starting from the Top
  3415. LOADUI R5 10 ; We move down by 10
  3416. FALSE R4 ; Flag leading Zeros
  3417. :numerate_number_0
  3418. DIVIDE R0 R3 R3 R2 ; Break off top 10
  3419. CMPSKIPI.E R0 0 ; If Not Zero
  3420. TRUE R4 ; Flip the Flag
  3421. JUMP.Z R4 @numerate_number_1 ; Skip leading Zeros
  3422. ADDUI R0 R0 48 ; Shift into ASCII
  3423. STOREX8 R0 R1 R6 ; write digit
  3424. ADDUI R6 R6 1 ; Increment by 1
  3425. :numerate_number_1
  3426. DIV R2 R2 R5 ; Look at next 10
  3427. CMPSKIPI.E R2 0 ; If we reached the bottom STOP
  3428. JUMP @numerate_number_0 ; Otherwise keep looping
  3429. :numerate_number_done
  3430. FALSE R0 ; NULL Terminate
  3431. STOREX8 R0 R1 R6 ; write
  3432. MOVE R0 R1 ; Return pointer to our string
  3433. ;; Cleanup
  3434. POPR R6 R15 ; Restore R6
  3435. POPR R5 R15 ; Restore R5
  3436. POPR R4 R15 ; Restore R4
  3437. POPR R3 R15 ; Restore R3
  3438. POPR R2 R15 ; Restore R2
  3439. POPR R1 R15 ; Restore R1
  3440. RET R15
  3441. :numerate_number_ZERO
  3442. LOADUI R0 48 ; Using Zero
  3443. STOREX8 R0 R1 R6 ; write
  3444. ADDUI R6 R6 1 ; Increment by 1
  3445. JUMP @numerate_number_done ; Be done
  3446. :Max_Decimal
  3447. '3B9ACA00'
  3448. ;; numerate_string function
  3449. ;; Receives pointer To string in R0
  3450. ;; Returns number in R0 equal to value of string
  3451. ;; Or Zero in the event of invalid string
  3452. :numerate_string
  3453. PUSHR R1 R15 ; Protect R1
  3454. PUSHR R2 R15 ; Protect R2
  3455. PUSHR R3 R15 ; Protect R3
  3456. PUSHR R4 R15 ; Protect R4
  3457. ;; Initialize
  3458. MOVE R1 R0 ; Get Text pointer out of the way
  3459. FALSE R2 ; Set Negative flag to false
  3460. FALSE R3 ; Set current count to Zero
  3461. LOAD8 R0 R1 1 ; Get second byte
  3462. CMPSKIPI.NE R0 120 ; If the second byte is x
  3463. JUMP @numerate_string_hex ; treat string like hex
  3464. ;; Deal with Decimal input
  3465. LOADUI R4 10 ; Multiply by 10
  3466. LOAD8 R0 R1 0 ; Get a byte
  3467. CMPSKIPI.NE R0 45 ; If - toggle flag
  3468. TRUE R2 ; So that we know to negate
  3469. CMPSKIPI.E R2 0 ; If toggled
  3470. ADDUI R1 R1 1 ; Move to next
  3471. :numerate_string_dec
  3472. LOAD8 R0 R1 0 ; Get a byte
  3473. CMPSKIPI.NE R0 0 ; If NULL
  3474. JUMP @numerate_string_done ; Be done
  3475. MUL R3 R3 R4 ; Shift counter by 10
  3476. SUBI R0 R0 48 ; Convert ascii to number
  3477. CMPSKIPI.GE R0 0 ; If less than a number
  3478. JUMP @numerate_string_done ; Terminate NOW
  3479. CMPSKIPI.L R0 10 ; If more than a number
  3480. JUMP @numerate_string_done ; Terminate NOW
  3481. ADDU R3 R3 R0 ; Don't add to the count
  3482. ADDUI R1 R1 1 ; Move onto next byte
  3483. JUMP @numerate_string_dec
  3484. ;; Deal with Hex input
  3485. :numerate_string_hex
  3486. LOAD8 R0 R1 0 ; Get a byte
  3487. CMPSKIPI.E R0 48 ; All hex strings start with 0x
  3488. JUMP @numerate_string_done ; Be done if not a match
  3489. ADDUI R1 R1 2 ; Move to after leading 0x
  3490. :numerate_string_hex_0
  3491. LOAD8 R0 R1 0 ; Get a byte
  3492. CMPSKIPI.NE R0 0 ; If NULL
  3493. JUMP @numerate_string_done ; Be done
  3494. SL0I R3 4 ; Shift counter by 16
  3495. SUBI R0 R0 48 ; Convert ascii number to number
  3496. CMPSKIPI.L R0 10 ; If A-F
  3497. SUBI R0 R0 7 ; Shove into Range
  3498. CMPSKIPI.L R0 16 ; If a-f
  3499. SUBI R0 R0 32 ; Shove into Range
  3500. ADDU R3 R3 R0 ; Add to the count
  3501. ADDUI R1 R1 1 ; Get next Hex
  3502. JUMP @numerate_string_hex_0
  3503. ;; Clean up
  3504. :numerate_string_done
  3505. CMPSKIPI.E R2 0 ; If Negate flag has been set
  3506. NEG R3 R3 ; Make the number negative
  3507. MOVE R0 R3 ; Put number in R0
  3508. POPR R4 R15 ; Restore R4
  3509. POPR R3 R15 ; Restore R3
  3510. POPR R2 R15 ; Restore R2
  3511. POPR R1 R15 ; Restore R1
  3512. RET R15
  3513. ;; Keywords
  3514. :union
  3515. "union"
  3516. :struct
  3517. "struct"
  3518. :constant
  3519. "CONSTANT"
  3520. :main_string
  3521. "main"
  3522. :argc_string
  3523. "argc"
  3524. :argv_string
  3525. "argv"
  3526. :if_string
  3527. "if"
  3528. :else_string
  3529. "else"
  3530. :do_string
  3531. "do"
  3532. :while_string
  3533. "while"
  3534. :for_string
  3535. "for"
  3536. :asm_string
  3537. "asm"
  3538. :goto_string
  3539. "goto"
  3540. :return_string
  3541. "return"
  3542. :break_string
  3543. "break"
  3544. :continue_string
  3545. "continue"
  3546. :sizeof_string
  3547. "sizeof"
  3548. :plus_string
  3549. "+"
  3550. :minus_string
  3551. "-"
  3552. :multiply_string
  3553. "*"
  3554. :divide_string
  3555. "/"
  3556. :modulus_string
  3557. "%"
  3558. :left_shift_string
  3559. "<<"
  3560. :right_shift_string
  3561. ">>"
  3562. :less_than_string
  3563. "<"
  3564. :less_than_equal_string
  3565. "<="
  3566. :greater_than_equal_string
  3567. ">="
  3568. :greater_than_string
  3569. ">"
  3570. :equal_to_string
  3571. "=="
  3572. :not_equal_string
  3573. "!="
  3574. :bitwise_and
  3575. "&"
  3576. :logical_and
  3577. "&&"
  3578. :bitwise_or
  3579. "|"
  3580. :logical_or
  3581. "||"
  3582. :bitwise_xor
  3583. "^"
  3584. :arrow_string
  3585. "->"
  3586. ;; Frequently Used strings
  3587. ;; Generally used by require_match
  3588. :open_curly_brace
  3589. "{"
  3590. :close_curly_brace
  3591. "}"
  3592. :open_paren
  3593. "("
  3594. :close_paren
  3595. ")"
  3596. :open_bracket
  3597. "["
  3598. :close_bracket
  3599. "]"
  3600. :semicolon
  3601. ";"
  3602. :equal
  3603. "="
  3604. :percent
  3605. "%"
  3606. :newline
  3607. "
  3608. "
  3609. :underline
  3610. "_"
  3611. ;; Global types
  3612. ;; NEXT (0), SIZE (4), OFFSET (8), INDIRECT (12), MEMBERS (16), TYPE (20), NAME (24)
  3613. :global_types
  3614. &type_void
  3615. :prim_types
  3616. :type_void
  3617. &type_int ; NEXT
  3618. '00 00 00 04' ; SIZE
  3619. NOP ; OFFSET
  3620. &type_void ; INDIRECT
  3621. NOP ; MEMBERS
  3622. &type_void ; TYPE
  3623. &type_void_name ; NAME
  3624. :type_void_name
  3625. "void"
  3626. :type_int
  3627. &type_char ; NEXT
  3628. '00 00 00 04' ; SIZE
  3629. NOP ; OFFSET
  3630. &type_int ; INDIRECT
  3631. NOP ; MEMBERS
  3632. &type_int ; TYPE
  3633. &type_int_name ; NAME
  3634. :type_int_name
  3635. "int"
  3636. :type_char
  3637. &type_file ; NEXT
  3638. '00 00 00 01' ; SIZE
  3639. NOP ; OFFSET
  3640. &type_char_indirect ; INDIRECT
  3641. NOP ; MEMBERS
  3642. &type_char ; TYPE
  3643. &type_char_name ; NAME
  3644. :type_char_name
  3645. "char"
  3646. :type_char_indirect
  3647. &type_file ; NEXT
  3648. '00 00 00 04' ; SIZE
  3649. NOP ; OFFSET
  3650. &type_char_double_indirect ; INDIRECT
  3651. NOP ; MEMBERS
  3652. &type_char_indirect ; TYPE
  3653. &type_char_indirect_name ; NAME
  3654. :type_char_indirect_name
  3655. "char*"
  3656. :type_char_double_indirect
  3657. &type_file ; NEXT
  3658. '00 00 00 04' ; SIZE
  3659. NOP ; OFFSET
  3660. &type_char_double_indirect ; INDIRECT
  3661. NOP ; MEMBERS
  3662. &type_char_indirect ; TYPE
  3663. &type_char_double_indirect_name ; NAME
  3664. :type_char_double_indirect_name
  3665. "char**"
  3666. :type_file
  3667. &type_function ; NEXT
  3668. '00 00 00 04' ; SIZE
  3669. NOP ; OFFSET
  3670. &type_file ; INDIRECT
  3671. NOP ; MEMBERS
  3672. &type_file ; TYPE
  3673. &type_file_name ; NAME
  3674. :type_file_name
  3675. "FILE"
  3676. :type_function
  3677. &type_unsigned ; NEXT
  3678. '00 00 00 04' ; SIZE
  3679. NOP ; OFFSET
  3680. &type_function ; INDIRECT
  3681. NOP ; MEMBERS
  3682. &type_function ; TYPE
  3683. &type_function_name ; NAME
  3684. :type_function_name
  3685. "FUNCTION"
  3686. :type_unsigned
  3687. NOP ; NEXT (NULL)
  3688. '00 00 00 04' ; SIZE
  3689. NOP ; OFFSET
  3690. &type_unsigned ; INDIRECT
  3691. NOP ; MEMBERS
  3692. &type_unsigned ; TYPE
  3693. &type_unsigned_name ; NAME
  3694. :type_unsigned_name
  3695. "unsigned"
  3696. ;; debug_list function
  3697. ;; Receives struct token_list* in R0
  3698. ;; Prints contents of list and HALTS
  3699. ;; Does not return
  3700. :debug_list
  3701. MOVE R9 R0 ; Protect the list Pointer
  3702. FALSE R1 ; Write to TTY
  3703. :debug_list_iter
  3704. ;; Header
  3705. LOADUI R0 $debug_list_string0 ; Using our first string
  3706. CALLI R15 @file_print ; Print it
  3707. COPY R0 R9 ; Use address of pointer
  3708. CALLI R15 @numerate_number ; Convert it into a string
  3709. CALLI R15 @file_print ; Print it
  3710. ;; NEXT
  3711. LOADUI R0 $debug_list_string1 ; Using our second string
  3712. CALLI R15 @file_print ; Print it
  3713. LOAD32 R0 R9 0 ; Use address of pointer
  3714. CALLI R15 @numerate_number ; Convert it into a string
  3715. CALLI R15 @file_print ; Print it
  3716. ;; PREV
  3717. LOADUI R0 $debug_list_string2 ; Using our third string
  3718. CALLI R15 @file_print ; Print it
  3719. LOAD32 R0 R9 4 ; Use address of pointer
  3720. CALLI R15 @numerate_number ; Convert it into a string
  3721. CALLI R15 @file_print ; Print it
  3722. ;; S
  3723. LOADUI R0 $debug_list_string3 ; Using our fourth string
  3724. CALLI R15 @file_print ; Print it
  3725. LOAD32 R0 R9 8 ; Use address of pointer
  3726. CALLI R15 @numerate_number ; Convert it into a string
  3727. CALLI R15 @file_print ; Print it
  3728. ;; S Contents
  3729. LOADUI R0 $debug_list_string4 ; Using our Prefix string
  3730. CALLI R15 @file_print ; Print it
  3731. LOAD32 R0 R9 8 ; Use address of pointer
  3732. CMPSKIPI.NE R0 0 ; If NULL Pointer
  3733. LOADUI R0 $debug_list_string_null ; Give meaningful message instead
  3734. CALLI R15 @file_print ; Print it
  3735. ;; TYPE
  3736. LOADUI R0 $debug_list_string5 ; Using our fifth string
  3737. CALLI R15 @file_print ; Print it
  3738. LOAD32 R0 R9 12 ; Use address of pointer
  3739. CALLI R15 @numerate_number ; Convert it into a string
  3740. CALLI R15 @file_print ; Print it
  3741. ;; PREV
  3742. LOADUI R0 $debug_list_string6 ; Using our sixth string
  3743. CALLI R15 @file_print ; Print it
  3744. LOAD32 R0 R9 16 ; Use address of pointer
  3745. CALLI R15 @numerate_number ; Convert it into a string
  3746. CALLI R15 @file_print ; Print it
  3747. ;; Add some space
  3748. LOADUI R0 10 ; Using NEWLINE
  3749. FPUTC
  3750. FPUTC
  3751. ;; Iterate if next not NULL
  3752. LOAD32 R9 R9 0 ; TOKEN = TOKEN->NEXT
  3753. JUMP.NZ R9 @debug_list_iter
  3754. ;; Looks lke we are done, wrap it up
  3755. HALT
  3756. :debug_list_string0
  3757. "Token_list node at address: "
  3758. :debug_list_string1
  3759. "
  3760. NEXT address: "
  3761. :debug_list_string2
  3762. "
  3763. PREV address: "
  3764. :debug_list_string3
  3765. "
  3766. S address: "
  3767. :debug_list_string4
  3768. "
  3769. The contents of S are: "
  3770. :debug_list_string5
  3771. "
  3772. TYPE address: "
  3773. :debug_list_string6
  3774. "
  3775. ARGUMENTS address: "
  3776. :debug_list_string_null
  3777. ">::<NULL>::<"
  3778. :STACK