Sinon dans le code d'origine
Code:
; set x
orcc #1 ; set carry (x < 0)
tst x_h ; test sign of x using the 16 bit input value
bmi > ; branch if (x > 0)
andcc #$FE ; clear carry
bra @a
! nega
@a rol octant ; set octant b2 if x is negative
Si je comprends bien: si x(16bits)<0 on ajoute 1 dans octant et on fait un neg de la partie basse. Sinon (x>=0) on injecte un 0 dans octant et on ne touche pas la partie basse. C'est ca ?
Or le NEGA m'interroge. Il touche à la carry. Or si lors du "BMI >" on a bel et bien la carry à 1 à cause du ORCC juste avant, le NEGA peut la nettoyer, et le ROL injectera 0 et pas 1 comme attendu. C'est peut-être l'une des cause des erreurs de calcul. Il vaudrait mieux déplacer le ORCC juste après le NEGA en fait. Comme ca la carry serra bien positionnée avant le ROL. En plus ca fait gagner quelques cycles (on ne set pas la carry à 1 pour la passer à 0 juste après). On remarque aussi que la CARRY est exactement le bit de poids fort de x_h. On peut l'extraire en ajoutant 128 à x_h, ou encore avec une rotation.
Fort de cette précédente remarque, je pense que cette partie peut être optimisée sans aucun saut.
On remarque que x_h n'a en réalité que 2 valeurs possible après l'étape du "@shift": $00 ou $FF. On peut alors faire ceci:
Code:
LDA x_h ; A=$FF ou $00
ASRA ; CC=1 si x_h<0, 0 sinon. Dans tous les cas A est inchangé.
ROL octant
EORA x_l
Le EORA fait presque NEG. En fait il manque +1, mais on on s'en fiche, le code 6502 fait la même approximation. Le résultat sera juste un poil moins précis.