@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