48Fermer50
FarewellLe 23/07/2009 à 21:08
Ma version, je poste l'ensemble du handler. Ca compile, mais c'est pas testé, j'attends encore une fois le verdict avant de me casser les dents ...

Description : le but est de retourner une valeur dans d0 ou un pointeur dans a0 sans avoir détruit le moindre registre, ou encore d'appeler un ramcall sans rien avoir détruit non plus.
Pour ce, il faut distinguer deux cas, vu que le ramcall retournera au programme : si le vecteur a été appelé en mode superviseur (à priori ça devrait être rare), il faut mettre l'adresse de retour du handler sur la pile superviseur, sinon, il faut la mettre dans la pile utilisateur qui sera ajustée à cet effet. Encore une fois, tous les avis sont les bienvenus.
(au passage, il est possible de pousser un registre en moins sur la pile, pour deux octets de plus, avec un simple move.l a1,d1). Je le fais au cas où. Je fournirai aussi le patch.
; 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
	cmpi.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'
		subi.w	#$F800,d0	; Clean data
		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
			move.w	d0,(VAR_SYSTEM1).w	; For debug purpose
			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:
	subi.w #$F000,d0				; Clean data
	cmpi.w	#MAX_RAMCALL,d0				; Valid ramcall ?
	bcc.s	\crash					; No, it's a crash
		move.b	RAM_TABLE_TYPE(pc,d0.w),d2	; Read type of ramcall (table of bytes)
		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
		tst.b	d2				; What type of ramcall ?
		bmi.s	\ReturnPtr			; -1 : return a ptr in a0
		beq.s	\ReturnData			; 0  : return data in d0
			btst.b	#5,28(sp)		; Called in supervisor mode ?
			beq.s	\UserMode		; No
				move.w	7*4(sp),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
	
\ReturnPtr:
	move.l	a1,12(sp)				; Modify saved a0
	bra.s	\EndDataPtr				; Useless ?
\ReturnData:
	move.l	a1,(sp)					; Modify saved d0
\EndDataPtr:
	movem.l	(sp)+,d0-d2/a0-a3			; Restore destroyed registers
	addq.l	#2,2(sp)				; Return adress points now after the 'crash'
	rte						; And come back

\crash:	lea	Line1111_str(Pc),a0
	bra	FATAL_ERROR

RAM_TABLE_TYPE:						; -1 : ptr. 0 : data. +1 : routine
	dc.b	-1,0,0,-1,0,0,0,0,0,0,0,0,0,-1,-1,0,-1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,1,0,0,0,0,0,1,1,1,1,-1,-1,-1
	even