> MOS/S v1.02 > ARM CoPro base MOS to add SWI vectors and module support : (Q 25-Jul-2008 JGH: SWI handler manages SPSR/CPSR and return from claimed SWIs 2: swiV in main RAM, code now ROM-able <9 26-Jul-2008 JGH: Split source into seperate modules F9 27-Jul-2008 JGH: *Command search and dispatch works P+ 29-Jul-2008 JGH: Works in real ROM!!! ZE 30-Jul-2008 JGH: X_SWIs returned correctly, SWIs 0-127 vectored d+ Added OS_PrettyPrint nE 22-Aug-2008 JGH: *Help and OS_CLI goes through modules forwards xe OS_Module moved to ModuleHandler module, added stubs for core ARMTube commands : list%=-  : " @ ";: : fname$="MOS" 'swiVsys=&EC : System SWI vector %vecbase=&2000 : Base of vectors (R12base=&2200 : Base of R12 values *swiV=&2404 : Secondary SWI vector 'modtable=&2400 : Module table base :  mcode% &1000 P=0 1 P%=0:O%=mcode% [OPT P*(2-list%)+4 \ ================== "\ *** MOS ULE *** ,\ ================== 6 .MOS_Base @B MOS_Start JEQUD MOS_Init TEQUD 0 :\ MOS_Final ^EQUD MOS_Service hEQUD MOS_Title rEQUD MOS_Help |EQUD MOS_Commands EQUD 0 :\ MOS_SWIBase EQUD 0 :\ MOS_SWIHandler EQUD 0 :\ MOS_SWITable EQUD 0 :\ MOS_SWICode : .MOS_Title EQUS "MOS":EQUB 0:ALIGN  .MOS_Help ] ":EQUB 0:ALIGN : .cmdGOS_Help FEQUS "*GOS enters the supervisor. Use *Quit to exit.":EQUB 0:ALIGN : .cmdGO_Help jEQUS "*GO enters code at the specified address, default &8000. Text after ';' is environment.":EQUB 13 ?EQUS "Syntax: *GO [
] [; environment]":EQUB 0:ALIGN : .cmdHelp_Help WEQUS "*Help attempts to give useful information on the selected topics."  EQUB 0:ALIGN :  .cmdInitS_Help *vEQUS "*InitStore fills user memory with the specified data, or the value &E6000010 if no parameter given.":EQUB 13 48EQUS "Syntax: *InitStore [|reg>]":EQUB 0:ALIGN >: H.cmdMemory_Help RJEQUS "*Memory displays the values in the memory in ARM words.":EQUB 13 \]EQUS "Syntax: *Memory [B] [+|-] [+ ]]":EQUB 0:ALIGN f: p.cmdQuit_Help z8EQUS "*Quit leaves the current application.":EQUB 13 %EQUS "Syntax: *Quit":EQUB 0:ALIGN : .cmdShowR_Help ?EQUS "*ShowRegs displays the stored ARM registers.":EQUB 13 )EQUS "Syntax: *ShowRegs":EQUB 0:ALIGN :  .cmdDummy ALDR R0,SWI_CLIpasson :\ Magic word to pass on unclaimed (MOV PC,R14 :\ Return : L\EQUD 0:\EQUD 0:EQUD 0:EQUD 0:EQUD 0 :\ Padding for ADR MOS_Base-4 : : \ -------------- \ Core MOS setup \ -------------- $=\ On entry, R0=&80 if Tube startup passed code to execute .(\ R1=entry point if R0=&80 8\ R13=stack B"\ R14=return address L'\ All registers trashable V*\ No Currently Active Object `#\ On exit, Nothing significant j\ t.MOS_Start ~STMFD R13!,{R14} : 5\ Redirect SWI vector to vector low numbered SWIs 5\ ----------------------------------------------- MOV R2,#0 ADR R1,swiNull 0MOV R0,#vecbase :\ Base of vectors .MOS_InitVectors 0STR R2,[R0,#512] :\ Clear R12 value ;STR R1,[R0],#4 :\ Set vectors to null return CMP R0,#vecbase+&200 BCC MOS_InitVectors : LDR R0,swiVop  MOV R1,#swiV-4 :STR R0,[R1],#4 :\ Insert LDR PC,P%+4 opcode ,MOV R2,#swiVsys :\ System swiV (0LDR R0,[R2] :\ Get system swiV 2:STR R0,[R1] :\ Copy to MOS module's swiV <ADR R0,swiHandler FADR R0,MOS_Base-4 :\ Point to start of ROM modules >STR R0,[R9],#8 :\ (&2208)=>start of ROM modules module start 8ADD R2,R0,#5*4 :\ R2=>module title offset 7LDR R2,[R2] :\ R2=module title offset 1ADD R2,R2,R1 :\ R2=>module title >STR R1,[R9],#4 :\ Store pointer to module start 8STR R3,[R9],#4 :\ Clear workspace pointer >STR R2,[R9],#4 :\ Store pointer to module title 1STR R3,[R9],#4 :\ Clear spare word 5LDR R2,[R0] :\ Get length of module 9ADD R0,R1,R2 :\ Point past end of module 7LDR R1,[R0] :\ Get next module length CMP R1,#0 "0BNE MOS_ModBuildList :\ Loop until zero ,6STR R1,[R9],#-16 :\ Store zero terminator 6MOV R0,#modtable @9STR R9,[R0,#12] :\ Store last entry pointer J: T\ Initialise modules ^\ ------------------ hMOV R7,#modtable r:ADD R7,R7,#&10 :\ R8=>start of module chain |.MOS_InitModLoop 1LDR R8,[R7],#16 :\ R8=>Module start CMP R8,#0 BEQ MOS_InitModDone 0ADD R9,R8,#4 :\ R8=>Module_Init 6ADR R10,NullString :\ No environment string 1MOV R11,#0 :\ Module is in ROM 2SUB R12,R7,#12 :\ R12=>private word BL CallModuleR9 B MOS_InitModLoop .MOS_InitModDone /LDMFD R13!,{PC} :\ Return to core : .NullString EQUB 13:ALIGN :  .swiVop &EQUD &E51FF004 0: :.CallModuleR9 D\ R9=module entry address N\ R8=module base address XSTMDB R13!,{R0} bLDR R0,[R9] lCMP R0,#0 vLDMEQIA R13!,{R0} Q PC,R14 TST R0,#&FC000003 ADDEQ R9,R0,R8 LDMIA R13!,{R0} MOV PC,R9 : : \ =========== \ SWI Handler \ =========== 5.swiHandler :\ SPSR=CPSR, CPSR=SVC +STMFD R13!,{R10-R12,R14} :\ Save regs 8CMP PC,R0 :\ Clear V, NVZ undefined 5LDR R10,[R14,#-4] :\ Get SWI instruction  0BIC R10,R10,#&FF000000 :\ R10=SWI number 5\MRS R11,SPSR :\ R11=saved CPU mode  4EQUD &E14FB000 :\ R11=saved CPU mode *ASTMFD R13!,{R10-R11} :\ Save SWI number, CPU mode+flags 44BIC R10,R10,#&00020000 :\ R10=raw SWI number >9CMP R10,#&80 :\ Pass on SWI>127 to core H>BCS swiHandOn :\ NB, SWI 0,1,2,3 a bit fiddly R: \ADR R14,swiClaimed f>STMFD R13!,{R14} :\ Push return for claimed call p5MOV R11,#R12base :\ Point to R12 values z;LDR R12,[R11,R10,LSL #2] :\ Set R12 for vectored code 2MOV R11,#vecbase :\ Point to vectors \ &2010 - &04 OS_ReadC * RdchV Same as Software Vectors F$\ &2014 - &05 OS_CLI * CLIV P%\ &2018 - &06 OS_Byte * ByteV Z%\ &201C - &07 OS_Word * WordV d%\ &2020 - &08 OS_File * FileV n%\ &2024 - &09 OS_Args * ArgsV x%\ &2028 - &0A OS_BGet * BGetV %\ &202C - &0B OS_BPut * BPutV %\ &2030 - &0C OS_GBPB * GBPBV %\ &2034 - &0D OS_Find * FindV )\ &2038 - &0E OS_ReadLine * ReadLineV \ \ &2078 - &1E OS_Module \ &207C - &1F OS_Claim \ &2080 - &20 OS_Release \ &20A4 - &29 OS_FSControl \ &20C0 - &30 OS_ServiceCall #\ &20FC - &3F OS_CheckModeValid \ &2110 - &44 OS_PrettyPrint \ &2188 - &62 OS_ClaimSWI \ &218C - &63 OS_ReleaseSWI \ &21DC - &77 OS_ClaimOSSWI \ ",\ &2200-&23FF Software vector R12 values ,\ &2200 R12 for OS_WriteC 6 \ etc. @\ J\ &2400 LDR PC,swiV T0\ &2404 Secondary swiV to system SWI handler ^ h"\ &2408+ Module chain pointers r(\ &2408 => start of ROM module chain |,\ &240C => last module chain pointer---+ ,\ &2410 => Start of first module | ,\ &2414 = private workspace word | ,\ &2418 => Title of first module | ,\ &241C = spare | ,\ &2420 => Start of second module | ,\ etc. | ,\ &24ss => Start of last module <-----+ $\ &24tt = private workspace word #\ &24uu => Title of last module \ &24vv = spare \ &24ww = &00000000 \ : : \ =================== \ MOS SERVICE ENTRIES &\ =================== 0: : .MOS_Init DB\ Can't OS_ClaimSWI vectors, as OS_ClaimSWI doesn't yet exist! NB\ ------------------------------------------------------------ XFMOV R1,#vecbase :\ Base of vectors bCADR R0,SWI_CLI :STR R0,[R1,#&05*4] :\ Claim OS_CLI lKADR R0,SWI_PrettyPrint:STR R0,[R1,#&44*4] :\ Claim OS_PrettyPrint vHADR R0,SWI_ClaimSWI :STR R0,[R1,#&62*4] :\ Claim OS_ClaimSWI JADR R0,SWI_ReleaseSWI :STR R0,[R1,#&63*4] :\ Claim OS_ReleaseSWI MOV PC,R14 : .MOS_Service MOV PC,R14 : : \ ================ \ MOS SWI ROUTINES \ ================ : %\ OS_ClaimSWI - Claim OS SWI call %\ ------------------------------- .SWI_ClaimSWI \ R0=vector number \ R1=claiming routine \ R2=R12 to use in call *STMFD R13!,{R0} 4CMP R0,#128 >MOVCC R0,R0,LSL #2 HADDCC R0,R0,#vecbase RSTRCC R1,[R0] \STRCC R2,[R0,#512] fLDMFD R13!,{R0,PC} p: z)\ OS_ReleaseSWI - Release OS SWI call )\ ----------------------------------- .SWI_ReleaseSWI \ R0=vector number \ R1=claiming routine \ R2=R12 to use in call STMFD R13!,{R0,R1} CMP R0,#128 MOVCC R0,R0,LSL #2 ADDCC R0,R0,#vecbase ADRCC R1,swiNull STRCC R1,[R0] MOVCC R1,#0 STRCC R1,[R0,#512] LDMFD R13!,{R0,R1,PC} : : $\ ========================= .\ OS_CLI - *Command handler 8\ ========================= B .SWI_CLI L\ R0=>command V\ R10-R12 corruptable `.SWI_CLIpreskip jLDRB R10,[R0],#1 tTEQ R10,#" " ~TEQNE R10,#"*" 0BEQ SWI_CLIpreskip :\ Skip '*'s and ' 's SUB R0,R0,#1 CMP R10,#" " !MOVCC R0,#0 :\ Return 0 $LDMCCFD R13!,{PC} :\ Null string CMP R10,#"|" Q R0,#0 :\ Return 0 'LDMEQFD R13!,{PC} :\ Comment string CMP R10,#"A" 4MOVCC PC,R14 :\ Doesn't start with a letter : &\ R0=>real start of command string STMFD R13!,{R1,R6-R9}  MOV R9,#modtable :\&2200 8ADD R9,R9,#16 :\ Point to first module infoblock  ( \ R9+0 => => Start of module 2&\ R9+4 => = private workspace word <\ R9+8 => => Module title F\ module+0 = Start P\ module+24 = Commands Z d\ R0=>command line n\ R6=>parsing command line x \ R7=>char from command line !\ R8=>char from command table \ R9=>module infoblock \ R10=>start of module \ R11=>module command table \ R12=>private word  .SWI_CLIscanmodulelist &LDR R10,[R9] :\ R10=>module TEQ R10,#0 BEQ SWI_CLIunclaimed /LDR R11,[R10,#&18] :\ R11=>command pointer CMP R11,#0 BEQ SWI_CLInocommands -ADD R11,R11,R10 :\ R11=>command table ,ADD R12,R9,#4 :\ R12=>private word .SWI_CLIentry "LDRB R8,[R11,#0] ,0CMP R8,#0 :\ End of command table? 6BEQ SWI_CLInocommands @4MOV R6,R0 :\ R6=>start of command line J.match_chars T5LDRB R7,[R6],#1 :\ Get char from command line ^6LDRB R8,[R11],#1 :\ Get char from command table hCMP R7,#&60 r,SUBCS R7,R7,#32 :\ Ensure upper case |CMP R8,#&60 ,SUBCS R8,R8,#32 :\ Ensure upper case CMP R8,#0 BEQ match_entry CMP R7,R8 BEQ match_chars CMP R7,#"." BEQ match_dot .skip_table 3LDRB R8,[R11],#1 :\ Get next char from table CMP R8,#0 BNE skip_table ADD R11,R11,#3 BIC R11,R11,#3 ADD R11,R11,#4*4 B SWI_CLIentry : &.match_entry 0CMP R7,#"A" :LBCS skip_table :\ Matched table entry, but command string is longer DB matched_entry N: X.match_dot b3LDRB R8,[R11],#1 :\ Get next char from table lCMP R8,#0 vBNE match_dot .matched_entry ADD R11,R11,#3 BIC R11,R11,#3 : 1SUB R6,R6,#1 :\ Prepare for skipspaces .match_skip_spaces LDRB R7,[R6],#1 CMP R7,#" " BEQ match_skip_spaces 2STMFD R13!,{R0,R14} :\ Save command line, link +SUB R0,R6,#1 :\ R0=>command tail 3MOV R1,#255 :\ R1= number of parameters 8LDR R9,[R11] :\ R9=offset or absolute address (TST R9,#&FF000000 :\ Top bits set?  .ADDEQ R9,R9,R10 :\ R9=>command routine   #\ On entry to command routines, *\ R0=>command tail 4\ R1= number of parameters >\ R12=>private word H\ R13=stack R\ R14=return address \ fMOV R14,PC p*MOV PC,R9 :\ Call routine zLDR R14,SWI_CLIpasson TEQ R0,R14 4LDMFD R13!,{R6,R14} :\ Get command line, link 9Q R0,R6 :\ If passed on, R0=>command line 8BEQ SWI_CLIunclaimed :\ and jump to exit unclaimed 5LDMFD R13!,{R1,R6-R9} :\ Restore everything else ,LDMFD R13!,{PC} :\ Return claimed : .SWI_CLInocommands \SUB R9,R9,#16 \CMP R9,#modtable :\&2200 \BNE SWI_CLIscanmodulelist ADD R9,R9,#16 B SWI_CLIscanmodulelist .SWI_CLIunclaimed 5LDMFD R13!,{R1,R6-R9} :\ Restore everything else .MOV PC,R14 :\ Return unclaimed $: ..SWI_CLIpasson 8EQUS "PASS" B: L: V\ ============= `\ MOS *COMMANDS j\ ============= t: ~ \ *Help  \ -----  .cmdHelp !STMFD R13!,{R1-R4,R9,R10,R14} *MOV R4,R0 :\ R4=>command tail MOV R9,#modtable 9ADD R9,R9,#16 :\ Point to first module infoblock ;MOV R1,#0 :\ Use System PrettyPrint dictionary   \ R9+0 => => Start of module &\ R9+4 => = private workspace word \ R9+8 => => Module title \ module+0 = Start \ module+24 = Commands   .cmdHelp_scanmodulelist +LDR R10,[R9] :\ R10=>module (TEQ R10,#0 2BEQ cmdHelp_exit <SWI "OS_NewLine" F0LDR R2,[R9,#8] :\ R2=>module title P6LDR R0,[R10,#&14] :\ R0=>module help string ZTST R0,#&FF000000 dADDEQ R0,R0,R10 n8SWI "OS_PrettyPrint" :\ Print module help string xSWI "OS_NewLine" LDRB R0,[R4] CMP R0,#" "  - just list titles : 1LDR R0,[R10,#&18] :\ R0=>command table CMP R0,#0 BEQ cmdHelp_nextmodule TST R0,#&FF000000 ADDEQ R0,R0,R10 .cmdHelp_loop LDRB R3,[R0] CMP R3,#0 BEQ cmdHelp_next SWI "OS_WriteS" -EQUS "==> Help on keyword ":EQUB 0:ALIGN 7MOV R2,R0 :\ R2=>command for PrettyPrint ")SWI "OS_Write0" :\ Print command ,SWI "OS_NewLine" 6ADD R0,R0,#3 @BIC R0,R0,#3 JADD R3,R0,#12 TLDR R0,[R3] ^TST R0,#&FF000000 hADDEQ R0,R0,R10 rSWI "OS_PrettyPrint" |SWI "OS_NewLine" ADD R0,R3,#4 B cmdHelp_loop .cmdHelp_next .cmdHelp_nextmodule ADD R9,R9,#16  B cmdHelp_scanmodulelist .cmdHelp_exit DLDR R0,SWI_CLIpasson :\ Magic word to pass on unclaimed +LDMFD R13!,{R1-R4,R9,R10,PC} :\ Return : :  \ ==========================  \ MISC. SUPPORT SWI ROUTINES  \ ========================== : .SWI_PrettyPrint &\ R0=>string 0\ R1=>dictionary :\ R2=>parameter D:\ NB, column counter doesn't count embedded text at R2 N\ XSTMFD R13!,{R0-R3,R14} bMOV R1,R0 lMOV R3,#0 v.SWI_PrettyLp LDRB R0,[R1],#1 CMP R0,#0 9LDMEQFD R13!,{R0-R3,R14,PC} :\ End at zero byte 4CMP R0,#9 :BEQ SWI_PrettyTab :\ Expand TABs 2CMP R0,#10:BEQ SWI_PrettyLp :\ Skip $CMP R0,#27:BEQ SWI_PrettyEsc 4ADD R3,R3,#1 :\ Inc. column CMP R0,#13 :Q R3,#0 :\ Clear column counter >SWIEQ 256+10 :\ Prefix with SWI "OS_WriteC" B SWI_PrettyLp .SWI_PrettyTab SWI 256+32  ADD R3,R3,#1 TST R3,#7  BNE SWI_PrettyTab *B SWI_PrettyLp 4.SWI_PrettyEsc >LDRB R0,[R1],#1 HCMP R0,#1 RBCC SWI_PrettyR2 \BNE SWI_PrettyLp fSWI "OS_WriteS" p$EQUS "Syntax: *":EQUB 0:ALIGN z\CMP R0,#0 \BNE SWI_PrettyLp .SWI_PrettyR2 MOV R0,R2 SWI "OS_Write0" B SWI_PrettyLp : : ] :A$="*SAVE "+fname$+" "+~mcode%+" "+~O%+" 0 FFFFFA00"  A$:"Stamp "+fname$