Readme voor reggraph:
Dit is een editor die oorspronkelijk alleen was bedoeld voor het maken van register-graphs voor assembler.
Dit moet helpen om registernamen in assembler, waarvan je meteen na het omzetten uit een source meestal meer hebt dan 16, zo te combineren dat je overal slechts maximaal 16 tegelijk in gebruik zijnde registers overhoudt. Dus om de registers maximaal effectief in te zetten om je variabelen in te bergen. Er wordt gebruik gemaakt van het gegeven dat niet alle variabelen steeds actief zijn, of ook wel even opzij gezet kunnen worden.
Dit werkt middels een grafische representatie, met verticale lijnen waarop is aangegeven of een
register bij een bepaalde instructie, live of dead is; toekenningen worden als een rondje aangegeven, uitlezing als een kruisje. Registers kunnen ook in subroutines ongewijzigd blijven of corrupt worden; als een register in een subroutine corrupt raakt, is dat door een driekantje (gevarendriehoek!) aangemerkt; oorspronkelijk had het programma hier een = voor, als teken dat de doorgaande lijn verstoord raakte. Bij ongewijzigd loopt de lijn door als verticaal streepje. Of staat er niks. Afhankelijk van of het register op dat punt gegevens draagt die later nog moeten worden gebruikt. Uitlezen en toekennen allebei, wordt door een gevuld rondje aangegeven. 'Halve' open of halve gevulde rondjes zijn conditioneel.
Gebruik van de register-grapher:
Trek een BASIC file met assembler erin op de !RegGraph applicatie en selecteer het deel assembler wat je ermee wilt bekijken. Liefst met LOCAL declaratie en registernamen-assignments erbij. LOCAL declaraties niet nodig in te sluiten; registerassignments wel - anders verzint het programma zelf de nummers, vanaf 16 en hoger. 
Selecteer de procedure of functie waarvan de assembler moet worden bekeken.
Ga in menu op hoofdwindow naar Selection --> Reggraph. De grapher moet een aantal passes doen, het aantal kan via een submenu op 'mainmenu-->selection-->reggraph' worden veranderd. Bij hogere passes wordt het gedrag van subroutines (BL..) verwerkt in de graph van de aanroepende code. Dit is vaak complex en niet in 1 keer te doen.
Als eerste worden de instructies binnen een selectie geparse'd en worden interne tabellen opgebouwd, eventuele fouten worden onthouden. Twee tabellen zijn vooral belangrijk, een die instructie koppelt aan de daarbij betrokken registers, en een die registreert of registers toegekend of uitgelezen worden. Voor swi's en (sub)routines die buiten de te-graphen code vallen, is er de mogelijkheid het gedrag bij die call-instructie (branchlink of swi) te specificeren. Dit kan op twee manieren:

(1)Meteen na de instructie de tekens \@ en dan voor swi 10 tekens;voor branch/branchwithlink 15 tekens. Deze tekens zijn |(regs. niet beinvloed door deze instructie)) 0(toekenning) X(uitlezing) =(verstoring, bv. swi:'register is corrupted'; * uitlezing en opnieuw toekenning
Voorbeeld:SWI"XOS_SWINumberToString"\@XXO|||||||\ R0,R1 uitgelezen,R2 toegekend,rest onveranderd
          BL subroutine \@*XX0===|||||||||\  R0 uitgelezen & toegekend;R1,R2 uitgelezen;R3 toegekend;R4-R6 corrupted. De rest onveranderd.
     
(2)Meteen na de instructie een \ en dan <registernaam>teken  zovaak als nodig, afgesloten met\
Voorbeeld SWI"XOS_SWINumberToString"\<R0>X<R1>X<R2>0\
          BL subroutine \<R0>*<R1>X<R2>X<R3>O<R4>=<R5>=<R6>=\
    Hier zijn dus geen | tekens nodig; mag wel, Volgorde van de registers maakt niet uit. Je mag ook namen geven aan de registers, als je die overigens ook gebruikt;bv
         BL subroutine\<offset>X<pointer>X<result>O<hulpreg>=\
SWI's kunnen in de database worden ingevoerd, als ze daarin staan hoef je niets meer in te voeren. Deze database staat in de file swidbase, en kan worden bijgewerkt via Iconbarmenu-->SWI/regmap. Van sommige SWI's bestaan meerdere vormen, afhankelijk van de waarde van R0. Het programma kan soms zelf uitvinden wat de R0-waarde is; anders moet je het specificeren met \[R0=..]\ waar je de waarde moet invullen op de plaats van de 2 puntjes. Als het niet lukt via de database te werken met SWI's dan is het gedrag natuurlijk altijd met een \@ X*0=||||||\ string,10 tekens, toe te voegen. Ook PRM boekdeel en pagina zijn hier in te vullen.
(3) Na de instructie een \, en daarna {input_regs,separated by commas},{output_regs,separated by commas},{registers corrupted by the instruction,separated by commas}. Bv. BL routine\{input0,input1,input2},{output0,output2,output3},{hulp0,hulp1,hulp3}. Als bv, input0=output0,input1=output3 komt dit overeen met \<input0>*<input1>*<input2>X<output2>O<hulp0>=<hulp1>=<hulp3}=\

Het is mogelijk dat sommige SWI's in de database als 'OS_User' genoemd worden; de computer kent
ze dan niet; bv. de Printer SWI's van Riscos 3.60, die onder Riscos5 niet worden herkend omdat ze daar niet meer worden gebruikt. Of ADFS swi's met een RaspberryPi. De herkende SWI's zijn uitsluitend die welke op dat moment in RiscOS actief/bekend zijn. Dit moet nog eens worden veranderd met een extra datatabel.
Het aantal te specificeren registers volgens methode 2 is maximaal 32.
Subroutines of branches die ook in de selectie-voor-reggraph staan hoef je niet zo te markeren, dat probeert het programma zelf wel te doen. Wat het programma zelf uitvindt is ondergeschikt aan de door jou aangebrachte aanwijzingen. Alleen als er geen aanwijzingen staan, zoekt het programma het zelf uit.
De afsluitende \ is wel verplicht; dan weet het programma dat er niets meer komt (weet niet zeker of dit nog geldt???)

Het programma heeft af en toe wat hulp nodig. Het is geen emulator; runtime variabelen worden
niet begrepen. Conditionele assemblage ook niet:
IFa% THEN
[OPT pass%
MOV R0,#0:]
ELSE
[OPT pass%
MOV R0,#1:]
ENDIF
dit geeft vele errormeldingen.
Het programma kan ook niet rekenen:bv. MOV reg*2,reg1*4  wordt niet begrepen.
Voor programcounter (PC)-based jumps is ook hulp nodig:
ADD pc,register0,register1 LSL amount_of_shift kan je laten volgen door een aanwijzing:
\offs + ....,jumps ....,incr...\
Op de puntjes moeten achtereenvolgend de offsets vanaf DEZE instructie staan in hex of decimaal, of een labelnaam; het aantal sprongen dat kan worden gedaan (hex/dec), de grootte van de sprongen (hex,decimaal;in bytes). De komma's tussen de 3 zijn verplicht. Vooralsnog de '\' aan het einde ook.
Na offs kan er + of - staan, afhankelijk van hoeveel de offset is en of het een pos.of neg.offs.is
Voorbeeld 
CMP destination,#5:ADDLT pc,pc,destination,LSL#2\offs+8,jumps 5,incr 4\
ADR table,_jumphere:CMP offs,#10:ADDLT pc,table,offs,LSL#3\offs _jumphere,jumps 10,incr 8\

Als offset wordt weggelaten, wordt standaard +8 aangenomen; als incr wordt weggelaten dan standaard 4. Jumps is wel nodig. Dit klopt voor een structuur als:
CMP item,#max_no_of_items%:ADDMI pc,pc,item,LSL #2\jumps 20\:B nothing_to_do
B item0
B item1
B item2
B item3
..
B lastitem
.nothingtodo. 'max_no_of_items' is hier uiteraard te vervangen door '(nothingtodo-item0)DIV4'. 
Er bestaat nog een directive \out , hiermee kan je aangeven welke registers bewaard moeten blijven zodat je niet te enthousiast lijnen gaat opvullen waar eigenlijk nog actieve registers zijn. Hiervoor moet een label staan .exit\out @XXXXXXXXX||||||\  markeert R0-R8 ;hetzelfde is
.label \out <0>X<1>X<2>X<3>X<4>X<5>X<6>X<7>X\ Ipv. 0 mag R0 ook, of een naam bv,'address' als deze eerder was verklaard: address=0 Bijvoorbeeld. Ook is geoorloofd \{result_regs,separated by commas},{input_regs,separated by commas},{regs required at entry and exporting values at exit, separated by commas} te doen. Bijvoorbeel mov 15,14\out{0,1,2,3}{}{}  
Het directive 'from' legt lijnen van labels 'terug' naar een adres waar ze allen vandaan komen:
bijvoorbeeld de routine char_to_offset berekent voor een char,0-255, een offset naar routines waar elk van de 256 chars verwerkt worden. De routines liggen niet op regelmatige afstanden van elkaar:.case LDR offset,[jumptable,char,LSL#2]:ADD pc,pc,offset:.for_char_0\from case\:ADD R1,R2,char:....B endcase:.for_char_1\from case\:MOV R0,#0:MOV R1,#2:MUL R9,R3,R4...B endcase: .for_char_3\from case\: ....etc. Zo'n structuur is bv, te gebruiken om CASE te implementeren. 

Buiten de [ ] assemblerhaken worden alleen variabele-toekenningen,GOTO en LOCAL begrepen, en REM als je geluk hebt. Houd de selectie dus zo krap mogelijk. Het programma weet zelf of het in of buiten assembler begint. Dus je mag best kleine stukjes assembler behandelen; alleen weet het programma dan vaak niet wat de waarden van registers zijn - of de standaardbenamingen (R0-R12,sp,link,lr,pc) moeten al gebruikt zijn.

In de --ongecomprimeerde-- source van deze editor staan veel voorbeelden -  voor 't grootste deel is deze editor gebruikt om zichzelf te schrijven en te controleren. 

In tweede pass worden vanaf de laatste instructie naar de eerste, een soort live-dead analyse gemaakt. Als een register wordt uitgelezen wordt hij 'live' gemaakt, als hij wordt toegekend wordt hij'dead' gemaakt. Conditie van de instructie wordt hierbij in rekening gebracht. Verder worden lijsten gemaakt van waarheen en waarvandaan  instructies springen. Ook wordt een nieuwe tabel gemaakt met tekens die aangeven of een register op dat punt dead is, live maar niet veranderd, uitgelezen,(conditioneel)toegekend ,uitgelezen en toegekend etcetera.
Als laatste worden lijnen aangebracht tussen spronginstructies en labels. Deze lijnen zijn altijd zo kort mogelijk, dus er zitten soms onverwachte knikken in. Over verbetering wordt nagedacht.
Lijnen zijn aan en uit te zetten, via het menu op de grapher zelf. 

Er is een klein venstertje waarin de registernamen zijn te zien, en alternatief de drukte op de registers, zowel per register als bezettingsgraad per instructie: houd voor het laatste het venstertje, in register_frequency mode, rechts naast de registergraph. De status van het venstertje is te veranderen met een menu-entry op het registergraph-window, of door Adjust te klikken op het venstertje.
De lijnen in het registerwindow'tje hebben de vorm: nummer : lijst van namen
Tussen het nummer en de dubbele-punt KAN een sterretje of een plusje staan. Dit is om aan te geven welke variabelen samen in 1 register gecombineerd zouden kunnen worden. Klikken op een registeraanduiding in dit venstertje, plaatst een sterretje, en de variabelen die met dit register gecombineerd zouden kunnen worden krijgen een plusje. Vertrouw niet blindelings op deze truuk; meestal klopt het wel aardig.
Op het menu op het reggraph window is nog een optie om de register-graph als sprite te saven; in inverse colour met 2 kleuren laat zich goed printen op een zwart-wit printer. Ook is er een optie om stalls aan te geven (voor Iyonix Xscale, voorlopig), er komen 1 of 2 nummers bij, het eerste zegt hoelang een instructie er typisch over doet, het tweede hoe veel tikken de xscale stokt.
Ik kan niet instaan voor de exactheid hiervan; het gaat er alleen om, de stalls zo kort mogelijk te houden; dat lukt aardig met deze methode (1 andere instructie tussen toekennen van een register dmv dataop en gebruiken ervan; 2 andere bij toekennen dmv LDR en gebruiken ervan). Het gedrag van processoren met meer dan 1 integer rekenunit per kern, en die zelf intern de de-stalling doen, zoals in ARM8, is niet verwerkt. Bij dit soort processoren is het van belang om de programmaloop zo voorspelbaar mogelijk te maken en vooral om code zoveel mogelijk in de codecache te laten passen. Het is me gebleken dat ARM8 graag 2 andere integer instructies heeft tussen het toekennen van een register middels een data-op,  en uitlezing ervan; en 4 voor het toekennen middels een LDR en uitlezing ervan. In !Reggraph_Runimage zit een crc-bepalings-algoritme dat hiervan gebruik maakt. Voor Pi4 en Pi5 heeft het 9 tot 11 tikken nodig voor de 17 instructies in deze hoofdlus. Gezegd moet worden dat het vaak voorkomt dat je geen andere instructies in de buurt hebt die je tussen toekenning en uitlezing kunt zetten. Bovendien maak je de code nogal onleesbaar en gevoelig voor fouten.
In het algemeen is de volgorde van werken:
- Zet je source om in assembler.
- Selecteer de procedure of functie waarin de assembler voorkomt, inclusief de BASIC met de registertoewijzingen (indien aanwezig) 
- Zet het register-raampje in workload/statistics mode.
- Beweeg het raampje langs de rechterzijde van het reggraph-window. Je ziet nu hoeveel registers er bij elke instructie bezet, dwz. 'live' zijn. Omdat de ARM (26 of 32 bit mode) maar 16 registers beschikbaar heeft mogen/kunnen er niet meer gebruikt worden. Dat betekent, als er teveel zijn moet je er wat aan doen. Vooral als het in een lus is,kan je de registers die tijdens die lus rechtdoor lopen, ie wel in gebruik maar nooit toegegrepen, tijdelijk op de stack zetten. Of je kan soms wat schuiven met registers, al is het mogelijk dat daardoor meer stalls optreden. Meer stalls of meer registers op de stack, is een afweging.
Begin het optimaliseren in elk geval met die subroutines die zelf geen subroutines meer hebben. 
Let er goed op dat je hierin geen registers gebruikt die in de aanroepende routine rechtdoor moeten lopen, of zet ze voor de duur van de subroutine op de stack.
- Inspecteer ook het Branchlijnenbeeld en de Stalls. Als er nog genoeg registers over zijn of het weghalen van stalls geen extra registers vergt, kun je instructies omwisselen zodat er minstens 1 andere instructie staat tussen toekennen van een register en weer uitlezen, of twee instructies als het om een load (LDR/LDRB) gaat. De Branchlijnen zijn belangrijk om te bepalen waar stmfd's en ldmfd's terecht moeten komen als er meer registers nodig zijn (de tijdelijk onveranderlijke kan men dan even opzijzetten). Voor registers die alleen worden uitgelezen kan men in plaats van ldmfd/stmfd overwegen om ze (pas) in te laden (of opnieuw te laden) als ze (weer) nodig zijn.
- als alles er goed uitziet en je, met de statistics instelling, het registerwindow'tje rechts van de graph houdt, alles binnen het maximum aan 15 registers valt (er wordt een verticale lijn zichtbaar als je er meer nodig hebt) dan kun je beginnen met variabelen een registertoekenning te geven, bv.
'array=0:ptr=1:hulp=2' etc. Als je A%..H% gebruikt om de code te CALLen ligt het voor de hand om de met A%..H% corresponderende variabelen de registernummers 0..7 te geven. Meestal geef ik lange doorlopende registerlijnen een laag nummer en de kortere stukjes komen dan in de overblijvende lege ruimtes, soms moet je een variabele hernoemen bv. 'add hulp,array,ptr:ldr word,[hulp,#4]' wordt ingeval er geen ruimte is voor 'hulp', 'add hulp1,array,ptr:ldr word,[hulp1,#4]'. Soms kun je het inladen van een variabele wat later doen zijn of het wegschrijven van een variabele wat eerder. 
Het gedrag van subroutines (BL..) is niet goed genoeg gedaan. Getracht is om registers die op de stack worden gezet en later er weer worden afgehaald, weer te geven alsof er niets mee is gedaan. Helaas worden uitlezingen van het register nadat het op de stack is gezet, en beschrijvingen van de stacklocatie niet gemeld als resp. uitlezing en toekenning. Dit is een tekortkoming.
-------------------------------------------------
Dit programma werd ontwikkeld om te helpen om ARM-assembler te schrijven. ARM heeft een beperkt aantal registers; het is vaak moeilijk om een stukje code in assembler om te zetten en daarvoor dan voldoende registers te hebben. Dit programma laat zien welke registers waar in gebruik zijn; met wat passen en meten en puzzelen kom je dan onder de 16 registers uit. En als dat niet lukt laat het zien welke registers op knelpunten niet of weinig toegegrepen worden, zodat je de inhoud op de stack kan zetten zodat ze vrijkomen. Het is ook nuttig om fouten te vinden. Niet-geinitialiseerde registers verraden zich immers omdat hun lijn doorloopt tot boven hun labelnaam. LOCAL verklaarde registernamen maar vergeten-een-getal-te-geven blijven in de graph een hoog getal (>15) houden; bij assembleren krijgen ze registernummer R0 toegedeeld. LOCAL initialiseert variabelen nu eenmaal op 0. Nooit-uitgelezen registers vertonen een losstaand rondje zonder een 'live' lijn eraan. Een schijnbaar 'losstaand rondje' vlak voor een spronginstructie KAN echter achter die sprong terdege uitgelezen worden!
In het kleine register-window'tje worden de namen voorafgegaan door niets, een * of een +. Klikken op een registernaam brengt de * voor die registernaam en een + voor alle registernamen die met de naam van '*' te combineren zouden zijn. 
Het registernamen-windowtje in Workload toestand, geeft aan hoeveel malen er registers weggeschreven en ingeladen worden. Beide dingen tegelijk, bv, ADD R0,R1,R0 ( .. R0) of STMFD (sp)!,{R0-R4} (.. sp) tellen dubbel. Men moet hier niet teveel op afgaan, want het gebruik van registers in lussen is belangrijker voor de werklast. Als je het registerwindow'tje naast de graph houdt zie je hoeveel registers per lijn in gebruik zijn.

Truken om registers te sparen:
--------------------------------
Als een register naar de basis van een datablok wijst, en er nog meer datablokken voorkomen dan kunnen ze misschien gecombineerd worde; zet 1 register in het midden, lees/schrijf het ene datablok met
MVN pointer,pointer:LDR data0,[base,pointer,LSL#2]:MVN pointer,pointer
- en het andere met: LDR data1,[base,pointer,LSL#2]
Hier wordt het base-register dus 'tweezijdig' gebruikt. 
Of bv. een floatingpoint blok met 8 bits exponent, 32 bits mantisse: DIM flpt% 500:ADR flpt,flpt%+100:MOVN ptr1,ptr:LDRB exp,[flpt,-ptr1]:LDR mantisse,[flpt,ptr,LSL#2]. 
Als de elementen [datablock,#0] gelijk zijn en blijven kan ook
           LDR data0,[datablock,-pointer,LSL#shift]   en LDR data1,[datablock,pointer1,LSL#shift]
    Let op, dat in het tweede geval de data van de 'onderste' tabel (1<<shift) hoger moeten liggen tov. het eerste geval.
Vergelijk-instructies naar voren halen, bevrijdt soms het vergeleken register
Bv. ...code....IFb%<0 d%=a% ---> CMP b,#0: ..code (zonder vergelijk-instructies!)..MOVLT d,a
CMP,CMN,ADDS,ADCS,SUBS,SBCS,RSBS,RSCS beinvloeden alle conditiecodevlaggen (NZVC); TEQ,TST,MOVS,MVNS,ORRS,EORS,BICS,ANDS alleen de N en Z vlaggen maar OOK de C vlag als er een shift <>0 voorkomt. De V vlag (signed overflow) blijft over deze laatste groep instructies bestaan en kun je verderop gebruiken; de C vlag blijft staan als je geen shift erbij gebruikt (=LSL#0). Maar de C vlag kan als input worden gebruikt bij ADC,RSC,SBC,RRX.
Een datablok met 2 pointers (bv. rondlopende buffer) die < 64K is (ie.2^16):hiervan kunnen de 2 pointers gecombineerd worden; zet ze in bits 2--15 en 18--31 respectievelijk; zorg dat de pointer die je nodig hebt in bits 18--31 is geroteerd. Voorbeeld, circulaire buffer.
MOV pointers,pointers,ROR#16
LDRB one_value,[datablock,pointers,LSR#16]
MOV pointers,pointers,ROR#16
LDRB other_value,[datablock,pointers,LSR#16]
-------------------------------------
Kleine informatie, loslopende bits en vlaggen, kun je soms kwijt in de lsb  of msb bits van andere variabelen; logical-rotate die andere variabelen dan tijdens het gebruik zodat de aanhangende troep niet te zien is. 
(Deze truuk wordt bv. in !A310Em gebruikt voor de vertaalslag te-emuleren geheugenadres-->mmupagetabel-->logische adres in emulerende computer ; het betreffende adres zit hier in bits 0--19, andere informatie in bits 20--31. Niet in de mmu zittende pagina's hebben bv. deze bits allen '1' gezet zodat een instructie,MVNS dummy,page,ASR#20:BEQ addressexception volstaat. Inhoud Host adres wordt dan gevonden met LDR data,[logical_archimedes_address,mmupage,LSL#12]. In bits 20-31 zitten 2 accessvlaggen, een videobit en 9 bits voor pagenummer)
\---------------------------------------------------------------------------------
Om de graph utility heen,is een Zap-achtige editor gemaakt om eea wat makkelijker te maken.
Deze editor kan alleen Basic aan; laadt het in 'oude'formaat en 3-byte-per-lijnnummer formaat; of als tekst -- als tekst hoeft het geen lijnnummers hebben maar als ze er wel in staan, moeten deze in volgorde staan. Is niet zo kieskeurig, ook ongetypeerde files met executie-adres &8023 worden ingeladen. Soms is de editor in staat 6502-era BASIC te detecteren, zet dan een vlag en is dan ook in staat deze oude programma's te crunchen.
Zap save't gehele BASIC files als oud-formaat, en selecties als nieuw-formaat; als de selectie niet aan het begin van een lijn begint, dan zonder begin-lijnnummer. !Reggraph probeert dit zo goed mogelijk te begrijpen.
Saven gaat als deze 2 BASIC formaten en als tekst met &D,&A,&DA,&AD als lijnseparator. Te wisselen door met Select te klikken op BASIC-icon in savewindow.
Op een behoorlijk aantal punten verschilt het gedrag van Zap. Zo blijft de file in de editor aanwezig als je het venster sluit. Kleuringsmogelijkheden zijn beperkt, 16 verschillende achtergrondkleuren en alleen lijnnummers, REM, voorgrond, tekst binnen quotes en zoekterm (indien ingesteld). Anders dan Zap, print deze applicatie niet per keyword, uit de BASIC source, maar uit de gedetokenisede tekst. Rem, quotes en lijnnummer vond ik genoeg.
Op het moment is het gedrag dusdanig dat bij program errors van de editor zelf, de applicatie meteen ophoudt te bestaan, zonder bestaande files weg te schrijven. Onder bepaalde omstandigheden kan er in !Boot.!Scrap een kopie gezet zijn, nl. bij sommige bewerkingen die bij mij in het verleden crashes veroorzaakten. Maak voor belangrijke files dus altijd een backup. Dit gedrag kan waarschijnlijk wel veranderd worden maar voor de ontwikkeling is het makkelijker zo. 

Het is eigenlijk wel de bedoeling om nog e.e.a. uit te breiden aan deze software. Maar je weet nooit hoe ver je komt met de to-do-lijst, dus hang me er niet aan op.

Om uit te proberen hoe het werkt of hoe het eruitziet, probeer bv. de assembler in !ChangeFSI, of routines in deze !RunImage. Let wel, er zit in ChangeFSI een functiedeclaratie (DEFFNGET) middenin een andere functie, en kennelijk worden ook precieze variabelenamen gebruikt als input
voor enkele assemblerroutines. Mij is het nog niet gelukt het te crunchen en tegelijkertijd functioneel te houden. Of de assembler van RegGraph zelf; al mijn software is geschreven met deze editor en assembler is ermee geoptimaliseerd.

Zoekfunctie: F7 terwijl mainwindow inputfocus heeft, of menu op hoofdwindow. Er zijn de gebruikelijke opties zoals !Zap die ook heeft; de optie Highlight SourceText zorgt ervoor dat de zoekterm in de zoekkleur in het hoofdwindow te zien is. Als er een selectie bestaat en minder dan 40 karakters, zorgt Ctrl+F ervoor dat de selectie wordt gebruikt als zoekterm.

Totnutoe volledig of gedeeltelijk geimplementeerd:
Character designer. Het kwam zo uit, dat de editor 8*8 char. definities nodig had, dus toe maar. De voltooide definitie komt als een VDU23,.. statement te staan bij de cursor in het hoofd-window.
Xref. Van de Procedure/functie waar de caret op dat moment staat, worden de variabelen geanalyseerd en getoond. Dus als je de juiste xref niet krijgt, even klikken ergens in die routine.
Local xref is te bereiken via menu op hoofdwindow.
Kleuren betekenen:
wit -- kan global zijn, wordt in elk geval niet local-verklaard of als parameter meegegeven
oranje -- local of parameter, wordt ook uitgelezen.
groen -- local of parameter en wordt alleen toegekend. Wanneer de variabele althans niet 'glocal' in een subroutine van deze proc/fn wordt gebruikt zou je hem kunnen weghalen zonder problemen.
Select klikken op de variabele brengt je naar de eerste keer dat deze voorkomt in de onderhavige procedure of functie. Adjust klikken, geeft een lijst van functies+ procedures waar deze variabele wordt gebruikt, met gegevens als: locaal,als parameter, toegekend? uitgelezen?
De eerste lijn van een local-xref window is wel interessant: Het eerste woord is de functie-of procedurenaam waarin de local xref wordt toegepast. Adjust erop klikken, geeft een lijst waar deze functie/procedure voorkomt, identiek dus aan het gedrag bij klikken op een variabele verderop in de lijst. Select klikken: geeft een window met de onderlinge samenhang van functie of procedure met zijn soubroutines. Select klikken op beginlijnnummer brengt je naar deze lijn; evenzo Select op laatste lijnnummer brengt naar laatste lijn; Adjust klikken op deze lijnnummers selecteert de functie of procedure. De windows afgaande van local xref hebben een laatste lijn die je terugbrengt naar de local xref.
Selecteren van een functie of procedure is ook te bereiken door in de utilities, menuoptie DEFFN/PROC te kiezen, vandaaruit een pijl naar links volgen brengt je weer in een menu.
Onder Xref staat een submenu waar je kunt switchen naar Global xref. Daaronder zit weer een submenu om ook de nooit geschreven of uitgelezen variabelen te kunnen uitzeven, of variabelen die minder dan een in te stellen aantal malen voorkomen. Voor foutzoeken kan dit van nut zijn. Het menu op de window met xref-resultaten geeft de mogelijkheid types te kiezen en ze per type of gezamenlijk weg te saven.
Als Menu wordt gekozen op hoofdwindow en muispointer toevallig boven een SYS statement of swi staat, komt er een extra menu-optie die alvast PRM pagina aangeeft, pijl volgen opent window met
hex aanduiding van deze SWI, of met SWI string, alnaargelang wat er onder de muispointer stond.De PRM pagina's zijn van de papieren versie,PRM 1-- 4 December92,Issue1; 5a Augustus95,Issue1. 

Lijst van Functies/procedures. Wit- gedeclareerd en gebruikt
Groen -- alleen gedeclareerd. Via het submenu kan je deze in hun geheel verwijderen.
rood -- wel gebruikt maar niet gedeclareerd.
matgroen - dubbel gedefinieerd. BASIC gebruikt de definitie die het meest bovenaan staat (laagste lijnnummer).
Deze kleuren zijn in te stellen voorzover ik me kan herinneren; rood, wit en groen zijn de kleuren in de standaard instelling.

Lijst van Assembler labels: Wit is intern binnen de assembler gebruikt; oranje is buiten de assembler gebruikt; groen zijn labels die alleen als label voorkomen maar nooit worden gebruikt. Donkergroen de labels die dubbel voorkomen. Wat natuurlijk ongezond kan zijn!
Als je Adjust klikt op de menu-optie dan worden de extern gebruikte labels als een file 'ExtLabels' weggeschreven in de !Reggraph directory (ik weet het, dit kan netter). Dit is te gebruiken als je de assemblersource uit je distributieversie wilt houden, en de assembler als een blok wilt inladen en dus de extern aangeroepen labels nodig hebt. Scheelt tijd met opstarten, verkort het programma, maakt onderhoud zo goed als onmogelijk.

Program check: Is nogal beperkt; controleert balans van aanhalingstekens, haakjes () en blokhaken [], en aantal parameters van subroutines. Verder de balans van CASE-ENDCASE en IF..THEN..ENDIF. Tussen een IF en een ELSE kunnen geen CASE zonder ENDCASE, en tussen 2 WHEN's (of WHEN/ENDCASE of WHEN/OTHERWISE) kunnen geen IF..THEN (laatste op de lijn) zonder afsluitende ENDIF staan. 
 FOR..NEXT,While en Endwhile heeft, wat BASIC betreft, natuurlijk veel meer vrijheid; dit wordt dan ook niet gecontroleerd. Want in feite worden hiermee alleen sprongadressen gezet -- die je niet hoeft te gebruiken: FOR zonder NEXT mag; WHILE zonder ENDWHILE (zolang de eerste vergelijking, na WHILE, maar TRUE is; prog springt bij FALSE naar achter ENDWHILE en moet deze dan wel kunnen vinden); REPEAT zonder UNTIL. 

Crunch: comprimeert het aanwezige programma; afhankelijk van de aangevinkte items. Ook oude BBC-programma's en 6502-assembler. Het voordeel van crunchen is, minder geheugenbeslag (typisch de helft), en sneller (tot 2X) Het is wel heel verstandig om het programma te controleren alvorens te crunchen. Als er GOTO's/GOSUBS zijn die springen naar adressen buiten functies of procedures, gebruik dan de 'Remove between FN/Procs" optie niet. Oude BASIC varianten (8-bit) begrijpen in assembler niet = ipv. EQUS, en & ipv. EQUD. Deze opties niet aanzetten voor oude progs, dus. 
Er kan een Excludefile worden gebruikt, dwz. een tekstfile met comma-separated de variabelen die je zo wilt laten. Dit kan heel nuttig zijn voor bepaalde assemblerprogamma's die als parameters niet A%--H% gebruiken maar zelf variabelen analyseren door via de gegevens op de stack, de locaties zelf op te zoeken. Daarvoor moeten de variabelenamen wel intact blijven. Zie de CALL descriptie in BASIC manuals. De door assembler gebruikte variabelen dan niet meecrunchen. In constructies met EVAL() of VAL() geldt ook dat men moet kijken of wat hierna volgt, wellicht geen variabele-namen zijn die wel evalueerbaar moeten blijven, dwz. deze selectief niet crunchen. a%=EVAL("FNaaa"+STR$char%+"(param1%,param2%)) is een voorbeeld; alle FNaaa0,FNaaa1,FNaaa2 etc, en variabelen param1% en param2% mogen hier niet worden gecruncht.
Na crunchen is een tekstfile met de oude en de nieuwe namen uit te saven.

Loaden & Saven van programma's kan ook als tekst; in het Save window met Adjust klikken op het
draggable Basic-icon verandert dit icon. Line-separators zijn in te stellen door te klikken op de desbetreffende icon. In-te-laden files kunnen Basic en Tekst zijn, wel moeten ze opvolgende lijnnummers hebben. Bij Save van gehele bestand, is er een menu-button die een crunched-program-window opent; dit zet het programma om een een lzw12- gecomprimeerd Absolute bestand. Optioneel kan de decoder en het lzw-bestand nog verder worden verhaspeld. Als de environment string moet worden meegegeven, moet 'Copy environment string in MakeApp$CLI worden aangevinkt. In je programma mot de environment string dan uit MakeApp$CLI worden gehaald.
De Save en de Search-Replace windows zijn door draggen van de window-icon rechtsonder, te vergroten zodat extra functies zichtbaar worden.
De types waarin er gesaved kan worden zijn: 
(1) 'originele BASIC file dwz. elke lijn bestaat uit: char 13 (&D), lijnnummer MSB, lijnnummer LSB, lengte (max. 255 voor Archimedes en later, 239 voor BBC-era), de eigenlijke lijn, afgesloten door &D van de volgende lijn. Het geheel afgesloten met &D,&FF.
(2) Zap-style BASIC file dwz er is geen lengtebyte maar de 3 eerste (na de &D) bytes zijn net zo gecodeerd als lijnnummers bij GOTO, GOSUB, RESTORE etc. Maar dan zonder de voorafgaande &8D.
(3) Textfile, 8 characters gereserveerd voor het lijnnummer en de lijn-scheidingstekens zijn zelf te kiezen. &A.&D.&AD.&DA.
(4) Lijnnummerloos, verder als textvile. Alleen de lijnnummers zijn geheel weggelaten. Uiteraard kan dit alleen als er geen lijnnummerverwijzingen in het programma staan, zoals na GOTO, GOSUB, RESTORE, RENUMBER, DELETE, AUTO en nog enkele. Mochten deze keywords met lijnnummers er wel in staan dan wordt automatisch overgegaan op saven als text MET lijnnummers.

SWI/regmap window: Database voor 'gedrag' van SWI's. PRM's 1-5a reeds ingevoerd. Na invoeren is een SWI-descriptie meteen te gebruiken, de database-file wordt bij quitten van de editor bijgewerkt - of meteen wanneer de Add to database button met Adjust wordt aangeklikt. Vna sommige SWI's MOET de waarde van R0 worden gespecificeerd. Vertrouw niet teveel op de juistheid van de reeds ingevoerde waarden. Ook het PRM is knap wazig over hoe bepaalde SWI's zich gedragen.Deze SWI registergedragingen zijn nodig voor de register-grapher. SWI/regmap is te bereiken via iconbarmenu.
 
abcANDfix: Indien Aangevinkt worden spaties in het programma gezet op plaatsen waar (real) variabelen en BASIC-functies te dicht bijeen staan, in het algemeen waar ze-vlakbij-elkaar-zetten kan resulteren in incorrecte re-tokenisatie. Voorbeeld: Een prog. kan de reele variabele 'abc' laten volgen door een getokenised keyword AND, bv. 'z=abcAND1'. Omdat van de laatste de code >=127 is begrijpt BASIC dat nog. Als een editor de lijn detokenise't, zoals !Edit altijd doet, en dan weer tokenise't, krijg je de variabele abcAND. Dit ongewenste gedrag voorkom je door alvast bij het inladen extra spaties te zetten in pijnpunten. Idem bv. IFa=bc=dELSEc=e. Of: IFa%=&190ELSEa%=0. Let wel, iets als bv. IFa=bPRINT"zz" gaat goed omdat de P geen onderdeel van een hexadecimaal nummer is.

Als de cursor in de tekst boven een SWI of SYS staat en men Menu indrukt op Mainwindow, dan krijg je als laatste menu-entry informatie over een SWI. SWI naam wordt vertaald in SWI nummer vice versa; en men krijgt PRM deel en bladzij (papieren versie). Als de SWI bekend is, tenminste. Als de SWI +nummer geselecteerd zijn, en je staat met muispointer op SWI naam/nummer dialoogwindow en klikt daarop dan wordt in de tekst de naam veranderd in een nummer, of andersom.

Als onder muispointer een VDU23,.. character reprogram string staat, dan opent met Menu (als het goed gaat) het character design window. Constructies met ; (ie. halfwords) en | (ie. string van 8 nul-bytes) zijn nog niet geimplementeerd.

Simple calculator in Utilities menu: is wat de naam zegt, simpel. Er zijn 3 modi: gewone berekeningen, vinden van priemgetallen en vinden van crc-getallen. Voor gewone berekeningen en voor priemgetallen is dit mogelijk t/m 128 bits, voor crc-getallen 32 bits. Voor het vinden van 1 crc-getal met n bits moet er (2^n-1) gecycled worden alvorens vaststaat dat een getal een crc-getal is. Elk bit meer verdubbelt de benodigde tijd ongeveer. Het kan sneller: de daarvoor benodigde methode (met opzoeken van voorbrekende waarden) doet weliswaar meerdere bits in 1 keer (compromis tussen snelheid en geheugenbehoefte is 12-13 bits tegelijk) maar waar bij een een-voor-een-methode vele kandidaten al snel sneuvelen en snel met de volgende kan worden doorgegaan, worden bij een snelle methode deze sneuvelpunten meestal gemist en kan pas na 2^n -1 stappen worden geconcludeerd dat het geen crc-getal is (want niet teruggekeerd naar begingetal). Daarbij loop je het risico dat de reekslengte deelbaar is door (2^n-1) en zo vind je 'crc'getallen die afgewezen hadden moeten worden. Bijvoorbeeld voor n=32, getallen met een reekslengte van &33333333. Het alternatief, hier gebruikt, is om wel een opzoekmethode te gebruiken maar de uitkomst bij elke stap te vergelijken met alle waarden die vooraf zouden zijn gegaan aan de uitgangssituatie. Dit kost meer tijd, maar de benodigde instructies kunnen op moderne ARM processors per twee tegelijk worden uitgevoerd en ze wegen ruimschoots op tegen de tijd die zonder opzoekmethode nodig was geweest. Het scheelt een factor 3. Voor crc-getallen die men wil gebruiken om randomreeksen of ruis te maken, is het verstandig ongeveer evenveel '0' en als '1'-en in het getal te hebben en goed verspreid over het getal. Neem ook voldoende iteraties tussen de opvolgende samples en vergelijk het eindresultaat met een fft. Deze getallen te vinden was de aanleiding een soort rekenmachine in te sluiten.
De priemgetallenvinder gebruikt de kleine methode van Fermat, maar met alle priemgetallen tot 256 (of produkten daarvan) als basis. Dit elimineert pseudoprimes als ze coprime zijn met deze basis-priemgetallen maar voorkomt andere pseudopriemgetallen niet volledig. In elk geval is het beter dan PGP wat maar 3 primes gebruikt. Voor het vinden van meer waterdichte priemgetallen neme men !Primes, elders op deze website. (dit berekent priemgetallen met de zeef van Eratosthenes, maar boven zegmaar 2^80 wordt het erg traag). De inhoud van de bovenste en de onderste writable-icons in het Simple Calc window kan men verslepen, naar het editor hoofdwindow zelf, naar een andere van de 3 invoericons of naar buiten.
Crc getallen verwijzen naar een polynoom; in dit polynoom zijn bit 0 en bit n '1' (met n=aantal bits voor het crcgetal) En nog 1,3,5.. meer bits ook '1'. Het getal laat het bit n weg. CRC- getallen die een sequentie van 2^n-1 veroorzaken blijken 3 eigenschappen te hebben: bit 0 altijd '1' ('oneven'); de 0- en 1 bits zijn te spiegelen wat betreft hun positie in het polynoom, dwz. als voorbeeld, als voor n=29, 5 een crc-getal is, dan is &8000001 dat ook: (polynomen x^29+x^2+2^0 resp. x^29+x^27+2^0), en alle geschikte polynomen hebben een oneven aantal termen dus de getallen (waarin je de msb term, x^n, weglaat) hebben een even aantal 1-en. Alles samen versnelt het vinden van crc-getallen achtmaal. Het vinden van geschikte crc-getallen voor bv. random-numbers voor ruis, is trial-and-error. Opvolgende ruisamplitudes zoals gevonden met een crc-routine* moeten zo min mogelijk aan elkaar gerelateerd zijn (dus meermalen vermenigvuldigen met het crc-getal voor 1 ruiswaarde) en het aantal 0-en en 1- en van het crc-getal moeten elkaar ongeveer in evenwicht houden. En dan nog is het verstandig om te controleren met een fast-fourier-transform of het frequentiespectrum acceptabel vlak is. Dit gaat het best met een fft met zoveel mogelijk bits, liefst voldoende om de hele ruiswave in 1 keer te bevatten. Want anders mis je laagfrequente fluctuaties.
Om langere random-sequenties te vinden zou men meerdere CRC's, maar wel van verschillende bitlengte, kunnen combineren. Een 32- en een 31-bit crc samen, leidt in principe tot een herhalingslengte van &FFFFFFFF * &7FFFFFFF = bijna 2^63. Start bijvoorbeeld beide sequenties met '1', voor elke nieuwe sample doe zowel de 32bit als de 31bit routine en combineer de 2 tussenwaardes, bv. de bits ervan om en om. Pas na 9.223.337.030.412.324.865 stappen komt de '1' weer terug. Dat kan natuurlijk ook met nog meer sequenties, bv. 32,31,30,29 etc. Er zijn situaties waarin enorm grote sequenties van belang zijn, bij sudoku's bijvoorbeeld minstens evenveel als er sudoku's van een bepaald type bestaan. Want anders blijft een groot deel van de mogelijke sudoku's nooit-ontdekt. 
*routine, VINDEN van een crc-getal -- n:=0; found=FALSE; seed=2^aantal_bits-1;mask:=seed;nmin1:=n-1; repeat v:=seed%>>>nmin1;seed:=seed<<1;seed:=seed and mask; ifv<>0 seed:=seed eor crc;n+=1;until n==mask or seed==mask;  if seed==mask and n==mask found=TRUE. De polynoomvinder is redelijk snel, op een RPI5 zijn er per 9 stappen, maar 6 kloktikken nodig zodat om de 4G stappen te checken voor een 32-bit crc-polynoom, even meer dan 1 seconde nodig is (bij 2.4 GHz). 

Het gedrag van de editor bij crunchen van zeer grote programma's met meer variabelen dan wat in 256K past, is onbekend. De variabele die de grootte aangeeft van de desbetreffende geheugenruimte, heet 'swimenusize' (deze ruimte wordt dubbel gebruikt, ook voor de swi menu's). Je kunt dit zelf aanpassen in het bestand !Runimage, en deze dan eventueel crunchen tot !Runimage' (of de naam veranderen in !Run van het bestand dat gedraaid moet worden). Evt. ook Wimpslot groter maken in de !Run file. Als de editor bij zulke grote hoeveelheden variabelen crash't vergroot dan de waarde van deze variabele in de source !Runimage. Tot zeker 1600 variabelen, en programmagrootte 1257K, lukte totnutoe met de nu gebruikte instellingen. Zoals bekend is voordeel van crunchen de grotere snelheid (circa 2X voor zuiver BASIC met 'normaal betekenisvolle' variabele-namen en 'normale' hoeveelheid comments in de code. De cruncher zou hier en daar nog wat effectiever kunnen, maar voor de programmasnelheid maakt het weinig meer uit en geheugen heb je tegenwoordig toch meer dan genoeg.
Ovrigens om de !Runimage van !reggraph te crunchen met de editor zelf, kun je alle vinkjes aanzetten alleen 'in DATA lines, too' niet. In de Save dialoogbox (volg het menu-icon) kun je ervoor kiezen om het programma dat in het geheugen zit, te saven als een 12-bit gecrunchte LZW file met uitpakcode voorop. De uitpakker kan daarbij ook nog worden geklutst en een populaire methode om het programma te stoppen zodra hij probeert aan de slag te gaan, kan worden uitgezet. 'Beschermen' heette dit vroeger, maar dit soort methoden leiden ertoe dat programma's niet te bekijken zijn en aan te passen aan nieuwe omgevingen. Ik zou voorstellen, verspreid de ongecrunchte !Runimage en daarnaast de gecrunchte versie voor snelheid, en zorg ervoor dat de lijnnummers daarin te herleiden zijn tot het origineel. Om de gecrunchte versie verder te obfusceren kan naast Save een menu-button worden gevonden waar het bestand, al dan niet gecruncht, als een executable kan worden gesaved. De 'Unset Alias$Basic' optie voorkomt dat de methode van Poole kan worden gebruikt. Met !Zap is de code echter alsnog te bekijken (Iconbarmenu van Zap-->Create-->Read memory), je zou in je programma na de initialisatie alle lijnen die initialistiecode bevatten (dus maar 1X worden uitgevoerd) kunnen overschrijven met onzi, met behoud van lijnnummers en lijnlengtes uiteraard. Dat maakt het veel lastiger om met Zap het programma te reconstrueren omdat essentiele informatie weg is. 

Printen.
Reggraph kan listings printen, 1-5 kolommen naast elkaar en charactersizes (scaled) van 5 tot 32,
Menu op hoofwindow, kies Print to jpegs. In het geopende dialoogwindow kies de parameters en doe Open previewwindow. 
Daar is keuze Save als sprite of save als jpeg te maken. Sleep eerste sprite/jpeg ergens naar toe en als de filenaam is zoals 'verwacht', dwz. met een volgnummer van maximaal 3 characters en een extensie van hetzij ,ff9 or /jpg dan zijn de volgende sprites/jpegs achtereenvolgens zonder slepen te saven.
Deze sprites/jpegs kunnen ook naar een applicatie worden gesleept maar dan is het niet mogelijk om automatisch de volgende te verslepen.
Voor jpegs moet  de JComp Module aanwezig zijn.
Waarschijnlijk omdat VFP niet aanwezig is in Risc_Os_Linux_Bimary ???? werkt jpeg save hier niet. Voor printn naar jpegs is gekozen omdat je dan vanuit Linux vrij gemakkelijk alles kunt printen, ook op een RaspberryPi naar een met Wifi verbonden printer.
Jan de Boer