Monday, December 31, 2012

I've been working for an hour or less most days since the last update, and it didn't make sense to write an update for each day. So here's a summary of what's been happening.

I had originally intended 32-bit multiplies to be implemented in libgcc, but instead GCC is trying to cobble something together using 16-bit multiplies. That results in unexpectedly wrong results when signed multiplication is used. The problem here is that MPY does only unsigned multiplication, but the way the MULHI3 pattern is written, GCC assumes that signed multiplication is used. Unfortunately, I could find no way to rewrite this instruction to result in nice-looking code.

The only way I could resolve the situation was to implement a MULSI3 instruction for inline 32-bit multiplies. There was an implementation commented out in the machine description file, but I was able to reduce it to nine instructions and two temporary registers. I'm not happy about this, but I can't think of a better solution.

The implementation of the TMS9900 libgcc source code has been totally refactored. Initially, I had an individual file for each libgcc function. There were quite a lot of them, and I would see default code unexpectedly linked into the test code. The problem there was that libgcc expects all assembly optimizations to be stored in a single file, pointed to the LIB1ASMSRC symbol in the makefile. Additionally, the LIB1ASMFUNCS symbol needs to contain a list of the implemented functions so the default ones will not be linked into the library. This was annoying to track down, since I couldn't find documentation for any of this, and had to rely on code used by other processors. All the libgcc functions have been tested, and work as expected.

I looked at the floating point emulation code, but it is mostly a mess of precompiler macros, and fails to build for 16-bit architectures. I think I got an error like "Here's a nickel kid, buy yourself a real processor..." This did not make me happy. My options now are to either refactor the existing code to support 16-bit machines, or write a new library from scratch. If I'm honest the second option seems more interesting.

After looking though the GCC documentation, I may have found a way to get rid of the fake PC register using UNSPEC instructions. These are unspecified machine-specific operations that might be used to handle returns or maybe even byte-to-word conversions. I would need to do some major testing for that one though.

Thursday, December 13, 2012

All functions are now implemented, now it's time for validation testing. I've already checked out the divide and modulus functions, since I knew that they would tricky.

I've started testing 32-bit multiplies, and I keep seeing results consistent with unsigned multiply, regardless of the type of operation called for. I'm also seeing that the __mulsi3 function in libgcc is not being used. It's been long enough that I've forgotten if I've implemented a 32-bit multiply recipe in the machine description file. I better check that out.

Sunday, November 25, 2012

I spent the last couple of days working on libgcc, and got all missing functions done except the division and modulus stuff.

Once this is done, I need to review everything and look for some bugs to fix. I know there's a problem with register counts for the function prologue and epilogoue, so that should be interesting.

Wednesday, November 21, 2012

So for the past few days I've been working on libgcc, making sure the compiler covers all instructions up to 32-bit operations.

Missing operations:

Count leading zero bits
__ctzsi2,__ctzhi2, __ctzqi2

Count trailing zero bits
__clzsi2,__clzhi2, __clzqi2

Find index of least significant bit
__ffssi2,__ffshi2, __ffsqi2

Return one if an even number of bits set
__paritysi2, __parityhi2, __parityqi2

Return number of set bits
__popcountsi2, __popcounthi2, __popcountqi

Signed division of 32-bit values
__divsi3

Unsigned division of 32-bit values
__udivsi3

Calculate modulus of 32-bit values
__modsi3

Calculate unsigned modulus of 32-bit values
__umodsi3

Do both division and modulus calculations
__divmodsi3

Do both unsigned division and modulus calculations
__udivmodsi3

Multiply 32-bit values
__mulsi3

For now, the trapped arithmetic instructions will be implemented using the default code. These functions call "abort" when there is an overflow condition, and are only needed in rare cases. The TMS9900 updates an overflow flag which we can use for this, but we can do that work later.

The other routines in libgcc are for floating-point and fixed-point math, odds are they are too big to really use. But again, I can fix that later.

Wednesday, November 7, 2012

I was trying to build libgcc to make the missing functions like __udivsi3 mentioned earlier. Unfortunately, there's a bug in GCC which causes the libgcc build to fail:

eric@compaq:~/dev/tios/toolchain/gcc-4.4.0/libgcc$ make
Makefile:143: ../.././gcc/libgcc.mvars: No such file or directory
make: *** No rule to make target `../.././gcc/libgcc.mvars'.  Stop.

After looking into this a bit, it tuns out my build directions were lacking. The GNU people always do their builds from a seperate directory, and say that any problems arising from building in the source directory will not be fixed.

So, rather than fight the world on this, I'm changing the build instructions. The following are to be done from the top level of the GCC source directory.

  $ mkdir build
  $ cd build
  $ ../configure --prefix /home/eric/dev/tios/toolchain --target=tms9900 --enable-languages=c
  $ make all-gcc
  $ make install
  $ mkdir libgcc/build
  $ cd libgcc/build
  $ ../../../libgcc/configure --prefix /home/eric/dev/tios/toolchain/ --host=tms9900
  $ make
  $ make install

Sunday, November 4, 2012

After being super busy at work for the last few months, I finally got some time to work on TI stuff again. I was in the middle of something earlier, but heck if I can remember what that was.

One of the people on AtariAge wanted to know if a FAT library would compile OK for the TI. Sounds like a good question, let's find out.

The first pass failed due to missing the libc headers for TI. For now, I'm using the i386 headers. As long as I don't try to link anything, it should be fine.

The second pass failed too, there is an invalid instruction being generated. This was super tedious to track down.

    inv  r2
    neg  >4    * invalid, only registers my be used
    inc  r2

(insn 418 417 784 fat_access.c:167 (set (reg:SI 2 r2 [230])
        (neg:SI (reg:SI 2 r2 [230]))) 68 {negsi2} (nil))

Once the instruction was isolated, the problem was obvious. I was overrunning an RTX array in the NEGSI2 instruction and the junk found there showed up in the final output. By using a properly-sized array for this instruction, all is well.


total:
  [Nr] Name              Type            Size(Hex)  Size(Dec)
  [ 1] .text             PROGBITS        00005462 = 21602
  [ 3] .data             PROGBITS        00000030 = 48
  [ 4] .bss              NOBITS          00000CCA = 3274

Of course, this is missing a lot of other stuff:
puts
printf
__udivsi3
strncpy
strncmp
memcpy
memset

So, yes, this library is compilable for the TI, but needs about 24KB for everything. Probably impractical.

I've seen this a few places in the output. It would be easy to optimize this, but this may be a rarely-used pattern, and not worth special attention.
        mov  r2, *r1
        mov  r2, @>2(r1)

This could better be written as:
    mov  r2, *r1+
    mov  r2, *r1


As an unrelated note, I thought for a minute that using the X instruction might be useful for the function prologue and epilogue, since we're iterating though registers. Unfortunately, it's not. At most, there are four instructions for either 'logue, and a lot more would be required if X were used. Never mind.

Sunday, July 15, 2012

Binutils 2.19.1 patch 1.4

Changes this version:

Fixed bug prohibiting the use of single quotes in a string Strings my be in either TI-style 'stuff' or C-style "stuff" TI-style strings follow E/A text rules C-style strings may include standard escape codes "example\n"

Download:
binutils-2.19.1-tms9900-1.4-patch.tar.gz