> ModHand/s v0.02  ARM CoPro Module handler : (9 28-Jul-2008 JGH: Split source into seperate modules 26 21-Aug-2008 JGH: OS_Module moved from MOS module <> 02-May-2009 JGH: OS_Module,2 sets USR32, calls FSControl F: P list%=- Z : " @ ";: dfname$="ModHandler" n: xmodtable=&2400 os_ClaimSWI=&62 :  mcode% &1000 P=0 1 P%=0:O%=mcode% [OPT P*(2-list%)+4 \ ====================== \ *** ULE HANDLER *** \ ====================== .Module_Base EQUD 0:\ Module_Start B Module_Init B Module_Final B Module_Service EQUD Module_Title EQUD Module_Help "EQUD Module_Commands ,EQUD 0:\ Module_SWIBase 6EQUD 0:\ Module_SWIHandler @EQUD 0:\ Module_SWITable JEQUD 0:\ Module_SWICode T: ^.Module_Title h%EQUS "ModuleHandler":EQUB 0:ALIGN r.Module_Help |>EQUS "Module Handler"+9+"0.02 (02 May 2009)":EQUB 0:ALIGN : .Module_Commands eEQUS "Modules" :EQUB 0:ALIGN:EQUD cmdModules :EQUD 0:EQUD cmdModules_Syntax :EQUD cmdModules_Help eEQUS "RMClear" :EQUB 0:ALIGN:EQUD cmdRMClear :EQUD 0:EQUD cmdRMClear_Syntax :EQUD cmdRMClear_Help dEQUS "RMKill" :EQUB 0:ALIGN:EQUD cmdRMKill :EQUD 0:EQUD cmdRMKill_Syntax :EQUD cmdRMKill_Help dEQUS "RMLoad" :EQUB 0:ALIGN:EQUD cmdRMLoad :EQUD 0:EQUD cmdRMLoad_Syntax :EQUD cmdRMLoad_Help fEQUS "RMReInit":EQUB 0:ALIGN:EQUD cmdRMReInit:EQUD 0:EQUD cmdRMReInit_Syntax:EQUD cmdRMReInit_Help cEQUS "RMRun" :EQUB 0:ALIGN:EQUD cmdRMRun :EQUD 0:EQUD cmdRMRun_Syntax :EQUD cmdRMRun_Help dEQUS "RMTidy" :EQUB 0:ALIGN:EQUD cmdRMTidy :EQUD 0:EQUD cmdRMTidy_Syntax :EQUD cmdRMTidy_Help EQUB 0:ALIGN fEQUS "RMEnsure":EQUB 0:ALIGN:EQUD cmdRMEnsure:EQUD 0:EQUD cmdRMEnsure_Syntax:EQUD cmdRMEnsure_Help fEQUS "RMFaster":EQUB 0:ALIGN:EQUD cmdRMFaster:EQUD 0:EQUD cmdRMFaster_Syntax:EQUD cmdRMFaster_Help fEQUS "RMInsert":EQUB 0:ALIGN:EQUD cmdRMInsert:EQUD 0:EQUD cmdRMInsert_Syntax:EQUD cmdRMInsert_Help pEQUS "ROMModules":EQUB 0:ALIGN:EQUD cmdROMModules :EQUD 0:EQUD cmdROMModules_Syntax :EQUD cmdROMModules_Help dEQUS "Unplug" :EQUB 0:ALIGN:EQUD cmdUnplug :EQUD 0:EQUD cmdUnplug_Syntax :EQUD cmdUnplug_Help EQUB 0:ALIGN &: 0.cmdModules_Help :bEQUS "*Modules lists the modules currently loaded, giving the name and address of the module," D:EQUS " and also the address of its workspace.":EQUB 13 N.cmdModules_Syntax X(EQUS "Syntax: *Modules":EQUB 0:ALIGN b: l.cmdRMClear_Help vIEQUS "*RMClear deletes all relocatable modules from the RMA.":EQUB 13 .cmdRMClear_Syntax (EQUS "Syntax: *RMClear":EQUB 0:ALIGN : .cmdRMEnsure_Help EQUS "*RMEnsure checks that a module is present and is the given version number, or a more recent one. The command is executed if this is not the case.":EQUB 13 .cmdRMEnsure_Syntax UEQUS "Syntax: *RMEnsure [<*command>]":EQUB 0:ALIGN : .cmdRMFaster_Help ":EQUB 0:ALIGN : .cmdRMInsert_Help  pEQUS "*RMInsert reverses the effect of *Unplug, but does not reinitialise the specified ROM module.":EQUB 13 .cmdRMInsert_Syntax  IEQUS "Syntax: *RMInsert []":EQUB 0:ALIGN *: 4.cmdRMKill_Help >BEQUS "*RMKill kills and deletes a relocatable module.":EQUB 13 H.cmdRMKill_Syntax R5EQUS "Syntax: *RMKill ":EQUB 0:ALIGN \: f.cmdRMLoad_Help pFEQUS "*RMLoad loads and initialises a relocatable module.":EQUB 13 z.cmdRMLoad_Syntax 2EQUS "Syntax: *RMLoad ":EQUB 0:ALIGN : .cmdRMReInit_Help pEQUS "*RMReInit reinitialises a relocatable module, reversing the action of *Unplug if appropriate.":EQUB 13 .cmdRMReInit_Syntax 7EQUS "Syntax: *RMReInit ":EQUB 0:ALIGN : .cmdRMRun_Help 4EQUS "*RMRun runs a relocatable module.":EQUB 13 .cmdRMRun_Syntax 1EQUS "Syntax: *RMRun ":EQUB 0:ALIGN : .cmdRMTidy_Help NEQUS "*RMTidy compacts the RMA and reinitialises all the modules.":EQUB 13 .cmdRMTidy_Syntax 'EQUS "Syntax: *RMTidy":EQUB 0:ALIGN $: ..cmdROMModules_Help 8NEQUS "*ROMModules lists the relocatable modules currently in ROM.":EQUB 13 B.cmdROMModules_Syntax L+EQUS "Syntax: *ROMModules":EQUB 0:ALIGN V: `.cmdUnplug_Help jHEQUS "*Unplug stops the given ROM module being initialised.":EQUB 13 tLEQUS "*Unplug with no argument lists the unplugged ROM modules.":EQUB 13 ~.cmdUnplug_Syntax IEQUS "Syntax: *Unplug [ []]":EQUB 0:ALIGN : : !\ Module Handler entry points !\ =========================== .Module_Init STMFD R13!,{R14} MOV R0,#&1E ADR R1,SWI_Module MOV R2,#0 /SWI os_ClaimSWI :\ Claim SWI OS_Module LDMFD R13!,{PC} :  .Module_Final :MOV PC,R14 .Module_Service :MOV PC,R14 : (: 2\ Module Handler *COMMANDS <\ ======================== F: P\ -------- Z\ *Modules d\ -------- n.cmdModules xSTMFD R13!,{R14} SWI "OS_WriteS" &EQUS "No. Position Workspace Name"  EQUB 10:EQUB 13:EQUB 0:ALIGN &MOV R8,#0 :\ Module number MOV R9,#modtable .ADD R9,R9,#&10 :\ Start of module chain 'SUB R13,R13,#12 :\ Space on stack .cmdModulesLp LDR R3,[R9],#4  CMP R3,#0 ,BEQ cmdModulesEnd :\ End of module chain  MOV R0,R8 MOV R1,R13 MOV R2,#12 SWI "OS_ConvertCardinal1" .cmdModulesNumber "!CMP R2,#12:BEQ cmdModulesShow ,SWI 256+" " 6ADD R2,R2,#1 @B cmdModulesNumber J.cmdModulesShow TSWI "OS_Write0" ^SWI 256+" " h'MOV R0,R3 :\ R0=position rMOV R1,R13 |MOV R2,#12 SWI "OS_ConvertHex8" SWI "OS_Write0" SWI 256+" " (LDR R0,[R9],#4 :\ R0=workspace MOV R1,R13 MOV R2,#12 SWI "OS_ConvertHex8" SWI "OS_Write0" SWI 256+" " SWI 256+" " $LDR R0,[R9],#8 :\ R0=>title SWI "OS_Write0" SWI "OS_NewLine" ADD R8,R8,#1 B cmdModulesLp .cmdModulesEnd &/ADD R13,R13,#12 :\ Release space on stack 0LDMFD R13!,{PC} :: D: N&\ -------------------------------- X&\ *RMRun () b&\ -------------------------------- l"\ R0=> v .cmdRMRun MOV R2,#0:B RMCommand : '\ --------------------------------- '\ *RMLoad () '\ --------------------------------- "\ R0=> .cmdRMLoad MOV R2,#1:B RMCommand : \ ---------------------- \ *RMReInit \ ---------------------- \ R0=> .cmdRMReInit  MOV R2,#3:B RMCommand :  \ -------------------- *\ *RMKill 4\ -------------------- >\ R0=> H.cmdRMKill RMOV R2,#4:B RMCommand \: f \ ------- p \ *RMTidy z \ ------- .cmdRMTidy MOV R2,#8:B RMCommand :  \ ------- \ *RMClear  \ ------- .cmdRMClear MOV R2,#9:\B RMCommand : .RMCommand STMFD R13!,{R14} MOV R1,R0 MOV R0,R2 SWI "XOS_Module" LDMFD R13!,{PC} : $.cmdRMEnsure ..cmdRMFaster 8.cmdRMInsert B.cmdROMModules L.cmdUnplug VMOV PC,R14 `: j: t!\ Module handler SWI routines ~!\ =========================== : \ --------- \ OS_Module \ --------- .SWI_Module CMP R0,#10 5ADDCC PC,PC,R0,LSL #2 :\ Jump into dispatch table ;MOV PC,R14 :\ Out of range, return unclaimed : $MOV PC,R14 :\ 0 - Run +B ModuleLoad \MOV PC,R14 :\ 1 - Load &B ModuleEnter :\ 2 - Enter 'MOV PC,R14 :\ 3 - ReInit 'MOV PC,R14 :\ 4 - Delete ,MOV PC,R14 :\ 5 - DescribeRMA &B ModuleClaim :\ 6 - Claim (%MOV PC,R14 :\ 7 - Free 2%MOV PC,R14 :\ 8 - Tidy <&MOV PC,R14 :\ 9 - Clear F: P: Z.ModuleClaim d \ On entry, R3=required size n\ On exit, R0 preserved x!\ R2=>claimed block \ R3 preserved STMFD R13!,{R0,R3,R4,R14} 7MOV R4,R3 :\ R4=size required 1ADD R4,R4,#3:BIC R4,R4,#3 :\ Align size MOV R0,#0:MOV R1,#0 MOV R2,#0:MOV R3,#0 9SWI "OS_ChangeEnvironment" :\ Read top of memory !SUBS R1,R1,R4:BCC NoRMASpace MOV R0,#0:MOV R4,R1 MOV R2,#0:MOV R3,#0 >SWI "OS_ChangeEnvironment" :\ Write new top of memory 8MOV R2,R4 :\ R2=>claimed block CLDMFD R13!,{R0,R3,R4,R14,PC} :\ Restore registers and return : .NoRMASpace ADR R0,errNoRMASpace "CMP R0, #1<<31 ,,CMNVC R0, #1<<31 :\ Set V 6CLDMFD R13!,{R1,R3,R4,R14,PC} :\ Return with not enough space @.errNoRMASpace J/EQUD 100:EQUS "No room in RMA":EQUB 0:ALIGN T: ^: h.ModuleEnter r\ On entry, R0= 2 |\ R1=>module name \ R2=>parameters \ On exit, does not return STMFD R13!,{R0-R7,R14} MOV R3,#modtable .ModuleEnterLp 9ADD R3,R3,#&10 :\ Step to next module infoblock LDR R4,[R3] TEQ R4,#0 /BEQ ModuleEnterEnd :\ End of module chain %LDR R4,[R3,#8] :\ R4=>title 0MOV R5,R1 :\ R5=>name to look for .ModuleEnterFind 6LDRB R6,[R4],#1 :\ Get char from module title CMP R6,#&60 -SUBCS R6,R6,#32 :\ Ensure upper case :LDRB R7,[R5],#1 :\ Get char from name to look for &CMP R7,#&60 0-SUBCS R7,R7,#32 :\ Ensure upper case :TEQ R6,#0 DBEQ ModuleEnterMatch NCMP R6,R7 XBEQ ModuleEnterFind bBNE ModuleEnterLp l.ModuleEnterMatch vCMP R7,#"!" ?BCS ModuleEnterLp :\ Search name longer than module name : -\ R3=>module infoblock for matched module : /MOV R10,R1 :\ R10=>module name 3LDR R11,[R3,#0] :\ R11=>start of module :ADD R12,R3,#4 :\ R12=>private workspace word 9MOV R0,#2 :\ R0=Application starting up /MOV R1,R2 :\ R1=>command tail 2MOV R2,R11 :\ R2=CAO=Module Start =MOV R3,R10 :\ R3=>command name (module name) USWI "XOS_FSControl" :\ Notify new application starting, set environment, etc. : 6LDMFD R13!,{R0-R7,R14} :\ Restore everything else .MOV R0,R10 :\ R0=>module name =LDR R10,[R11,#0] :\ R10=word at module entry point /TST R10,#&FC000003 :\ Is it an opcode? *:ADDEQ R11,R11,R10 :\ Add offset if not an opcode 4: >7MOV R13,#&0B00 :\ Reset SVC stack H8EQUD &E10FA000 ; MRS R10,CPSR :\ Copy CPSR to R10 R7BIC R10,R10,#&1F :\ Clear mode bits \6R R10,R10,#&10 :\ Set mode to 32 f@EQUD &E121F00A ; MSR CPSR_c,R10 :\ Copy status back to CPSR p>MOV R0,R0 :\ Let processor catch up z: +MOV PC,R11 :\ Jump to entry : .ModuleEnterEnd 0LDMFD R13!,{R0-R7,R14} :\ Restore everything CMOV PC,R14 :\ Return unclaimed, pass on to Tube MOS : : .ModuleLoad +\ On entry, R1=>pathname and parameters \ On exit, R0 preserved \ R1 preserved STMFD R13!,{R1-R14} :MOV R10,R1 :\ R10=>filename for later MOV R0,#5 8SWI "XOS_File" :\ Read file information JLDMVSFD R13!,{R1-R7,R10-R14,PC} :\ Error, restore registers and return $4\ r1=type, r1=>name, r2=load, r3=exec, r4=length .CMP R0,#1 8BNE ModuleLoadNotFile B1MOV R3,R4 :\ R3=size needed L:BL ModuleClaim :\ Try to claim some space VFLDMVSFD R13!,{R1-R14,PC} :\ Error, restore registers and return `\ r3=>memory j*MOV R0,#255 :\ R0=Load t/MOV R1,R10 :\ R1=>Filename ~9MOV R2,R3 :\ R2=>address to load to CMOV R3,#0 :\ R3=0 - load to specified address /STMFD R13!,{R2} :\ Save address ,SWI "XOS_File" :\ Load file 3LDMFD R13!,{R9} :\ Get address back FLDMVSFD R13!,{R1-R14,PC} :\ Error, restore registers and return @\ Need to check loaded data to check it actually is a module : MOV R7,#modtable :ADD R7,R7,#12 :\ R7=>link to last module 8LDR R8,[R7] :\ R8=>last module block =ADD R8,R8,#16 :\ Point to next module block MOV R11,#0 ?STR R11,[R8] :\ Ensure module block is clear  STR R11,[R8,#4] STR R11,[R8,#8] STR R11,[R8,#12] (FSTR R11,[R8,#16] :\ Put terminator in next module block 2MOV R12,R8 <6ADD R12,R12,#4 :\ R12=>workspace word F0MOV R11,#0 :\ Instantiation P\ R9=>module start ZSTMFD R13!,{R7-R9} d:MOV R8,R9 :\ R8=>module base address n2ADD R9,R9,#4 :\ R9=>Module_Init xABL CallModuleR9 :\ Call Module's Init entry point LDMFD R13!,{R7-R9} :STR R9,[R8] :\ Store address of module =LDR R10,[R9,#16] :\ R10=offset to title string 4ADD R10,R10,R9 :\ R10=>title string @STR R10,[R8,#8] :\ Store address of title string : =LDMFD R13!,{R1-R14,PC} :\ Restore registers and return : .CallModuleR9 \ R9=module entry address \ R8=module base address STMDB R13!,{R0} LDR R0,[R9] CMP R0,#0 LDMEQIA R13!,{R0} Q PC,R14 "TST R0,#&FC000003 ,ADDEQ R9,R0,R8 6LDMIA R13!,{R0} @MOV PC,R9 J: T.ModuleLoadNotFile ^ADR R0,errModNotFile hCMP R0, #1<<31 r,CMNVC R0, #1<<31 :\ Set V |8LDMFD R13!,{R1-R14,PC} :\ Return with error .errModNotFile 3EQUD 100:EQUS "Not an module file":EQUB 0:ALIGN : : ] :A$="*SAVE "+fname$+" "+~mcode%+" "+~O%+" 0 FFFFFA00"  A$:"Stamp "+fname$