samedi 26 mai 2012

Code optimisation (III)

Voici une autre vieille routine que j'ai retrouvée suite au précédent article concernant le code 'déroulé', appelé aussi par les anglophones 'unrolled'.

Cette technique était utilisée sur des CPUs sans code cache L1 ou L2 (68000 et 68010), qui rappelons-le est une mémoire rapide au sein même du processeur qui conserve le code afin de minimiser les échanges beaucoup plus lents entre le 68k et la fastram.

La routine ici a été codé par les ingénieurs de Commodore dans les années 1983/84/85 (Kickstart 1.2), donc pour le 68000. Ce sont les vecteurs d'interruptions, les autovec de l'exec.library. Ils n'ont par la suite pas été retravaillé dans le Kickstart 3.1 et même dans le 3.9 :

Or, à partir du 68020, Motorola ajoute à ces nouveaux CPUs ce fameux code cache, mais hélas sans son compagnon le branch cache. Ce dernier n'arrive en effet que sur le 68060. Le branch cache est une nouvelle astuce qui permet d'éviter des cycles de branchements, indispensable pour maximiser encore l'efficience les boucles (loops) présentes dans le code cache. Peu importe de toutes façons, il n'y a aujourd'hui plus aucun intérêt à optimiser pour tout ce qui est en dessous du 68060.

Pour donc utiliser au mieux toutes les spécificités du 68060, il n'y a pas d'autres solutions que de tout reprogrammer, avec bien en tête l'architecture du 060.

Les six routines autovec font au total 544 octets. Il faut bien se souvenir que :
  1. Les accès fastram sont lents sur nos Amiga Classic, c'est à dire que le temps de transfère du code contenu de la mémoire pour traitement dans le CPU est élevé,
  2. Lorsque le CPU demande du contenu fastram, il attends de la recevoir de la mémoire.

Bref, pour ce genre de routine, plus le code est court et plus rapide c'est pour un CPU comme le 68060.

Avec donc une autre technique de programmation utilisant le moins possible le code avec des boucles, le résultat final ne nous donne plus que 134 octets !

Pour chaque autovec, un longword informatif est envoyé dans d1, contenant :
  1. Le nombre de décalage de bits (.b),
  2. Le décalage initial (.b),
  3. L'offset ($54 pour IntVec0) (.w).

Le registre d1 est ensuite utilisé par la boucle pour tester les bits relatifs aux six autovec :

Voilà donc 134 octets 68060 qui donnent un résultat identique aux 544 initiaux 68000 : c'est quatre fois moins. Notez qu'ici, ce nouveau code est totalement compatible avec le 68000, mais peut-être légèrement plus lent pour lui.

Une cerise est encore belle et bien présente ici : le gain de place dans le Kickstart, 410 octets de sauvés pour cet exemple. Commodore avait bourré au maximum toutes ses roms, et il n'y avait plus de disponibilité pour des commandes très utiles comme par exemple la 'dir'... En économisant donc le plus d'octets possibles, il sera tout à fait possible de rajouter ces routines quasi-indispensables pour les utilisateurs ! Qui n'a pas pesté ici au moins mille fois pour un 'dir' à charger d'abord par une disquette ou sur disque dur pour obtenir un directory ?

Pour finir, sachez que tous les CPUs ont des points forts et des points faibles. Ici pour ce qui concerne le 060, sa plus grande faiblesse est qu'il nécessite du code bien réfléchi et bien ordonné pour donner le meilleur de lui-même !

Monsieur le 68060 se régale avec du code bien optimisé pour sa personne !!
  

6 commentaires:

  1. Super intéressant, j'essaye de me mettre aussi à l'assembleur 68000. Je me suis trouvé "Le livre du langage machine". tip top :)

    Tu utilise quoi comme assembleur ? Asm-Pro semble pas mal...

    RépondreSupprimer
  2. ... Personnellement je m'étais plus spécialisé dans les optimisations 68020/68030 dans les années 90, ...

    ... savoir optimiser pour les différents modèles de 68k et particulièrement le 68060 est un gros boulot et une connaissance aigüe du fonctionnement du pipeline et de la liste des instructions et des cas particulier émulés sont nécessaires (pour certaines mode d'adressage on peut utiliser certains registres et pas d'autres en 68040/68060, ce qui est très peu connu ( ce sera fonctionnels mais émulé )

    un bon forum encore actif ou des idées d'optimisation énorme en 680x0 surgissent régulièrement:

    http://ada.untergrund.net/forum/index.php?action=vtopic&forum=4

    ... sur 68060 les démomakers déroulent parfois les boucles, moins pour optimiser le test retour que pour "scrambler" les instructions de façon a paralléliser les calculs.

    ce qui peut donner ce genre de fil sur le forum:
    http://ada.untergrund.net/forum/index.php?action=vthread&forum=4&topic=190&page=0

    ... bon je retourne faire des movem.w pour optimiser des ext en 68000 moi...

    RépondreSupprimer
  3. Sur ce coup là, je n'y comprends rien, et génralement quand je n'y comprends rien et que je vois que vous vous comprenez, je suis impressionné.
    Dire que j'ai fait de l'assembleur 68705 et PIC pendant plusieurs années au boulot et que j'ai tout oublié, il faut croire que ça ne m'intéressait vraiment pas...
    Chapeau bas quand même car optimiser 20 ans après du code, c'est beau.

    RépondreSupprimer
  4. C'est assez simple en fait : je pensais pareil que toi au début quand je débutais, je n'y pigeais rien. Et puis, il faut déjà commencer par comprendre la 'logique' du CPU, comment il fonctionne, et après apprendre ses mnémoniques et ça va tout seul ensuite...

    RépondreSupprimer
  5. Il y a aussi des idées reçues non-positives comme quoi l'assembleur c'est dur et compliqué. En réalité, de mon mon point de vue, l'asm (et surtout l'asm 68k) est bien plus simple que le C/C++ par exemple...

    RépondreSupprimer

Posté vos remarques :