Est-ce que cette version (légèrement différente en fonctionnalité) t'irait ?
; If $FFF0,
; ~ jsr abs.l (Return address +6 / jsr to a1 ->Crash code+2 a1+(a1)
; Ex: dc.w $FFF0 dc.l JumpAdr-*
; If $FFF2,
; ROM_CALL avec un word.
; Example: dc.w $FFF2, HeapAlloc*4
LINE_1111:
movem.l d0-d2/a0-a3,-(sp) ; Musn't trash any register for ramcalls. a3 won't be trashed, but it reserves space
move.w 4*7(sp),d1 ; Get Old SR
movea.l 4*7+2(sp),a0 ; Get Address of the 'crash'
move.w (a0)+,d0 ; We get the instruction and a0 ->next instruction
subi.w #$F800,d0 ; Is it > $F800 ?
bls.s \ramcall ; No, so it is perhaps a ramcall (FirstWindow is not a romcall)
lea.l 4*7+6(sp),sp ; Pop 7 registers + SR + Address of the 'crash'
movea.l a0,a1 ; Jsr/Jmp with a 32 bits offset
cmpi.w #$FFF0-$F800,d0
bne.s \NoRelJsr
adda.l (a0)+,a1 ; Get the Sub Routine
bra.s \Jump
\NoRelJsr cmpi.w #$FFF1-$F800,d0
bne.s \NoRelJmp
adda.l (a0)+,a1 ; Get the Sub Routine
move.w d1,SR ; Restore SR
jmp (a1) ; Jmp with a 32 bits offset
\NoRelJmp cmpi.w #$FFF2-$F800,d0
bne.s \NoBigRomCall
move.w (a0)+,d0 ; Read Offset
lsr.w #2,d0
\NoBigRomCall movea.l ($C8).w,a1 ; The address of the rom_call table
cmp.w -(a1),d0 ; Compare rom_call and number of entries
bcc.s \crash ; Out of range ? => Crash
lsl.w #2,d0 ; * 4
movea.l 2(a1,d0.w),a1 ; + ($C8) MAX: 8000 rom_calls
\Jump move.w d1,SR ; Restore SR
pea (a0) ; Push return address
jmp (a1) ; Jump to Rom_call function
\ramcall:
addi.w #$F800-$F000,d0 ; Clean data
cmpi.w #MAX_RAMCALL,d0 ; Valid ramcall ?
bcc.s \crash ; No, it's a crash (>=)
lea RAM_TABLE(Pc),a1 ; Ptr to the Ramcall table
lsl.w #2,d0 ; Table of longwords
movea.l 0(a1,d0.w),a1 ; Read ramcall
cmp.l #kernel::BeginSharedLinker,a1 ; Compare the address. Is-it inside the PreOs kernel routine?
bcs.s \NotAFunctionCall
cmp.l #kernel::EndSharedLinker,a1 ; Compare the address. Is-it inside the PreOs kernel routine?
bhi.s \NotAFunctionCall
btst.b #5,d1 ; Called in supervisor mode ?
beq.s \UserMode ; No
move.w d1,6*4(sp) ; Rewrite SR (need another return adress on the stack)
move.l a1,6*4+2(sp) ; Set the ramcall ptr as the return adress of the handler
move.l a0,7*4+2(sp) ; Push the return adress of the ramcall
movem.l (sp)+,d0-d2/a0-a2 ; Restore registers, but not a3 which hasn't ben destroyed
rte ; And quit the handler, calling the ramcall
\UserMode:
move.l USP,a2 ; Read user stack pointer
move.l a0,-(a2) ; And push the return adress of the ramcall
move.l a2,USP ; Save the new stack pointer
move.l a1,4*7+2(sp) ; Set the ramcall ptr as the return adress of the handler
movem.l (sp)+,d0-d2/a0-a3 ; Restore all registers
rte ; Call ramcall
\NotAFunctionCall:
move.l a1,12(sp) ; Modify saved a0
move.l a1,(sp) ; Modify saved d0
movem.l (sp)+,d0-d2/a0-a3 ; Restore destroyed registers
addq.l #2,2(sp) ; Fix adress points after the 'crash'
rte ; And come back
\crash: lea Line1111_str(Pc),a0
bra FATAL_ERROR
Plus de table : on teste si c'est une routine kernel (Moins d'erreur en cas d'ajout de RAMCALL ou d'erreur dans la table).
et on retourne toujours dans d0/a0 la valeur.
Une modif de PreOs est nécessaire:
--- a/src/sld.asm
+++ b/src/sld.asm
@@ -53,6 +53,8 @@ UNRELOC_MODE EQU 1
CALC_FLAG EQU 0
endif
+kernel::BeginSharedLinker:
+
; Standards relocs functions for _nostub programs.
reloc: movem.l d1-d7/a1-a6,-(a7)
lea kernel::relocation(Pc),a4 ; Relocation Mode selected
@@ -1741,3 +1743,5 @@ PatchTitanium:
rts
endif
+kernel::EndSharedLinker:
+
\ No newline at end of file