60

Tous les ramcalls, non, mais au moins la moitié, oui. Si tu pouvais me corriger la table des types, sûrement fausse, ça m'aiderait. Je ne sais même pas à quoi correspondent tous les ramcalls donc j'aurai du mal à le faire...

superviseur -> je fais ça tout de suite, même pas pensé, je m'en servirai jamais ^^



Superviseur, testé sur trois fonctions, la fonction voulue est bien exécutée. Testé suur la moitié en utlisateur. Vérifié tous les registres, c'est bon.
En superviseur et utilisateur, les registres sont bien tous restaurés correctement à chaque fois (données et adresse), j'ai pas testé toutes les valeurs, mais toutes celles que j'ai demandées sont bonnes. J'ai besoin de la table corrigée pour les tester toutes ^^

61

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

62

Ah super, je savais pas comment tu t'y prendrais ^^. Ecoute oui, j'y vois pas d'inconvénient perso. C'est vrai que c'est surtout pour les fonctions qui utilisent des registres qu'il fallait faire gaffe à ne pas les péter, pour les données et les pointeurs on s'en fout, surtout que c'est a0/d0, on y garde jamais rien.

Va pour ça. ^^

(et en effet, j'aurais pu tester le S-flag dans d1 au lieu de 28(sp). et au passage, les btst sur les registres sont toujours en .l, fais gaffe qu'A68k te ponde pas une surprise de son crû ^^)

63

Yep, ./61 est une très bonne idée smile
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

64

pencil Puis ça prend moins de place, je crois que c'est important c'est temps-ci ^^

65

J'ai... euh... un peu optimisé le handler de fline ... fear

Euh... bon voilà :
; 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
	;; Copyright 2009 Martial Demolins
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 
			lsl.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 ( >= ) 
+	bcc.s	\CheckPedroMCall			; 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.l	#5,d1			; Called in supervisor mode ? 
+\FunctionCall:		btst.l	#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,3*4(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 
 
+\CheckPedroMCall:
+	addi.w	#$F100-F000,d0					; PedroM lib calls : $F100 + #func/var
+	cmpi.w	#MAX_PEDROM_CALL,d0				; Out of range ?
+	bcc.s	\crash
+		lea.l	PedroMLibExportTable+2(Pc),a1		; Ptr to the PedroM calls table
+		lsr.w	#2,d0					; Table of longwords
+		movea.l	0(a1,d0.w),a1				; Read PedroM call
+		cmp.l	#pedrom::BeginVariablesTable,a1		; Inside variables table ?
+		bcc.s	\FunctionCall
+		cmp.l	#pedrom::EndVariablesTable,a1
+		bhi.s	\FuntionCall
+		bra.s	\NotAFunctionCall
\crash:	lea	Line1111_str(Pc),a0 
	bra	FATAL_ERROR 


(Au fait, le label s'appelle PedomLibExportTable dans Library.asm ^^)

En fait, pour utiliser les appels de PedroM en flash, je dois faire ça :
PrintAndQuit:
	pea.l	4<<16+0				| Push function + version (pedrom:: printf)
	bsr.s	PushStrPedroM			| Push lib name
	.asciz	"pedrom"			| Lib name
	.even
PushStrPedroM:
	RAMC	RAM_kernel__LibsExec		| kernel::LibsExec(pedrom:: printf)
	lea.l	12(%sp),%sp			| *string + function+version + pedrom str
	rts					| And quit

Avec le patch, plus besoin. C'est peut-être bien d'avoir les appels système dans un vecteurs, non ?

=> Pas compilé ni testé, j'ai ce message quand j'essaye :
c:\Documents and Settings\user\>make
'make' n'est pas reconnu en tant que commande interne ou externe, un programme éxécutable ou un fichier de commande

Et là j'ai rien d'autre sous la main. ^^

66

Folco (./65) :
J'ai... euh... un peu optimisé le handler de fline ... peur.gif


Grrrr..... black

67

Je m'en doutais gros comme ça. grin

En fait, sur beaucoup d'autres plateformes, les appels systèmes sont faits par trap ou autre interruptions. Sur TI, le fait d'être limités en puissance nous a conduits à optimiser les appels système en les relogeant. Parfait, c'était effectivement le moyen le plus efficace, c'est clair. Mais pour exploiter pleinement toutes les features qu'offre PedroM, ce genre de manière de faire (les interruptions) me semble plutôt pas mal. Ok, on est pas habitués à cette manière de faire, et on vient tout juste d'étendre les capacités de ce handler, donc ya le côté "ça fait chier" (ou plutôt "je fais chier" tongue). Mais d'un autre côté, ça permet d'étendre à fond les avantages et capacités de PedroM par rapport à AMS et au nostub. Vous pensez pas ? smile

(ps : je ne vois, après ça, plus de raison de toucher à ce handler)

68

Nan, mais après on va me demander d'appeler directement la librairie bidule, puis machin, puis truc, ....

69

Sauf qu'une lib, à part celle de PedroM qui sert de librairie standard, ne sera pas une lib système. Puis quitte à taper dans le handler, maintenant qu'il est rendu à peu près inutilisable pour les autres applications (par exemple pour ma manière d'appeler une lib dynamique sans relogemnt), autant en profiter ?

70

;===========================================================
;	Get STDERR
;===========================================================
	lea.l	PedromStr(pc),a0		; Get lib name
	moveq.l	#0,d1				; Version
	RAMC	RAM_kernel::LibsBegin		; Get a descriptor
	moveq.l	#PEDROM_stdin,d0		; #Var
	RAMC	RAM_kernel::LibsPtr		; Get its ptr
	movea.l	a0,a1				; Save it
	RAMC	RAM_kernel::LibsEnd		; Close the lib
	addq.l	#8,a1				; pedrom::stderr
	move.l	(a1),STDERR(a6)			; Save it

Simple, isn't it ? tripo
(et encore, là je sais que la lib existe et la variable aussi ^^)