home *** CD-ROM | disk | FTP | other *** search
- ; virtual.s
- ; Part of the !Virtual distribution
- ; (c) bdb/nas/fo, 1992-3
-
- ; Assemble with:
- ;aasm s.Virtual Virtual -M -Q
-
- GBLL DEBUG
- DEBUG SETL {FALSE}
- GBLL SWIS
- SWIS SETL {TRUE}
-
- GBLL OLD_VERSION
- OLD_VERSION SETL {FALSE}
-
- R0 RN 0
- R1 RN 1
- R2 RN 2
- R3 RN 3
- R4 RN 4
- R5 RN 5
- R6 RN 6
- R7 RN 7
- R8 RN 8
- R9 RN 9
- SL RN 10
- FP RN 11
- IP RN 12
- SP RN 13
- LR RN 14
- PC RN 15
- a1 RN 0
- a2 RN 1
- a3 RN 2
- a4 RN 3
- v1 RN 4
- v2 RN 5
- v3 RN 6
- v4 RN 7
- v5 RN 8
- v6 RN 9
- fp RN 10
- ip RN 11
- sp RN 12
- lr RN 14
- pc RN 15
-
- N_bit * 1 :SHL: 31
- Z_bit * 1 :SHL: 30
- C_bit * 1 :SHL: 29
- V_bit * 1 :SHL: 28
- I_bit * 1 :SHL: 27
- F_bit * 1 :SHL: 26
-
- USR_mode * 0
- FIQ_mode * 1
- IRQ_mode * 2
- SVC_mode * 3
-
- GET Hdr.Swis
- GET Hdr.Module
-
- SUBT S.Virtual - virtual memory thing.
-
- swibase * &47900 ; Acorn-allocated :-)
-
- MACRO
- CLRV $cc
- CMP$cc pc,#0
- MEND
-
- MACRO
- NOP
- ANDEQ R0,R0,R0
- MEND
-
- ; per task workspace
-
- ^ 0,ip
- regs # 64
- stacktop # 4
-
- AREA |!!!Module$$Header|,CODE,READONLY
-
- base & start-base
- & init-base
- & finish-base
- & service-base
- & title-base
- & help-base
- & cmdtab-base
- [ SWIS
- & swibase
- & swihandler-base
- & switable-base
- & 0
- ]
-
- title = "Virtual",0
- help = "Virtual Memory",9,"0.37 (07 Sep 1993) by BDB/NAS/FO",0
-
- cmdtab = "Virtual",0
- ALIGN
- & Virtual-base
- = 0,0,20,0
- & Virtualsynx-base
- & Virtualhelp-base
- & 0
-
- Virtualhelp = "The *Virtual command allows a task to be run with virtual memory.",13,10
-
- Virtualsynx = "Syntax: *Virtual [<command>] [-wimpslot <n>K] [-discslot <n>M] [-name <taskname>] [-nice <n>] [-ctrl] [-display] [-quit]",13,10
- = " <command> is the command to be executed",13,10
- = " -wimpslot sets the physical memory to be allocated; the virtual memory is set by the -discslot parameter, default 24M",13,10
- = " -nice sets the task priority: 9 low priority, 0 high priority, default 4",13,10
- = " -name sets the task name",13,10
- = " -ctrl allows control characters through",13,10
- = " -display opens the task window immediately, rather than waiting for a character to be printed",13,10
- = " -quit makes the task quit after the command even if the task window has been opened",13,10
- = "Note that fields must be in "" "" if they comprise more than one word", 0
-
- [ SWIS
- ALIGN
- switable = "Virtual",0
- = "TaskInfo",0
- = "Physical",0
- = 0
- ]
-
- ;SL env WriteS
- ;FP instantiation number
- ;IP currently preferred instantiation
- ;SP SVC mode stack
- ;Preserve R7-FP,SP
-
- IMPORT |__RelocCode|
- IMPORT Cinit
-
- init STMDB SP!,{SL,FP,LR}
- BL |__RelocCode|
- MOV a1,IP
- MOV sp,SP
- SUB SP,SP,#1024
- MOV fp,#0
- BL Cinit
- CLRV
- TEQ R0,#0
- TEQNEP PC,#V_bit+SVC_mode
- ADD SP,SP,#1024
- LDMIA SP!,{SL,FP,PC}
-
- ;R1 service number, may zero
- ;IP currently preferred instantiation
- ;SP a stack, SVC or IRQ
- ;Preserve R0,R2-R8 unless returning values
- ;May corrupt IP
-
- service TEQ R1,#&11 ;Service_Memory
- MOVNE PC,LR
- ADR IP,base
- TEQ R2,IP
- MOVEQ R1,#0 ;claim
- MOV PC,LR
-
- ;R0 command tail
- ;R1 command count
- ;IP currently preferred instantiation
- ;SP SVC mode stack
- ;Preserve R7-FP
-
- Virtual STMFD SP!,{LR}
- LDR IP,[IP]
- MOV R2,R0 ;parameters
- MOV R0,#2 ;Enter
- ADR R1,title
- SWI XOS_Module
- LDMFD SP!,{PC}
-
- ;SL fatal flag
- ;FP instantiation number
- ;IP currently preferred instantiation
- ;SP SVC mode stack
- ;Preserve R7-FP,SP
-
- IMPORT Cfinish
-
- finish STMDB SP!,{SL,FP,LR}
- MOV a1,IP
- MOV sp,SP
- SUB SP,SP,#1024
- MOV fp,#0
- BL Cfinish
- CLRV
- TEQ R0,#0
- TEQNEP PC,#V_bit+SVC_mode
- ADD SP,SP,#1024
- LDMIA SP!,{SL,FP,PC}
-
- [ SWIS
- ;(R9 SWI chunk *4)
- ;(SL routine addr)
- ;FP SWI number mod 64
- ;IP private word
- ;SP super stack (R9 LR swi-no SL FP IP)
- ;LR flags of caller with VC
- ;(R9,)SL-IP may be corrupted, return with MOVS
- ;R0-R8 as caller
- ;IRQs (NOT) disabled on entry, may enable them
-
- swihandler LDR IP,[IP]
- STMFD SP!,{R0-R3,LR}
- CMP FP,#(endjumptable-jumptable)/4
- ADDCC PC,PC,FP,LSL#2
- B unknownswierror
- jumptable B TaskInfo
- B DoPhysical
- endjumptable
- unknownswierror LDMFD SP!,{R0-R3,LR}
- ADR R0,unknownswimsg
- ORRS PC,LR,#V_bit
- unknownswimsg & &1E6
- = "Unknown Virtual SWI",0
- ALIGN
-
- ; R0 task id
- ; R1 Virtual address
- ; R2 buffer
- ; R3 len
- ; CDoPhysical passed private workspace as 5th arg
-
- IMPORT CDoPhysical
-
- DoPhysical
- SUB SP,SP,#1024
- STR IP,[SP,#1020] ;caution, IP=sp
- ADD sp,SP,#1020
- MOV fp,#0
- BL CDoPhysical
- ADD SP,SP,#1024
- LDMFD SP!,{R0-R3,PC}^
- ]
-
- ; Virtual_TaskInfo
- ; Obtains information from the Virtual taskwindow module
- ; On entry
- ; R0 = 0 (actually we don't care)
- ; On exit
- ; R0 = 0 if not called from inside a virtual taskwindow, else non-zero
-
- TaskInfo
- MOV R0, #0 ; Always return not from here
- LDMFD SP!,{R0-R3,PC}^
-
-
- ;R0 cmd string
- ;IP currently preferred instantiation
-
- IMPORT |__main|
-
- start
- SWI OS_EnterOS
- STR SP,svcstacktop ;record what a flat svcstack is
- TEQ PC,#0
- NOP
- LDR ip,[IP]
- MOV R6,R0
- SWI OS_GetEnv
- MOV sp,R1 ;stack at top of memory
- MOV R0,#&8000
- LDR R2,=&AAAAAAAA
-
- [ OLD_VERSION
- TEQ R0,sp
- 00 STRNE R2,[R0],#4
- TEQ R0,sp
- BNE %B00
- |
- MOV R3, R2
- MOV R4, R2
- MOV R5, R2
- ; TEQ R0,sp
- 00 STMIA R0!, {R2,R3,R4,R5}
- CMP R0,sp
- BLT %B00
- MOV sp, #&10000 ; stack pointer at 32K to allow
- ; increasing wimpslot!
- ]
-
- MOV a2,R6 ;command tail
- MOV a1,ip ;worksp.
- MOV fp,#0
- BL |__main|
- SWI OS_Exit
-
- ;**************** Start of Virtual mode interface routines *************
-
-
- IMPORT CVSWIV
- EXPORT VSWIV
-
- VSWIV TST lr,#SVC_mode ;was it user mode?
- LDRNE pc,workOldSWIV ;no, goto old routine
-
- STR lr,templr
-
- LDR lr,svcstacktop
- TEQ lr,SP ;flat svcstack?
- LDRNE lr,templr
- LDRNE pc,workOldSWIV ;no, goto old routine
-
- MOV lr,#1
- STR lr,worksemaphore
- TEQP pc,#SVC_mode ;Enable ints
- NOP
- LDR lr,workptr ;point at our workspace
- STMIA lr,{R0-lr}^ ;Save all user regs
- NOP
- MOV ip,lr
- LDR sp,stacktop
- LDR lr,templr
-
- STR lr,regs+15*4
- MOV a1,ip
- BIC a2,lr,#&FC000003
- LDR a2,[a2,#-4]
- MOV fp,#0
- ADR lr,ToCode
- ORR lr,lr,#SVC_mode
- B CVSWIV ;must return w again
-
- EXPORT VPrefetchAbort
-
- VPrefetchAbort
- STR lr,templr
- MOV lr,#1
- STR lr,worksemaphore
- TEQP pc,#SVC_mode ;Enable ints
- NOP
- LDR lr,workptr ;point at our workspace
- STMIA lr,{R0-lr}^ ;Save all user regs
- NOP
- MOV ip,lr
- LDR sp,stacktop
- LDR lr,templr
-
- SUB lr,lr,#4 ;adjust
-
- BIC R3,lr,#&FC000003
- MOV R4,#4
- B VWantAddr
-
- ;This is some static workspace, for when we don't have wksp ptr around.
- ;Used with care, we are still "reentrant" for use by different Wimp tasks.
- ;Set up anew each time we go into virtual mode.
- ;Its placed in the middle of the code that wants to use it to stay in
- ;addressing range.
-
- EXPORT workptr
- EXPORT workOldSWIV
- EXPORT worksemaphore
- EXPORT svcstacktop
-
- workptr & 0 ;Pointer to workspace
- workOldSWIV & 0 ;Place to forward SVC mode swi calls
- worksemaphore & 0
- templr & 0
- svcstacktop & 0
-
- EXPORT VDataAbort
- VDataAbort
- STR lr,templr
- MOV lr,#1
- STR lr,worksemaphore
- TEQP pc,#SVC_mode ;Enable ints
- NOP
- LDR lr,workptr ;point at our workspace
- STMIA lr,{R0-lr}^ ;Save all user regs
- NOP
- MOV ip,lr
- LDR sp,stacktop
- LDR lr,templr
- BIC R0,lr,#&FC000003
- STR R0,regs+15*4 ;For use of pc-relative
-
- SUB lr,lr,#8 ;adjust
-
- BIC R0,lr,#&FC000003
- LDR R1,[R0] ;instruction
- AND R2,R1,#&f0000 ;base register
- LDR R3,[ip,R2,LSR #16-2] ;get its contents
- TST R1,#(1:SHL:26)
- BNE isSTRLDR
- TST R1,#(1:SHL:23) ;direction
- MOVEQ R6,#-4
- MOVNE R6,#4
- MOV R4,#0
- MOV R5,R1,LSL#16
- 02 MOVS R5,R5,LSL#1
- ADDCS R4,R4,R6
- BNE %BT02
- TST R1,#(1:SHL:21) ;writeback ?
- SUBNE R3,R3,R4
- STRNE R3,[ip,R2,LSR #16-2]
- B VWantAddr
-
-
- isSTRLDR TST R1,#(1:SHL:24)
- BEQ %FT01 ;post index
- MOV R4,R1,LSL#32-12 ;12 bits of offset
- MOV R4,R4,LSR#32-12
- TST R1,#(1:SHL:25)
- BEQ %FT02 ;immed offset
- AND R5,R4,#2_1111 ;reg Rm
- LDR R5,[ip,R5,LSL#2]
-
- AND R6,R4,#2_1100000 ; ALU instruction types, no register specific shift amounts
- ; So we have to divide by 2 here to get the 4 instruction
- ; offsets 0x00, 0x10, 0x20, 0x30
- ADD pc,pc,R6, ASR#1
- & 0
- MOV R6,R4,LSR#7 ;immed shift LSL 0x00
- MOV R4,R5,LSL R6
- B %FT02
- & 0
- MOVS R6,R4,LSR#7 ;immed shift LSR 0x10
- ORREQ R6,R6,#32
- MOV R4,R5,LSR R6
- B %FT02
- MOVS R6,R4,LSR#7 ;immed shift ASR 0x20
- ORREQ R6,R6,#32
- MOV R4,R5,ASR R6
- B %FT02
- MOVS R6,R4,LSR#7 ;immed shift ROR 0x30
- BEQ itsRRX
- MOV R4,R5,ROR R6
- B %FT02
-
- itsRRX TEQ pc,lr,LSL#3 ;get aborted C flag
- MOV R4,R5,RRX
- 02 TST R1,#(1:SHL:23)
- SUBEQ R3,R3,R4 ;down
- ADDNE R3,R3,R4 ;up
- 01 MOV R4,#4
-
- ; R3+R4 = access range, ip = worksp.
- ; resume to R0-R15 on stack
-
- IMPORT CVWantAddr
-
- VWantAddr
- STR lr,regs+15*4 ;now save proper pc
- [ DEBUG
- MOV R0,R3
- ADR R1,addr
- MOV R2,#8
- SWI XOS_ConvertHex8
- LDR R0,[ip,#15*4]
- ADR R1,addr2
- MOV R2,#8
- SWI XOS_ConvertHex8
- ADR R0,mesg
- SWI XOS_Write0
- ]
- MOV a1,ip
- MOV a2,R3
- MOV a3,R4
- MOV fp,#0
- ADR lr,ToCode+SVC_mode
- B CVWantAddr ;must return a1 again.
-
- [ DEBUG
- mesg = "Abort for addr &"
- addr = "00000000 at "
- addr2 = "00000000",13,10,0
- ALIGN
- ]
-
- ;Return to user code, with callback semaphore zeroed.
- ;a1 points to workspace
-
- ToCode
- MOV lr,pc
- TST lr,#3
- ADREQ R0,ToCodeErr
- SWIEQ OS_GenerateError
-
- TEQP pc,#SVC_mode+I_bit ;disable ints
- NOP
-
- LDR lr,worksemaphore
- SUBS lr,lr,#1
- BNE VCallBack1
- STR lr,worksemaphore
-
- MOV lr,a1 ;reg block to a SVC reg
- LDMIA lr,{R0-lr}^ ;load user regs
- NOP
- LDR lr,[lr,#15*4] ;user pc
- MOVS pc,lr ;into user mode and go!
-
- ToCodeErr & 0
- = "Life is bad in ToCode",0
- ALIGN
-
- IMPORT CVCallBack
- EXPORT VCallBack
- VCallBack
- MOV a1,IP
- MOV ip,a1
- LDR sp,stacktop
- MOV lr,#1
- VCallBack1
- STR lr,worksemaphore
- TEQP pc,#SVC_mode ;enable ints
- NOP
- MOV fp,#0
- ADR lr,ToCode+SVC_mode
- B CVCallBack ;must return a1 again.
-
- ;Regular Ticker CallEvery Centi-second
-
- EXPORT OurCallEvery
- OurCallEvery LDR IP,worksemaphore
- TEQ IP,#0
- ADDNE IP,IP,#1
- STRNE IP,worksemaphore
- MOVNES pc,lr
- STMFD SP!,{lr}
- MOV IP,pc
- TEQP pc,#I_bit+SVC_mode
- NOP
- STMFD SP!,{lr}
- SWI XOS_SetCallBack
- LDMFD SP!,{lr}
- TEQP IP,#0
- NOP
- LDMFD SP!,{pc}^
-
- ; Convert various sorts of events to C
-
- IMPORT CVUpCall
- EXPORT VUpCall
- VUpCall STMFD SP!,{R1-IP,LR}
- MOV a4,IP
- MOV sp,SP
- SUB SP,SP,#1024
- MOV fp,#0
- BL CVUpCall
- ADD SP,SP,#1024
- LDMFD SP!,{R1-IP,PC}^
-
- EXPORT VError
- VError SWI OS_GenerateError
-
- EXPORT VExit
- VExit SWI OS_Exit ;call in user mode to caught by VSWIV
-
- ; Convert various sorts of events to C
-
- IMPORT CExtUpCall
- EXPORT ExtUpCall
- ExtUpCall STMFD SP!,{R1-IP,LR}
- MOV a4,IP
- MOV sp,SP
- SUB SP,SP,#1024
- MOV fp,#0
- BL CExtUpCall
- ADD SP,SP,#1024
- LDMFD SP!,{R1-IP,PC}^
-
- IMPORT CExtError
- EXPORT ExtError
- ExtError MOV ip,R0
- LDR sp,stacktop
- MOV fp,#0
- BL CExtError
- SWI OS_GenerateError
-
- IMPORT CExtExit
- EXPORT ExtExit
- ExtExit
- MOV a1,IP
- MOV ip,a1
- LDR sp,stacktop
- MOV fp,#0
- BL CExtExit
- SWI OS_Exit
-
- IMPORT CExtWriteC
- K * &80000001
- ;return K to pass vector on with input flag values
- ;return K-1 for VC CC
- ;return K+1 for VC CS
- ;return K-2 for VS CC
-
- EXPORT ExtWriteC
- ExtWriteC
- STMFD SP!,{R0-IP,LR}
- SUB SP,SP,#8
- STMIA SP,{SP,LR}^
- NOP
- MOV a2,IP
- MOV sp,SP
- SUB SP,SP,#1024
- MOV fp,#0
- BL CExtWriteC
- ADD SP,SP,#1024
- LDMIA SP,{SP,LR}^
- NOP
- ADD SP,SP,#8
- CMP R0,#K
- LDMEQFD SP!,{R0-IP,PC}^
- LDMFD SP!,{R0-IP,LR,PC}
-
- ; Convert various sorts of events to C
-
- IMPORT CNormWriteC
- ;return K to pass vector on with input flag values
- ;return K-1 for VC CC
- ;return K+1 for VC CS
- ;return K-2 for VS CC
-
- EXPORT NormWriteC
- NormWriteC
- STMFD SP!,{R0-IP,LR}
- SUB SP,SP,#8
- STMIA SP,{SP,LR}^
- NOP
- MOV a2,IP
- MOV sp,SP
- SUB SP,SP,#1024
- MOV fp,#0
- BL CNormWriteC
- ADD SP,SP,#1024
- LDMIA SP,{SP,LR}^
- NOP
- ADD SP,SP,#8
- CMP R0,#K
- LDMEQFD SP!,{R0-IP,PC}^
- LDMFD SP!,{R0-IP,LR,PC}
-
- IMPORT CNormUpCall
- EXPORT NormUpCall
- NormUpCall STMFD SP!,{R1-IP,LR}
- MOV a4,IP
- MOV sp,SP
- SUB SP,SP,#1024
- MOV fp,#0
- BL CNormUpCall
- ADD SP,SP,#1024
- LDMFD SP!,{R1-IP,PC}^
-
- IMPORT CNormError
- EXPORT NormError
- NormError MOV ip,R0
- LDR sp,stacktop
- MOV fp,#0
- BL CNormError
- SWI OS_GenerateError
-
- IMPORT CNormExit
- EXPORT NormExit
- NormExit
- MOV a1,IP
- MOV ip,a1
- LDR sp,stacktop
- MOV fp,#0
- BL CNormExit
- SWI OS_Exit
-
- ; Mode changing
- ; Now we use R12 as stack, less messy, and idempotent
-
- EXPORT usermode
- usermode MOV a2,lr
- TEQP pc,#USR_mode
- NOP
- MOV pc,a2
-
- EXPORT svcmode
- svcmode MOV a2,lr
- SWI XOS_EnterOS
- MOV pc,a2
-
- EXPORT CallEscapeHandler
- CallEscapeHandler
- MOV ip, sp
- STMFD sp!, {v1, v2, fp, ip, lr, pc}
- SUB fp, ip, #4
- MOV v1, fp ; save fp and SP
- MOV v2, SP
- MOV SP, sp ; pass our stack on
- MOV ip, a3 ; R11 escape condition
- MOV sp, a2 ; R12
- MOV lr, pc
- MOV pc, a1 ; call user escape handler
- MOV a1, sp ; R12 is return call back flag
- MOV SP, v2 ; restore fp and SP
- MOV fp, v1
- LDMEA fp, {v1, v2, fp, sp, pc}^
-
- END
-