; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; TTL => Kernel : SWI Despatch, simple SWIs SUBT Arthur Variables OPT 4 ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; handy macros: ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MACRO $l CheckSpaceOnStack $space, $faildest, $tmp [ True ; SKS $l MOV $tmp, sp, LSR #15 ; Stack base on 32K boundary SUB $tmp, sp, $tmp, LSL #15 ; Amount of stack left CMP $tmp, #$space ; Must have at least this much left BMI $faildest | $l MOV $tmp, #32*1024 ; assume stack ends at next 32K boundary SUB $tmp, $tmp, #1 AND $tmp, $tmp, stack CMP $tmp, #$space BLT $faildest ] MEND MACRO assert $condition [ :LNOT: ($condition) ! 1,"Assert failed: $condition" ] MEND ; one that builds a module command table entry: ; set Module_BaseAddr to module base before use. GBLA Module_BaseAddr Module_BaseAddr SETA 0 ; Command $cmd, $max, $min - declared in hdr.macros. ; debug macro: set the border colour MACRO $l SetBorder $reg1, $reg2, $red, $green, $blue, $delay ! 0, "Setborder used" $l LDR $reg1, =VIDC [ VIDC_Type = "VIDC20" ; Note $reg, $green and $blue are 4 bit values LDR $reg2, =&40000000+(($red)*&11)+(($green)*&1100)+(($blue)*&110000) | LDR $reg2, =&40000000+ $red + $green *16 + $blue *256 ] STR $reg2, [$reg1] [ "$delay"<>"" MOV $reg1, #$delay 10 SUBS $reg1, $reg1, #1 BNE %BT10 ] MEND ; Fake a 26-bit pc, given a PSR currently in lr, and the 32-bit address on ; the stack. The stacked address is pulled, and the result is left in lr. MACRO FakeLR $temp, $dontpull AND $temp,lr,#&F0000003 AND lr,lr,#I32_bit+F32_bit ORR $temp,$temp,lr,LSL #IF32_26Shift [ "$dontpull" = "dontpull" LDR lr,[sp] | LDR lr,[sp],#4 ] BIC lr,lr,#ARM_CC_Mask ORR lr,lr,$temp MEND ; Ickle macros. We want to be able to turn IRQs on and off fast in the ; code in various places. To do this easily, have a name for the ; SVC26/32 mode we run in [ No26bitCode USR2632 * USR32_mode SVC2632 * SVC32_mode | USR2632 * USR26_mode SVC2632 * SVC26_mode ] ; [ AddTubeBashers [ TubeType = Tube_Normal DebugTUBE * &03340000+3*&4000 ; tube in podule #3 ; Tube register offsets ^ 0 R1STAT # 4 R1DATA # 4 | DebugTUBE * &03000000 ; simulator tube address R1DATA * 0 ] ] ; routine to stuff a char down the Tube ; should be inside above conditional, but AAsm winges pitifully. MACRO $l TubeChar $reg1, $reg2, $charset, $stackthere ! 0, "TubeChar used." $l [ "$stackthere"="" Push "$reg1, $reg2" ] LDR $reg1, =DebugTUBE [ TubeType = Tube_Normal ; normal tubes have status register, simulator one doesn't 01 LDRB $reg2, [$reg1, #R1STAT] TST $reg2, #&40 BEQ %BT01 ] $charset STRB $reg2, [$reg1, #R1DATA] [ "$stackthere"="" Pull "$reg1, $reg2" ] MEND MACRO $l TubeString $reg1, $reg2, $reg3, $string, $cc LDR $reg1, =DebugTUBE ADR $reg2, %FT20 10 [ TubeType = Tube_Normal LDRB $reg3, [$reg1, #R1STAT] TST $reg3, #&40 BEQ %BT10 ] LDRB $reg3, [$reg2], #1 TEQ $reg3, #0 STRNEB $reg3, [$reg1, #R1DATA] BNE %BT10 B %FT30 20 = "$string" [ "$cc" = "" = 10, 13 ] = 0 ALIGN 30 MEND MACRO $l TubeDumpNoStack $dump, $t1, $t2, $t3 $l MOV $t1, #7 01 ADRL $t2, HexTable TubeChar $t3, $t2, "LDRB $t2, [$t2, $dump, LSR #28]", NoStack MOV $dump, $dump, ROR #28 SUBS $t1, $t1, #1 BPL %BT01 TubeChar $t3, $t2, "MOV $t2, #"" """, NoStack MEND MACRO $l TubeNewlNoStack $t1, $t2 $l TubeChar $t1, $t2, "MOV $t2, #10", NoStack TubeChar $t1, $t2, "MOV $t2, #13", NoStack MEND ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Various constants ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MinAplWork * 40*1024 ; minimum size of AplWork ; Fixed addresses MEMCADR * &3600000 ROM * &3800000 OSMD * &11111111 VideoPhysRam * &02000000 ; Amazing - it's in the same place! DRAM0PhysRam * &10000000 ; 4 DRAM banks DRAM1PhysRam * &14000000 DRAM2PhysRam * &18000000 DRAM3PhysRam * &1C000000 DRAMBaseAddressMask * &1C000000 ; used to mask off bits after stealing video RAM PhysSpaceSize * &20000000 ; IOMD physical map is 512M big PhysROM * &00000000 ; and real ROM starts at 0 [ STB PhysExtROM * &01000000 ; 2nd ROM bank starts at 16M ] SAMLength * 512*4 ; SAM length in bytes for 1 bank of VRAM EASISpacePhys * &08000000 EASISpace * PhysSpace + EASISpacePhys ; Manifests CR * 13 LF * 10 space * " " ; Registers SPIRQ RN R13 ; Callback byte bits: CBack_OldStyle * 1 CBack_Postpone * 2 CBack_VectorReq * 4 ; Set up symbols for the SWIs which aren't really there yet AbortTrapSWI * NoSuchSWI SUBT Arthur Code OPT 4 ; ***************************************************************************** ; ; Now ready to start the code: off we go! ; ; ***************************************************************************** ORG ROM GBLS DoMorrisROMHeader [ MorrisSupport DoMorrisROMHeader SETS " GET s.Morris" | DoMorrisROMHeader SETS "" ] ; now include the test code, if there is any GBLS DoTestThings [ IncludeTestSrc DoTestThings SETS " GET TestSrc.Begin" | DoTestThings SETS "" ] $DoTestThings [ IncludeTestSrc DoMorrisROMHeader SETS "" ] $DoMorrisROMHeader ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; If there is no test code then we want a branch table at the start of ROM to ; handle reset and any aborts etc. in the reset code. ; If MorrisSupport we've already generated 16/32 ROM entry code, so skip this bit [ :LNOT: IncludeTestSrc :LAND: :LNOT: MorrisSupport [ ResetIndirected LDR pc, .+ResetIndirection ; load PC, PC relative | [ MEMC_Type = "IOMD" B CONT ; PhysROM is at zero on IOMD | B MOSROMVecs+CONT ; executed out of ROM or RAM ] ] B UndInstInReset B SWIInReset B PrefAbInReset B DataAbInReset B AddrExInReset B IRQInReset UndInstInReset SUB pc, pc, #8 SWIInReset SUB pc, pc, #8 PrefAbInReset SUB pc, pc, #8 DataAbInReset SUB pc, pc, #8 AddrExInReset SUB pc, pc, #8 IRQInReset SUB pc, pc, #8 ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; This bit (up to EndFiq) is copied to location 0. Processor vectors are ; indirected through 0 page locations so that they can be claimed using ; OS_ClaimProcessorVector. IRQs are initially handled specially so that the ; keyboard can be handled during reset but the load is replaced with the ; standard one later on. MOSROMVecs LDR pc, MOSROMVecs+ProcVec_Branch0 LDR pc, MOSROMVecs+ProcVec_UndInst LDR pc, MOSROMVecs+ProcVec_SWI LDR pc, MOSROMVecs+ProcVec_PrefAb LDR pc, MOSROMVecs+ProcVec_DataAb LDR pc, MOSROMVecs+ProcVec_AddrEx LDR pc, MOSROMVecs+InitKbdHandler MOV r10, #IOC ; we dunno what to do with it - ; so cut it off - right off! STRB r10, [r10, #IOCFIQMSK] ; :LSB: IOC = 0 SUBS pc, r14, #4 EndFiq ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; This is the table of default processor vectors which is copied to 0 page. DefaultProcVecs & RESET1 & UndPreVeneer & SVC & PAbPreVeneer & DAbPreVeneer & AdXPreVeneer & Initial_IRQ_Code ASSERT (.-DefaultProcVecs) = ProcVec_End-ProcVec_Start ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; These are preveneers which must be copied to 0 page locations so that the ; relevant handler can be branched to. This is mainly for non-ARM600 platforms ; although the address exception preveneer (which should not actually be required ; on ARM600) is always copied. DefaultPreVeneers [ No26bitCode UndPreVeneer * ProcVecPreVeneers+(.-DefaultPreVeneers) LDR PC, DefaultPreVeneers-ProcVecPreVeneers+UndHan PAbPreVeneer * ProcVecPreVeneers+(.-DefaultPreVeneers) LDR PC, DefaultPreVeneers-ProcVecPreVeneers+PAbHan DCD 0 | DCD 0 DCD 0 DCD 0 ] AdXPreVeneer * ProcVecPreVeneers+(.-DefaultPreVeneers) LDR PC, DefaultPreVeneers-ProcVecPreVeneers+AdXHan ASSERT (.-DefaultPreVeneers) = ProcVecPreVeneersSize [ ResetIndirected :LAND: :LNOT: IncludeTestSrc ; We now waste space until the offset into the ROM is the same as the RAM address of ResetIndirection ; This is so that ; a) on a reset, ROM is paged in at the bottom, so we jump to CONT, and ; b) on a break, RAM is paged in at the bottom, so we jump to CONT_Break ASSERT .-ROM <= ResetIndirection % ResetIndirection-(.-ROM) & CONT-ROM+PhysROM ; address of reset code in physical space ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Now some initialised workspace/vectors that go at &100 ; All the stuff from here to after the DirtyBranch instruction is read ; consecutively out of ROM, so don't put anything in between without changing ; the code StartData ASSERT IRQ1V = &100 & DefaultIRQ1V ASSERT ESC_Status = IRQ1V+4 & &00FF0000 ; IOCControl set to FF on reset ASSERT IRQsema = ESC_Status+4 & 0 EndData ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI return handler: checks callback SVCDespatcher ROUT SWIRelocation * SVCDespatcher-SWIDespatch SLVK_SetV * {PC}-SWIRelocation ORR lr, lr, #V_bit SLVK_TestV * {PC}-SWIRelocation ! 0,"SLVK_TestV at ":CC:(:STR:SLVK_TestV) ORRVS lr, lr, #V_bit SLVK * {PC}-SWIRelocation ! 0,"SLVK at ":CC:(:STR:SLVK) LDR r11, [sp], #4 TST lr, #V_bit BEQ %FT40 ! 0,"VSetReturn at ":CC:(:STR:({PC}-SWIRelocation)) TST r11, #Auto_Error_SWI_bit BEQ VSet_GenerateError + SWIRelocation SWIReturn * {PC}-SWIRelocation ! 0,"SWIReturn at ":CC:(:STR:SWIReturn) 40 MOV r10, #0 LDRB r11, [r10, #CallBack_Flag] CMP r11, #0 BNE callback_checking + SWIRelocation SWIReturnNoCallback * {PC}-SWIRelocation ! 0,"SWIReturnNoCallback at ":CC:(:STR:SWIReturnNoCallback) back_to_user * SWIReturnNoCallback msr AL, CPSR_c, #I32_bit + SVC32_mode ; IRQs off for SPSR use back_to_user_irqs_already_off * {PC}-SWIRelocation msr AL, SPSR_cxsf, lr LDR lr, [sp], #4 Pull "r10-r12" MOVS pc, lr ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; The SWI Despatch routine SVC * {PC}-SWIRelocation Push "r10-r12" LDR r11, [r14, #-4] ; r11 = calling instruction STR r14, [r13, #-4]! ; push return address mrs AL, r14, SPSR ; r14 = saved PSR SVCContinue * {PC}-SWIRelocation BIC r11, r11, #&FF000000 STR r11, [r13, #-4]! ; push SWI number [ StrongARM SVC_CallASWI * {PC}-SWIRelocation ; CallASWI,CallASWIR12 re-entry point ] BICS r11, r11, #Auto_Error_SWI_bit BEQ SWIWriteC + SWIRelocation AND r10, r14, #I32_bit+F32_bit ORR r10, r10, #SVC2632 ; set IFTMMMMM = IF0x0011 msr AL, CPSR_c, r10 ; restore caller's IRQ state CMP r11, #OS_BreakPt CMPNE r11, #OS_CallAVector BICNE r14, r14, #V_bit ; clear V unless BreakPoint/CallVector CMP r11, #OS_WriteI LDRLO pc, [pc, r11, LSL #2] B NotMainMOSSwi + SWIRelocation ASSERT {PC}-SVCDespatcher = SWIDespatch_Size ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; The SWI table JTABLE & SWIWriteC ; this entry never gets used (see ^) & SWIWriteS & SWIWrite0 & SWINewLine ; next section is one where VectorNumber = SWINumber & VecSwiDespatch ; readc & VecSwiDespatch ; cli & NoIrqVecSwiDespatch ; byte & NoIrqVecSwiDespatch ; word & VecSwiDespatch ; file & VecSwiDespatch ; args & BGetSWI ; bget & BPutSWI ; bput & VecSwiDespatch ; gbpb & VecSwiDespatch ; find & VecSwiDespatch ; readline & SCTRL & SWI_GetEnv_Code & SEXIT & SSTENV & SINTON & SINTOFF & SCALLB & SENTERSWI & SBRKPT & SBRKCT & SUNUSED & SSETMEMC & SSETCALL & VecMouse & HeapEntry & ModuleHandler & ClaimVector_SWICode & ReleaseVector_SWICode & ReadUnsigned_Routine & GenEvent & ReadVarValue & SetVarValue & GSINIT & GSREAD & GSTRANS & CvtToDecimal & FSControlSWI & ChangeDynamicSWI & GenErrorSWI & ReadEscapeSWI & ReadExpression & SwiSpriteOp & SWIReadPalette & Issue_Service_SWI & SWIReadVduVariables & SwiReadPoint & DoAnUpCall & CallAVector_SWI & SWIReadModeVariable & SWIRemoveCursors & SWIRestoreCursors & SWINumberToString_Code & SWINumberFromString_Code & ValidateAddress_Code & CallAfter_Code & CallEvery_Code & RemoveTickerEvent_Code & InstallKeyHandler & SWICheckModeValid & ChangeEnvironment & SWIClaimScreenMemory & ReadMetroGnome & XOS_SubstituteArgs_code & XOS_PrettyPrint_code & SWIPlot & SWIWriteN & Add_ToVector_SWICode & WriteEnv_SWICode & RdArgs_SWICode & ReadRAMFSLimits_Code & DeviceVector_Claim & DeviceVector_Release & Application_Delink & Application_Relink & HeapSortRoutine & TerminateAndSodOff & ReadMemMapInfo_Code & ReadMemMapEntries_Code & SetMemMapEntries_Code & AddCallBack_Code & ReadDefaultHandler & SWISetECFOrigin & SerialOp & ReadSysInfo_Code & Confirm_Code & SWIChangedBox & CRC_Code & ReadDynamicArea & SWIPrintChar & ChangeRedirection & RemoveCallBack & FindMemMapEntries_Code & SWISetColour & NoSuchSWI ; Added these to get round OS_ClaimSWI and & NoSuchSWI ; OS_ReleaseSWI (should not have been allocated here). [ AssemblePointerV & PointerSWI | & NoSuchSWI ] & ScreenModeSWI & DynamicAreaSWI & AbortTrapSWI [ CPU_Type = "ARM600" & MemorySWI | & NoSuchSWI ] [ ProcessorVectors & ClaimProcVecSWI | & NoSuchSWI ] & PerformReset [ CPU_Type = "ARM600" & MMUControlSWI | & NoSuchSWI ] [ STB & NoSuchSWI | & ResyncTimeSWI ] [ StrongARM & PlatFeatSWI & SyncCodeAreasSWI & CallASWI & AMBControlSWI & CallASWIR12 | & NoSuchSWI & NoSuchSWI & NoSuchSWI & NoSuchSWI & NoSuchSWI ] ; The following SWIs are not available in this kernel. & NoSuchSWI ; SpecialControl & NoSuchSWI ; EnterUSR32SWI & NoSuchSWI ; EnterUSR26SWI ; End of unavailable SWIs. ; Should not cause any problems on any machine. STB flag just to be safe though. [ STB :LAND: {TRUE} & VIDCDividerSWI | & NoSuchSWI ] & NVMemorySWI MaxSwi * (.-JTABLE)/4 ASSERT MaxSwi < OS_ConvertStandardDateAndTime ; SWIs for time/date conversion are poked in specially ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; The fudge branch to exit a dirty SWI handler DirtyBranch B SLVK +DirtyBranch-BranchToSWIExit ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ [ StrongARM ;StrongARM needs these ;SWI number passed in r10 CallASWI ROUT LDR r11, [sp, #8] ;pick-up target SWI code (r10 pushed by dispatcher) BIC r11, r11, #&FF000000 ;just in case STR r11, [sp, #0] ;CallASWI now incognito as target SWI B SVC_CallASWI ;re-dispatch ;SWI number passed in r12 (better for C veneers) CallASWIR12 ROUT LDR r11, [sp, #16] ;pick-up target SWI code (r12 pushed by dispatcher) BIC r11, r11, #&FF000000 ;just in case STR r11, [sp, #0] ;CallASWIR12 now incognito as target SWI B SVC_CallASWI ;re-dispatch ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; In return address, r10-r12 stacked, lr has SPSR for return VSet_GenerateError ROUT Push lr MOV r1, #Service_Error BL Issue_Service MOV r10, #ErrorV BL CallVector ; Normally gets to default handler... Pull lr ; which raises error; otherwise just BIC lr, lr, #V_bit ; return with V clear: error claimed! B SWIReturn LTORG ; ....................... default owner of ErrorV ............................. ; In r0 -> error in current error block ; Out Exits to user's error handler routine as given by ErrHan ; r1-r9 possibly corrupt. Indeed r10-r12 MAY be duff ... eg. REMOTE ErrHandler ROUT BL OscliTidy ; close redirection, restore curr FS MOV r10, #0 LDR r11, [r10, #ErrBuf] ; Get pointer to error buffer [ No26bitCode LDR sp_svc, =SVCSTK-4*4 ; Just below top of stack Pull r14 STR r14, [r11], #4 ; Return PC for error | LDR sp_svc, =SVCSTK-5*4 ; Just below top of stack Pull r14 ; PSR will be on stack if error at top level FakeLR r12 ; Fake up the PC+PSR STR r14, [r11], #4 ] LDR r14, [r0], #4 ; Copy error number STR r14, [r11], #4 ; Copy error string - truncating at 252 MOV r12, #256-4 10 LDRB r14, [r0], #1 SUBS r12, r12, #1 MOVLS r14, #0 STRB r14, [r11], #1 TEQ r14, #0 BNE %BT10 LDR r14, [r10, #ErrHan] ; And go to error handler [ :LNOT: No26bitCode BIC r14, r14, #ARM_CC_Mask ] STR r14, [r10, #Curr_Active_Object] LDR r0, [r10, #ErrHan_ws] ; r0 is his wp LDRB r11, [r10, #CallBack_Flag] CMP r11, #0 mrs ,r12, CPSR BIC r12, r12, #I32_bit+F32_bit+&0F ; USR26/32 mode, ARM, IRQs enabled [ :LNOT: NoSPSRcorruption msr EQ, CPSR_c, #I32_bit+SVC32_mode ; disable interrupts for SPSR use ] msr EQ, SPSR_cxsf, r12 Pull "r10-r12", EQ MOVEQS pc, r14 ; USR mode, IRQs enabled Push r14 ; Stack return address MOV r14, r12 ; Put PSR in R14 B Do_CallBack ; Can't need postponement, r0,r14,stack ; such that callback code will normally ; call error handler ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; check for CallBack possible callback_checking TST lr, #I32_bit+&0F ; user 26/32 mode, ints enabled? [ {FALSE} ; original code Pull "r10-r12", NE MOVNES pc, lr ; Skip the branch for SVC code speed | BNE SWIReturnNoCallback ; hey, it'll be in the cache (probably) ] ; Further checks: postpone callback if returning V set and R0->RAM TST lr, #V_bit BEQ Do_CallBack TST r11, #CBack_Postpone ; only one postponement BNE Do_CallBack ; allowed. CMP r0, #ROM BGE Do_CallBack msr ,CPSR_c, #I32_bit + SVC32_mode ; ints off while flag updated LDRB r11, [r10, #CallBack_Flag] ORR r11, r11, #CBack_Postpone ; signal to IRQs STRB r11, [r10, #CallBack_Flag] B back_to_user_irqs_already_off Do_CallBack ; CallBack allowed: TST r11, #CBack_VectorReq ; now process any vector entries MOV r12,lr BLNE process_callback_chain MOV lr,r12 TST r11, #CBack_OldStyle BEQ back_to_user [ :LNOT:No26bitCode TST r14, #&10 ; must be returning to 26-bit BNE back_to_user ; on 26-bit systems ] [ {TRUE} ; LRust, Fix RP-0609 ; Check that SVC_sp is empty (apart from r14,r10-r12), i.e. system truly is idle LDR r11, =SVCSTK-4*4 ; What SVC_sp should be if system idle CMP sp, r11 ; Stack empty? BLO back_to_user ; No then no call back ] msr ,CPSR_c, #I32_bit + SVC2632 ; ints off while flag updated LDRB r11, [r10, #CallBack_Flag] BIC r11, r11, #CBack_Postpone+CBack_OldStyle STRB r11, [r10, #CallBack_Flag] MOV r12, #0 LDR R12, [R12, #CallBf] [ No26bitCode STR r14, [r12, #4*16] ; user PSR Pull r14 STR r14, [r12, #4*15] ; user PC | FakeLR r10 STR r14, [r12, #4*15] ; user PC/PSR ] MOV r14, r12 Pull "r10-r12" [ SASTMhatbroken STMIA r14!,{r0-r12} STMIA r14,{r13,r14}^ ; user registers NOP ; doesn't matter that r14 is different | STMIA r14, {r0-r14}^ ; user registers ] MOV R12, #CallAd_ws LDMIA R12, {R12, PC} ; jump to CallBackHandler ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Also called from source.pmf.key, during readc process_callback_chain ROUT Push "r0-r6, r10-r12, lr" ; save some for the callee too. MOV r10, #0 msr ,CPSR_c, #I32_bit + SVC2632 ; ints off while flag updated LDRB r11, [r10, #CallBack_Flag] BIC r11, r11, #CBack_VectorReq STRB r11, [r10, #CallBack_Flag] 01 msr ,CPSR_c, #I32_bit + SVC2632 ; ints off while flag updated MOV r2, #0 LDR r2, [r2, #CallBack_Vector] TEQ r2, #0 [ No26bitCode msr EQ ,CPSR_c, #SVC2632 ; ensure exit with ints on Pull "r0-r6, r10-r12, PC",EQ | Pull "r0-r6, r10-r12, PC",EQ,^ ] LDMIA r2, {r10, r11, r12} ; link, addr, r12 MOV r0, #HeapReason_Free STR r10, [r0, #CallBack_Vector-HeapReason_Free] ; Keep head valid msr ,CPSR_c, #SVC2632 ; enable ints for long bits [ ChocolateSysHeap ASSERT ChocolateCBBlocks = ChocolateBlockArrays + 0 MOV r1,#ChocolateBlockArrays LDR r1,[r1,#0] BL FreeChocolateBlock LDRVS r1, =SysHeapStart SWIVS XOS_Heap | LDR r1, =SysHeapStart SWI XOS_Heap ] MOV lr, pc MOV pc, r11 ; call im, with given r12 B %BT01 ; loop LTORG ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_WriteC ; In r11 = 0 (look, up there ^) ! SWIWriteC ROUT msr ,CPSR_c, #SVC2632 ; enable interrupts BIC lr, lr, #V_bit ; clear caller's V cos we didn't before Push lr LDR r11, [r11, #VecPtrTab+WrchV*4] ; load top node pointer CMP r11, #ROM [ StrongARM BCC WrchThruVector Push pc, CS ; need to get to ReturnFromVectoredWrch - push PC+12 (old ARM) or PC+8 (StrongARM) BCS PMFWrchDirect MOV R0,R0 ; NOP for PC+8 | Push pc, CS ; push address of ReturnFromVectoredWrch (PC+12) BCS PMFWrchDirect BCC WrchThruVector ] ReturnFromVectoredWrch Pull lr B SLVK_TestV WrchThruVector MOV r10, #WrchV BL CallVector B ReturnFromVectoredWrch ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SWINewLine ROUT MOV r11, lr SWI XOS_WriteI+10 SWIVC XOS_WriteI+13 MOV lr, r11 B SLVK_TestV ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_WriteI+n SWIWriteI ROUT MOV r10, r0 AND r0, r11, #&FF MOV r11, lr ; NB. Order !!! SWI XOS_WriteC MOVVC r0, r10 MOV lr, r11 B SLVK_TestV ; return setting V ; ............................................................................. ; define module SWI node format ModSWINode_CallAddress * 0 ModSWINode_MListNode * 4 ModSWINode_Link * 8 ModSWINode_Number * 12 ModSWINode_Size * 16 ; not a field - the node size! MACRO $l ModSWIHashvalOffset $swino, $startreg [ "$startreg"="" $l MOV $swino, $swino, LSR #4 | $l MOV $swino, $startreg, LSR #4 ] AND $swino, $swino, #(ModuleSHT_Entries-1)*4 MEND MACRO $l ModSWIHashval $swino, $startreg $l ModSWIHashvalOffset $swino, $startreg ADD $swino, $swino, #ModuleSWI_HashTab MEND NotMainMOSSwi ; Continuation of SWI despatch CMP R11, #&200 BCC SWIWriteI ; ............................................................................. ; Look round RMs to see if they want it ExtensionSWI ROUT Push "r9, lr" ; first construct the link to pass on. [ No26bitCode ADR lr, %FT02 | AND r10, lr, #&F0000000 ; copy in user CCodes AND r12, lr, #F32_bit+I32_bit ; (inc. IRQ state) ORR r10, r10, r12, LSL #IF32_26Shift ADR lr, %FT02 + SVC_mode ORR lr, lr, r10 ] BIC r12, r11, #Module_SWIChunkSize-1 ModSWIHashvalOffset r10, r12 LDR r10, [r10, #ModuleSWI_HashTab] loopoverhashchain CMP r10, #0 BEQ VectorUserSWI LDR r9, [r10, #ModSWINode_Number] CMP r9, r12 LDRNE r10, [r10, #ModSWINode_Link] BNE loopoverhashchain LDMIA r10, {r10, r12} LDR r12, [r12, #Module_incarnation_list] ; preferred life CMP r12, #0 [ FixR9CorruptionInExtensionSWI Pull "r9", NE ; restore corrupted r9 before calling SWI handler ;RCM added 'NE' above to fix MED=04655 ] ANDNE r11, r11, #Module_SWIChunkSize-1 ADDNE r12, r12, #Incarnation_Workspace MOVNE pc, r10 VectorUserSWI ; Not in a module, so call vec [ FixR9CorruptionInExtensionSWI Pull "r9" ; restore corrupted r9 before calling UKSWIV ] MOV r10, #UKSWIV ; high SWI number still in R11 B CallVector ; lr still has user CCs (if 26bit) & points at%FT02 02 [ FixR9CorruptionInExtensionSWI Pull "lr" ; r9 already pulled off stack before calling SWI handler or UKSWIV | Pull "r9,lr" ] mrs AL, r10, CPSR BIC lr, lr, #&F0000000 ; Can mangle any/all of punter NZCV flags AND r10, r10, #&F0000000 ORR lr, lr, r10 B SLVK ; ....................... default owner of UKSWIV ............................. ; Call UKSWI handler ; Also used to call the upcall handler ; In r12 = HiServ_ws (or UpCallHan_ws) CallUpcallHandler HighSWI ROUT ; no one on vec wants it: give to handler Pull lr ; the link pointing at %BT02 to pass in. LDMIA r12, {r12, pc} ; ........................ default UKSWI handler .............................. NoSuchSWI ROUT Push lr BL NoHighSWIHandler Pull lr B SLVK_SetV ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; .................... default Unused SWI handler ............................. NoHighSWIHandler ROUT MOV r0, #0 LDR r0, [r0, #IRQsema] CMP r0, #0 ADR r0, ErrorBlock_NoSuchSWI ; Must return static error here [ No26bitCode BEQ %FT01 SETV MOV pc, lr 01 | ORRNES pc, lr, #V_bit ] ; Not in IRQ: can safely build a dynamic error [ International Push "r1-r4, lr" SUB sp, sp,#12 MOV r1, sp MOV r2, #12 MOV r0, r11 SWI XOS_ConvertHex6 ; SWI argument is 00xxxxxx MOV r4, r0 ; now strip leading 0s 02 LDRB r2, [r4], #1 CMP r2, #"0" BEQ %BT02 SUB r4,r4,#1 ADR r0, ErrorBlock_NoSuchSWI1 BL TranslateError_UseR4 ADD sp,sp,#12 Pull "r1-r4, lr" [ No26bitCode SETV MOV pc, lr | ORRS pc, lr, #V_bit ] MakeErrorBlock NoSuchSWI1 | Push "r1-r3, lr" LDR r1, =EnvString LDMIA r0!, {r2, r3} ; number, "SWI " STMIA r1!, {r2, r3} MOV r2, #"&" STRB r2, [r1], #1 MOV r3, r0 MOV r0, r11 MOV r2, #256 SWI XOS_ConvertHex6 ; SWI argument is 00xxxxxx ; now strip leading 0s MOV r1, r0 02 LDRB r2, [r1], #1 CMP r2, #"0" BEQ %BT02 CMP r2, #0 ADDEQ r1, r0, #1 BEQ %FT03 04 STRB r2, [r0], #1 LDRB r2, [r1], #1 CMP r2, #0 BNE %BT04 MOV r1, r0 03 MOV r2, #" " 01 STRB r2, [r1], #1 CMP r2, #0 LDRNEB r2, [r3], #1 BNE %BT01 Pull "r1-r3, lr" LDR r0, =EnvString [ No26bitCode SETV MOV pc, lr | ORRS pc, lr, #V_bit ] ] MakeErrorBlock NoSuchSWI ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Fast SWI handlers for BGet and BPut caches BGetSWI ROUT ; Done separately for highest speed Push lr MOV r10, #BGetV ; Cache hit failed, call victor BL CallVector Pull lr ; Punter lr has VClear BIC lr, lr, #C_bit ; Copy C,V to punter lr ORRCS lr, lr, #C_bit B SLVK_TestV ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BPutSWI ROUT ; Done separately for highest speed Push "lr" MOV r10, #BPutV ; Cache hit failed, call victor BL CallVector Pull "lr" ; Destack lr(VC) B SLVK_TestV ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI handlers for all the vectored SWIs that have vecnum=swinum ; All defined to affect C & V at most FSControlSWI ROUT MOV r11, #FSCV ; Pretend to be vecnum = swinum swi ; and just drop through to ... VecSwiDespatch ROUT Push lr ; this is user's link (or PSR in 32-bit case) MOV r10, r11 ; SWI number from R11->R10 [ No26bitCode mrs AL, r11, CPSR AND r14, r14, #&F0000000 ; extract caller's CCs BIC r11, r11, #&F0000000 ; mask out ours BIC r11, r11, #I32_bit ; enable IRQs ORR r11, r11, r14 ; add in CCs msr ,CPSR_cf, r11 ; and set it all up | ORR r14, lr, #SVC_mode BIC r14, r14, #I_bit ; Enable IRQs TEQP r14, #0 ] BL CallVector ; So the vectored routine can update the pushed link CCodes if wanted ; No update return is therefore LDMIA stack!, {PC}^ (sort of) ; Update return pulls lr, molests it, then MOVS PC, lr ; Note either return enables IRQ, FIQ ; ???? Is the DEFAULT owner allowed to corrupt r10,r11 IFF he claims it ???? Pull lr ; Punter lr has VClear BICCC lr, lr, #C_bit ; Copy C,V to punter lr ORRCS lr, lr, #C_bit B SLVK_TestV NoIrqVecSwiDespatch ROUT Push lr ; this is user's link MOV r10, r11 ; SWI number from R11->R10 [ No26bitCode mrs AL, r11, CPSR AND r14, r14, #&F0000000 ; extract caller's CCs BIC r11, r11, #&F0000000 ; mask out ours ORR r11, r11, #I32_bit ; disable IRQs ORR r11, r11, r14 ; add in CCs msr AL, CPSR_cf, r11 ; and set it all up | ORR r14, lr, #SVC_mode+I_bit ; Disable IRQ TEQP r14, #0 ] BL CallVector Pull lr ; Punter lr has VClear BICCC lr, lr, #C_bit ; Copy C,V to punter lr ORRCS lr, lr, #C_bit B SLVK_TestV ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_GetEnv SWI_GetEnv_Code ROUT LDR r0, =EnvString MOV r1, #0 LDR r1, [r1, #MemLimit] LDR r2, =EnvTime B SLVK ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_Exit SEXIT ROUT BL OscliTidy ; shut redirection, restore FS ; now see if it's an abort Exit LDR r12, ABEX CMP r1, r12 [ No26bitCode TSTEQ r0, #3 | TSTEQ r0, #ARM_CC_Mask ] MOVNE r2, #0 MOV r12, #0 STR r2, [r12, #ReturnCode] LDR r12, [r12, #RCLimit] CMP r2, r12 SWIHI OS_GenerateError ; really generate an error ADD sp, sp, #8 ; junk SWI no and R14 on stack Pull "r10-r12" MOV r0, #0 LDR lr, [r0, #SExitA] STR lr, [r0, #Curr_Active_Object] LDR r12, [r0, #SExitA_ws] LDR sp_svc, =SVCSTK [ No26bitCode mrs AL, r0, CPSR [ :LNOT: NoSPSRcorruption msr ,CPSR_c, #I32_bit+SVC2632 ; IRQs off (to protect SPSR_svc) ] BIC r0, r0, #I32_bit+F32_bit+&0F msr AL, SPSR_cxsf, r0 ; Get ready for USR26/32, IRQs on MOVS pc, lr ; lr->pc, SPSR->CPSR | BICS pc, lr, #ARM_CC_Mask ] ABEX = "ABEX" ; Picked up as word ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_CallBack: Set/read callback buffer and handler SCALLB MOV r10, #CallBackHandler handlecomm Push "r2, r3, lr" MOV r3, r0 ; buffer MOV r0, r10 BL CallCESWI MOV r0, r3 Pull "r2, r3, lr" B SLVK_TestV ; ............................................................................. ; SWI OS_BreakSet: Set/read breakpoint buffer and handler SBRKCT MOV r10, #BreakPointHandler B handlecomm ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_ReadEscapeState ReadEscapeSWI ROUT MOV r10, #0 LDRB r10, [r10, #ESC_Status] TST r10, #1 :SHL: 6 BICEQ lr, lr, #C_bit ORRNE lr, lr, #C_bit B SLVK ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_ServiceCall Issue_Service_SWI ROUT Push lr BL Issue_Service Pull lr B SLVK [ StrongARM ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI XOS_PlatformFeatures PlatFeatSWI ROUT Push lr CMP r0, #0 ;Is it a known reason code? BNE %FT50 ;No, so send out a service call ;Ok, it's the 'code_features' reason code. LDRB r0,[r0, #ProcessorFlags] TST r0, #2 ;Is the 'no irq enable/disable' bit set? ADRNE r1, platfeat_irqinsert ;Yep, so point R1 to the delay routine MOVEQ r1, #0 Pull lr B SLVK ;Return platfeat_irqinsert MOV r0, r0 MOV r0, r0 MOV r0, r0 MOV r0, r0 MOV r0, r0 MOV pc, lr 50 [ {FALSE} Push "r1-r8" MOV r1, #Service_UnknownPlatformFeatures Pull "r2-r9" BL Issue_Service CMP r1, #0 BNE %FT75 Push "r2-r9" Pull "r1-r8" B SLVK ;Return ] 75 ;Get here if the service call isn't claimed. ADR R0,platfeaterror [ International Push "lr" BL TranslateError Pull "lr" ] B SLVK_SetV platfeaterror & 0 [ International = "BadPlatReas", 0 | = "Unknown OS_PlatformFeatures reason code", 0 ] ALIGN ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_GenerateError GenErrorSWI * SLVK_SetV ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ END