@Artur Jarosik, post #1
x86
include win95.i
CONTEXT_ip equ 0
CONTEXT_esp equ 4
CONTEXT_ebp equ 8
CONTEXT_ebx equ 12
CONTEXT_ecx equ 16
CONTEXT_esi equ 20
CONTEXT_edi equ 24
BEGIN_CODE
_start_::
EXTERN _main_context : DWORD
public _context_init_main
_context_init_main proc near
; void context_init_main(CONTEXT *main_context)
mov eax,dword ptr 4[esp] ; eax = save_context
mov dword ptr CONTEXT_esp[eax],esp ; save esp
mov dword ptr CONTEXT_ebp[eax],ebp ; save ebp
mov dword ptr CONTEXT_ebx[eax],ebx ; save ebx
mov dword ptr CONTEXT_ecx[eax],ecx ; save ecx
mov dword ptr CONTEXT_esi[eax],esi ; save esi
mov dword ptr CONTEXT_edi[eax],edi ; save edi
ret
_context_init_main endp
public _context_kill_switch
_context_kill_switch proc near
; void context_kill_switch(Context *restore_context)
; put in new context and jump to new ip
mov eax,4[esp] ; move context to eax
jmp go_context
public _context_switch
_context_switch proc near
; int context_switch(Process *to,Process *from);
; EAX is scratch
; return address is in [ESP]
; args in stack before return address
;
; save current context with the return address as the new ip of the saved
; context, then load a new context and jump to it's new ip.
mov eax,dword ptr 8[esp] ; eax = save_context
pop dword ptr CONTEXT_ip[eax] ; pop return address into ip
mov dword ptr CONTEXT_esp[eax],esp ; save esp
mov dword ptr CONTEXT_ebp[eax],ebp ; save ebp
mov dword ptr CONTEXT_ebx[eax],ebx ; save ebx
mov dword ptr CONTEXT_ecx[eax],ecx ; save ecx
mov dword ptr CONTEXT_esi[eax],esi ; save esi
mov dword ptr CONTEXT_edi[eax],edi ; save edi
mov eax,[esp] ; move goto context to eax
go_context:: ; put in new context and jump to new ip
mov esp, dword ptr CONTEXT_esp[eax] ; now on new stack
mov ebp,dword ptr CONTEXT_ebp[eax] ; restore ebp
mov ebx,dword ptr CONTEXT_ebx[eax] ; restore ebx
mov ecx,dword ptr CONTEXT_ecx[eax] ; restore ecx
mov esi,dword ptr CONTEXT_esi[eax] ; restore esi
mov edi,dword ptr CONTEXT_edi[eax] ; restore edi
jmp dword ptr CONTEXT_ip[eax] ; launch new context
_context_switch endp
_context_kill_switch endp
public _context_jump
_context_jump proc near
; int local_context_jump(Context *to);
;
; jump to a new entry point within the same context setting new
; stack and frame to the input
;
mov eax,dword ptr 4[esp] ; eax = save_context
mov esp, dword ptr CONTEXT_esp[eax] ; now on new stack
mov ebp,dword ptr CONTEXT_ebp[eax] ; restore ebp
jmp dword ptr CONTEXT_ip[eax] ; jump to new entry point
_context_jump endp
end @Artur Jarosik, post #2
; Struktura CONTEXT dla 68k
CONTEXT_ip EQU 0 ; Adres instrukcji (PC)
CONTEXT_a7 EQU 4 ; Stack pointer (A7/SP)
CONTEXT_a6 EQU 8 ; Frame pointer (A6/FP)
CONTEXT_d2 EQU 12 ; Zachowane rejestry
CONTEXT_d3 EQU 16
CONTEXT_d4 EQU 20
CONTEXT_d5 EQU 24
CONTEXT_d6 EQU 28
CONTEXT_d7 EQU 32
CONTEXT_a2 EQU 36
CONTEXT_a3 EQU 40
CONTEXT_a4 EQU 44
SECTION TEXT
; void context_init_main(CONTEXT *main_context)
_context_init_main:
MOVE.L 4(A7),A0 ; A0 = wskaźnik kontekstu (pierwszy parametr)
MOVE.L A7,CONTEXT_a7(A0) ; Zapisz wskaźnik stosu
MOVE.L A6,CONTEXT_a6(A0) ; Zapisz wskaźnik ramki
MOVE.L D2,CONTEXT_d2(A0) ; Zapisz rejestry, które muszą być zachowane
MOVE.L D3,CONTEXT_d3(A0)
MOVE.L D4,CONTEXT_d4(A0)
MOVE.L D5,CONTEXT_d5(A0)
MOVE.L D6,CONTEXT_d6(A0)
MOVE.L D7,CONTEXT_d7(A0)
MOVE.L A2,CONTEXT_a2(A0)
MOVE.L A3,CONTEXT_a3(A0)
MOVE.L A4,CONTEXT_a4(A0)
RTS
; void context_kill_switch(CONTEXT *restore_context)
_context_kill_switch:
MOVE.L 4(A7),A0 ; A0 = wskaźnik kontekstu do przywrócenia
BRA go_context ; Skocz do wspólnego kodu przywracania kontekstu
; int context_switch(CONTEXT *to, CONTEXT *from);
_context_switch:
MOVE.L 8(A7),A0 ; A0 = wskaźnik kontekstu do zapisania (from)
MOVE.L (A7),CONTEXT_ip(A0) ; Zapisz adres powrotu jako nowy IP
ADDQ.L #4,A7 ; Skoryguj stos (pominięcie adresu powrotu)
MOVE.L A7,CONTEXT_a7(A0) ; Zapisz wskaźnik stosu
MOVE.L A6,CONTEXT_a6(A0) ; Zapisz wskaźnik ramki
MOVE.L D2,CONTEXT_d2(A0) ; Zapisz rejestry
MOVE.L D3,CONTEXT_d3(A0)
MOVE.L D4,CONTEXT_d4(A0)
MOVE.L D5,CONTEXT_d5(A0)
MOVE.L D6,CONTEXT_d6(A0)
MOVE.L D7,CONTEXT_d7(A0)
MOVE.L A2,CONTEXT_a2(A0)
MOVE.L A3,CONTEXT_a3(A0)
MOVE.L A4,CONTEXT_a4(A0)
MOVE.L 4(A7),A0 ; A0 = wskaźnik kontekstu do przywrócenia (to)
go_context:
MOVE.L CONTEXT_a7(A0),A7 ; Przywróć wskaźnik stosu
MOVE.L CONTEXT_a6(A0),A6 ; Przywróć wskaźnik ramki
MOVE.L CONTEXT_d2(A0),D2 ; Przywróć rejestry
MOVE.L CONTEXT_d3(A0),D3
MOVE.L CONTEXT_d4(A0),D4
MOVE.L CONTEXT_d5(A0),D5
MOVE.L CONTEXT_d6(A0),D6
MOVE.L CONTEXT_d7(A0),D7
MOVE.L CONTEXT_a2(A0),A2
MOVE.L CONTEXT_a3(A0),A3
MOVE.L CONTEXT_a4(A0),A4
MOVE.L CONTEXT_ip(A0),A1 ; Pobierz adres skoku
JMP (A1) ; Skocz do nowego kontekstu
; int context_jump(CONTEXT *to);
_context_jump:
MOVE.L 4(A7),A0 ; A0 = wskaźnik kontekstu
MOVE.L CONTEXT_a7(A0),A7 ; Przywróć wskaźnik stosu
MOVE.L CONTEXT_a6(A0),A6 ; Przywróć wskaźnik ramki
MOVE.L CONTEXT_ip(A0),A1 ; Pobierz adres skoku
JMP (A1) ; Skocz do nowego punktu wejścia @Artur Jarosik, post #3
; Definicje offsetów dla struktury kontekstu
CONTEXT_pc equ 0 ; licznik programu (PC)
CONTEXT_a7 equ 4 ; wskaźnik stosu (A7)
CONTEXT_a6 equ 8 ; wskaźnik bazowy (A6, odpowiednik EBP)
CONTEXT_d2 equ 12 ; rejestr danych D2 (odpowiednik EBX)
CONTEXT_d3 equ 16 ; rejestr danych D3 (odpowiednik ECX)
CONTEXT_d4 equ 20 ; rejestr danych D4 (odpowiednik ESI)
CONTEXT_d5 equ 24 ; rejestr danych D5 (odpowiednik EDI)
BEGIN_CODE
; void context_init_main(CONTEXT *main_context)
public _context_init_main
_context_init_main:
movem.l d2-d5/a6/a7,-(a7) ; Zapisz rejestry dla bezpieczeństwa
move.l 4(a7),a0 ; Załaduj main_context (parametr na stosie)
move.l a7,(CONTEXT_a7,a0) ; Zapisz aktualny A7 (wskaźnik stosu)
move.l a6,(CONTEXT_a6,a0) ; Zapisz aktualny A6 (wskaźnik bazowy)
move.l d2,(CONTEXT_d2,a0) ; Zapisz D2 (odpowiednik EBX)
move.l d3,(CONTEXT_d3,a0) ; Zapisz D3 (odpowiednik ECX)
move.l d4,(CONTEXT_d4,a0) ; Zapisz D4 (odpowiednik ESI)
move.l d5,(CONTEXT_d5,a0) ; Zapisz D5 (odpowiednik EDI)
movem.l (a7)+,d2-d5/a6/a7 ; Przywróć zapisane rejestry
rts
; void context_kill_switch(Context *restore_context)
public _context_kill_switch
_context_kill_switch:
movem.l d2-d5/a6/a7,-(a7) ; Zapisz rejestry dla bezpieczeństwa
move.l 4(a7),a0 ; Załaduj restore_context
bra go_label ; Przejdź do etykiety przełączania
; int context_switch(Context *to, Context *from)
public _context_switch
_context_switch:
move.l (a7)+,(CONTEXT_pc,a1) ; Zapisz PC (adres powrotu) do from->pc, symulując pop
addq.l #4,a7 ; Dostosuj stos (symulacja pop)
move.l 4(a7),a1 ; Załaduj 'from' (parametr na stosie, po pop)
move.l (a7),a0 ; Załaduj 'to' (parametr na stosie, po pop)
move.l a7,(CONTEXT_a7,a1) ; Zapisz aktualny A7 do from->a7
move.l a6,(CONTEXT_a6,a1) ; Zapisz aktualny A6 do from->a6
move.l d2,(CONTEXT_d2,a1) ; Zapisz D2 do from->d2
move.l d3,(CONTEXT_d3,a1) ; Zapisz D3 do from->d3
move.l d4,(CONTEXT_d4,a1) ; Zapisz D4 do from->d4
move.l d5,(CONTEXT_d5,a1) ; Zapisz D5 do from->d5
bra go_label ; Przejdź do etykiety przełączania
go_label:
move.l (CONTEXT_a7,a0),a7 ; Ustaw nowy wskaźnik stosu z to->a7
move.l (CONTEXT_a6,a0),a6 ; Ustaw nowy wskaźnik bazowy z to->a6
move.l (CONTEXT_d2,a0),d2 ; Ustaw nowy D2 z to->d2
move.l (CONTEXT_d3,a0),d3 ; Ustaw nowy D3 z to->d3
move.l (CONTEXT_d4,a0),d4 ; Ustaw nowy D4 z to->d4
move.l (CONTEXT_d5,a0),d5 ; Ustaw nowy D5 z to->d5
jmp (CONTEXT_pc,a0) ; Skocz do nowego PC z to->pc
; int local_context_jump(Context *to)
public _context_jump
_context_jump:
move.l 4(a7),a0 ; Załaduj 'to' (parametr na stosie)
move.l (CONTEXT_a7,a0),a7 ; Ustaw nowy wskaźnik stosu
move.l (CONTEXT_a6,a0),a6 ; Ustaw nowy wskaźnik bazowy
jmp (CONTEXT_pc,a0) ; Skocz do nowego PC
END_CODE
end @Artur Jarosik, post #4
; Motorola 68k – wersja procedur przełączania kontekstu
; Definicje offsetów w strukturze CONTEXT:
CONTEXT_IP equ 0 ; adres powrotu (instrukcja, do której nastąpi skok)
CONTEXT_SP equ 4 ; wskaźnik stosu (A7)
CONTEXT_FP equ 8 ; wskaźnik ramki (A6)
CONTEXT_D2 equ 12 ; symulacja rejestru ebx -> D2
CONTEXT_D3 equ 16 ; symulacja rejestru ecx -> D3
CONTEXT_D4 equ 20 ; symulacja rejestru esi -> D4
CONTEXT_D5 equ 24 ; symulacja rejestru edi -> D5
;--------------------------------------------------------------------
; void context_init_main(CONTEXT *main_context)
;
; Zapisuje bieżące wartości rejestrów (stos, ramka, D2-D5) do struktury
; głównego kontekstu.
; Argument (wskaźnik do CONTEXT) jest przekazywany na stosie pod offsetem 4.
;--------------------------------------------------------------------
PUBLIC _context_init_main
_context_init_main:
move.l 4(A7), A0 ; A0 = wskaźnik do main_context
move.l A7, CONTEXT_SP(A0) ; zapisuje aktualny A7 (SP)
move.l A6, CONTEXT_FP(A0) ; zapisuje aktualny A6 (FP)
move.l D2, CONTEXT_D2(A0) ; zapisuje D2 (odpowiada ebx)
move.l D3, CONTEXT_D3(A0) ; zapisuje D3 (odpowiada ecx)
move.l D4, CONTEXT_D4(A0) ; zapisuje D4 (odpowiada esi)
move.l D5, CONTEXT_D5(A0) ; zapisuje D5 (odpowiada edi)
rts
;--------------------------------------------------------------------
; void context_kill_switch(Context *restore_context)
;
; Natychmiast przełącza kontekst na wskazany (przekazany jako argument).
;--------------------------------------------------------------------
PUBLIC _context_kill_switch
_context_kill_switch:
move.l 4(A7), A0 ; A0 = wskaźnik do restore_context
bra go_context
;--------------------------------------------------------------------
; int context_switch(Process *to, Process *from)
;
; Procedura zapisuje bieżący kontekst ("from") – w tym adres powrotu,
; stos, ramkę i rejestry (D2-D5) – a następnie przełącza kontekst na "to".
;
; Układ stosu przy wywołaniu:
; 0(A7) : adres powrotu
; 4(A7) : wskaźnik do kontekstu docelowego ("to")
; 8(A7) : wskaźnik do kontekstu bieżącego ("from")
;--------------------------------------------------------------------
PUBLIC _context_switch
_context_switch:
move.l 8(A7), A1 ; A1 = wskaźnik do kontekstu "from"
move.l (A7)+, D0 ; pobiera adres powrotu (popuje ze stosu)
move.l D0, CONTEXT_IP(A1) ; zapisuje adres powrotu w from->ip
move.l A7, CONTEXT_SP(A1) ; zapisuje aktualny SP
move.l A6, CONTEXT_FP(A1) ; zapisuje aktualny FP
move.l D2, CONTEXT_D2(A1) ; zapisuje D2
move.l D3, CONTEXT_D3(A1) ; zapisuje D3
move.l D4, CONTEXT_D4(A1) ; zapisuje D4
move.l D5, CONTEXT_D5(A1) ; zapisuje D5
move.l (A7), A1 ; A1 = wskaźnik do kontekstu "to" (pierwszy argument)
go_context:
move.l CONTEXT_SP(A1), A7 ; przywraca SP (A7)
move.l CONTEXT_FP(A1), A6 ; przywraca FP (A6)
move.l CONTEXT_D2(A1), D2 ; przywraca D2
move.l CONTEXT_D3(A1), D3 ; przywraca D3
move.l CONTEXT_D4(A1), D4 ; przywraca D4
move.l CONTEXT_D5(A1), D5 ; przywraca D5
move.l CONTEXT_IP(A1), A0 ; pobiera zapisany adres powrotu
jmp (A0) ; skok do nowego punktu wykonania
;--------------------------------------------------------------------
; int local_context_jump(Context *to)
;
; Skacze do nowego punktu wejścia w ramach tego samego kontekstu – przywraca
; stos i ramkę zapisane w strukturze kontekstu.
;--------------------------------------------------------------------
PUBLIC _context_jump
_context_jump:
move.l 4(A7), A0 ; A0 = wskaźnik do kontekstu (argument)
move.l CONTEXT_SP(A0), A7 ; przywraca SP ze struktury
move.l CONTEXT_FP(A0), A6 ; przywraca FP ze struktury
move.l CONTEXT_IP(A0), A0 ; pobiera zapisany adres powrotu
jmp (A0) ; skok do zapisanego punktu wejścia
END @Artur Jarosik, post #1
; Motorola 68000 version of CONTEXT.ASM
; Context switching implementation for 68K architecture
; Register offset definitions
CONTEXT_pc EQU 0 ; Program counter
CONTEXT_sp EQU 4 ; Stack pointer (A7)
CONTEXT_fp EQU 8 ; Frame pointer (A6)
CONTEXT_d0 EQU 12 ; Data register D0
CONTEXT_d1 EQU 16 ; Data register D1
CONTEXT_d2 EQU 20 ; Data register D2
CONTEXT_d3 EQU 24 ; Data register D3
CONTEXT_d4 EQU 28 ; Data register D4
CONTEXT_d5 EQU 32 ; Data register D5
CONTEXT_d6 EQU 36 ; Data register D6
CONTEXT_d7 EQU 40 ; Data register D7
CONTEXT_a0 EQU 44 ; Address register A0
CONTEXT_a1 EQU 48 ; Address register A1
CONTEXT_a2 EQU 52 ; Address register A2
CONTEXT_a3 EQU 56 ; Address register A3
CONTEXT_a4 EQU 60 ; Address register A4
CONTEXT_a5 EQU 64 ; Address register A5
CONTEXT_SIZE EQU 68 ; Total context size
SECTION TEXT
; External references
XREF _main_context
; void context_init_main(CONTEXT *main_context)
; Initialize main context by saving current register state
XDEF _context_init_main
_context_init_main:
MOVE.L 4(SP),A0 ; Load context pointer to A0
MOVE.L SP,CONTEXT_sp(A0) ; Save stack pointer
MOVE.L A6,CONTEXT_fp(A0) ; Save frame pointer
MOVE.L D0,CONTEXT_d0(A0) ; Save D0
MOVE.L D1,CONTEXT_d1(A0) ; Save D1
MOVE.L D2,CONTEXT_d2(A0) ; Save D2
MOVE.L D3,CONTEXT_d3(A0) ; Save D3
MOVE.L D4,CONTEXT_d4(A0) ; Save D4
MOVE.L D5,CONTEXT_d5(A0) ; Save D5
MOVE.L D6,CONTEXT_d6(A0) ; Save D6
MOVE.L D7,CONTEXT_d7(A0) ; Save D7
MOVE.L A0,CONTEXT_a0(A0) ; Save A0
MOVE.L A1,CONTEXT_a1(A0) ; Save A1
MOVE.L A2,CONTEXT_a2(A0) ; Save A2
MOVE.L A3,CONTEXT_a3(A0) ; Save A3
MOVE.L A4,CONTEXT_a4(A0) ; Save A4
MOVE.L A5,CONTEXT_a5(A0) ; Save A5
RTS
; void context_kill_switch(Context *restore_context)
; Switch to a new context without saving current one
XDEF _context_kill_switch
_context_kill_switch:
MOVE.L 4(SP),A0 ; Move context ptr to A0
BRA.S go_context ; Jump to context loading code
; int context_switch(Process *to, Process *from)
; Save current context to "from" and switch to "to"
XDEF _context_switch
_context_switch:
MOVE.L 8(SP),A1 ; A1 = save_context
MOVE.L (SP)+,CONTEXT_pc(A1) ; Save return address as PC
MOVE.L SP,CONTEXT_sp(A1) ; Save stack pointer
MOVE.L A6,CONTEXT_fp(A1) ; Save frame pointer
MOVE.L D0,CONTEXT_d0(A1) ; Save D0
MOVE.L D1,CONTEXT_d1(A1) ; Save D1
MOVE.L D2,CONTEXT_d2(A1) ; Save D2
MOVE.L D3,CONTEXT_d3(A1) ; Save D3
MOVE.L D4,CONTEXT_d4(A1) ; Save D4
MOVE.L D5,CONTEXT_d5(A1) ; Save D5
MOVE.L D6,CONTEXT_d6(A1) ; Save D6
MOVE.L D7,CONTEXT_d7(A1) ; Save D7
MOVE.L A0,CONTEXT_a0(A1) ; Save A0
MOVE.L A1,CONTEXT_a1(A1) ; Save A1
MOVE.L A2,CONTEXT_a2(A1) ; Save A2
MOVE.L A3,CONTEXT_a3(A1) ; Save A3
MOVE.L A4,CONTEXT_a4(A1) ; Save A4
MOVE.L A5,CONTEXT_a5(A1) ; Save A5
MOVE.L 4(SP),A0 ; A0 = to_context
; Common code to load context from A0
go_context:
MOVE.L CONTEXT_sp(A0),SP ; Restore stack pointer
MOVE.L CONTEXT_fp(A0),A6 ; Restore frame pointer
MOVE.L CONTEXT_d0(A0),D0 ; Restore D0
MOVE.L CONTEXT_d1(A0),D1 ; Restore D1
MOVE.L CONTEXT_d2(A0),D2 ; Restore D2
MOVE.L CONTEXT_d3(A0),D3 ; Restore D3
MOVE.L CONTEXT_d4(A0),D4 ; Restore D4
MOVE.L CONTEXT_d5(A0),D5 ; Restore D5
MOVE.L CONTEXT_d6(A0),D6 ; Restore D6
MOVE.L CONTEXT_d7(A0),D7 ; Restore D7
MOVE.L CONTEXT_a0(A0),A0 ; Restore A0 - must be last!
MOVE.L CONTEXT_a1(A0),A1 ; Restore A1
MOVE.L CONTEXT_a2(A0),A2 ; Restore A2
MOVE.L CONTEXT_a3(A0),A3 ; Restore A3
MOVE.L CONTEXT_a4(A0),A4 ; Restore A4
MOVE.L CONTEXT_a5(A0),A5 ; Restore A5
MOVE.L CONTEXT_pc(A0),-(SP) ; Push return address
RTS ; Jump to new context
; int context_jump(Context *to)
; Jump to a new entry point within the same context
XDEF _context_jump
_context_jump:
MOVE.L 4(SP),A0 ; A0 = to_context
MOVE.L CONTEXT_sp(A0),SP ; Restore stack pointer
MOVE.L CONTEXT_fp(A0),A6 ; Restore frame pointer
MOVE.L CONTEXT_pc(A0),-(SP) ; Push return address
RTS ; Jump to new entry point
END @Artur Jarosik, post #7
; Motorola 68040 version of CONTEXT.ASM
; Context switching implementation for 68040 architecture
; Uses 68040-specific instructions where appropriate
; Register offset definitions
CONTEXT_pc EQU 0 ; Program counter
CONTEXT_sp EQU 4 ; Stack pointer (A7)
CONTEXT_fp EQU 8 ; Frame pointer (A6)
CONTEXT_d0 EQU 12 ; Data register D0
CONTEXT_d1 EQU 16 ; Data register D1
CONTEXT_d2 EQU 20 ; Data register D2
CONTEXT_d3 EQU 24 ; Data register D3
CONTEXT_d4 EQU 28 ; Data register D4
CONTEXT_d5 EQU 32 ; Data register D5
CONTEXT_d6 EQU 36 ; Data register D6
CONTEXT_d7 EQU 40 ; Data register D7
CONTEXT_a0 EQU 44 ; Address register A0
CONTEXT_a1 EQU 48 ; Address register A1
CONTEXT_a2 EQU 52 ; Address register A2
CONTEXT_a3 EQU 56 ; Address register A3
CONTEXT_a4 EQU 60 ; Address register A4
CONTEXT_a5 EQU 64 ; Address register A5
; 68040 FPU registers
CONTEXT_fp0 EQU 68 ; FP register FP0 (12 bytes)
CONTEXT_fp1 EQU 80 ; FP register FP1 (12 bytes)
CONTEXT_fp2 EQU 92 ; FP register FP2 (12 bytes)
CONTEXT_fp3 EQU 104 ; FP register FP3 (12 bytes)
CONTEXT_fp4 EQU 116 ; FP register FP4 (12 bytes)
CONTEXT_fp5 EQU 128 ; FP register FP5 (12 bytes)
CONTEXT_fp6 EQU 140 ; FP register FP6 (12 bytes)
CONTEXT_fp7 EQU 152 ; FP register FP7 (12 bytes)
CONTEXT_fpsr EQU 164 ; FPU status register
CONTEXT_fpcr EQU 168 ; FPU control register
; 68040 MMU registers
CONTEXT_tc EQU 172 ; Translation Control Register
CONTEXT_srp EQU 176 ; Supervisor Root Pointer
CONTEXT_urp EQU 180 ; User Root Pointer
CONTEXT_dtt0 EQU 184 ; Data Transparent Translation 0
CONTEXT_dtt1 EQU 188 ; Data Transparent Translation 1
CONTEXT_itt0 EQU 192 ; Instruction Transparent Translation 0
CONTEXT_itt1 EQU 196 ; Instruction Transparent Translation 1
CONTEXT_SIZE EQU 200 ; Total context size
SECTION TEXT
; External references
XREF _main_context
; void context_init_main(CONTEXT *main_context)
; Initialize main context by saving current register state
XDEF _context_init_main
_context_init_main:
MOVEA.L 4(SP),A0 ; Load context pointer to A0
; Save integer registers
MOVE.L SP,CONTEXT_sp(A0) ; Save stack pointer
MOVE.L A6,CONTEXT_fp(A0) ; Save frame pointer
MOVEM.L D0-D7/A0-A5,(CONTEXT_d0,A0) ; Save all data and address registers in one instruction
; Save FPU registers (using 68040 FMOVEM instruction)
FMOVEM.X FP0-FP7,(CONTEXT_fp0,A0) ; Save all FP registers
FMOVE.L FPSR,CONTEXT_fpsr(A0) ; Save FP status register
FMOVE.L FPCR,CONTEXT_fpcr(A0) ; Save FP control register
; Save MMU registers (privileged, would need to be in supervisor mode)
; These would normally be saved only when in supervisor mode
; and using MOVEC instructions for each register
; MOVEC TC,D0
; MOVE.L D0,CONTEXT_tc(A0)
; MOVEC SRP,D0
; MOVE.L D0,CONTEXT_srp(A0)
; etc.
RTS
; void context_kill_switch(Context *restore_context)
; Switch to a new context without saving current one
XDEF _context_kill_switch
_context_kill_switch:
MOVEA.L 4(SP),A0 ; Move context ptr to A0
BRA go_context ; Jump to context loading code
; int context_switch(Process *to, Process *from)
; Save current context to "from" and switch to "to"
XDEF _context_switch
_context_switch:
MOVE.L 8(SP),A1 ; A1 = save_context
MOVE.L (SP)+,CONTEXT_pc(A1) ; Save return address as PC
MOVE.L SP,CONTEXT_sp(A1) ; Save stack pointer
MOVE.L A6,CONTEXT_fp(A1) ; Save frame pointer
; Save all registers in one instruction (68040 optimization)
MOVEM.L D0-D7/A0-A5,(CONTEXT_d0,A1) ; Save all data and address registers
; Save FPU registers (using 68040 FMOVEM instruction)
FMOVEM.X FP0-FP7,(CONTEXT_fp0,A1) ; Save all FP registers
FMOVE.L FPSR,CONTEXT_fpsr(A1) ; Save FP status register
FMOVE.L FPCR,CONTEXT_fpcr(A1) ; Save FP control register
; Save MMU registers if in supervisor mode (privileged)
; These would use MOVEC instructions for each register
MOVEA.L 4(SP),A0 ; A0 = to_context
; Common code to load context from A0
go_context:
; 68040 cache instruction to flush caches before context switch
CPUSHA BC ; Push and invalidate both caches
; Restore MMU registers if in supervisor mode (privileged)
; These would use MOVEC instructions for each register
; Restore FPU registers (using 68040 FMOVEM instruction)
FMOVEM.X (CONTEXT_fp0,A0),FP0-FP7 ; Restore all FP registers
FMOVE.L CONTEXT_fpsr(A0),FPSR ; Restore FP status register
FMOVE.L CONTEXT_fpcr(A0),FPCR ; Restore FP control register
; Restore integer registers
MOVE.L CONTEXT_fp(A0),A6 ; Restore frame pointer
; We need to save A0 temporarily because MOVEM will overwrite it
LEA CONTEXT_d0(A0),A1 ; Get address of register save area
MOVEA.L A0,A2 ; Save A0 temporarily
MOVEA.L CONTEXT_sp(A0),SP ; Restore stack pointer
MOVEM.L (A1),D0-D7/A0-A5 ; Restore all data and address registers
; Jump to the stored PC
MOVE.L CONTEXT_pc(A2),-(SP) ; Push saved PC as return address
RTS ; Jump to new context
; int context_jump(Context *to)
; Jump to a new entry point within the same context
XDEF _context_jump
_context_jump:
MOVEA.L 4(SP),A0 ; A0 = to_context
MOVEA.L CONTEXT_sp(A0),SP ; Restore stack pointer
MOVEA.L CONTEXT_fp(A0),A6 ; Restore frame pointer
MOVE.L CONTEXT_pc(A0),-(SP) ; Push return address
RTS ; Jump to new entry point
END @Artur Jarosik, post #1
dc.w $0001, $0002
Start1 dc.l "FORM" End1 dc.w End1-Start1
;CNOP 0, 4 WOLF20_IMG: DB 0BDH, 007H, 000H, 043H, 078H, 005H, 000H, 084H, 041H, 05EH, 001H, 0A0H, 021H, 014H, 041H, 000H DB 08CH, 040H, 0C4H, 015H, 0E0H, 018H, 002H, 0C1H, 084H, 008H, 041H, 080H, 018H, 040H, 081H, 008H ....
dc.b $BD,$07,$43,$78......
dc.b $DB,$70,$34,$87......
@bfgmatik, post #10
@Don_Adan, post #9
MOV ah,0a0h ; asm x86
move.b #$a0,d0 ; asm 68k
@Artur Jarosik, post #5
@Don_Adan, post #9
cnop 0,4. ; uzywa sie jesli nastepne dane musza zaczynac sie od adresu podzielnego przez 4. WOLF20_IMG dc.b $BD,$07,$00,$43,$78......
cnop 0,4 WOLF20_IMG incbin ram:WOLF20_IMG
@Don_Adan, post #14
@tukinem, post #16
@Jacques, post #19
@Jacques, post #23
@Artur Jarosik, post #2
_context_init_main:
dc.w $4afc ; illegal
rts
_context_kill_switch:
dc.w $4afc ; illegal
rts
_context_switch:
dc.w $4afc ; illegal
rts
_go_context
dc.w $4afc ; illegal
rts
_context_jump:
dc.w $4afc ; illegal
rts