60Fermer62
PpHdLe 24/07/2009 à 21:33
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