1

I am looking to modify GCC 4.6 to be able to target the M68K-based TI graphing calculators. I am not looking to use any of the GCC4TI command-line frontends, IDEs, etc., but rather to create a standard cross compiler that can be used with standard build systems and development tools. I plan to look over the existing GCC4TI patches, but I was wondering if anyone had ideas for a less invasive way to add a GCC backend, making it easier to update to newer versions of GCC as they are released.

Finally, if I get this working, would GCC4TI be interested in me contributing the work back, or would it become yet another TI M68K compiler?

Thank you much,
Erik

2

Hi Erik smile

You're not the first person to mention the making of a standard toolchain, usable with standard build systems and development tools, targetting TI-68k calculators. The idea has already floated several times in other places of community, during the past year smile


If you want to make something easier to update to newer versions of GCC+binutils, it's clear that you should stay away from the GCC4TI patches to the compiler and binutils. They're huge, and contain platform-specific changes for a couple dozens of areas, mixed up into a single patch (well, two: one for GCC, one for binutils).
I once spent a couple hours partitioning the GCC patch, see the raw result at the end of the post.

However, there's a rationale for pretty much every single platform-specific change, and very few of the changes of the patchsets are unwanted. Some hunks revert backwards-incompatible changes in upstream GCC, so they obviously couldn't have been pushed upstream, but a number of important improvements might have been usefully pushed upstream at some point...
One of the rationales for having a platform-specific linker is backwards compatibility with AmigaOS files, but the linker does much more than this - for instance, special linker builtins for controlling various aspects of the linking, or the entire startup code handling (which makes maintenance of the equivalent of crt0.s much easier), and more.

Also noteworthy is the fact that support for generic m68k COFF was removed from GCC in GCC 4.4: http://gcc.gnu.org/gcc-4.4/changes.html , so ELF is the way forward for GCC 4.6+. With good linker scripts, we can think that ELF could do the job smile

Finally, if I get this working, would GCC4TI be interested in me contributing the work back, or would it become yet another TI M68K compiler?

Well, I'm not refusing the principle, but I'm afraid that the amount of possible sharing between a clean standard ELF-based toolchain, based on recent tool versions, and a mass of platform-specific changes and platform-specific COFF-based tools, would be slim... I'd accept being proved wrong, though smile


Two general notes:
* toolchains for other comparable calculator models (HPGCC for HP-49G+ family calculators, the Ndless development kit for Nspires, the third-party Casio Prizm development kits) don't have such huge patches to the toolchain, so many platform-specific changes, and such a messy build system (though GCC4TI's is slightly better than that of TIGCC). Probably a bad thing for ease of program development and backwards compatibility (as a user, I appreciate some of the silly changes of upstream GCC having been reverted), but a clear boon to maintenance.

* for building cross-compilation toolchains, I know of crosstool-ng. And I'm told by someone I trust that devkitpro is quite a good example of a cross-platform toolchain.



First pass on splitting gcc-4.1-tigcc-patch constituents (needs more work):
* win32 changes: config.guess, gcc/config/i386/xm-mingw32.h, gcc/gcc.c, libcpp/files.c
* fiddling with default attributes: gcc/attribs.c, gcc/c-common.c, gcc/c-common.h, gcc/c-decl.c, gcc/c-lang.c, gcc/c-tree.h, gcc/langhooks-def.h, gcc/langhooks.h, gcc/system.h
* changes to the GCC built-in functions, among which is __builtin_ER_throw: gcc/builtin-attrs.def, gcc/builtins.c, gcc/builtins.def
* stkparm / regparm parameter passing: gcc/builtins.c, gcc/c-decl.c, gcc/config/m68k/m68k.c, gcc/config/m68k/m68k.h, gcc/config/m68k/m68k-protos.h, gcc/c-parser.c, gcc/c-tree.h, gcc/function.c, gcc/function.h
* SMAP II BCD support: gcc/c-cppbuiltin.c, gcc/c-format.c, gcc/combine.c, gcc/config/m68k/m68k.md, gcc/config/m68k/m68k-modes.def, gcc/config/m68k/predicates.md, gcc/config/smapbcd.h, gcc/config.gcc, gcc/convert.c, probably gcc/c-pretty-print.c, gcc/dwarf2out.c, gcc/emit-rtl.c, probably gcc/explow.c, gcc/expr.c, gcc/final.c, gcc/fold-const.c, gcc/genmodes.c, gcc/machmode.def, gcc/optabs.c, gcc/output.h, gcc/print-rtl.c, gcc/print-tree.c, gcc/real.c, gcc/real.h, gcc/rtlanal.c, gcc/simplify-rtx.c, gcc/tree.c, gcc/tree-pretty-print.c, gcc/varasm.c
* global cast constructors / compound literals: gcc/c-decl.c, gcc/common.opt, gcc/flags.h, gcc/varasm.c
* -fno-function-cse changes: gcc/cfgexpand.c, gcc/gimplify.c, gcc/tree-ssa-dom.c, gcc/tree-ssa-pre.c
* kill global include paths, usage of environment variables, hard-coded prefixes, etc.: gcc/c-incpath.c, gcc/c-opts.c, gcc/cppdefault.c, gcc/gcc.c
* changes related to forward or backslashes in paths: gcc/c-incpath.c, gcc/toplev.c
* multi-line strings: probably gcc/c-lex.c, probably gcc/c-ppoutput.c, libcpp/internal.h, libcpp/lex.c
* constant pools, section merging, moving stuff between bss/data/rodata: gcc/common.opt, gcc/config/m68k/m68k.c, gcc/config/m68k/m68k.h, gcc/config/m68k/m68k.md, gcc/config/m68k/m68k-none.h, gcc/config/m68k/m68k.opt, gcc/config/m68k/m68k-ti.h, gcc/flags.h, gcc/varasm.c
* register-relative addressing & global register variables: gcc/common.opt, gcc/config/m68k/m68k.c, gcc/config/m68k/m68k.h, gcc/config/m68k/m68k.md, gcc/final.c, gcc/gcse.c, gcc/ifcvt.c, gcc/opts.c
* default to not initializing the BSS section: gcc/common.opt
* debugging support: maybe gcc/config/dbxcoff.h, gcc/config/m68k/m68k.c, gcc/dwarf2.h, gcc/dwarf2out.c, gcc/toplev.c, gcc/varasm.c
* OPTIMIZE_ROM_CALLs: gcc/config/m68k/m68k.c
* no long branches: gcc/config/m68k/m68k.c + external patcher (with a "FIXME: should be moved to GCC")
* platform-specific changes such as greater optimization, or different printf/scanf/memset/etc., or peepholes: gcc/c-format.c, gcc/config/m68k/m68k.c, gcc/config/m68k/m68k.h, gcc/config/m68k/m68k.md, gcc/config/m68k/m68k-none.h, gcc/config/m68k/m68k.opt, gcc/config/m68k/m68k-ti.h, gcc/config/m68k/predicates.md, gcc/expr.c, gcc/opts.c, gcc/postreload.c, gcc/stmt.c, gcc/tree-object-size.c
* no-auto-octals: gcc/c.opt, gcc/c-opts.c, libcpp/include/cpplib.h, libcpp/init.c
* changes to default warnings: gcc/c-decl.c -> what with "Each undeclared identifier is reported only once" ?, gcc/c-opts.c
* reverting the removal of casts-as-lvalues: gcc/c-parser.c, gcc/c-typeck.c, gcc/tree.h
* gcc/c-pretty-print.c -> what's the second hunk ?
* reference the TIGCC infrastructure which does not make public the bug report content: gcc/diagnostic.c, gcc/version.c
* a warn_unused_result-related change: gcc/gimplify.c
* a patch related to using hard register variables as an asm input: gcc/loop.c
* gcc/sdbout.c -> ?
* inlining-related fix: gcc/tree-inline.c
* a change without comments in gcc/tree-ssa-ccp.c
* pragma poison (why ?): libcpp/directives.c
* binary numbers (0b...) support: libcpp/expr.c
* SYMSTR optimization: libcpp/macro.c

git / svn blame is unhelpful, need to look up in the Changelog and commit history...


Known bugs (besides being a nightmare to port forward to newer GCC versions, and not being directly portable above GCC 4.4):
* http://tichessteamhq.yuku.com/topic/4793 : in CALLBACK functions, a5 is not reinitialized to __jmp_tbl, which can yield a crash.
- N3buk4dn3zz4r: "I managed to find the reason for this special error: Using #define OPTIMIZE_ROM_CALLS causes this code to crash(who knows why?), if this option is not set, the above code should work pretty well."

- Lionel: "When OPTIMIZE_ROM_CALLS is defined, the startup code initializes the a5 processor register to the address of the ROM_CALL table, and the rest of the program uses that to read the addresses of ROM_CALLs.
However, AMS uses a5 for its own purposes in a number of functions. When AMS calls back into your program, the value of a5 can be different from what the program expects. Any CALLBACK or interrupt handler function using a5 (or, in general, any global register variable) without having reinitialized it to the expected value will trigger one of the processor exceptions when trying to call TE_handleEvent.

There are at least two fixes to the problem:
* some inline ASM for reinitializing a5;
* using F-Line ROM_CALLs, with an internal emulator if you want your program to run on AMS <= 2.03 without requiring your users to install some form of F-Line ROM_CALL handler. F-Line ROM_CALLs are smaller than optimized ROM_CALLs (potentially large savings on programs containing many ROM_CALLs), but have some overhead in the call/return sequence (not that it matters much in practice)."

- Kevin: "To fix this properly, we need to have CALLBACK expand to a dedicated GCC attribute, add that attribute to GCC, and then add a similar hack to GCC's config/m68k/m68k.c to what we already have for interrupt handlers (__attribute__((interrupt_handler))), search for OPTIMIZE_ROM_CALLS in the TIGCC patch or the TIGCC-patched config/m68k/m68k.c."
(it's not just OPTIMIZE_ROM_CALLS, Kevin - all global register variables are affected by this infrequent problem, i.e. -freg-relative-a<n> and other user-defined global register variables are affected, though we can't do much for the latter)
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

3

Hey Erik

As Lionel said You aren't the first person to suggest this, me being one of the others and I agree there would be much to gain by starting fresh with a new tool-chain.

I had thought of this project myself and after recently building a simple tool chain for the Casio Prizm based on GCC I realized a lot more how feasible this would be while at the same time where the most work would be. These are the steps I would take in order to achieve the goal of a clean GCC based TI Tool-chain.

1. Build binutils and gcc targeting m68k, http://wiki.osdev.org/GCC_Cross-Compiler#Step_1_-_Bootstrap is a good tutorial on that and it will work with both *nix and mingw

2. Write a _start function/crt0.s and ld scripts for the calculators, for the ld script just have it target binary, the _start/crt0.s would need to be written in m68k asm by someone who is familiar with writing ASM programs for the calculators. The _start function is responsible for setting up the ram and flash data sections and making sure they are in the correct locations, with the LD script specifying where those locations are. Again you have to be familiar with how the AMS works, where programs are located in memory when ran and other such things.

3. Write a tool to take the outputted binary and wrap it in an 89p or w/e format it should be. Starting with http://www.ticalc.org/archives/files/fileinfo/399/39967.html might be a good idea, and it may even be possible to use unmodified. Currently tigcc uses a custom linker that is just a mess and uses the COFF format making it totally unusable for with newer GCC's as Lionel said. It may also be worth writing a tool not based on libtifiles as to avoid the glib dependency though I'm not sure how big a deal this really is.

4. Get the libraries in order, much of libtigcc may be reusable here such as sprite and AMS specific routines, I would avoid any that use SMC as if we want to support Applications in the future they will be unusable. Newlib may also be worth looking into for libc, libm and such, though I'm not sure what AMS provides for stdc functions.

5. Distribute it nicely as I suggested to Lionel and he mentioned in his post DevKitPro, which is a set of GCC based cross-platform tools-chains for the NDS, WII and PSP, do this wonderfully in a manor that allows for minimal platform specific work, though toolchains on Windows are always a bit of a pain no matter how you do it.

6. Add Flash Application support if you didn't already handle it with 2. I know nothing about the 68k calcs flash application formats and what is involved there but I'm sure Lionel and others would be of help.

If you have questions or wish to discuss this further you can find me and many others who may be willing to help in the #ti IRC channel on Efnet. I am not a regular member here, as you can tell from my post count but I will try to check back for replys as well. I usually frequent the English speaking forums, specifically http://cemetech.net where I host much of my Casio Prizm tool-chain work and am one of the Sites admins. (This wasn't intended as advertising, just informing the OP of ways to reach me)

4

BTW, I'm not sure that GCC is the easyest toolchain to use for such a goal. I think that something like llvm will be really easier to adapt than GCC and will provide much more than GCC is actually capable..

But that's my own opinion.
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

5

Godzil (./4) :
BTW, I'm not sure that GCC is the easyest toolchain to use for such a goal. I think that something like llvm will be really easier to adapt than GCC and will provide much more than GCC is actually capable..

But that's my own opinion.

As cool of a project as LLVM is, I don't believe it has an m68k backend nor is it really mature enough IMO on anything that isn't x86, PPC or Arm to really be of use as a cross compiler as of yet. I looked into it when I was making my Casio Prizm Toolchain but it lacked a SuperH backend so I threw it out right then and there.

6

llvm/clang are used by Apple for the iOS platform, and it work marvelously, so you're wrong, LLVM/Clang is ready and mature for other platform. The only thing that is still missing, is to be able to switch between target without recompiling the whole LLVM.
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

7

At the time of this writing, http://llvm.org/docs/CodeGenerator.html#targetfeatures shows six lines with a "Y" in the "is generally reliable" row. However:
* Hexagon is a brand-new architecture which basically nobody uses yet, and the support for Hexagon was merged this week (which shows that this table was updated very recently, and ought to be reasonably valid);
* MIPS and Sparc have little beyond the "Y" in the "is generally reliable" row; MIPS64 is barely supported; there's no m68k backend.

This leaves us with the truly usable architectures of LLVM/Clang being x86/x86_64, PPC and ARM, which is exactly what Jonimus mentioned... and iOS is precisely usually used on ARM platforms, so it's no wonder it works reasonably well wink


LLVM/Clang is clearly easier to adapt to a new architecture than GCC is, but with GCC+binutils supporting m68k and LLVM/Clang not supporting it at all, chances are that making a brand-new toolchain requires more work on the LLVM/Clang side than on the GCC side.
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

8

Sorry for digging up this old thread, but a few remarks (it shows that you have never been a member of the TIGCC Team!):
Lionel Debroux (./2) :
Also noteworthy is the fact that support for generic m68k COFF was removed from GCC in GCC 4.4: http://gcc.gnu.org/gcc-4.4/changes.html , so ELF is the way forward for GCC 4.6+.

Both the generic m68k and generic COFF support is still there, so readding the m68k-coff pieces to GCC shouldn't be hard. It's a bigger problem with GNU as, where non-BFD_ASSEMBLER support was removed, and m68k-coff was never ported to BFD_ASSEMBLER. So one would have to try enabling BFD_ASSEMBLER and seeing what breaks. Several other COFF targets use it. But at least the custom TIGCC changes would have to be ported to the BFD_ASSEMBLER code branches. But it should also be possible to use a newer GCC with an older GNU as.

I think the much bigger effort will be to deal with the various changes in the core of GCC which break our patches, at least that has always been the main source of work when porting the TIGCC patch to a newer GCC. Sometimes, I was forced to revert the upstream changes, sometimes to readd removed functions in parallel to the new ones, sometimes to rewrite the TIGCC changes (almost) from scratch against the new code.
With good linker scripts, we can think that ELF could do the job smile

IMHO, ELF can do the job if and only if support can be added to ld-tigcc, including all the special ld-tigcc features. Unlike the original poster, I do not believe that a generic toolchain is suitable at all.

So, now to the notes on your patch analysis:
* fiddling with default attributes: gcc/attribs.c, gcc/c-common.c, gcc/c-common.h, gcc/c-decl.c, gcc/c-lang.c, gcc/c-tree.h, gcc/langhooks-def.h, gcc/langhooks.h, gcc/system.h

This is needed because the new way to handle the default attributes in current upstream GCC relies on the builtin functions, which we don't use for various reasons (reliance on stdio features we don't have, wrong floating-point format etc.). So I had to readd the old code which supported default attributes for non-builtin functions. It's basically just a reversion of an upstream patch(set).
* changes to the GCC built-in functions, among which is __builtin_ER_throw: gcc/builtin-attrs.def, gcc/builtins.c, gcc/builtins.def

See above why we do the removals. We add __builtin_ER_throw because it is the cleanest way to support ER_throw (and GCC didn't have __builtin_unreachable back then; these days, we could use a macro with an asm and a __builtin_unreachable();, which would produce basically the same intermediate representation as __builtin_ER_throw, which just generates an asm and a "barrier" (i.e. a "this is unreachable")).
* SMAP II BCD support: gcc/c-cppbuiltin.c, gcc/c-format.c, gcc/combine.c, gcc/config/m68k/m68k.md, gcc/config/m68k/m68k-modes.def, gcc/config/m68k/predicates.md, gcc/config/smapbcd.h, gcc/config.gcc, gcc/convert.c, probably gcc/c-pretty-print.c, gcc/dwarf2out.c, gcc/emit-rtl.c, probably gcc/explow.c, gcc/expr.c, gcc/final.c, gcc/fold-const.c, gcc/genmodes.c, gcc/machmode.def, gcc/optabs.c, gcc/output.h, gcc/print-rtl.c, gcc/print-tree.c, gcc/real.c, gcc/real.h, gcc/rtlanal.c, gcc/simplify-rtx.c, gcc/tree.c, gcc/tree-pretty-print.c, gcc/varasm.c

Yes, the c-pretty-print.c (first hunk) and explow.c changes are part of it. The main part is a complete rewrite of floating-point handling to work on BCD numbers even internally (to avoid rounding errors from conversion), see especially real.c. And a fairly invasive part is support for unpadded 10-bit numbers (BFmode), a non-multiple-of-4, which GCC didn't support at all.
* changes related to forward or backslashes in paths: gcc/c-incpath.c, gcc/toplev.c

That's really part of the W32 changes.
* multi-line strings: probably gcc/c-lex.c, probably gcc/c-ppoutput.c, libcpp/internal.h, libcpp/lex.c

Yes, the c-lex.c and c-ppoutput.c changes are part of this.
* default to not initializing the BSS section: gcc/common.opt

Actually, this should say "default to not putting zero-initialized variables into the BSS section". This is a backwards-compatibility and consistency change:
int x=0;
puts x into the data section (in particular, will retain the value if the program is not archived nor compressed) (as opposed to the BSS section which is the upstream default), same as:
int x=1;
(but of course with a different initializer) whereas:
int x;
will put the data into the BSS section, allocated at runtime and usually initialized to 0 (unless this is disabled at linker level) (same as upstream).

Note: With -mno-bss, x will always be put in the data section, i.e. int x; will behave exactly like int x=0;.

Another note: This has the paradoxical effect that, with the default options, int x; actually guarantees that x is zero at program startup, whereas int x=0; does not! But it is the only behavior that makes sense from both a compatibility and a consistency standpoint. And the upstream default behavior makes int x=0; behave the same as int x;, which does not allow specifying the equivalent of int x=0; at all.
* debugging support: maybe gcc/config/dbxcoff.h, gcc/config/m68k/m68k.c, gcc/dwarf2.h, gcc/dwarf2out.c, gcc/toplev.c, gcc/varasm.c* OPTIMIZE_ROM_CALLs: gcc/config/m68k/m68k.c

Yes, the dbxcoff.h change is related to debugging support, but in the deprecated COFF-native format (as opposed to DWARF 2 or even Stabs), so I think it could probably just be dropped.
* no long branches: gcc/config/m68k/m68k.c + external patcher (with a "FIXME: should be moved to GCC")

Yes, IMHO, that'd better be done directly inside GCC, but it's more work to do that way (a lot of places inside GCC to patch).
* platform-specific changes such as greater optimization, or different printf/scanf/memset/etc., or peepholes: gcc/c-format.c, gcc/config/m68k/m68k.c, gcc/config/m68k/m68k.h, gcc/config/m68k/m68k.md, gcc/config/m68k/m68k-none.h, gcc/config/m68k/m68k.opt, gcc/config/m68k/m68k-ti.h, gcc/config/m68k/predicates.md, gcc/expr.c, gcc/opts.c, gcc/postreload.c, gcc/stmt.c, gcc/tree-object-size.c

I think this category could use splitting. wink (Some others maybe too, but this one in particular.)
* changes to default warnings: gcc/c-decl.c -> what with "Each undeclared identifier is reported only once" ?

Sebastian removed that "feature" because it confuses the IDE.
* gcc/c-pretty-print.c -> what's the second hunk ?

It processes ({…}) expressions in the statement printer, as used in the _rom_call macros, so you get warnings like "Too many arguments to function '*(*200u + 1656u)'" (for ClrScr(1)) rather than "Too many arguments to function 'statement expression'".
* reference the TIGCC infrastructure which does not make public the bug report content: gcc/diagnostic.c, gcc/version.c

The "which does not make public the bug report content" is very much off-topic here. (FWIW, there are hardly any bugs reported through that form in the first place these days anyway.) And of course, referencing the correct downstream bug form, in addition to obviously making sense, is actually a request by upstream GCC.

I could put up a Trac for TIGCC on CalcForge (I've been considering it), but I'm not sure it's even worth it anymore. sad
* a warn_unused_result-related change: gcc/gimplify.c

No warning if the unused result is cast to void. It's stupid to warn if the programmer explicitly asked not to.
* a patch related to using hard register variables as an asm input: gcc/loop.c

Enforces that the register variable is actually in the register it's supposed to be in when hitting an asm. IMHO a bugfix!
* gcc/sdbout.c -> ?

Changes absolute lines to relative lines, related to the dbxcoff.h change discussed above. Both these changes were done to allow the old "parser" to more easily find the source lines to patch into the generated assembly code. I think this change is obsolete now that the "parser" is gone (replaced by proper debugging support), and that it can therefore be removed.
* inlining-related fix: gcc/tree-inline.c

This goes along with a change to c-typeck.c (the #if 0 added). See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg00683.html for the discussion. Basically, the problem was that casting a function pointer to a different function pointer type could crash the inliner if the function got inlined, and the upstream "fix" to the problem was to make it an error (well, a warning and a generated call to abort();, because the standard doesn't allow making it a compile-time error) to cast a function pointer this way, which is both unnecessary and backwards-incompatible. It particularly breaks things in TIGCC due to the short vs. int mess among other issues. So I reverted that "fix" and instead applied the original proposed patch for the crash, which actually fixes the problem.
* a change without comments in gcc/tree-ssa-ccp.c

This just disables the whole ccp_fold_builtin function, it's part of the builtin function removal. (I added this when porting the TIGCC patch to GCC 4.0, with "gcc/tree-ssa-ccp.c (ccp_fold_builtin): Do nothing." as the changelog entry, as looking up the date (which I did add as a comment) in the changelog would have told you. And it isn't particularly hard to figure out what happens when I #if 0 the whole function and replace it with a "return NULL_TREE;". wink As for why I did it, see the discussion about builtins further up.)
* pragma poison (why ?): libcpp/directives.c

Backwards compatibility.
git / svn blame is unhelpful, need to look up in the Changelog and commit history...

That's what the changelog is for.
Known bugs (besides being a nightmare to port forward to newer GCC versions, and not being directly portable above GCC 4.4):
* http://tichessteamhq.yuku.com/topic/4793 : in CALLBACK functions, a5 is not reinitialized to __jmp_tbl, which can yield a crash.
- N3buk4dn3zz4r: "I managed to find the reason for this special error: Using #define OPTIMIZE_ROM_CALLS causes this code to crash(who knows why?), if this option is not set, the above code should work pretty well."

- Lionel: "When OPTIMIZE_ROM_CALLS is defined, the startup code initializes the a5 processor register to the address of the ROM_CALL table, and the rest of the program uses that to read the addresses of ROM_CALLs.However, AMS uses a5 for its own purposes in a number of functions. When AMS calls back into your program, the value of a5 can be different from what the program expects. Any CALLBACK or interrupt handler function

This is actually incorrect, there's a special hack for OPTIMIZE_ROM_CALLS and interrupt handlers (as I had already pointed out in my reply back then!). (It checks if %a5 is a global register variable, and if yes, it asks the preprocessor if OPTIMIZE_ROM_CALLS is defined (to double-check), and if still yes, it adds a move.l 0xc8,%a5 to the special interrupt handler prolog.)
using a5 (or, in general, any global register variable) without having reinitialized it to the expected value will trigger one of the processor exceptions when trying to call TE_handleEvent.

There are at least two fixes to the problem:
* some inline ASM for reinitializing a5;
* using F-Line ROM_CALLs, with an internal emulator if you want your program to run on AMS <= 2.03 without requiring your users to install some form of F-Line ROM_CALL handler. F-Line ROM_CALLs are smaller than optimized ROM_CALLs (potentially large savings on programs containing many ROM_CALLs), but have some overhead in the call/return sequence (not that it matters much in practice)."

- Kevin: "To fix this properly, we need to have CALLBACK expand to a dedicated GCC attribute, add that attribute to GCC, and then add a similar hack to GCC's config/m68k/m68k.c to what we already have for interrupt handlers (__attribute__((interrupt_handler))), search for OPTIMIZE_ROM_CALLS in the TIGCC patch or the TIGCC-patched config/m68k/m68k.c."(it's not just OPTIMIZE_ROM_CALLS, Kevin - all global register variables are affected by this infrequent problem, i.e. -freg-relative-a<n> and other user-defined global register variables are affected, though we can't do much for the latter

That's exactly my point, "we can't do much for the latter", OPTIMIZE_ROM_CALLS is the only case which we can make work with a special hack.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

9

Jonimoose (./3) :
As Lionel said You aren't the first person to suggest this, me being one of the others and I agree there would be much to gain by starting fresh with a new tool-chain.

I think there would be much more to lose than to gain! Not only would this be completely incompatible with TIGCC and all existing software for it, it would also have some additional issues:
2. Write a _start function/crt0.s and ld scripts for the calculators, for the ld script just have it target binary, the _start/crt0.s would need to be written in m68k asm by someone who is familiar with writing ASM programs for the calculators. The _start function is responsible for setting up the ram and flash data sections and making sure they are in the correct locations, with the LD script specifying where those locations are. Again you have to be familiar with how the AMS works, where programs are located in memory when ran and other such things.

Having one fixed crt0.s would lead to much larger binaries and/or much less flexibility (probably both) than ld-tigcc's configurable startup code.

It is also not possible (without very ugly hacks) to execute the code in a fixed location, so relocation is a MUST. Remember that we do not have the luxury of an MMU, nor do we have large spaces of "safe" RAM as on the Z80 OSes (which are written in assembly and thus handle memory very differently).
3. Write a tool to take the outputted binary and wrap it in an 89p or w/e format it should be. Starting with http://www.ticalc.org/archives/files/fileinfo/399/39967.html might be a good idea, and it may even be possible to use unmodified. Currently tigcc uses a custom linker that is just a mess and uses the COFF format making it totally unusable for with newer GCC's as Lionel said. It may also be worth writing a tool not based on libtifiles as to avoid the glib dependency though I'm not sure how big a deal this really is.

You cannot just "wrap" a binary, you need to actually link it. Otherwise, relocations will not work. See above. (Even the most minimalist "converter", obj2ti, at least did the most basic relocation conversion. But it was scrapped in favor of ld-tigcc which is just much more powerful than the GNU ld + obj2ti chain we used before. Yes, we actually moved away from using GNU ld plus a converter to using a custom linker.)

And as I replied to Lionel, 1. I think we can make COFF work with a newer GCC and 2. if not, then support for whatever replacement format we pick must be added to ld-tigcc. (It is made to handle more than one format, it already supports 2 of them: AmigaOS Hunks and COFF.)
4. Get the libraries in order, much of libtigcc may be reusable here such as sprite and AMS specific routines, I would avoid any that use SMC as if we want to support Applications in the future they will be unusable. Newlib may also be worth looking into for libc, libm and such, though I'm not sure what AMS provides for stdc functions.

The AMS provides several standard C functions, but not all of them. The problem is that we really want to use the functions in AMS where they exist for space reasons, but that they aren't always fully ISO compliant and that mixing newlib and AMS functions isn't going to be easy. Newlib is also quite a mess licensing-wise (a copy&paste of tons of different BSD-style licenses, all requiring that you accompany binaries with a copy of the license if they include the given function, a total mess logistically; needless to say, most programs using newlib do not comply with the licenses of the newlib functions at all roll).
5. Distribute it nicely as I suggested to Lionel and he mentioned in his post DevKitPro, which is a set of GCC based cross-platform tools-chains for the NDS, WII and PSP, do this wonderfully in a manor that allows for minimal platform specific work, though toolchains on Windows are always a bit of a pain no matter how you do it.

I don't think it can be distributed any more nicely than TIGCC already is.
6. Add Flash Application support if you didn't already handle it with 2. I know nothing about the 68k calcs flash application formats and what is involved there but I'm sure Lionel and others would be of help.

That's a job for ld-tigcc (and actually wanted now that there are at least 2 ways around the signature lockout).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

10

Kevin Kofler (./9) :
Jonimoose (./3) :
As Lionel said You aren't the first person to suggest this, me being one of the others and I agree there would be much to gain by starting fresh with a new tool-chain.
I think there would be much more to lose than to gain! Not only would this be completely incompatible with TIGCC and all existing software for it, it would also have some additional issues:

Compatiblity is and should not be an initial goal of a project like this. If someone wants to implement some backwards compatible features and functions that is fine, but right now making it so it is a smaller burden to maintain, package, and improve would be my goals.
2. Write a _start function/crt0.s and ld scripts for the calculators, for the ld script just have it target binary, the _start/crt0.s would need to be written in m68k asm by someone who is familiar with writing ASM programs for the calculators. The _start function is responsible for setting up the ram and flash data sections and making sure they are in the correct locations, with the LD script specifying where those locations are. Again you have to be familiar with how the AMS works, where programs are located in memory when ran and other such things.

Having one fixed crt0.s would lead to much larger binaries and/or much less flexibility (probably both) than ld-tigcc's configurable startup code.
It is also not possible (without very ugly hacks) to execute the code in a fixed location, so relocation is a MUST. Remember that we do not have the luxury of an MMU, nor do we have large spaces of "safe" RAM as on the Z80 OSes (which are written in assembly and thus handle memory very differently).
It doesn't have to be one singular crt0.s for all situations, but having a simple default one and then optional alternates for things such as Kernels and shells.
3. Write a tool to take the outputted binary and wrap it in an 89p or w/e format it should be. Starting with http://www.ticalc.org/archives/files/fileinfo/399/39967.html might be a good idea, and it may even be possible to use unmodified. Currently tigcc uses a custom linker that is just a mess and uses the COFF format making it totally unusable for with newer GCC's as Lionel said. It may also be worth writing a tool not based on libtifiles as to avoid the glib dependency though I'm not sure how big a deal this really is.

You cannot just "wrap" a binary, you need to actually link it. Otherwise, relocations will not work. See above. (Even the most minimalist "converter", obj2ti, at least did the most basic relocation conversion. But it was scrapped in favor of ld-tigcc which is just much more powerful than the GNU ld + obj2ti chain we used before. Yes, we actually moved away from using GNU ld plus a converter to using a custom linker.)
And as I replied to Lionel, 1. I think we can make COFF work with a newer GCC and 2. if not, then support for whatever replacement format we pick must be added to ld-tigcc. (It is made to handle more than one format, it already supports 2 of them: AmigaOS Hunks and COFF.)
The linking would be handled by ld and with a proper ld script your final linking/wrapping code should be able to be done easily. The lack of a MMU does complicate things somewhat most of that complications should be handled by the crt0.s from what I understand.

I get that you moved away from GNU ld and a converter in the past, but ld and friends have grown since then and it may be worth looking back down that route.

I don't want to make COFF work with a newer GCC because I want to avoid patching gcc as much as possible. Any patches we do have should aim to be small and easy to port to new versions. Part of the goal is to limit the amount of code that has to be maintained and one of the worst culprits there is ld-tigcc.
4. Get the libraries in order, much of libtigcc may be reusable here such as sprite and AMS specific routines, I would avoid any that use SMC as if we want to support Applications in the future they will be unusable. Newlib may also be worth looking into for libc, libm and such, though I'm not sure what AMS provides for stdc functions.

The AMS provides several standard C functions, but not all of them. The problem is that we really want to use the functions in AMS where they exist for space reasons, but that they aren't always fully ISO compliant and that mixing newlib and AMS functions isn't going to be easy. Newlib is also quite a mess licensing-wise (a copy&paste of tons of different BSD-style licenses, all requiring that you accompany binaries with a copy of the license if they include the given function, a total mess logistically; needless to say, most programs using newlib do not comply with the licenses of the newlib functions at all roll).
Yes, as I found out newlib is a bit of a mess. In the case of the Casio Prizm we are slowly reimplementing the needed libc functions as we go. Its actually working quite nicely and they are close to having a working port of Python.
5. Distribute it nicely as I suggested to Lionel and he mentioned in his post DevKitPro, which is a set of GCC based cross-platform tools-chains for the NDS, WII and PSP, do this wonderfully in a manor that allows for minimal platform specific work, though toolchains on Windows are always a bit of a pain no matter how you do it.
I don't think it can be distributed any more nicely than TIGCC already is.
ROFL. The fact that you need a rather complex script to automate the build and install process even on linux tells me otherwise. DevKitPro's toolchain build script is very simple, basically patch, configure, make, install run 4 times. And the patches are mostly to add the target to GCC, the most invasive of which is the Wii patches as the CPU and binary format is customised more than others. Though the Wii is nice enough to have a proper elf loader.
6. Add Flash Application support if you didn't already handle it with 2. I know nothing about the 68k calcs flash application formats and what is involved there but I'm sure Lionel and others would be of help.

That's a job for ld-tigcc (and actually wanted now that there are at least 2 ways around the signature lockout).
[/cite]It may be possible to do with ld-tigcc, but considering that libtigcc would need complete rewrite as it is to support applications there isn't much of the existing toolchain worth using and there is little reason to hold onto ld-tigcc when you are replacing everything else.

11

Jonimoose (./10) :
Compatiblity is and should not be an initial goal of a project like this. If someone wants to implement some backwards compatible features and functions that is fine, but right now making it so it is a smaller burden to maintain, package, and improve would be my goals.

A toolchain which is incompatible with all the existing programs would be of very little use, and compatibility as an afterthought is not going to work. Many existing programs depend on TIGCC features which can only be implemented if you design for them from ground up.
It doesn't have to be one singular crt0.s for all situations, but having a simple default one and then optional alternates for things such as Kernels and shells.

Have you looked at how many options the TIGCCLIB startup code has? Say hello to combinatory explosion! ld-tigcc allows the startup code to be pieced together at link time of the final executable, even with boolean logic (we have pieces of startup code for "option X and option Y and not option Z"), it would take thousands of different versions of crt0.s to handle all the combinations of options.
The linking would be handled by ld and with a proper ld script your final linking/wrapping code should be able to be done easily.

I strongly doubt that ld linker scripts can do all the things ld-tigcc can do. It might be doable by heavily patching GNU ld, but you don't want heavy patches! And I actually find ld-tigcc to be a much easier to maintain codebase than GNU ld, so I wouldn't want to start poking around in GNU ld to implement the missing features. Try reading GNU ld code and ld-tigcc code, then decide for yourself what is easier to maintain.
The lack of a MMU does complicate things somewhat most of that complications should be handled by the crt0.s from what I understand.

If you rely on the startup code to do the linker's job, the executable will be both larger and slower to start up. On a calculator, this matters! In addition, in practice, smart features (such as compressed relocation formats) require support from BOTH the startup code AND the linker, you can't just move everything to the startup code.
I get that you moved away from GNU ld and a converter in the past, but ld and friends have grown since then and it may be worth looking back down that route.

We found it to be much harder to make things work nicely if you have to work with a 3-step linking toolchain (objcopy to convert A68k AmigaOS Hunks objects to COFF ones*, ld -r to link together COFF objects, obj2ti to convert COFF to the native format) than if you have just one of them, for several reasons:
1. Every conversion step tends to lose information, but that information is needed to implement advanced features, and sometimes even to make basic things work without bugs or artificial limitations!
2. Adding a feature in a 3-step toolchain means 3 programs to modify instead of one (with GNU ld in particular being poorly maintainable). We already have to add support for most things in GCC, GNU as, A68k and ld-tigcc, having 3 linkers is not helpful! In practice, this meant that the old toolchain had nowhere near the features ld-tigcc has (see http://tigcc.ticalc.org/doc/ld.html).
3. As already mentioned, we found the GNU ld code to be very hard to work with, so we designed ld-tigcc to be much more maintainable.
4. The obj2ti converter was also subject to a licensing dispute with its original author (who in particular wasn't happy with us making changes he didn't approve of), and its code was very poorly readable (and ridiculously, the author complained about my changes to his mess of a code being "unreadable"), so seeing it gone was a nice side effect of the change.
5. ld-tigcc also made it possible to easily add debugging support (which had been planned for a long time). It produces both calculator output with all the debugging information stripped out and a ".dbg" file (actually a renamed COFF .o file) which can be loaded into Emu-TIGCC (or rather its builtin patched copy of GDB), both in a single linker run (whereas with GNU ld, you actually need to run something like eu-strip on the output to separate the debugging information from the rest). And ld-tigcc can even delete sections referenced only from the debugging sections from the calculator output, they end up in a section named ".deleted" in the .dbg file (not in .text, where only the actual program memory contents are in, in the same order as on the calculator, so the debugging information can be properly relocated by Emu-TIGCC).

* Note that we couldn't manage to get GNU ld to work directly on the A68k objects without running AmigaOS-patched objcopy on them. GNU ld is a really ugly codebase you really don't want to have to work on.

I was very sceptical at first when Sebastian started ld-tigcc, but when he showed me what even the first alpha version was able to do, I was quickly convinced that it was the way to go. We put months of work into it, adding more powerful features. Throwing it away would be a very big mistake.
I don't want to make COFF work with a newer GCC because I want to avoid patching gcc as much as possible. Any patches we do have should aim to be small and easy to port to new versions.

I think that's an unnecessary and unhelpful goal. It's a much better idea to invest the time needed to port the patch to newer versions (it used to take me 1-2 weeks for every new GCC branch). And if none of us can find the time to port the patchset, then it's much better to just stick with what's there (it's not like GCC 4.1 magically stopped working) than to throw away everything and attempt a rewrite (which IMHO would require much more resources to do properly than just porting the patchset). That said, I do think porting the GCC patchset to newer versions of GCC should be a priority and I complained many times about GCC4TI not even having it on their todo list while wasting weeks on micro-optimizations saving a couple bytes somewhere in TIGCCLIB, unnecessary build script changes etc. I think both you and the GCC4TI folks are overestimating the effort it is to port the patchset (though of course, the longer we wait, the more work it will be, because GCC is moving on!).
Part of the goal is to limit the amount of code that has to be maintained

Doing that at the expense of all the features which make TIGCC unique and at the expense of any kind of backwards compatibility would be a major disservice to our users.
and one of the worst culprits there is ld-tigcc.

It's one of the most maintainable linkers ever, we even tried to design it to be portable to other targets (though of course it would need some changes to actually achieve that). I actually think it's a big mistake of e.g. the Ndless toolchain to not have ported ld-tigcc instead of their quick linking hack and its limitations. (The Ndless toolchain also suffers from insisting on not using any GCC or GNU ld patches, instead relying on wrapper scripts and various hacks to work around GCC's and ld's limitations and inappropriate behavior for the target. IMHO, building a custom GCC with custom patches is unavoidable to build a clean, well-integrated, powerful and reliable toolchain.)
I don't think it can be distributed any more nicely than TIGCC already is.
ROFL. The fact that you need a rather complex script to automate the build and install process even on linux tells me otherwise. DevKitPro's toolchain build script is very simple, basically patch, configure, make, install run 4 times. And the patches are mostly to add the target to GCC, the most invasive of which is the Wii patches as the CPU and binary format is customised more than others. Though the Wii is nice enough to have a proper elf loader.

You have a very strange definition of "distributed nicely"! My definition of "distributed nicely" is that it's nice for the user! The build process is complex, so what? The user just has to run setup.exe or "yum install ktigcc" and has a fully working toolchain with an IDE and everything set up. And even if they insist on building from source (that's supposed to be the packager's job, I did it for Fedora and W32), it's all scripted. DevKitPro doesn't even include an IDE!
It may be possible to do with ld-tigcc,

s/may be/is/ !
but considering that libtigcc would need complete rewrite as it is to support applications

Nonsense. It wouldn't need a complete rewrite at all. Just have non-SMC versions of the few functions which use SMC, or put the SMC in a data section (FlashApps can have BSS sections handled by AMS, data sections are easily implementable in terms of BSS sections by the linker: just store their initial contents in the text section and memcpy them to the BSS section at startup) and use the enter_ghost_space hack (which can actually be used to unprotect any 12, 28 or 68 KiB range of RAM depending on the AMS version; in conjunction with the ghost space trick, you can get at least 68 KiB of execution-unprotected RAM on all models, without dangerously messing directly with the protection mechanism) to unprotect the FlashApp's BSS section. And most of the "SMC" is not actually SMC, but only variables, those can easily be put in a data or BSS section. So what needs to be done is going through TIGCCLIB, finding the SMC and either changing it entirely or making a non-SMC version.

The startup code could need a rewrite, but I'm not sure FlashApps should even have startup code. I'd start with something very minimal or empty and port the parts of the regular TIGCCLIB startup code which make sense as I find them needed or useful.
there isn't much of the existing toolchain worth using

Nonsense. You're overestimating the changes required for FlashApp support by a lot. For TIGCCLIB, see above. For ld-tigcc, they are just a new output format, it's designed to handle multiple ones (see e.g. the Flash OS support!). For everything else, it should need little to no changes.
and there is little reason to hold onto ld-tigcc when you are replacing everything else.

But we aren't.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

12

By the way, it's very telling that Lionel attempted to reverse-engineer the TIGCC patch and never even bothered to try just asking me what the things are for, especially those he wasn't able to figure out. I wasn't aware of this thread or I would have answered earlier. How do you intend to maintain code you don't understand?
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

13

I didn't bother wasting time replying to the previous round of personal attacks and provocations... but you're now piling more and further derailing the topic. How unsurprising and disappointing...

I won't edit or lock your post, though.

My summary
First pass on splitting gcc-4.1-tigcc-patch constituents (needs more work):

and footer
qit / svn blame is unhelpful, need to look up in the Changelog and commit history...

preceded by
I once spent a couple hours partitioning the GCC patch

should have been a clear indication to you that the list was a first step. It was more than enough for the purpose of estimating the number of changes lumped together in a single patch (yes, I have known for many years that basically all of those are necessary). I had the feeling that it was at least 20 changes, now I have a rough number (which is in that range, BTW).
The purpose was obviously not to do a thorough job of splitting the patch down to each individual hunk (for that purpose, as I wrote, I knew it was needed to spend more time than just a couple hours, and to look in the Changelog and commit history), which was unnecessary for this discussion anyway.

But as usual, you're missing the point, and as usual (in the 12 or so past years), you're sending multiple attacks against people. This thread was posted at a time you were banned for bad behaviour, which is a good reason why you couldn't reply to it...
If I had bothered you for such a simple task as estimating the amount of mixing in your patch (as shown above, I clearly didn't need to), you'd have attacked me for being so incompetent that I cannot even do such simple tasks...

14

LOL, I go through the trouble of dissecting your incomplete patch analysis, answering all the questions you raised in it, and pointing out and correcting the couple mistakes you made, and instead of thanking me for it, you accuse me of "personal attacks and provocations"? mur
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

15

Stop both of you. Only usefull post allowed from now