Seulement, si le support de l'architecture SuperH est relativment "natif" pour GCC, le support des librairies et des parties spécifique aux calculatrices Casio l'est beaucoup moins. Ainsi, si il est possible de récupérer les fonctions correspondants à "fxlib.h" dans un format utilisable par GCC, la librairie C standard fournie par casio dans le SDK ne semble pas aussi simple à récupérer (voire irrécupérable
? ).
Le plus simple est je pense de "réecrire" une bibliothèque standard C.
A mon avis, il pourrait aussi être intéressant d'essayer de s'affranchir de la bibliothèque "fxlib" fournie par Casio, toujours en la réecrivant (c'est à dire simplement refaire les appels de Syscalls pour la plupart des fonctions, "fxlib" étant majoritairement basée sur les Syscalls), mais en travaillant sur certains points et avoir d'emblée une compatibilité SH4 par exemple. On "enlèverait" aussi la plupart du code propriétaire de Casio (bien qu'il reste les syscalls, mais bon...
).
Ce qui concerne "fxlib" n'est que mon point de vue étant donné qu'on peut très bien conserver le fichier de Casio, j'amorce juste une réflexion à ce niveau là ;).
Quoi qu'il en soit, ce topic est là pour permettre de réfléchir sur le projet ,c'est à dire la réimplémentation d'une bibliothèque C à peu près standard (en s'appuyant sur les syscalls déjà existants, va faloir sortir la doc
) pour fonctionner sur GCC de manière correcte, voire plus intéressante que sur le SDK de Casio (pourquoi pas implémenter des fopen(...) par exemple, là encore, simple suggestion à cogiter
).
C'est aussi pour voir si il y a des gens qui seraient intéressés pour travailler là dessus, et voir vos idées sur la manière de travailler dessus.
Je pense qu'à la longue, un dépot git (ou autre) sur gitorious ou quelque chose du même style pourrait servir, qu'en dites vous ? Enfin, le projet semble intéressant, d'autant plus qu'un GCC bien fonctionnel pour compiler des add-ins, ça serait cool ! :D.
Donc n'hésitez pas à mettre vos idées pour commencer et avancer !
Citer : Posté le 18/06/2014 17:15 | #
C'est ça. Je te laisse constater les 0x200 premiers octets d'un add-in de gcc.
Ajouté le 18/06/2014 à 17:16 :
Non, il n'y a pas un checksum ?
Ajouté le 18/06/2014 à 17:19 :
Putain, j'ai eu une "Copy protection ERROR".
Ajouté le 18/06/2014 à 17:22 :
Sinon, "Data ERROR" si je copie entièrement le header depuis un add-in du SDK, donc je me demande s'il n'y a pas un checksum...
Citer : Posté le 18/06/2014 20:35 | #
... Bon, si je sors la bible sur les FXes
Offset b Size b Description
0 8 File identifier: “USBPower”
8 1 File type identifier
9 5 {0x00, 0x10, 0x00, 0x10, 0x00}
0xE 1 Control byte: (LSB of filesize (at offset 0x13)) + 0x41
0xF 1 0x01
0x10 4 Total file size as unsigned integer, big endian format
0x14 1 Control byte: (LSB of filesize (at offset 0x13)) + 0xB8
0x15 9 Unknown purpose (maybe 4-alignment), appears insignificant
0x1E 2 Number of objects contained, if file is of type G1M or G1R
0x20 ... Subheader depending on particular file type
Citer : Posté le 18/06/2014 20:38 | #
Déjà fait.
Ajouté le 04/07/2014 à 08:40 :
Bon, j'ai étudié le système de linkage de gcc.
→ Lorsqu'on n'inclus pas la lib ou qu'on ne l'utilise pas, elle n'est pas présente dans l'exécutable, et la taille de ce dernier est minimale.
→ Néanmoins, qu'on utilise une, deux ou toutes les fonctions de la lib, la taille de l'exécutable est identique. J'en déduis comme je l'avais pensé que tout la lib (.a) est incluse.
Maintenant pour en revenir à ce qu'on avait fait, on avait proposé une lib réduite et une complète. Puisque la lib réduite est prévue pour être entièrement intégrée, on pourra simplement la pré-archiver (.a), mais pour la lib complète ? Si on ne veut que compiler les fonctions utiles, on ne peut pas l'archiver.
Donc soi on en fait un snippet -- ce qui serait vraiment moche --, soit on accepte qu'on l'inclus en entier. Je pense que la seconde solution est la meilleure, mais qu'en pensez-vous ?
Citer : Posté le 04/07/2014 19:08 | #
Non non, je me répète mais crois moi, une lib statique est liée au niveau des fichiers objets, et seul ceux qui possèdent au moins un symbole en bind "GLOBAL", qui correspond au nom d'un symbol précédemment rencontré marqué comme "UNDEFINED" sont utilisés.
Si tu n'observe aucune différence alors que tu teste l'utilisation de différentes fonctions (qui DOIVENT être implémentées dans différents fichiers .c indépendants!), la seule hypothèse que je vois c'est que pour une raison ou pour une autre des symboles des autres fichiers objets sont utilisés (par ce qu'ils utilisent une variable globale définie aileurs, une fonction d'un autre module... une simple référence à un objet/fonction externe, genre utilisation d'un pointeur vers ce symbole, provoque l'émission d'un symbole non défini!).
(je ne te demande pas de me croire sur parole, mais refait des tests, et si tu as toujours le même résultat, envoie moi par MP ce que contient ton test, je te dirais ce qui ne va pas)
Citer : Posté le 04/07/2014 19:10 | #
Mais je sais bien, je faisais des expérimentations avec un seul fichier.
C'était pour justifier qu'on ait un fichier source et donc un fichier objet par fonction.
Ajouté le 06/07/2014 à 09:07 :
Bon, je voulais me remettre à un projet en le passant sous gcc, mais je souffre horriblement du manque de sprintf() et autres fonctions de stdio...
Je signale donc que je m'occupe de sprintf().
Ajouté le 06/07/2014 à 09:12 :
Évidemment, j'avais oublié les listes d'arguments variables... on risque de devoir les implémenter aussi.
Citer : Posté le 06/07/2014 11:33 | #
Implémenter la gestion des arguments variables ? GCC n'est pas capable de gérer ça de lui même, je veux dire dire, c'est dépendant de l'architecture ?
Citer : Posté le 06/07/2014 17:01 | #
Implémenter la gestion des arguments variables ? GCC n'est pas capable de gérer ça de lui même, je veux dire dire, c'est dépendant de l'architecture ?
Si, en effet, c'est heutement dépendant de l'architecture, et c'est GCC qui l'implémente en tant que builtins (même pas des fonctions de la libgcc, sur SH3 et -presque?- toutes les architectures c'est du code "inliné" qui est généré).
Le seul problème est que les définitions sont dans stdarg.h (encore une fois, include de GCC, pas de la libc), donc non accessible si vous utilisez -nostdinc pour compiler.
Vous pouvez zieuter ce fichier dans votre install de GCC, c'est vraiment du pure ifdef/define/typedef, rien de bien méchant à redéfinir soit-même (en gros, le type va_list est un typedef sur __builtin_va_list, va_start()/va_end()/va_arg() sont des defines transformés respectivement en __builtin_va_start()/__builtin_va_end()/__builtin_va_arg()...).
Tous les __builtin_* sont connus de GCC, pas besoin de header ou d'implémentation. En utilisant explicitement ces types et fonctions builtin, le seul problème est de perdre la portabilité vers les autres compilos, mais je crois pas que ce soit un gros problème dans votre projet.
Après, vous pourriez vous amusez à réimplémenter tout ça vous même, vous allez me dire, mais n'oubliez pas que "..." et le passage des arguments n'est pas modifiable, donc c'est "codé en dur" dans GCC, et le seul moyen d'être sûr de faire exactement comme lui, quelque soit la version ou les options de compilation, c'est de passer par les builtin qu'il fourni.
Bon, je voulais me remettre à un projet en le passant sous gcc, mais je souffre horriblement du manque de sprintf() et autres fonctions de stdio...
Je signale donc que je m'occupe de sprintf().
A toi de voir à quel point tu veux suivre le standard, mais si tu veux tout suivre à la lettre (tous les modifieurs et types d'arguments possibles), l'implémentation est vraiment lourde (autour de 20 Kio pour l'implémentation de Newlib une fois compilé), et tu es quasiment obligé de jouer avec du malloc pour formater tes chaînes.
Plein de choses sont horriblement lourdes à implémenter, et ne sont pas indispensables pour 99.9% des situations
Citer : Posté le 06/07/2014 20:26 | #
Ouf, je suis content que tout stdarg soit du builtin, car sinon on aurait eu des problèmes. Je m'y penche ce soir ou demain.
sprintf()... c'est bien la fonction de la libc dont on ne peut pas se passer ! Je pense que sans tout à fait suivre le standard, on devrait implémenter atoi(), atof() et atol(), puis y ajouter itoa(), ftoa() et ltoa(). sprintf() pourra s'appuyer dessus.
Une fonction que je ne pense pas implémenter, c'est sscanf(), pour la simple et bonne raison que je n'ai jamais compris si on pouvait fixer le nombre de caractères lus en modifiant le format ou si on ne faisait que mettre un minimum...
Après, avec string, stdlib et stdio (qui devra aussi gérer la mémoire, dont on souhaite simplifier le fonctionnement), on a tout ou presque. Le reste n'est que subsidiaire, quand tu vois stddef, ctype ou stdarg qui ne contiennent presque aucune fonction...
Ajouté le 06/07/2014 à 21:19 :
J'avais pas fait attention, mais le sh3eb-elf-gcc ne renvoie pas de fatal sur stdarg.h, contrairement à stdio.h.
Je m'en suis rendu compte lorsque la commande find m'a trouvé un stdarg.h dans un dossier du sh3eb-elf-gcc... du coup, ça fait un bon problème de résolu -- le gcc classique renvoyait lui une fatal à cause de l'argument "-nostdlib"...
Ajouté le 06/07/2014 à 21:39 :
Bon, ça fonctionne visiblement.
Au fait -- ça n'a rien à voir --, j'ai trouvé d'autres choses utiles.
- La modification de l'icône utilisée par le Cg1aWrapperMaster : Ce dernier ne lit que les icônes qui ont un header précis, mais j'ai réussi à en modifier une depuis un éditeur hexa -- facile...
- Du coup, je pense le modifier pour faciliter le traitement de ces bitmaps (actuellement bloquant), et en profiter pour y inclure un mode silencieux par option -- au make, j'ai la moitié de lignes récurrentes (et monotones), à force c'est énervant.
- La compilation avec -Wall -Werror sous le sh3eb-elf-gcc posait problème à cause d'un warning récurrent ; en effet, il attend au main() des arguments de type int et char **, or on lui envoie un int et un unsigned short. Pour se débarasser de ce warning, il suffit d'ajouter l'option -Wno-main (le warning étant généré par -Wmain).
- Bien entendu, le compilateur sh3eb-elf-g++ fonctionne à merveille si vous avez pris la peine d'utiliser --enable-languages=c,c++ à la compilation de gcc.
- Les headers suivants sont supportés nativement par le sh3eb-elf-gcc : float.h, iso646.h, stdalign.h, stdarg.h, stdbool.h, stddef.h, stdfix.h, stdint-gcc.h, stdint.h, stdnoreturn.h, tgmath.h, unwind.h, varargs.h. Ce ne sont peut-être pas les seuls.
Citer : Posté le 06/07/2014 21:52 | #
Ah ! Niquel du coup ! Ce permet de commencer à avoir pas mal de chose de manière potable du coup !
Citer : Posté le 06/07/2014 21:55 | #
Du coup, j'ai fait un Makefile complet qui ressemble presque à du configure, dans le genre bien adapté aux modulations de projets. Je vous l'enverrai quand il sera bien finalisé.
Ajouté le 07/07/2014 à 08:57 :
J'ai facilement implémenté ltoa() (l'algo fait 4 lignes...), et j'ai terminé l'algo pour ftoa(), mais il reste un problème. Voilà la sortie du programme de test :
[ftoa() arg ] 2764.982910
[ftoa(2764.983)] 2764.982
Comme vous pouvez le voir, ftoa() ne renvoie pas la même chose que le premier printf(), effectué dans le main(). Mais la valeur arrive "déformée" dans la fonction ftoa()... je suppose que c'est dû à la taille des registres, et ça pourrait être identique sur la calto -- ses registres d'argument font 32 bits alors qu'elle fait le calcul flottant sur 128). L'autre solution reste d'utiliser des double, mais c'est pas la même taille en mémoire.
Du coup, je ne vois pas trop ce que je peux y faire pour l'instant...
Ajouté le 07/07/2014 à 09:12 :
Si j'ai bien compris, crt0.s représente (de manière générale) des fonctions d'initialisation. En fouillant un peu dans les données du sh3eb-elf-gcc, je suis tombé sur un fichier nommé crt1.o, et 6 autres du même genre. Par ailleurs, j'ai aussi trouvé libgcc.a, l'include limits.h, et la liste de toutes les applications sh3eb-elf (gcc, g++, objcopy, mais aussi ar, as et cpp, ld, gcov, etc...)
Citer : Posté le 07/07/2014 10:36 | #
Tiens, au fait, ce tuto pourrait vous être utile (peut être un peu tard...)
Coïncidence ? Je ne pense pas.
Citer : Posté le 07/07/2014 11:32 | #
J'ai presque terminé un sprintf() basisque. Voilà pour l'instante ce que ça donne :
Outre le problème de flottants, tous les formats sont respectés et le %u est bien traité en unsigned.
En revanche, je ne gère pas les notations exponentielles dans les float, et encore moins la notation hexa des flottants.
Il me reste encore les modifications de types à traiter (hd, ld, 2.3f, 03f, 12s, etc...).
Ajouté le 07/07/2014 à 16:55 :
J'ai intégré au g1awrapper la gestion de tous les bitmaps et nettoyé le code.
Sera-t-il intéressant que je partage ma version modifiée ?
Citer : Posté le 08/07/2014 17:50 | #
Yup, un fork du repo et un pull request pourrait être une bonne initiative.
Citer : Posté le 08/07/2014 17:56 | #
J'en ai discuté avec Kristaba. Du coup, j'ai créé un repo sur Bitbucket où j'ai envoyé une première version modifiée des sources.
Ajouté le 08/07/2014 à 22:04 :
J'ai passé le repo en public pour que les intéressés puissent y accéder. Je vais bosser dessus pendant quelques temps.
Ajouté le 09/07/2014 à 13:49 :
Je précise aux différents programmeurs qui bossent sur le projet. Sur la calculatrice, les long sont identiques aux int (même taille en mémoire, même plage de valeur). Du coup, je préconise qu'on les banisse de notre code puisqu'ils ne présentent pas d'intérêt supplémentaire.
Ajouté le 09/07/2014 à 15:45 :
J'ai fixé la liste des fonctions à réaliser dans stdlib à partir de la liste complète, en enlevant ce qui ne nous intéresse pas pour l'instant (la gestion des wchar, une partie des fonctions d'environnement, celles de C++11) et en rajoutant les fonctions itoa(), ltoa() et ftoa(). Le git est à jour.
Les détails concernant stdlib sont au début du header stdlib.h. Pensez à bien les lire et/ou les
Ajouté le 12/09/2014 à 14:38 :
Argh, j'ai posté un message et il a avalé une partie du message.
Pour résumer ce qui a été dit, j'ai fait les stats suivantes pour strlen() (1e5 opérations sur une chaîne de 10 caractères, résultats en ticks) :
182 : libfx (appelée telle quelle)
211 : fonction perso (Asm)
212 : C (gcc avec -O9)
218 : libfx (assemblée dans le g1a).
Comme vous pouvez le constater, l'apparente rapidité de la libfx ne réside pas dans l'algo, mais je pense plutôt, à la vitesse de l'accès de la zone mémoire.
De plus, certaines fonctions comme memcpy() sont plus lentes que celles de gcc même appelées telles quelles.
Edit :
Ok, memcpy() est tellement mal foutue qu'elle a sûrement été compilée.
Citer : Posté le 12/09/2014 16:23 | #
j'ai fait les stats suivantes pour strlen() (1e5 opérations
la vitesse de l'accès de la zone mémoire.
Citer : Posté le 12/09/2014 16:43 | #
C'est la notation C. 1e5 signifie 10^5.
Si c'est plus rapide, c'est sans doute parce que la zone mémoire dans laquelle se trouve le code natif (OS) n'est pas la même que celle où est chargé l'add-in (0x00300000).
Citer : Posté le 18/10/2014 19:50 | #
Petite mise à jour du git, j'ai rendu la partie stdio compilable (avec quelques modifs), ce fut un peu sportif avec les -Werror :E. Quoiqu'il en soit, pour l'instant ça compile les sources et ça linke tout ça dans un .a, mais je n'ai toujours pas la possibilité de tester directement, vu que ça ne passe toujours pas à l'émulateur, notamment pour les fonctions relatives aux fichiers... :sry:.
L'implémentation des dépendances en syscalls est un peu crade (je ne savais pas trop où les placer, ou où les déclarer ), mais c'était pour pouvoir compiler :).
Citer : Posté le 18/10/2014 19:57 | #
Vu que j'ai bien avancé le fxSDK, je pourrai m'y remettre de manière convenable.
Du coup, on devrait aussi pouvoir s'en servir... pour compiler.
Tu n'as pas de Graph, Nemhardy ?
Citer : Posté le 18/10/2014 20:32 | #
Non, je n'ai qu'une Prizm à l'heure actuelle :oops:... Du coup c'est pas évident pour tester... Pour tout ce qui reste du C "pur", non dépendant de la plateforme (par exemple les implémentations de sprintf, mem* ou encore str*) sont testables en les compilant avec un gcc classique, mais pour le reste c'est pas ce qu'il y a de plus évident ...
Mais, si on arrive à avoir quelque chose de bien, je pensais à, en parallèle porter cette libc sur Prizm (ce qui ne nécessiterait pas un travail monstre, la structure et les syscalls se ressemblant beaucoup), vu que la bibliothèque actuellement dispo est quelque peu buggée, et le code à l’intérieur n'est pas des plus organisé, il y a 3 forks différents, un mix de code sous plusieurs licences, enfin, pas la joie complète quoi :p. Mais c'est pas quelque chose à faire dans l'immédiat forcément.
Ajouté le 18/10/2014 à 20:35 :
Au fait on en avait discuté, mais je ne sais plus à quoi on avait abouti, on la place sous quelle licence celle ci ? Le domaine publique avait été retenu non ? Je ne sais plus ...
Citer : Posté le 18/10/2014 20:37 | #
Je l'avais proposé.
Disons que pour ma part, je suis tout à fait pour placer mon code dans le domaine public.
Si tu modifiais le post principal pour garder trace de ce que chacun souhaite ?
Citer : Posté le 28/10/2014 15:19 | # | Fichier joint
M'étant lancé dans la réécriture complète des fonctions de la famille de printf() -- la version précédente je le rappelle, ne gérait pas toutes les notations, et pas le moindre flag ni précision --, je dois avouer que c'est plus compliqué de gérer tous ces flags et ces histoires de précision que je ne l'avais pensé !
J'ai quand même mis au point l'analyse de format (notez que je détecte toujours un format dès que je vois un '%', ce qui n'est pas le cas normalement, mais je ne me suis pas embarrassé du format... des formats), et l'écriture des valeurs de type %d et %i. Toutes les options sont gérées, exception faite de celles mentionnées dans le fichier.
Je devrais pouvoir faire %o, %u, %x et %X assez facilement, par contre je garantis rien pour tout ce qui est flottants. :3
J'ai testé sur mon ordinateur et je n'ai pas trouvé de cas dans lequel le résultat ne soit pas identique à celui du printf() de mon système, y compris lorsque la taille de la chaîne dans laquelle écrire est limitée.
Quelqu'un pourrait tester pour confirmer mes dires ? Je joins le fichier.