cc_aarch64.s 140 KB

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