Logicielsmoto.com

Nous sommes le 19 Mar 2024, 03:47

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 5 messages ] 
Auteur Message
MessagePosté: 29 Mai 2022, 06:26 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 432
Localisation: Var
Hello,

En prenant comme base une routine trouvée ici (p168): http://datassette.nyc3.cdn.digitaloceanspaces.com/livros/6809assemblylanguageprogramming.pdf
(Que certains d'entre vous connaissent déjà, j'en suis sûr)

J'ai fait une routine pour multiplier un nombre sur 9bit (signé) avec un nombre 16bit (signé).
Le nombre 9bit représente -1 ($FF00) à 1 ($0100), le résultat est donc un nombre signé sur 16 bits.

A quoi ça sert ? A appliquer un cos/sin dont les valeurs sont encodées dans une plage $FF00 à $0100.

Seule chose manquante : dans le @neg1 après le bsr je devrait faire un neg sur le résultat 24 bits, même si je n'exploite que les 16 bits hauts.
Je ne sais pas faire autre chose que le neg 16 bits ... si qq sait faire sur 24 ?

Code:
; Multiply signed 9 bit (multiplier) by signed 16 bit (multiplicand)
; ------------------------------------------------------------------
; result = (product/256)
;
; input :
; d = signed 9 bit
; x = signed 16 bit
;
; output :
; d = signed 16 bit
;
; (a)    01 }
; (@m)   00 } multiplier (9 bit)
; (@m_h) 20 }
; (@m_l) 00 } multiplicand (16 bit)
;
; Result:
; (a)  20 }
; (b)  00 } 2000 is product/256

        SETDP   direct_page/256

@m      equ direct_page+115
@m_h    equ direct_page+116
@m_l    equ direct_page+117
@r_h    equ direct_page+118
@r_l    equ direct_page+119
@r      equ direct_page+120
;
Mul9x16
        tsta
        beq   @pos  ; $0000 <= d <= $00FF
        bpl   @p256 ; d = $0100
        tstb
        bne   @neg  ; $FF01 >= d >= $FFFF   
@n256   tfr   x,d   ; d = $FF00
        nega
        negb
        sbca  #0    ; *-1
        rts
@p256
        tfr   x,d   ; *1
        rts
@pos               
        stb   @m    ; positive multiplier
        stx   @m_h
        bpl   @mul  ; positive result
@neg2
        ldd   @m_h  ; negative multiplicand
        nega
        negb
        sbca  #0
        std   @m_h
        ldb   @m
@neg1   bsr   @mul
        nega        ; negative result
        negb
        sbca  #0
        rts
@neg   
        negb        ; negative multiplier
        stb   @m
        stx   @m_h
        bpl   @neg1 ; positive multiplicand
        ldd   @m_h  ; negative multiplicand and positive result
        nega
        negb
        sbca  #0
        std   @m_h
        ldb   @m
@mul
        lda   @m_l  ; get lsb's of multiplicand
        mul         ; multiply lsb's
        std   @r_l  ; save partial product
        lda   @m    ; get multiplier
        ldb   @m_h  ; get msb's of multiplicand
        mul         ; multiply msb's
        addb  @r_l  ; add lsb's to msb's of previous partial product
        adca  #0    ; add carry to msb's
        ;std   @r_h  ; save sum of partial products
        rts


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 29 Mai 2022, 10:16 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1800
Localisation: Brest
Le neg sur N bits c'est à la base ==> inverser tous les bits et ajouter 1. Donc un truc comme
Code:
  COMA           ! inversion des bits
  COMB           ! inversion des bits
  COM @r_l+1     ! inversion des bits
  INC @r_l+1     ! ajouter 1
  BNE nocarry
  ADDD #1        ! propagation retenue aux bits supérieurs
nocarry
  suite
A noter: COM suivi d'un INC sur la même adresse c'est juste un NEG. Donc au final on a:
Code:
  COMA
  COMB
  NEG @r_l+1
  BNE nocarry
  ADDD #1
nocarry
  suite
Si on a pas besoin de précision, on peut ignorer le +1 qui fera rarement propager la retenue au delà de quelques bits de poids faibles, et ne garder que l'inversion des bits sur les poids forts. Dans le cas présent cela revient à ne pas faire le NEG et la propag et ne garder que les COMA/COMB. Le résultat sera faux de 1 unité sur D une fois sur 256 (cas où @r_l+1 est à 0). Ca peut-être un résultat largement acceptable quand on cherche la vitesse et pas la précision.

Si on aime pas les sauts, on peut remarquer que si la carry est à 1, on a COMB suivi d'un ADDD #1, c'est à dire (~B+1) = -B, un NEGB. Aussi on pourrait faire un NEGB dès le début, et le transformer en simple COMB quand il y a une carry en la soustrayant après le neg. On peut faire pareil pour A et il vient:
Code:
  NEGA
  NEGB
  NEG @r_l+1
  SBCB #0
  SBCA #0
qui est juste la généralisation 24bits du NEGD. Ici les deux SBC coutent 4 cycles, alors que dans le code au dessus, le BNE (qui est vrai 255 fois sur 256) n'en coute que 3. En moyenne la version avec le saut est plus rapide de 255/256=0.996 cycles.

_________________
Good morning, that's a nice Tnetennba


Dernière édition par Samuel Devulder le 29 Mai 2022, 10:44, édité 1 fois.

Haut
 Profil  
Répondre en citant le message  
MessagePosté: 29 Mai 2022, 10:34 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 432
Localisation: Var
merci sam c'est bcp plus clair maintenant.
Oui effectivement si pas besoin de précision on peut rester sur des com.
je vais quand même garder la version "exacte".

Par contre le test bne va pas fonctionner, le neg ne renvoie 0 que quand l'octet est déjà à 0.
je pense qu'on doit plutot tester si @r est à 1 (avant le neg) et donc va donner $ff + 1 soit 0 (ce qui déclenche le addd #1 sur la partie supérieure) ?


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 29 Mai 2022, 10:51 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1800
Localisation: Brest
Citation:
Par contre le test bne va pas fonctionner
Ben si.
Citation:
le neg ne renvoie 0 que quand l'octet est déjà à 0.
Ben oui. C'est le seul cas où il faut propager la retenue.

Comme je l'ai dit plus haut le +1 sur N bits ne perturbe que quelques bits de poids faibles Pour qu'il aille changer les bits de poids fort, il faut que toute la partie "en dessous" soit à 0. Ici c'est à dire ici que l'octet de poids faible soit nul (avant ou après la négation peu importe). Donc on ne teste pas la carry ici (de toute façon INC ne la positionne pas), mais on teste à 0 le résultats avant (==résultat après) le NEG. Tu vois?

_________________
Good morning, that's a nice Tnetennba


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 29 Mai 2022, 17:11 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 432
Localisation: Var
Oui effectivement je me suis embrouillé ... la solution :

Code:
  COMA
  COMB
  NEG @r_l+1
  BNE nocarry
  ADDD #1
nocarry
  suite


fonctionne a merveille et est bien plus simple que ce que j'avais imaginé ...
Thx !


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 5 messages ] 

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 5 invités


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages
Vous ne pouvez pas joindre des fichiers

Rechercher:
Aller à:  
cron
Développé par phpBB® Forum Software © phpBB Group
Traduction par phpBB-fr.com