├── .gitmodules ├── README.md ├── build.sh ├── check.sh ├── doc ├── random-notes.txt └── shift-notes.txt ├── experimental └── fpmath.c ├── failproc ├── compile.sh └── failproc.ml ├── gcc.xfail ├── ldscripts ├── bbcb.cfg ├── bbcmaster.cfg ├── c64.cfg └── semi65x.cfg ├── libtinyc ├── abort.c ├── alloc.c ├── bbc │ └── fputc.c ├── c64 │ └── fputc.c ├── compile.sh ├── exit.c ├── fflush.c ├── fprintf.c ├── fputs.c ├── ftoa.S ├── fwrite.c ├── include │ ├── alloca.h │ ├── assert.h │ ├── errno.h │ ├── math.h │ ├── stddef.h │ ├── stdint.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── sys │ │ └── types.h │ ├── time.h │ └── unistd.h ├── math.c ├── memcmp.c ├── memcpy.c ├── memmove.c ├── memset.S ├── memset.c ├── printf.c ├── putchar.c ├── puts.c ├── rand.c ├── semi65x │ └── fputc.c ├── sprintf.c ├── stdfiles.c ├── strchr.c ├── strcmp.c ├── strcpy.c ├── strlen.S ├── strlen.c ├── strncmp.c ├── strncpy.c ├── strrchr.c ├── vfprintf.c ├── vprintf.c └── vsprintf.c ├── resultdb ├── compile.sh ├── db.sql └── resultdb.ml ├── semi65x ├── 6502core.cpp ├── 6502core.h ├── Makefile ├── dirify.sh ├── disas.cpp ├── disas.h ├── mapfile.cpp ├── mapfile.h ├── semi65cx-sim.exp ├── semi65x-sim.exp ├── semi65x.cpp ├── semi65x.h ├── site-orig.exp └── test │ ├── runtest.sh │ └── test.s ├── tests ├── args.c ├── fpcmp.c ├── hello.c ├── retcode.c ├── whatever.c ├── whatever10.c ├── whatever11.c ├── whatever12.c ├── whatever13.c ├── whatever14.c ├── whatever15.c ├── whatever2.c ├── whatever3.c ├── whatever4.c ├── whatever5.c ├── whatever6.c ├── whatever7.c ├── whatever8.c └── whatever9.c └── wrappers ├── 6502-ar └── 6502-ranlib /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "gcc-src"] 2 | path = gcc-src 3 | url = http://www.github.com/itszor/gcc-6502 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GCC 6502 bits 2 | ============= 3 | 4 | Build tools, tiny C library, etc. for gcc-6502 port. 5 | 6 | Prerequisites 7 | ------------- 8 | 9 | **Install the cc65 compiler suite** 10 | 11 | Most Linux distributions have a prepackaged cc65, but often it is outdated. Should you run into issues, build the latest version from https://github.com/cc65/cc65.git 12 | 13 | **Install the prerequisites for building GCC** 14 | 15 | For Debian-based distros: 16 | # apt-get build-dep gcc-4.8 17 | 18 | For RedHat-based distros: 19 | # yum install -y gcc gcc-c++ mpfr-devel gmp-devel libmpc-devel flex 20 | 21 | **Install Boost development libraries** 22 | 23 | For semi65x (the included simulator), you also need Boost development libraries: 24 | 25 | For Debian-based distros: 26 | # apt-get install libboost-dev libboost-regex-dev 27 | 28 | For RedHat-based distros: 29 | # yum install -y boost boost-devel 30 | 31 | **Install DejaGNU (optional)** 32 | 33 | For running the GCC regression tests you will need to have DejaGNU installed: 34 | 35 | For Debian-based distros: 36 | # apt-get install dejagnu 37 | 38 | For RedHat-based distros: 39 | # yum install -y dejagnu 40 | 41 | Work in progress 42 | ---------------- 43 | 44 | This is a work-in-progress compiler, and many bugs remain. You can build code for semi65x (the included simulator), and limited support also exists for Acorn BBC Model B or Master computers (you may see some references to the C64, but that's not properly implemented yet). Adding support for other systems shouldn't be too hard - contact me if you'd like to try that! 45 | 46 | Building 47 | -------- 48 | 49 | Check out this repository *recursively*: 50 | 51 | $ git clone --recursive https://github.com/itszor/gcc-6502-bits.git 52 | 53 | Now build by running the build.sh script, e.g. as: 54 | 55 | $ ./build.sh 2>&1 | tee build.log 56 | 57 | The default location for cc65 binaries is in /usr (so ca65, ld65 and so on are present in /usr/bin/ca65, etc). If installed in another location, set the CC65_PATH variable to the path where the binaries exist. For example: 58 | 59 | $ CC65_PATH=/usr/local/cc65/bin build.sh ... 60 | 61 | After a while, you should have a 6502 cross-compiler in a directory named 'prefix'. 62 | 63 | Running code 64 | ------------ 65 | 66 | Set your PATH to include prefix/bin: 67 | 68 | $ export PATH=`pwd`/prefix/bin:$PATH 69 | 70 | Now use the compiler like any other cross-compiler: 71 | 72 | $ 6502-gcc helloworld.c -O2 -o helloworld 73 | 74 | If you build the enclosed simulator (needs Boost, cd semi65x && make) you can run the generated code: 75 | 76 | $ semi65x/semi65x -l 0x200 ./helloworld 77 | Hello world 78 | $ 79 | 80 | To compile for other supported systems, e.g. the BBC Master computer, you can use a command like: 81 | 82 | # 6502-gcc -mmach=bbcmaster -mcpu=65C02 -O2 hello.c -o hello 83 | 84 | By default, the compiler will use a software stack that starts at a suitable location for use in MODE 7 (i.e. 0x7BFF downwards). To use another screen mode or stack address, set the stack top at link time like this: 85 | 86 | # 6502-gcc -mmach=bbcmaster -mcpu=65C02 -O2 hello.c -Wl,-D,__STACKTOP__=0x2fff -o hello 87 | 88 | The program start address will be set to 0xe00 for the Master, or 0x1900 for the Model B. You can probably use other load addresses if you supply your own linker script. 89 | 90 | To obtain a memory map of the final executable from the linker, use a command such as: 91 | 92 | # 6502-gcc [...] -Wl,-m,hello.map 93 | 94 | The semi65x simulator can read this map file in order to display symbolic addresses in trace output, which might be helpful for debugging. 95 | 96 | Running regression tests 97 | ------------------------ 98 | 99 | If you built semi65x, you can run GCC regression tests using: 100 | 101 | $ ./check.sh 102 | 103 | Results will appear in a directory like testresults-*date*-*sequence*. Results so far (2014-04-16) should look something like: 104 | 105 | ``` 106 | === gcc Summary === 107 | 108 | # of expected passes 62283 109 | # of unexpected failures 4165 110 | # of unexpected successes 1 111 | # of expected failures 104 112 | # of unresolved testcases 2543 113 | # of unsupported tests 2340 114 | ``` 115 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | thisdir="$(dirname "$0")" 3 | thisdir="$(readlink -f "$thisdir")" 4 | cd "$thisdir" 5 | 6 | startpos= 7 | endpos=3 8 | case "$1" in 9 | ""|"1") 10 | startpos=1 11 | ;; 12 | "2") 13 | startpos=2 14 | ;; 15 | "3") 16 | startpos=3 17 | ;; 18 | *-*) 19 | startpos="${1%-*}" 20 | endpos="${1#*-}" 21 | ;; 22 | *) 23 | echo "Don't know what '$1' means" 24 | echo "Use numeric start stage:" 25 | echo " 1 - stage 1 compiler" 26 | echo " 2 - C library" 27 | echo " 3 - stage 2 compiler" 28 | exit 1 29 | ;; 30 | esac 31 | 32 | #MAKETARGET=all-gcc 33 | #INSTALLTARGET=install-gcc 34 | 35 | DEBUG_FLAGS="-O0 -g" 36 | MAKETARGET=all 37 | INSTALLTARGET=install 38 | PARALLELISM="-j 4" 39 | 40 | CC65_PATH="${CC65_PATH:-/usr/bin}" 41 | CA65_PATH="${CC65_PATH}/ca65" 42 | LD65_PATH="${CC65_PATH}/ld65" 43 | 44 | MORE_OPTIONS="--enable-checking" 45 | 46 | if [ "$startpos" -le 1 ]; then 47 | rm -rf gcc-build 48 | mkdir gcc-build 49 | echo 50 | echo "*****************************" 51 | echo "* Building stage 1 compiler *" 52 | echo "*****************************" 53 | echo 54 | pushd gcc-build 55 | ../gcc-src/configure --prefix="$thisdir/prefix" --with-sysroot="$thisdir/prefix/6502" --with-build-sysroot="$thisdir/prefix/6502" --target=6502 --enable-languages=c --with-as=${CA65_PATH} --with-ld=${LD65_PATH} --without-headers --with-newlib --disable-nls --disable-decimal-float --disable-libssp --disable-threads --disable-libatomic --disable-libitm --disable-libsanitizer --disable-libquadmath --disable-lto --enable-sjlj-exceptions --without-isl $MORE_OPTIONS 56 | cat > do-make.sh << EOF 57 | #!/bin/bash 58 | set -e 59 | make $PARALLELISM BOOT_CFLAGS="$DEBUG_FLAGS" CFLAGS="$DEBUG_FLAGS" CXXFLAGS="$DEBUG_FLAGS" AR_FOR_TARGET="$thisdir/wrappers/6502-ar" RANLIB_FOR_TARGET="$thisdir/wrappers/6502-ranlib" $MAKETARGET 60 | make RANLIB_FOR_TARGET="$thisdir/wrappers/6502-ranlib" $INSTALLTARGET 61 | EOF 62 | chmod +x do-make.sh 63 | ./do-make.sh || exit 1 64 | popd 65 | fi 66 | 67 | if [ "$startpos" -le 2 ] && [ "$endpos" -ge 2 ]; then 68 | echo 69 | echo "***************************" 70 | echo "* Building tiny C library *" 71 | echo "***************************" 72 | echo 73 | set -e 74 | PATH="$thisdir/prefix/bin:$PATH" 75 | PREFIX="$thisdir/prefix" libtinyc/compile.sh 76 | set +e 77 | mkdir -p "$thisdir/prefix/6502/lib/cc65/cfg" 78 | install ldscripts/semi65x.cfg "$thisdir/prefix/6502/lib/cc65/cfg" 79 | mkdir -p "$thisdir/prefix/6502/bbcb/lib/cc65/cfg" 80 | install ldscripts/bbcb.cfg "$thisdir/prefix/6502/bbcb/lib/cc65/cfg" 81 | mkdir -p "$thisdir/prefix/6502/bbcm/lib/cc65/cfg" 82 | install ldscripts/bbcmaster.cfg "$thisdir/prefix/6502/bbcm/lib/cc65/cfg" 83 | mkdir -p "$thisdir/prefix/6502/c64/lib/cc65/cfg" 84 | install ldscripts/c64.cfg "$thisdir/prefix/6502/c64/lib/cc65/cfg" 85 | fi 86 | 87 | if [ "$startpos" -le 3 ] && [ "$endpos" -ge 3 ]; then 88 | echo 89 | echo "*****************************" 90 | echo "* Building stage 2 compiler *" 91 | echo "*****************************" 92 | echo 93 | rm -rf gcc-build-2 94 | mkdir gcc-build-2 95 | pushd gcc-build-2 96 | ../gcc-src/configure --prefix="$thisdir/prefix" --with-sysroot="$thisdir/prefix/6502" --with-build-sysroot="$thisdir/prefix/6502" --target=6502 --enable-languages=c --with-as=${CA65_PATH} --with-ld=${LD65_PATH} --disable-nls --disable-decimal-float --disable-libssp --disable-threads --disable-libatomic --disable-libitm --disable-libsanitizer --disable-libquadmath --disable-lto --enable-sjlj-exceptions --without-isl $MORE_OPTIONS 97 | cat > do-make.sh << EOF 98 | #!/bin/bash 99 | set -e 100 | make $PARALLELISM BOOT_CFLAGS="$DEBUG_FLAGS" CFLAGS="$DEBUG_FLAGS" CXXFLAGS="$DEBUG_FLAGS" AR_FOR_TARGET="$thisdir/wrappers/6502-ar" RANLIB_FOR_TARGET="$thisdir/wrappers/6502-ranlib" $MAKETARGET 101 | make RANLIB_FOR_TARGET="$thisdir/wrappers/6502-ranlib" $INSTALLTARGET 102 | EOF 103 | chmod +x do-make.sh 104 | ./do-make.sh || exit 1 105 | popd 106 | fi 107 | -------------------------------------------------------------------------------- /check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | declare -a BOARDS 4 | 5 | PARALLELISM=8 6 | 7 | # DejaGNU's "schedule of variations" multi-board support appears to not be 8 | # very useful for us, so just run one board at a time. 9 | BOARDS=("semi65x-sim" "semi65cx-sim") 10 | 11 | get_test_results_dir () { 12 | local board=$1 13 | local base 14 | local n=1 15 | base="testresults-$(date +%F)" 16 | while [ -d "$base-$n" ]; do 17 | n=$(( n + 1 )) 18 | done 19 | mkdir -p "$base-$n" 20 | echo "$base-$n" 21 | } 22 | 23 | thisdir="$(dirname "$0")" 24 | thisdir="$(readlink -f "$thisdir")" 25 | 26 | resdir=$(get_test_results_dir) 27 | 28 | for board in "${BOARDS[@]}"; do 29 | pushd "$thisdir"/gcc-build-2 >& /dev/null 30 | sed "s,BOARD_DIR_LOCATION,$thisdir/semi65x," < "$thisdir/semi65x/site-orig.exp" > "$thisdir/semi65x/site.exp" 31 | export DEJAGNU="$thisdir/semi65x/site.exp" 32 | export PATH="$thisdir/semi65x":$PATH 33 | make -j "$PARALLELISM" check-gcc RUNTESTFLAGS="--target_board=$board $*" 34 | popd >& /dev/null 35 | echo "Copying results to $resdir/$board" 36 | mkdir -p "$resdir"/"$board" 37 | cp "$thisdir/gcc-build-2/gcc/testsuite/gcc/gcc.sum" "$thisdir/gcc-build-2/gcc/testsuite/gcc/gcc.log" "$resdir"/"$board" 38 | done 39 | -------------------------------------------------------------------------------- /doc/random-notes.txt: -------------------------------------------------------------------------------- 1 | pseudo 16-bit registers 2 | ----------------------- 3 | 4 | low byte uses the physical register, high byte uses a ZP location. 5 | 6 | AH 7 | XH 8 | YH 9 | 10 | adds 11 | ==== 12 | 13 | res: zp op1: zp op2: zp clobbers: A 14 | lda op1 15 | clc 16 | adc op2 17 | sta res 18 | lda op1+1 19 | adc op2+1 20 | sta res+1 21 | 22 | res: A op1: zp op2: zp 23 | lda op1 24 | clc 25 | adc op2 26 | save-acc 27 | lda op1+1 28 | clc 29 | adc op2+1 30 | sta AH 31 | restore-acc 32 | 33 | res: zp op1: A op2: zp clobbers: A 34 | clc 35 | adc op2 36 | sta res 37 | lda AH 38 | adc op2+1 39 | sta res+1 40 | 41 | res: A op1: A op2: zp 42 | clc 43 | adc op2 44 | save-acc 45 | lda AH 46 | adc op2+1 47 | sta AH 48 | restore-acc 49 | 50 | lsl #1 51 | ====== 52 | 53 | res: A op1: A 54 | 55 | asl 56 | rol AH 57 | 58 | res: zp op1: A clobbers: A,X 59 | 60 | ldx AH 61 | stx res+1 62 | asl 63 | rol res+1 64 | sta res 65 | 66 | res: A op1: zp 67 | 68 | lda op1+1 69 | sta AH 70 | lda op1 71 | asl 72 | rol AH 73 | 74 | add #1 75 | ====== 76 | 77 | res: zp op1: zp (=res) 78 | 79 | inc op1 80 | bne skip 81 | inc op1+1 82 | skip: 83 | 84 | res: A op1: A 85 | 86 | inc a 87 | bne skip 88 | inc AH 89 | skip: 90 | 91 | res: X op1: X 92 | 93 | inx 94 | bne skip 95 | inc XH 96 | skip: 97 | 98 | mov 99 | === 100 | 101 | res: A src: X 102 | 103 | lda AH 104 | sta XH 105 | txa 106 | 107 | res: A src: zp 108 | 109 | lda src+1 110 | sta AH 111 | lda src 112 | 113 | res: X src: abs,y 114 | 115 | ldx abs+1,y 116 | stx XH 117 | ldx abs,y 118 | 119 | res: X src: (zp),y clobbers: A 120 | 121 | iny 122 | lda (zp),y 123 | sta XH 124 | dey 125 | lda (zp),y 126 | tax 127 | 128 | prologue/epilogue 129 | ================= 130 | 131 | A/X/Y/AH/XH/YH are call-clobbered. 132 | 133 | args on software stack can be accessed like: 134 | 135 | func: 136 | lda ssp 137 | sec 138 | sbc #framesize 142 | sta ssp+1 143 | 144 | ldy #arg 145 | lda (ssp),y 146 | 147 | rts 148 | 149 | it'd be nice for "software stack"-ABI functions to be able to use a number of ZP locations without worrying about them being clobbered over function calls. That means saving them in the prologue & restoring them in the epilogue. 150 | 151 | lda $70 : ldy #0 : sta (ssp),y 152 | lda $71 : ldy #1 : sta (ssp),y 153 | lda $72 : ldy #2 : sta (ssp),y 154 | 155 | ; save to "zero-page" stack 156 | 157 | lda zpsp 158 | sec 159 | sbc #8 160 | tax 161 | lda $77 : sta 7,x 162 | lda $76 : sta 6,x 163 | lda $75 : sta 5,x 164 | lda $74 : sta 4,x 165 | lda $73 : sta 3,x 166 | lda $72 : sta 2,x 167 | lda $71 : sta 1,x 168 | lda $70 : sta 0,x 169 | stx zpsp 170 | 171 | I'm not sure if that's actually going to be helpful. We really want to avoid wasting 75% of our cycles on boilerplate that doesn't really do anything... 172 | 173 | We could also do: 174 | 175 | lda $73 : pha 176 | lda $72 : pha 177 | lda $71 : pha 178 | lda $70 : pha 179 | 180 | pla : sta $70 181 | pla : sta $71 182 | pla : sta $72 183 | pla : sta $73 184 | 185 | pha is faster than zp,x addressing! This is probably fine if we don't need to stack too many locations. 186 | 187 | It might be possible to use an overflow check (somehow optional, e.g. a marker on deeply-recursive functions): 188 | 189 | tsx 190 | cpx #5 191 | bcs no_ovf 192 | jsr stack_ovf 193 | no_ovf: 194 | lda $73 : pha 195 | lda $72 : pha 196 | ... 197 | 198 | this would transfer the hardware stack contents somewhere else (the software-controlled stack), and push a cleanup routine onto the top of the fresh stack so that it is called when the current function returns, equivalent of: 199 | 200 | foo () { 201 | stack_ovf (); 202 | 203 | return cleanup_stack (rc); 204 | } 205 | 206 | the cleanup routine must return to the original caller, so that info must be extracted from the original stack in stack_ovf. 207 | 208 | arg registers 209 | ------------- 210 | 211 | Use 8 bytes of registers (e.g.) to pass arguments. These are ZP locations: give symbolic names a0-a7. 212 | 213 | lda #5 214 | sta a0 215 | lda #7 216 | sta a1 217 | jsr foo 218 | 219 | foo: 220 | lda a0 221 | ... 222 | rts 223 | 224 | further arguments passed on a software stack -- or on a "zero page", x-indexed stack? Using a "normal" software stack to start with might limit the amount of invention we need to do in GCC. 225 | 226 | So: 227 | 228 | lda #foo : sta a0 229 | ... 230 | lda #bar : sta a7 231 | lda #baz : ldy #0 : lda (sp),y 232 | 233 | having more than 256 bytes of args+locals is likely to be problematic... 234 | 235 | -------------------------------------------------------------------------------- /doc/shift-notes.txt: -------------------------------------------------------------------------------- 1 | HHHHHHHH LLLLLLLL 2 | 3 | 00000HHH HHHHHLLL 4 | 5 | 00000000 00000HHH 6 | 7 | xxxxxxHH HHHHHHLL LLLLLL00 8 | 9 | xxxxxxxH HHHHHHHL LLLLLLL0 10 | 11 | nv-bdizc 12 | 13 | asl a 2 14 | rol ah 5 15 | php 3 16 | asl a 2 17 | rol ah 5 18 | ; ah has the correct form for the low byte of the result now. 19 | pla 4 20 | ; now carry has bit 1 of the accumulator result, and N has bit 0. 21 | asl a 2 22 | adc #0 2 23 | and #3 2 24 | ldx ah 3 25 | sta ah 3 26 | txa 2 27 | 28 | total: 35 29 | naive: 42 30 | 31 | combine with add: 32 | 33 | asl a 34 | rol ah 35 | php 36 | asl a 37 | rol ah 38 | ; ah has the correct form for the low byte of the result now. 39 | pla 40 | ; now carry has bit 1 of the accumulator result, and N has bit 0. 41 | asl a 42 | adc #0 43 | and #3 44 | pha 45 | lda a2 46 | adc ah 47 | sta a4 48 | pla 49 | adc a3 50 | sta a5 51 | 52 | combine with eor/ora/and: 53 | 54 | asl a 55 | rol ah 56 | php 57 | asl a 58 | rol ah 59 | ; ah has the correct form for the low byte of the result now. 60 | pla 61 | ; now carry has bit 1 of the accumulator result, and N has bit 0. 62 | asl a 63 | adc #0 64 | and #3 65 | eor a3 ; for and #imm, can combine with prev insn. 66 | sta a5 67 | lda ah 68 | eor a2 69 | sta a4 70 | 71 | combine with store to ZP: 72 | 73 | asl a 74 | rol ah 75 | php 76 | asl a 77 | rol ah 78 | ; ah has the correct form for the low byte of the result now. 79 | pla 80 | ; now carry has bit 1 of the accumulator result, and N has bit 0. 81 | asl a 82 | adc #0 83 | and #3 84 | sta a3 85 | lda ah 86 | sta a2 87 | 88 | 89 | lsr #5, byteswapped result 90 | -------------------------- 91 | 92 | ah a 93 | -- - 94 | HHHHHHHH LLLLLLLL 95 | 96 | 00000HHH HHHHHLLL 97 | 98 | cmp #$80 ; 2 99 | rol ah ; 5 100 | rol a ; 2 101 | rol ah ; 5 102 | rol a ; 2 103 | rol ah ; 5 104 | rol a ; 2 105 | and #7 ; 2 106 | ldx ah ; 3 107 | sta ah ; 3 108 | txa ; 2 109 | 110 | HHHHHHHL 111 | LLLLLLLH 112 | HHHHHHLL 113 | LLLLLLHH 114 | HHHHHLLL 115 | LLLLLHHH 116 | 117 | lsr #6 again, using the same trick 118 | ---------------------------------- 119 | 120 | cmp #$80 ; 2 121 | rol ah ; 5 122 | rol a ; 2 123 | rol ah ; 5 124 | rol a ; 2 125 | and #3 ; 2 126 | 127 | 128 | Left shifts 129 | =========== 130 | 131 | asl #1 asl #2 asl #3 asl #4 132 | ------ ------ ------ ------ 133 | asl a asl a asl a asl a 134 | rol ah rol ah rol ah rol ah 135 | asl a asl a asl a 136 | rol ah rol ah rol ah 137 | asl a asl a 138 | rol ah rol ah 139 | asl a 140 | rol ah 141 | 142 | asl #5 asl #6 asl #7 asl #8 143 | ------ ------ ------ ------ 144 | asl a tax lsr ah sta ah 145 | rol ah lda ah ror a lda #0 146 | asl a ror a sta ah 147 | rol ah txa lda #0 148 | asl a ror a ror a 149 | rol ah ror ah 150 | asl a ror a 151 | rol ah ror ah 152 | asl a tax 153 | rol ah lda ah 154 | and #$c0 155 | stx ah 156 | 157 | asl #9 asl #10 asl #11 asl #12 158 | ------ ------- ------- ------- 159 | asl a asl a asl a asl a 160 | sta ah asl a asl a asl a 161 | lda #0 sta ah asl a asl a 162 | lda #0 sta ah asl a 163 | lda #0 sta ah 164 | lda #0 165 | 166 | asl #13 asl #14 asl #15 asl #16 167 | ------- ------- ------- ------- 168 | lsr a lsr a lsr a lda #0 169 | ror a ror a lda #0 sta ah 170 | ror a ror a sta ah 171 | ror a and #$c0 ror ah 172 | and #$e0 sta ah 173 | sta ah lda #0 174 | lda #0 175 | 176 | 177 | HHHHHHHH LLLLLLLL 178 | HHHLLLLL LLL00000 179 | 180 | tax 181 | lda ah 182 | ror a 183 | txa 184 | ror a 185 | ror ah 186 | ror a 187 | ror ah 188 | ror a 189 | ror ah 190 | tax 191 | lda ah 192 | and #$e0 193 | stx ah 194 | 195 | HLLLLLLL 196 | LHHHHHHH 197 | HHLLLLLL 198 | LLHHHHHH 199 | HHHLLLLL 200 | LLLHHHHH 201 | 202 | lsr a 203 | ror stmp HHHHHHHH 0LLLLLLL Lxxxxxxx 204 | lsr a 205 | ror stmp HHHHHHHH 00LLLLLL LLxxxxxx 206 | lsr a 207 | ror stmp HHHHHHHH 000LLLLL LLLxxxxx 208 | 209 | 210 | tax 2 211 | lda ah 3 212 | ror a 2 213 | txa 2 214 | ror a 2 215 | ror ah 5 216 | ror a 2 217 | ror ah 5 218 | tax 2 219 | lda ah 3 220 | and #$c0 2 221 | stx ah 3 222 | 223 | asl #7 224 | ------ 225 | 226 | HHHHHHHH LLLLLLLL 227 | HLLLLLLL L0000000 228 | 229 | lsr ah 230 | ror a 231 | sta ah 232 | lda #0 233 | ror a 234 | 235 | asl #13 236 | ------- 237 | 238 | sta ah 239 | lda #0 240 | lsr ah 241 | ror a 242 | lsr ah 243 | ror a 244 | lsr ah 245 | ror a 246 | sta ah 247 | lda #0 248 | 249 | asl #14 250 | ------- 251 | HHHHHHHH LLLLLLLL 252 | LL000000 00000000 253 | 254 | lsr a x7654321 255 | ror a 0x765432 256 | ror a 10x76543 257 | and #$c0 10______ 258 | stz ah 259 | 260 | 261 | asr #1 asr #2 asr #3 asr #4 262 | ------ ------ ------ ------ 263 | ldx ah ldx ah ldx ah ldx ah 264 | cpx #$80 cpx #$80 cpx #$80 cpx #$80 265 | ror ah ror ah ror ah ror ah 266 | ror a ror a ror a ror a 267 | cpx #$80 cpx #$80 cpx #$80 268 | ror ah ror ah ror ah 269 | ror a ror a ror a 270 | cpx #$80 cpx #$80 271 | ror ah ror ah 272 | ror a ror a 273 | cpx #$80 274 | ror ah 275 | ror a 276 | 277 | asr #5 278 | ------ 279 | cmp #$80 280 | rol ah HHHHHHHL 281 | rol a LLLLLLLH 282 | rol ah HHHHHHLL 283 | rol a LLLLLLHH 284 | rol ah HHHHHLLL 285 | rol a LLLLLHHH 286 | and #7 287 | ldx ah 288 | sta ah 289 | and #4 290 | beq nosignext 291 | lda ah 292 | ora #$f8 293 | sta ah 294 | nosignext 295 | txa 296 | 297 | asr #6 298 | ------ 299 | cmp #$80 300 | rol ah HHHHHHHL 301 | rol a LLLLLLLH 302 | rol ah HHHHHHLL 303 | rol a LLLLLLHH 304 | and #3 000000HH 305 | ldx ah 306 | sta ah 307 | and #2 308 | beq nosignext 309 | lda ah 310 | ora #$fc 311 | sta ah 312 | nosignext 313 | txa 314 | 315 | asr #7 316 | ------ 317 | HHHHHHHH LLLLLLLL 318 | sssssssH HHHHHHHL 319 | 320 | cmp #$80 321 | rol ah HHHHHHHL c=original high bit 322 | lda #0 323 | sbc #0 A = A - 0 - (1 - c) 324 | eor #$ff C=0 A = A - 0 - 1 325 | ldx ah C=1 A = A - 0 - 0 326 | sta ah 327 | txa 328 | 329 | asr #8 330 | ------ 331 | ldx #0 332 | bit ah 333 | bpl pos 334 | ldx #$ff 335 | pos 336 | lda ah 337 | stx ah 338 | 339 | normal: byteswapped: 340 | lda ah lda ah 341 | tax ora #$7f 342 | ora #$7f bmi neg 343 | bmi neg lda #0 344 | lda #0 neg 345 | neg 346 | sta ah 347 | txa 348 | 349 | asr #9 asr #10 asr #11 asr #12 350 | ------ ------- ------- ------- 351 | lda ah lda ah lda ah lda ah 352 | tax tax tax tax 353 | ora #$7f ora #$7f ora #$7f ora #$7f 354 | bmi neg bmi neg bmi neg bmi neg 355 | lda #0 lda #0 lda #0 lda #0 356 | neg neg neg neg 357 | sta ah sta ah sta ah sta ah 358 | txa txa txa txa 359 | cmp #$80 cmp #$80 cmp #$80 cmp #$80 360 | ror a ror a ror a ror a 361 | cmp #$80 cmp #$80 cmp #$80 362 | ror a ror a ror a 363 | cmp #$80 cmp #$80 364 | ror a ror a 365 | cmp #$80 366 | ror a 367 | 368 | asr #13 asr #14 asr #15/asr #16 369 | ------- ------- --------------- 370 | HHHHHHHH LLLLLLLL 371 | ssssssss sssssHHH 372 | 373 | asl ah asl ah asl ah 374 | php php lda #0 375 | lda #0 lda #0 sbc #0 376 | sbc #0 sbc #0 eor #$ff 377 | eor #$ff eor #$ff sta ah 378 | tax tax 379 | plp plp 380 | rol a rol a 381 | asl ah asl ah 382 | rol a rol a 383 | asl ah stx ah 384 | rol a 385 | stx ah 386 | -------------------------------------------------------------------------------- /experimental/fpmath.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /*** 9 | 10 | 31 24 23 16 15 8 7 0 11 | .--------.--------.--------.--------. 12 | |exponent|s| mant | mant | mant | 13 | '--------'--------'--------'--------' 14 | 15 | ***/ 16 | 17 | typedef uint32_t sftype; 18 | 19 | static int16_t s_exp; 20 | static uint64_t s_mant; 21 | static char s_sign; 22 | 23 | static void 24 | unpack (sftype x) 25 | { 26 | s_exp = x >> 24; 27 | s_sign = (x & 0x800000) != 0; 28 | s_mant = (uint64_t)(x & 0x7fffff) << 8; 29 | 30 | if (s_exp != 0) 31 | s_mant |= 0x80000000; 32 | } 33 | 34 | static sftype 35 | repack (uint64_t mant, uint16_t exp, char sign) 36 | { 37 | mant = mant >> 8; 38 | //assert (mant & 0x800000); 39 | return (mant & 0x7fffff) | ((sign & 1) << 23) | ((exp & 0xff) << 24); 40 | } 41 | 42 | typedef union 43 | { 44 | float f; 45 | uint32_t i; 46 | } u; 47 | 48 | sftype float_to_sftype (float x) 49 | { 50 | u tmp; 51 | tmp.f = x; 52 | return ((tmp.i & 0x80000000u) >> 8) 53 | | ((tmp.i & 0x7f800000u) << 1) 54 | | (tmp.i & 0x007fffffu); 55 | } 56 | 57 | static void 58 | denormalize (void) 59 | { 60 | //printf ("denormalize: s_mant=%.8llx, s_exp=%d -> ", s_mant, s_exp); 61 | while (s_exp < 130) 62 | { 63 | s_mant >>= 1; 64 | s_exp++; 65 | } 66 | //printf ("s_mant=%.8llx, s_exp=%d\n", s_mant, s_exp); 67 | } 68 | 69 | static void 70 | print_unpacked (const char *routine) 71 | { 72 | return; 73 | printf ("%s: ", routine); 74 | printf ("mantissa: %llx ", s_mant); 75 | printf ("exponent: %d ", s_exp); 76 | printf ("sign: %d\n", s_sign); 77 | } 78 | 79 | static void 80 | mul10 (void) 81 | { 82 | s_mant *= 10; 83 | 84 | while ((s_mant & ~0xffffffffull) != 0) 85 | { 86 | s_mant >>= 1; 87 | s_exp++; 88 | } 89 | print_unpacked ("mul"); 90 | } 91 | 92 | static void 93 | div10 (void) 94 | { 95 | s_exp -= 4; 96 | 97 | //printf ("div10 (0): s_mant: %.8llx\n", s_mant); 98 | 99 | s_mant += s_mant / 2; 100 | //printf ("div10 (1): s_mant: %.8llx\n", s_mant); 101 | s_mant += s_mant / 16; 102 | //printf ("div10 (2): s_mant: %.8llx\n", s_mant); 103 | s_mant += s_mant / 256; 104 | //printf ("div10 (3): s_mant: %.8llx\n", s_mant); 105 | s_mant += s_mant / 65536; 106 | //printf ("div10 (4): s_mant: %.8llx\n", s_mant); 107 | 108 | while ((s_mant & ~0xffffffffull) != 0) 109 | { 110 | s_mant >>= 1; 111 | s_exp++; 112 | } 113 | 114 | //printf ("div10: s_mant: %.8llx, s_exp: %d\n", s_mant, s_exp); 115 | 116 | print_unpacked ("div"); 117 | } 118 | 119 | sftype 120 | fp_add (sftype a, sftype b) 121 | { 122 | bool a_sign = (a & 0x800000) != 0; 123 | bool b_sign = (b & 0x800000) != 0; 124 | int16_t a_exp = a >> 24; 125 | int16_t b_exp = b >> 24; 126 | uint32_t a_mant = a & 0x7fffff; 127 | uint32_t b_mant = b & 0x7fffff; 128 | bool subtract = false; 129 | 130 | if (a_exp != 0) 131 | a_mant |= 0x800000; 132 | 133 | if (b_exp != 0) 134 | b_mant |= 0x800000; 135 | 136 | if (a_sign == b_sign) 137 | ; 138 | else if (b_sign) 139 | { 140 | /* A - B. */ 141 | subtract = true; 142 | b_sign = false; 143 | } 144 | else 145 | /* -A + B == B - A. */ 146 | return fp_add (b, a); 147 | 148 | if (a_exp > b_exp) 149 | { 150 | if (a_exp > b_exp + 23) 151 | return a; 152 | 153 | if (subtract) 154 | { 155 | a_mant -= b_mant >> (a_exp - b_exp); 156 | 157 | if (a_mant & 0x80000000) 158 | { 159 | a_mant = -a_mant; 160 | a_sign = !a_sign; 161 | } 162 | 163 | while ((a_mant & 0xff800000) == 0) 164 | { 165 | a_mant <<= 1; 166 | a_exp--; 167 | } 168 | } 169 | else 170 | a_mant += b_mant >> (a_exp - b_exp); 171 | 172 | while ((a_mant & 0xff000000) != 0) 173 | { 174 | a_mant >>= 1; 175 | a_exp++; 176 | } 177 | 178 | return repack (a_mant << 8, a_exp, a_sign); 179 | } 180 | else 181 | { 182 | if (subtract) 183 | { 184 | b_mant -= a_mant >> (b_exp - a_exp); 185 | 186 | b_sign = !b_sign; 187 | 188 | if (b_mant & 0x80000000) 189 | { 190 | b_mant = -b_mant; 191 | b_sign = !b_sign; 192 | } 193 | 194 | while ((b_mant & 0xff800000) == 0) 195 | { 196 | b_mant <<= 1; 197 | b_exp--; 198 | } 199 | } 200 | else 201 | { 202 | if (b_exp > a_exp + 23) 203 | return b; 204 | 205 | b_mant += a_mant >> (b_exp - a_exp); 206 | } 207 | 208 | while ((b_mant & 0xff000000) != 0) 209 | { 210 | b_mant >>= 1; 211 | b_exp++; 212 | } 213 | 214 | return repack (b_mant << 8, b_exp, b_sign); 215 | } 216 | } 217 | 218 | sftype 219 | fp_sub (sftype a, sftype b) 220 | { 221 | return fp_add (a, b ^ 0x800000); 222 | } 223 | 224 | sftype 225 | fp_mul (sftype a, sftype b) 226 | { 227 | bool a_sign = (a & 0x800000) != 0; 228 | bool b_sign = (b & 0x800000) != 0; 229 | int16_t a_exp = a >> 24; 230 | int16_t b_exp = b >> 24; 231 | uint32_t a_mant = a & 0x7fffff; 232 | uint32_t b_mant = b & 0x7fffff; 233 | uint64_t res; 234 | 235 | if (a_exp != 0) 236 | a_mant |= 0x800000; 237 | 238 | if (b_exp != 0) 239 | b_mant |= 0x800000; 240 | 241 | res = ((uint64_t) a_mant * b_mant) >> 23; 242 | 243 | while ((res & ~0xffffffull) != 0) 244 | { 245 | res >>= 1; 246 | a_exp++; 247 | } 248 | 249 | return repack (res << 8, a_exp + b_exp - 127, a_sign ^ b_sign); 250 | } 251 | 252 | sftype 253 | fp_div (sftype a, sftype b) 254 | { 255 | bool a_sign = (a & 0x800000) != 0; 256 | bool b_sign = (b & 0x800000) != 0; 257 | int16_t a_exp = a >> 24; 258 | int16_t b_exp = b >> 24; 259 | uint32_t a_mant = a & 0x7fffff; 260 | uint32_t b_mant = b & 0x7fffff; 261 | uint64_t res; 262 | 263 | if (a_exp != 0) 264 | a_mant |= 0x800000; 265 | 266 | if (b_exp != 0) 267 | b_mant |= 0x800000; 268 | 269 | res = ((uint64_t) a_mant << 23) / b_mant; 270 | 271 | while ((res & 0xff800000) == 0) 272 | { 273 | res <<= 1; 274 | a_exp--; 275 | } 276 | 277 | return repack (res << 8, a_exp - b_exp + 127, a_sign ^ b_sign); 278 | } 279 | 280 | void 281 | fp_add_s (uint64_t b_mant, int16_t b_exp, bool b_sign) 282 | { 283 | if (s_exp > b_exp) 284 | { 285 | if (s_exp > b_exp + 31) 286 | return; 287 | 288 | printf ("%.8llx\n", (long long) s_mant); 289 | printf ("%.8llx\n", (long long) (b_mant >> (s_exp - b_exp))); 290 | s_mant += b_mant >> (s_exp - b_exp); 291 | 292 | while ((s_mant & ~0xffffffffull) != 0) 293 | { 294 | s_mant >>= 1; 295 | s_exp++; 296 | } 297 | } 298 | else 299 | { 300 | abort(); 301 | if (b_exp > s_exp + 31) 302 | goto out; 303 | 304 | b_mant += s_mant >> (b_exp - s_exp); 305 | 306 | while ((b_mant & ~0xffffffffull) != 0) 307 | { 308 | b_mant >>= 1; 309 | b_exp++; 310 | } 311 | 312 | out: 313 | s_mant = b_mant; 314 | s_exp = b_exp; 315 | } 316 | } 317 | 318 | void 319 | fp_print (FILE *f, sftype x) 320 | { 321 | int dec_exp, place; 322 | bool print_exp = false; 323 | int i, sigfigs = 8; 324 | uint64_t bias_mant; 325 | int16_t bias_exp; 326 | bool bias_sign; 327 | static char output[16]; 328 | int optr = 0; 329 | 330 | unpack (float_to_sftype (5.0)); 331 | for (i = 0; i < sigfigs; i++) 332 | { 333 | printf ("%.8x\n", (int) s_mant); 334 | div10 (); 335 | } 336 | 337 | bias_mant = s_mant; 338 | bias_exp = s_exp; 339 | printf ("bias: %.2x\n", (int) bias_exp); 340 | 341 | unpack (x); 342 | 343 | bias_sign = s_sign; 344 | 345 | if (s_sign) 346 | output[optr++] = '-'; 347 | 348 | if (s_exp == 0 && s_mant == 0) 349 | { 350 | strcpy (&output[optr], "0"); 351 | goto do_print; 352 | } 353 | 354 | dec_exp = 0; 355 | 356 | print_unpacked ("start"); 357 | 358 | while (s_exp < 127) 359 | { 360 | mul10 (); 361 | dec_exp--; 362 | } 363 | 364 | while (s_exp > 130 || (s_exp == 130 && s_mant >= 0xa0000000)) 365 | { 366 | div10 (); 367 | dec_exp++; 368 | } 369 | 370 | fp_add_s (bias_mant, bias_exp, bias_sign); 371 | 372 | /* Did we overflow? */ 373 | while (s_exp > 130 || (s_exp == 130 && s_mant >= 0xa0000000)) 374 | { 375 | div10 (); 376 | dec_exp++; 377 | } 378 | 379 | if (dec_exp < -3 || dec_exp > 8) 380 | print_exp = true; 381 | 382 | if (dec_exp < 0 && !print_exp) 383 | { 384 | output[optr++] = '0'; 385 | output[optr++] = '.'; 386 | for (place = dec_exp; place < -1; place++) 387 | output[optr++] = '0'; 388 | } 389 | 390 | //printf ("dec_exp: %d\n", dec_exp); 391 | 392 | for (place = 0; 393 | place < sigfigs || (!print_exp && place <= dec_exp); 394 | place++) 395 | { 396 | uint32_t digit; 397 | bool lastplace = (place == sigfigs - 1); 398 | 399 | denormalize (); 400 | 401 | digit = s_mant >> 28; 402 | 403 | output[optr++] = digit + '0'; 404 | 405 | s_mant &= 0x0fffffffull; 406 | 407 | if ((print_exp && place == 0 && !lastplace) 408 | || (!print_exp && place == dec_exp && !lastplace)) 409 | output[optr++] = '.'; 410 | 411 | mul10 (); 412 | } 413 | 414 | place--; 415 | 416 | while (optr > 0 && output[optr - 1] == '0' && place > dec_exp) 417 | optr--, place--; 418 | 419 | if (optr > 0 && output[optr - 1] == '.') 420 | optr--; 421 | 422 | output[optr] = '\0'; 423 | 424 | if (print_exp) 425 | { 426 | output[optr++] = 'E'; 427 | optr += sprintf (&output[optr], "%d", dec_exp); 428 | } 429 | 430 | do_print: 431 | fputs (output, f); 432 | } 433 | 434 | 435 | int main (void) 436 | { 437 | float q; 438 | int i; 439 | 440 | /* fp_print (stdout, float_to_sftype (1.0)); 441 | fputc ('\n', stdout); 442 | 443 | fp_print (stdout, float_to_sftype (1.001)); 444 | fputc ('\n', stdout); 445 | 446 | fp_print (stdout, float_to_sftype (9.9999)); 447 | fputc ('\n', stdout); 448 | 449 | fp_print (stdout, float_to_sftype (0.001)); 450 | fputc ('\n', stdout); 451 | 452 | fp_print (stdout, float_to_sftype (10)); 453 | fputc ('\n', stdout);*/ 454 | 455 | fp_print (stdout, float_to_sftype (1.1)); 456 | fputc ('\n', stdout); 457 | 458 | /* fp_print (stdout, float_to_sftype (100)); 459 | fputc ('\n', stdout); 460 | 461 | fp_print (stdout, float_to_sftype (135)); 462 | fputc ('\n', stdout); 463 | 464 | fp_print (stdout, float_to_sftype (0.1)); 465 | fputc ('\n', stdout); 466 | 467 | fp_print (stdout, float_to_sftype (1234.56)); 468 | fputc ('\n', stdout); 469 | 470 | fp_print (stdout, float_to_sftype (1000000.5)); 471 | fputc ('\n', stdout); 472 | 473 | fp_print (stdout, float_to_sftype (23400000.5)); 474 | fputc ('\n', stdout); 475 | 476 | fp_print (stdout, float_to_sftype (8388608)); 477 | fputc ('\n', stdout); 478 | 479 | fp_print (stdout, float_to_sftype (16777216)); 480 | fputc ('\n', stdout); 481 | 482 | fp_print (stdout, float_to_sftype (-7.33)); 483 | fputc ('\n', stdout); 484 | 485 | for (i = 0; i < 30; i++) 486 | { 487 | fp_print (stdout, float_to_sftype ((float) 1.5 + i / 10.0)); 488 | fputc ('\n', stdout); 489 | } 490 | 491 | for (i = 0; i < 30; i++) 492 | { 493 | float rnd = drand48 () * 1000.0; 494 | printf ("num: %f\nmy routine: ", rnd); 495 | fp_print (stdout, float_to_sftype (rnd)); 496 | fputc ('\n', stdout); 497 | } 498 | 499 | fp_print (stdout, fp_add (float_to_sftype (1.0), float_to_sftype (2.0))); 500 | fputc ('\n', stdout); 501 | 502 | fp_print (stdout, fp_add (float_to_sftype (1.0), float_to_sftype (-2.0))); 503 | fputc ('\n', stdout); 504 | 505 | fp_print (stdout, fp_add (float_to_sftype (-1.0), float_to_sftype (-2.0))); 506 | fputc ('\n', stdout); 507 | 508 | fp_print (stdout, fp_add (float_to_sftype (-1.0), float_to_sftype (2.0))); 509 | fputc ('\n', stdout); 510 | 511 | fp_print (stdout, fp_add (float_to_sftype (2.0), float_to_sftype (1.0))); 512 | fputc ('\n', stdout); 513 | 514 | fp_print (stdout, fp_add (float_to_sftype (2.0), float_to_sftype (-1.0))); 515 | fputc ('\n', stdout); 516 | 517 | fp_print (stdout, fp_add (float_to_sftype (-2.0), float_to_sftype (-1.0))); 518 | fputc ('\n', stdout); 519 | 520 | fp_print (stdout, fp_add (float_to_sftype (-2.0), float_to_sftype (1.0))); 521 | fputc ('\n', stdout); 522 | 523 | fp_print (stdout, fp_sub (float_to_sftype (10.0), float_to_sftype (10.254))); 524 | fputc ('\n', stdout); 525 | 526 | fp_print (stdout, fp_mul (float_to_sftype (0.05), float_to_sftype (-999))); 527 | fputc ('\n', stdout); 528 | 529 | fp_print (stdout, fp_div (float_to_sftype (1.3333), float_to_sftype (0.125))); 530 | fputc ('\n', stdout); 531 | 532 | fp_print (stdout, 0x81200000); 533 | fputc ('\n', stdout); 534 | 535 | fp_print (stdout, 0x7e800000); 536 | fputc ('\n', stdout);*/ 537 | } 538 | -------------------------------------------------------------------------------- /failproc/compile.sh: -------------------------------------------------------------------------------- 1 | ocamlfind ocamlc -package str,fileutils -linkpkg failproc.ml -o failproc 2 | -------------------------------------------------------------------------------- /failproc/failproc.ml: -------------------------------------------------------------------------------- 1 | type result = PASS | FAIL | XPASS | XFAIL | ERROR | UNSUPPORTED | UNRESOLVED 2 | | WARNING | UNTESTED | KFAIL | GDB_compile_failed | Misc_error 3 | 4 | type line_type = Result of result * string 5 | | Test_error of result * string 6 | | Begin_exp of string 7 | | Summary of string 8 | | Unknown 9 | 10 | let output_line ofh str = 11 | Printf.fprintf ofh "%s\n" str 12 | 13 | let rec skip_header fh ofh = 14 | try 15 | let line = input_line fh in 16 | output_line ofh line; 17 | if String.length line >= 7 && (String.sub line 0 7) = "Running" then () 18 | else skip_header fh ofh 19 | with End_of_file -> () 20 | 21 | exception Bad_line 22 | 23 | let running_exp_file = Str.regexp "^Running \\([^ ]*\\)" 24 | 25 | let summary_line = Str.regexp "^[ \t]*=== [^ ]+ Summary ===" 26 | 27 | let classify line = 28 | if Str.string_match running_exp_file line 0 then 29 | Begin_exp (Str.matched_group 1 line) 30 | else if Str.string_match summary_line line 0 then 31 | Summary line 32 | else begin 33 | try 34 | let idx = String.index line ':' in 35 | let res = String.sub line 0 idx 36 | and test = String.sub line (idx + 2) ((String.length line) - (idx + 2)) in 37 | let restype = match res with 38 | "PASS" -> PASS 39 | | "FAIL" -> FAIL 40 | | "XPASS" -> XPASS 41 | | "XFAIL" -> XFAIL 42 | | "ERROR" -> ERROR 43 | | "UNSUPPORTED" -> UNSUPPORTED 44 | | "UNRESOLVED" -> UNRESOLVED 45 | | "WARNING" -> WARNING 46 | | "UNTESTED" -> UNTESTED 47 | | "KFAIL" -> KFAIL 48 | | _ -> raise Bad_line in 49 | Result (restype, test) 50 | with 51 | Not_found -> Unknown 52 | | Invalid_argument "String.sub" -> raise Bad_line 53 | end 54 | 55 | let contains_regex regex str = 56 | try 57 | let _ = Str.search_forward regex str 0 in 58 | true 59 | with Not_found -> false 60 | 61 | let expfile_strip expfile testsuite_dir = 62 | let path = FilePath.DefaultPath.filename_of_string expfile in 63 | let rec scan p = 64 | if FilePath.basename p = testsuite_dir then 65 | FilePath.make_relative p path 66 | else 67 | let updir = FilePath.dirname p in 68 | if FilePath.is_updir updir p then scan updir else expfile in 69 | scan path 70 | 71 | let string_of_result = function 72 | PASS -> "PASS" 73 | | FAIL -> "FAIL" 74 | | XPASS -> "XPASS" 75 | | XFAIL -> "XFAIL" 76 | | ERROR -> "ERROR" 77 | | UNSUPPORTED -> "UNSUPPORTED" 78 | | UNRESOLVED -> "UNRESOLVED" 79 | | WARNING -> "WARNING" 80 | | UNTESTED -> "UNTESTED" 81 | | KFAIL -> "KFAIL" 82 | | GDB_compile_failed -> "GDB_compile_failed" 83 | | Misc_error -> "Misc_error" 84 | 85 | exception Changed 86 | 87 | let process_sum_file sumfile outfile xfails = 88 | let gdb_comp_failed = Str.regexp "\\(^gdb compile failed, \\)" in 89 | let line_number = ref 1 90 | and current_expfile = ref "(unknown exp file)" 91 | and fh = open_in sumfile 92 | and ofh = open_out outfile in 93 | let unrescount = ref 0 94 | and passcount = ref 0 95 | and failcount = ref 0 96 | and xfailcount = ref 0 97 | and xpasscount = ref 0 98 | and unsupcount = ref 0 in 99 | skip_header fh ofh; 100 | try 101 | while true do 102 | let line = input_line fh in 103 | let classified = 104 | try 105 | classify line 106 | with Bad_line -> 107 | if Str.string_match gdb_comp_failed line 0 then 108 | let testname = Str.string_after line (Str.match_end ()) in 109 | Test_error (GDB_compile_failed, testname) 110 | else 111 | Test_error (Misc_error, line) in 112 | begin match classified with 113 | Unknown -> 114 | output_line ofh line 115 | | Begin_exp e -> 116 | let stripped = expfile_strip e "testsuite" in 117 | current_expfile := stripped; 118 | output_line ofh line 119 | | Result (res, test) -> 120 | begin try 121 | begin match res with 122 | PASS -> incr passcount 123 | | XFAIL -> incr xfailcount 124 | | XPASS -> incr xpasscount 125 | | UNSUPPORTED -> incr unsupcount 126 | | UNRESOLVED -> incr unrescount 127 | | FAIL -> 128 | begin try 129 | match Hashtbl.find xfails test with 130 | FAIL -> 131 | incr xfailcount; 132 | Printf.fprintf ofh "XFAIL: %s\n" test; 133 | raise Changed 134 | | _ -> failwith "XFAIL file should contain FAIL lines only" 135 | with Not_found -> 136 | incr failcount 137 | end 138 | | _ -> () 139 | end; 140 | output_line ofh line 141 | with Changed -> () 142 | end 143 | | Test_error (res, test) -> 144 | output_line ofh line 145 | | Summary line -> 146 | output_line ofh line; 147 | raise End_of_file 148 | end; 149 | incr line_number 150 | done; 151 | with End_of_file -> 152 | let print_summary ofh = 153 | Printf.fprintf ofh "\n# of expected passes\t\t%d\n" !passcount; 154 | Printf.fprintf ofh "# of unexpected failures\t%d\n" !failcount; 155 | Printf.fprintf ofh "# of unexpected successes\t%d\n" !xpasscount; 156 | Printf.fprintf ofh "# of expected failures\t\t%d\n" !xfailcount; 157 | Printf.fprintf ofh "# of unresolved testcases\t%d\n" !unrescount; 158 | Printf.fprintf ofh "# of unsupported testcases\t%d\n" !unsupcount in 159 | print_summary ofh; 160 | print_summary stdout; 161 | close_in fh; 162 | close_out ofh 163 | 164 | let read_xfail_file xfailfile = 165 | let line_number = ref 1 166 | and fh = open_in xfailfile 167 | and ht = Hashtbl.create 30 in 168 | try 169 | while true do 170 | let line = input_line fh in 171 | let classified = 172 | try 173 | classify line 174 | with Bad_line -> 175 | failwith (Printf.sprintf "Bad line in xfail file (%d)" 176 | !line_number) in 177 | begin match classified with 178 | Unknown | Begin_exp _ | Summary _ -> () 179 | | Result (res, test) 180 | | Test_error (res, test) -> 181 | if not (Hashtbl.mem ht test) then 182 | Hashtbl.add ht test res 183 | end; 184 | incr line_number 185 | done; 186 | failwith "unreachable" 187 | with End_of_file -> close_in fh; ht 188 | 189 | let _ = 190 | let insum = ref "" 191 | and outsum = ref "" 192 | and xfailfile = ref "" in 193 | let args = [ 194 | "-i", Arg.Set_string insum, "Input sum file"; 195 | "-o", Arg.Set_string outsum, "Output sum file"; 196 | "-x", Arg.Set_string xfailfile, "XFAILs file" 197 | ] 198 | and usage = "Usage: failproc -i -o -x " in 199 | Arg.parse args (fun _ -> ()) usage; 200 | if !insum = "" || !outsum = "" || !xfailfile = "" then 201 | failwith usage; 202 | let xfails = read_xfail_file !xfailfile in 203 | process_sum_file !insum !outsum xfails 204 | -------------------------------------------------------------------------------- /gcc.xfail: -------------------------------------------------------------------------------- 1 | # No nested function support. 2 | FAIL: gcc.c-torture/compile/20010903-2.c -O0 (test for excess errors) 3 | FAIL: gcc.c-torture/compile/20031011-1.c -O0 (test for excess errors) 4 | FAIL: gcc.c-torture/compile/20040310-1.c -O0 (test for excess errors) 5 | FAIL: gcc.c-torture/compile/20040317-3.c -O0 (test for excess errors) 6 | FAIL: gcc.c-torture/compile/20050119-1.c -O0 (test for excess errors) 7 | FAIL: gcc.c-torture/compile/20050119-1.c -O1 (test for excess errors) 8 | FAIL: gcc.c-torture/compile/20050119-1.c -O2 (test for excess errors) 9 | FAIL: gcc.c-torture/compile/20050119-1.c -Os (test for excess errors) 10 | FAIL: gcc.c-torture/compile/930506-2.c -O0 (test for excess errors) 11 | FAIL: gcc.c-torture/compile/930506-2.c -O1 (test for excess errors) 12 | FAIL: gcc.c-torture/compile/930506-2.c -O2 (test for excess errors) 13 | FAIL: gcc.c-torture/compile/930506-2.c -O3 -fomit-frame-pointer (test for excess errors) 14 | FAIL: gcc.c-torture/compile/930506-2.c -O3 -g (test for excess errors) 15 | FAIL: gcc.c-torture/compile/930506-2.c -Os (test for excess errors) 16 | FAIL: gcc.c-torture/compile/nested-2.c -O0 (test for excess errors) 17 | FAIL: gcc.c-torture/compile/pr21728.c -O0 (test for excess errors) 18 | FAIL: gcc.c-torture/compile/pr21728.c -O1 (test for excess errors) 19 | FAIL: gcc.c-torture/compile/pr21728.c -O2 (test for excess errors) 20 | FAIL: gcc.c-torture/compile/pr21728.c -O3 -fomit-frame-pointer (test for excess errors) 21 | FAIL: gcc.c-torture/compile/pr21728.c -O3 -g (test for excess errors) 22 | FAIL: gcc.c-torture/compile/pr21728.c -Os (test for excess errors) 23 | FAIL: gcc.c-torture/compile/pr35006.c -O0 (test for excess errors) 24 | FAIL: gcc.c-torture/compile/pr35006.c -O2 (test for excess errors) 25 | FAIL: gcc.c-torture/compile/pr35006.c -Os (test for excess errors) 26 | 27 | # Size of array too large. 28 | FAIL: gcc.c-torture/compile/20031023-4.c -O0 (test for excess errors) 29 | FAIL: gcc.c-torture/compile/20031023-4.c -O1 (test for excess errors) 30 | FAIL: gcc.c-torture/compile/20031023-4.c -O2 (test for excess errors) 31 | FAIL: gcc.c-torture/compile/20031023-4.c -O3 -fomit-frame-pointer (test for excess errors) 32 | FAIL: gcc.c-torture/compile/20031023-4.c -O3 -g (test for excess errors) 33 | FAIL: gcc.c-torture/compile/20031023-4.c -Os (test for excess errors) 34 | FAIL: gcc.c-torture/compile/pr35006.c -O1 (test for excess errors) 35 | 36 | # Shift count too big 37 | FAIL: gcc.c-torture/compile/20090721-1.c -O0 (test for excess errors) 38 | FAIL: gcc.c-torture/compile/20090721-1.c -O1 (test for excess errors) 39 | FAIL: gcc.c-torture/compile/20090721-1.c -O2 (test for excess errors) 40 | FAIL: gcc.c-torture/compile/20090721-1.c -O3 -fomit-frame-pointer (test for excess errors) 41 | FAIL: gcc.c-torture/compile/20090721-1.c -O3 -g (test for excess errors) 42 | FAIL: gcc.c-torture/compile/20090721-1.c -Os (test for excess errors) 43 | FAIL: gcc.c-torture/compile/920501-3.c -O0 (test for excess errors) 44 | FAIL: gcc.c-torture/compile/920501-3.c -O1 (test for excess errors) 45 | FAIL: gcc.c-torture/compile/920501-3.c -O2 (test for excess errors) 46 | FAIL: gcc.c-torture/compile/920501-3.c -O3 -fomit-frame-pointer (test for excess errors) 47 | FAIL: gcc.c-torture/compile/920501-3.c -O3 -g (test for excess errors) 48 | FAIL: gcc.c-torture/compile/920501-3.c -Os (test for excess errors) 49 | 50 | # No builtin_apply support 51 | FAIL: gcc.c-torture/compile/930623-1.c -O0 (internal compiler error) 52 | FAIL: gcc.c-torture/compile/930623-1.c -O0 (test for excess errors) 53 | FAIL: gcc.c-torture/compile/930623-1.c -O1 (internal compiler error) 54 | FAIL: gcc.c-torture/compile/930623-1.c -O1 (test for excess errors) 55 | FAIL: gcc.c-torture/compile/930623-1.c -O2 (internal compiler error) 56 | FAIL: gcc.c-torture/compile/930623-1.c -O2 (test for excess errors) 57 | FAIL: gcc.c-torture/compile/930623-1.c -O3 -fomit-frame-pointer (internal compiler error) 58 | FAIL: gcc.c-torture/compile/930623-1.c -O3 -fomit-frame-pointer (test for excess errors) 59 | FAIL: gcc.c-torture/compile/930623-1.c -O3 -g (internal compiler error) 60 | FAIL: gcc.c-torture/compile/930623-1.c -O3 -g (test for excess errors) 61 | FAIL: gcc.c-torture/compile/930623-1.c -Os (internal compiler error) 62 | FAIL: gcc.c-torture/compile/930623-1.c -Os (test for excess errors) 63 | 64 | # Maximum string size exceeded (assembler) 65 | FAIL: gcc.c-torture/compile/limits-stringlit.c -O0 (test for excess errors) 66 | FAIL: gcc.c-torture/compile/limits-stringlit.c -O1 (test for excess errors) 67 | FAIL: gcc.c-torture/compile/limits-stringlit.c -O2 (test for excess errors) 68 | FAIL: gcc.c-torture/compile/limits-stringlit.c -O3 -fomit-frame-pointer (test for excess errors) 69 | FAIL: gcc.c-torture/compile/limits-stringlit.c -O3 -g (test for excess errors) 70 | FAIL: gcc.c-torture/compile/limits-stringlit.c -Os (test for excess errors) 71 | FAIL: gcc.c-torture/compile/pr37669-2.c -O0 (test for excess errors) 72 | FAIL: gcc.c-torture/compile/pr37669-2.c -O1 (test for excess errors) 73 | FAIL: gcc.c-torture/compile/pr37669-2.c -O2 (test for excess errors) 74 | FAIL: gcc.c-torture/compile/pr37669-2.c -O3 -fomit-frame-pointer (test for excess errors) 75 | FAIL: gcc.c-torture/compile/pr37669-2.c -O3 -g (test for excess errors) 76 | FAIL: gcc.c-torture/compile/pr37669-2.c -Os (test for excess errors) 77 | 78 | # assembler syntax error (mangling) 79 | FAIL: gcc.c-torture/compile/mangle-1.c -O0 (test for excess errors) 80 | FAIL: gcc.c-torture/compile/mangle-1.c -O1 (test for excess errors) 81 | FAIL: gcc.c-torture/compile/mangle-1.c -O2 (test for excess errors) 82 | FAIL: gcc.c-torture/compile/mangle-1.c -O3 -fomit-frame-pointer (test for excess errors) 83 | FAIL: gcc.c-torture/compile/mangle-1.c -O3 -g (test for excess errors) 84 | FAIL: gcc.c-torture/compile/mangle-1.c -Os (test for excess errors) 85 | 86 | # assembler syntax (newline in string constant) 87 | FAIL: gcc.c-torture/compile/pr46534.c -O0 (test for excess errors) 88 | FAIL: gcc.c-torture/compile/pr46534.c -O1 (test for excess errors) 89 | FAIL: gcc.c-torture/compile/pr46534.c -O2 (test for excess errors) 90 | FAIL: gcc.c-torture/compile/pr46534.c -O3 -fomit-frame-pointer (test for excess errors) 91 | FAIL: gcc.c-torture/compile/pr46534.c -O3 -g (test for excess errors) 92 | FAIL: gcc.c-torture/compile/pr46534.c -Os (test for excess errors) 93 | 94 | # bad segments 95 | FAIL: gcc.c-torture/compile/pr60655-1.c -O0 (test for excess errors) 96 | FAIL: gcc.c-torture/compile/pr60655-1.c -O1 (test for excess errors) 97 | FAIL: gcc.c-torture/compile/pr60655-1.c -O2 (test for excess errors) 98 | FAIL: gcc.c-torture/compile/pr60655-1.c -O3 -fomit-frame-pointer (test for excess errors) 99 | FAIL: gcc.c-torture/compile/pr60655-1.c -O3 -fomit-frame-pointer -funroll-loops (test for excess errors) 100 | FAIL: gcc.c-torture/compile/pr60655-1.c -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions (test for excess errors) 101 | FAIL: gcc.c-torture/compile/pr60655-1.c -O3 -g (test for excess errors) 102 | FAIL: gcc.c-torture/compile/pr60655-1.c -Os (test for excess errors) 103 | 104 | # no simd support. 105 | FAIL: gcc.c-torture/compile/simd-1.c -O0 (test for excess errors) 106 | FAIL: gcc.c-torture/compile/simd-1.c -O1 (test for excess errors) 107 | FAIL: gcc.c-torture/compile/simd-1.c -O2 (test for excess errors) 108 | FAIL: gcc.c-torture/compile/simd-1.c -O3 -fomit-frame-pointer (test for excess errors) 109 | FAIL: gcc.c-torture/compile/simd-1.c -O3 -g (test for excess errors) 110 | FAIL: gcc.c-torture/compile/simd-1.c -Os (test for excess errors) 111 | FAIL: gcc.c-torture/compile/simd-5.c -O0 (test for excess errors) 112 | FAIL: gcc.c-torture/compile/simd-5.c -O1 (test for excess errors) 113 | FAIL: gcc.c-torture/compile/simd-5.c -O2 (test for excess errors) 114 | FAIL: gcc.c-torture/compile/simd-5.c -O3 -fomit-frame-pointer (test for excess errors) 115 | FAIL: gcc.c-torture/compile/simd-5.c -O3 -g (test for excess errors) 116 | FAIL: gcc.c-torture/compile/simd-5.c -Os (test for excess errors) 117 | FAIL: gcc.c-torture/compile/simd-6.c -O0 (test for excess errors) 118 | FAIL: gcc.c-torture/compile/simd-6.c -O1 (test for excess errors) 119 | FAIL: gcc.c-torture/compile/simd-6.c -O2 (test for excess errors) 120 | FAIL: gcc.c-torture/compile/simd-6.c -O3 -fomit-frame-pointer (test for excess errors) 121 | FAIL: gcc.c-torture/compile/simd-6.c -O3 -g (test for excess errors) 122 | FAIL: gcc.c-torture/compile/simd-6.c -Os (test for excess errors) 123 | FAIL: gcc.c-torture/compile/vector-4.c -O0 (test for excess errors) 124 | FAIL: gcc.c-torture/compile/vector-4.c -O1 (test for excess errors) 125 | FAIL: gcc.c-torture/compile/vector-4.c -O2 (test for excess errors) 126 | FAIL: gcc.c-torture/compile/vector-4.c -O3 -fomit-frame-pointer (test for excess errors) 127 | FAIL: gcc.c-torture/compile/vector-4.c -O3 -g (test for excess errors) 128 | FAIL: gcc.c-torture/compile/vector-4.c -Os (test for excess errors) 129 | FAIL: gcc.c-torture/compile/vector-align-1.c -O0 (test for excess errors) 130 | FAIL: gcc.c-torture/compile/vector-align-1.c -O1 (test for excess errors) 131 | FAIL: gcc.c-torture/compile/vector-align-1.c -O2 (test for excess errors) 132 | FAIL: gcc.c-torture/compile/vector-align-1.c -O3 -fomit-frame-pointer (test for excess errors) 133 | FAIL: gcc.c-torture/compile/vector-align-1.c -O3 -g (test for excess errors) 134 | FAIL: gcc.c-torture/compile/vector-align-1.c -Os (test for excess errors) 135 | 136 | # long long isn't long enough 137 | FAIL: gcc.c-torture/execute/20000402-1.c execution, -O0 138 | FAIL: gcc.c-torture/execute/20000402-1.c execution, -O1 139 | FAIL: gcc.c-torture/execute/20000402-1.c execution, -O2 140 | FAIL: gcc.c-torture/execute/20000402-1.c execution, -O3 -fomit-frame-pointer 141 | FAIL: gcc.c-torture/execute/20000402-1.c execution, -O3 -g 142 | FAIL: gcc.c-torture/execute/20000402-1.c execution, -Os 143 | FAIL: gcc.c-torture/execute/20000402-1.c execution, -Og -g 144 | 145 | # recursion too deep (should be tailcall?) 146 | FAIL: gcc.c-torture/execute/20000412-2.c execution, -O0 147 | FAIL: gcc.c-torture/execute/20000412-2.c execution, -O1 148 | FAIL: gcc.c-torture/execute/20000412-2.c execution, -O2 149 | FAIL: gcc.c-torture/execute/20000412-2.c execution, -Os 150 | FAIL: gcc.c-torture/execute/20000412-2.c execution, -Og -g 151 | 152 | # long long isn't long enough 153 | FAIL: gcc.c-torture/execute/20000717-2.c execution, -O0 154 | FAIL: gcc.c-torture/execute/20000717-2.c execution, -O1 155 | FAIL: gcc.c-torture/execute/20000717-2.c execution, -O2 156 | FAIL: gcc.c-torture/execute/20000717-2.c execution, -O3 -fomit-frame-pointer 157 | FAIL: gcc.c-torture/execute/20000717-2.c execution, -O3 -g 158 | FAIL: gcc.c-torture/execute/20000717-2.c execution, -Os 159 | FAIL: gcc.c-torture/execute/20000717-2.c execution, -Og -g 160 | 161 | # Lots of alloca/builtin_return_address calls -- who knows 162 | FAIL: gcc.c-torture/execute/20010122-1.c execution, -O0 163 | FAIL: gcc.c-torture/execute/20010122-1.c execution, -O1 164 | FAIL: gcc.c-torture/execute/20010122-1.c execution, -O2 165 | FAIL: gcc.c-torture/execute/20010122-1.c execution, -O3 -g 166 | FAIL: gcc.c-torture/execute/20010122-1.c execution, -Os 167 | FAIL: gcc.c-torture/execute/20010122-1.c execution, -Og -g 168 | 169 | # No nested function support 170 | FAIL: gcc.c-torture/execute/20010209-1.c execution, -O0 171 | FAIL: gcc.c-torture/execute/20010209-1.c execution, -O1 172 | FAIL: gcc.c-torture/execute/20010209-1.c execution, -Os 173 | 174 | # Not sure. 175 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -O0 176 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -O1 177 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -O2 178 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -O3 -fomit-frame-pointer 179 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -O3 -fomit-frame-pointer -funroll-loops 180 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions 181 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -O3 -g 182 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -Os 183 | FAIL: gcc.c-torture/execute/20020412-1.c execution, -Og -g 184 | -------------------------------------------------------------------------------- /ldscripts/bbcb.cfg: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | ZP: start = $0000, size = $0090, type = rw, define = yes; 3 | RAM: start = $1900, size = $6300, file = %O, define = yes; 4 | } 5 | SEGMENTS { 6 | STARTUP: load = RAM, type = ro; 7 | LOWCODE: load = RAM, type = ro, optional = yes; 8 | INIT: load = RAM, type = ro, define = yes, optional = yes; 9 | CODE: load = RAM, type = ro; 10 | RODATA: load = RAM, type = ro; 11 | DATA: load = RAM, type = rw, define = yes; 12 | BSS: load = RAM, type = bss, define = yes; 13 | HEAP: load = RAM, type = bss, define = yes, optional = yes; 14 | ZEROPAGE: load = ZP, type = zp; 15 | } 16 | FEATURES { 17 | CONDES: segment = INIT, 18 | type = constructor, 19 | label = __CONSTRUCTOR_TABLE__, 20 | count = __CONSTRUCTOR_COUNT__; 21 | CONDES: segment = RODATA, 22 | type = destructor, 23 | label = __DESTRUCTOR_TABLE__, 24 | count = __DESTRUCTOR_COUNT__; 25 | CONDES: type = interruptor, 26 | segment = RODATA, 27 | label = __INTERRUPTOR_TABLE__, 28 | count = __INTERRUPTOR_COUNT__; 29 | } 30 | SYMBOLS { 31 | __STACKTOP__: type = weak, value = $7bff; 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ldscripts/bbcmaster.cfg: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | ZP: start = $0000, size = $0090, type = rw, define = yes; 3 | RAM: start = $0e00, size = $7200, file = %O, define = yes; 4 | } 5 | SEGMENTS { 6 | STARTUP: load = RAM, type = ro; 7 | LOWCODE: load = RAM, type = ro, optional = yes; 8 | INIT: load = RAM, type = ro, define = yes, optional = yes; 9 | CODE: load = RAM, type = ro; 10 | RODATA: load = RAM, type = ro; 11 | DATA: load = RAM, type = rw, define = yes; 12 | BSS: load = RAM, type = bss, define = yes; 13 | HEAP: load = RAM, type = bss, optional = yes, define = yes; 14 | ZEROPAGE: load = ZP, type = zp; 15 | } 16 | FEATURES { 17 | CONDES: segment = INIT, 18 | type = constructor, 19 | label = __CONSTRUCTOR_TABLE__, 20 | count = __CONSTRUCTOR_COUNT__; 21 | CONDES: segment = RODATA, 22 | type = destructor, 23 | label = __DESTRUCTOR_TABLE__, 24 | count = __DESTRUCTOR_COUNT__; 25 | CONDES: type = interruptor, 26 | segment = RODATA, 27 | label = __INTERRUPTOR_TABLE__, 28 | count = __INTERRUPTOR_COUNT__; 29 | } 30 | SYMBOLS { 31 | __STACKTOP__: type = weak, value = $7fff; 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ldscripts/c64.cfg: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | ZP: start = $0002, size = $0070, type = rw, define = yes; 3 | LOADADDR: start = $07ff, size = $2, file = %O; 4 | EXEHDR: start = $0801, size = $0c, file = %O; 5 | RAM: start = $080d, size = $cfff-$0801, file = %O, define = yes; 6 | } 7 | SEGMENTS { 8 | LOADADDR: load = LOADADDR, type = ro; 9 | EXEHDR: load = EXEHDR, type = ro; 10 | STARTUP: load = RAM, type = ro, define = yes; 11 | LOWCODE: load = RAM, type = ro, optional = yes; 12 | INIT: load = RAM, type = ro, define = yes, optional = yes; 13 | CODE: load = RAM, type = ro; 14 | RODATA: load = RAM, type = ro; 15 | DATA: load = RAM, type = rw, define = yes; 16 | BSS: load = RAM, type = bss, define = yes; 17 | HEAP: load = RAM, type = bss, optional = yes, define = yes; 18 | ZEROPAGE: load = ZP, type = zp; 19 | } 20 | FEATURES { 21 | CONDES: segment = INIT, 22 | type = constructor, 23 | label = __CONSTRUCTOR_TABLE__, 24 | count = __CONSTRUCTOR_COUNT__; 25 | CONDES: segment = RODATA, 26 | type = destructor, 27 | label = __DESTRUCTOR_TABLE__, 28 | count = __DESTRUCTOR_COUNT__; 29 | CONDES: type = interruptor, 30 | segment = RODATA, 31 | label = __INTERRUPTOR_TABLE__, 32 | count = __INTERRUPTOR_COUNT__; 33 | } 34 | SYMBOLS { 35 | __STACKTOP__: type = weak, value = $cfff; 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /ldscripts/semi65x.cfg: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | ZP: start = $0000, size = $0070, type = rw, define = yes; 3 | RAM: start = $0200, size = $fd00, file = %O, define = yes; 4 | } 5 | SEGMENTS { 6 | STARTUP: load = RAM, type = ro; 7 | LOWCODE: load = RAM, type = ro, optional = yes; 8 | INIT: load = RAM, type = ro, define = yes, optional = yes; 9 | CODE: load = RAM, type = ro; 10 | RODATA: load = RAM, type = ro; 11 | DATA: load = RAM, type = rw, align=4, define = yes; 12 | BSS: load = RAM, type = bss, align=32, define = yes; 13 | HEAP: load = RAM, type = bss, define = yes, optional = yes; 14 | ZEROPAGE: load = ZP, type = zp; 15 | } 16 | FEATURES { 17 | CONDES: segment = INIT, 18 | type = constructor, 19 | label = __CONSTRUCTOR_TABLE__, 20 | count = __CONSTRUCTOR_COUNT__; 21 | CONDES: segment = RODATA, 22 | type = destructor, 23 | label = __DESTRUCTOR_TABLE__, 24 | count = __DESTRUCTOR_COUNT__; 25 | CONDES: type = interruptor, 26 | segment = RODATA, 27 | label = __INTERRUPTOR_TABLE__, 28 | count = __INTERRUPTOR_COUNT__; 29 | } 30 | SYMBOLS { 31 | __STACKTOP__: type = weak, value = $ffe0; 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /libtinyc/abort.c: -------------------------------------------------------------------------------- 1 | 2 | __attribute__((noreturn)) void 3 | abort (void) 4 | { 5 | register unsigned char retcode __asm__ ("a") = 1; 6 | __asm__ __volatile__ ("jmp 0" : : "Aq" (retcode)); 7 | while (1) 8 | ; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /libtinyc/alloc.c: -------------------------------------------------------------------------------- 1 | /* A really dumb dynamic memory allocator. */ 2 | 3 | #include "stdlib.h" 4 | #include "string.h" 5 | 6 | //#define DEBUG 7 | 8 | #ifdef DEBUG 9 | #include 10 | #include 11 | 12 | char *__HEAP_RUN__, *__HEAP_SIZE__; 13 | 14 | static void __attribute__((constructor)) 15 | init (void) 16 | { 17 | void *chunk = sbrk (65536); 18 | __HEAP_RUN__ = chunk; 19 | __HEAP_SIZE__ = 65536; 20 | } 21 | #endif 22 | 23 | extern char __RAM_START__; 24 | extern char __HEAP_RUN__; 25 | extern unsigned int __BSS_SIZE__, __RAM_SIZE__; 26 | 27 | /* This is a little hack to stop the linker discarding the otherwise-empty 28 | HEAP section. */ 29 | static char the_heap __attribute__((section("HEAP"), used)); 30 | 31 | typedef struct heapblock { 32 | struct heapblock *next; 33 | size_t size; /* The total block size, including the header. */ 34 | } heapblock; 35 | 36 | #define HEADER(P) ((heapblock *) ((char *) (P) - sizeof (heapblock))) 37 | #define BLOCK(P) (((char *) (P)) + sizeof (heapblock)) 38 | 39 | static heapblock *freelist = 0; 40 | 41 | /* FIXME: Use a constructor for this at program start. */ 42 | 43 | static void 44 | init_heap (void) 45 | { 46 | static int initialized = 0; 47 | 48 | if (!initialized) 49 | { 50 | freelist = (heapblock *) &__HEAP_RUN__; 51 | freelist->next = NULL; 52 | freelist->size = &__RAM_START__ + __RAM_SIZE__ - &__HEAP_RUN__; 53 | initialized = 1; 54 | } 55 | } 56 | 57 | #ifdef DEBUG 58 | static void 59 | print_freelist (void) 60 | { 61 | heapblock *walk; 62 | 63 | init_heap (); 64 | 65 | for (walk = freelist; walk; walk = walk->next) 66 | printf ("free block: %p, next %p, size %zu\n", walk, walk->next, 67 | walk->size); 68 | } 69 | #endif 70 | 71 | /* [HDR] [ ... ] 72 | | <- origsize -> | 73 | 74 | [HDR1] [ ... ] [HDR2] [ ... ] 75 | | <- carve+hdrsize -> | | origsize - (carve+hdrsize) | 76 | */ 77 | 78 | static heapblock * 79 | split_block (heapblock *hb, size_t carve) 80 | { 81 | heapblock *orig_next = hb->next; 82 | size_t origsize = hb->size; 83 | size_t newplushdr = carve + sizeof (heapblock); 84 | heapblock *remainder = (heapblock *) (((char *) hb) + newplushdr); 85 | 86 | hb->next = remainder; 87 | hb->size = newplushdr; 88 | remainder->next = orig_next; 89 | remainder->size = origsize - newplushdr; 90 | 91 | return remainder; 92 | } 93 | 94 | /* Walk over free list until we find a block big enough for SIZE. */ 95 | 96 | void * 97 | malloc (size_t size) 98 | { 99 | heapblock *prev = NULL, *walk; 100 | size_t sizeplusblk = size + sizeof (heapblock); 101 | 102 | init_heap (); 103 | 104 | for (walk = freelist; walk; walk = walk->next) 105 | { 106 | if (sizeplusblk < walk->size) 107 | { 108 | heapblock *rem = split_block (walk, size); 109 | 110 | if (prev) 111 | prev->next = rem; 112 | else if (walk == freelist) 113 | freelist = rem; 114 | 115 | return BLOCK (walk); 116 | } 117 | else if (sizeplusblk == walk->size) 118 | { 119 | /* Block fits exactly. */ 120 | if (prev) 121 | prev->next = walk->next; 122 | else if (walk == freelist) 123 | freelist = walk->next; 124 | 125 | return BLOCK (walk); 126 | } 127 | 128 | prev = walk; 129 | } 130 | 131 | return NULL; 132 | } 133 | 134 | /* When freeing we could tidy up by e.g. quicksorting the free list, and then 135 | merging adjacent blocks (maybe only when we run out of heap). For now 136 | though, just add the deleted block to the free list. */ 137 | 138 | void 139 | free (void *ptr) 140 | { 141 | heapblock *hb = HEADER (ptr); 142 | 143 | #ifdef DEBUG 144 | printf ("free: heapblock: %p\n", hb); 145 | #endif 146 | 147 | hb->next = freelist; 148 | freelist = hb; 149 | } 150 | 151 | void * 152 | calloc (size_t nmemb, size_t size) 153 | { 154 | size_t totsize = nmemb * size; 155 | void *newblk = malloc (totsize); 156 | memset (newblk, 0, totsize); 157 | return newblk; 158 | } 159 | 160 | void * 161 | realloc (void *ptr, size_t size) 162 | { 163 | void *newblk = malloc (size); 164 | memcpy (newblk, ptr, size); 165 | free (ptr); 166 | return newblk; 167 | } 168 | 169 | #ifdef DEBUG 170 | int main (int argc, char *argv) 171 | { 172 | char *ptr, *ptr2; 173 | 174 | print_freelist (); 175 | ptr = malloc (128); 176 | printf ("ptr: %p\n", ptr); 177 | print_freelist (); 178 | ptr2 = malloc (64); 179 | printf ("ptr2: %p\n", ptr2); 180 | print_freelist (); 181 | free (ptr); 182 | print_freelist (); 183 | printf ("allocate again:\n"); 184 | ptr = malloc (64); 185 | printf ("new ptr: %p\n", ptr); 186 | print_freelist (); 187 | return 0; 188 | } 189 | #endif 190 | -------------------------------------------------------------------------------- /libtinyc/bbc/fputc.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int fputc (int c, FILE *f) 4 | { 5 | register char x asm ("a") = c; 6 | if (x == '\n') 7 | /* OSNEWL */ 8 | __asm__ __volatile__ ("jsr $ffe7"); 9 | else 10 | /* OSWRCH */ 11 | __asm__ __volatile__ ("jsr $ffee" : : "Aq" (x)); 12 | 13 | return c; 14 | } 15 | -------------------------------------------------------------------------------- /libtinyc/c64/fputc.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int fputc (int c, FILE *f) 4 | { 5 | register char x asm ("a") = c; 6 | __asm__ __volatile__ ("jsr $ffd2" : : "Aq" (x)); 7 | 8 | return c; 9 | } 10 | -------------------------------------------------------------------------------- /libtinyc/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CC65_PATH=${CC65_PATH:-/usr/bin} 4 | AR65_PATH=${CC65_PATH}/ar65 5 | 6 | cd "$(dirname $0)" 7 | 8 | if [ ! "$PREFIX" ]; then 9 | echo "\$PREFIX must be set to build libtinyc." 10 | exit 1 11 | fi 12 | 13 | TARGET=6502 14 | 15 | declare -a MULTILIBS 16 | SAVED_IFS=$IFS 17 | IFS=$' 18 | ' 19 | MULTILIBS=( $($TARGET-gcc -print-multi-lib) ) 20 | IFS=$SAVED_IFS 21 | 22 | OBJECTS=( 23 | exit 24 | abort 25 | stdfiles 26 | fputc 27 | fputs 28 | putchar 29 | puts 30 | vfprintf 31 | fprintf 32 | vprintf 33 | printf 34 | sprintf 35 | vsprintf 36 | fflush 37 | memset 38 | memcpy 39 | memcmp 40 | strcmp 41 | strlen 42 | strcpy 43 | strchr 44 | strrchr 45 | memmove 46 | strncmp 47 | strncpy 48 | ftoa 49 | alloc 50 | fwrite 51 | rand 52 | ) 53 | 54 | set -e 55 | #set -x 56 | 57 | mkdir -p $PREFIX/$TARGET/usr/include 58 | cp -rf include/* $PREFIX/$TARGET/usr/include 59 | 60 | # Return the OS-specific source directory to use for a given multilib "OS" dir 61 | # given in $1. 62 | 63 | machine_specific_dir () 64 | { 65 | local osdir=$1 66 | 67 | case "$osdir" in 68 | .) 69 | echo semi65x 70 | ;; 71 | bbc*) 72 | echo bbc 73 | ;; 74 | c64) 75 | echo c64 76 | ;; 77 | *) 78 | echo "Unknown OS dir: $osdir" 1>&2 79 | exit 1 80 | esac 81 | } 82 | 83 | # Given a machine (multilib OS dir) in $1 and the name of an object in $2, 84 | # return the source file to use. If a machine-specific version is present, 85 | # use that, else use the default. Also prefer assembly source over C source 86 | # if available. 87 | 88 | src_for_machine () 89 | { 90 | local osdir=$1 91 | local obj=$2 92 | local machinedir 93 | machinedir="$(machine_specific_dir "$osdir")" 94 | 95 | if [ -e "$machinedir/$obj.S" ]; then 96 | echo "$machinedir/$obj.S" 97 | elif [ -e "$machinedir/$obj.c" ]; then 98 | echo "$machinedir/$obj.c" 99 | elif [ -e "$obj.S" ]; then 100 | echo "$obj.S" 101 | elif [ -e "$obj.c" ]; then 102 | echo "$obj.c" 103 | else 104 | echo "No source for '$obj' for $machinedir!" 1>&2 105 | exit 1 106 | fi 107 | } 108 | 109 | expand_opts () 110 | { 111 | local opts=$1 112 | echo $opts | sed 's/@/ -/g' 113 | } 114 | 115 | for mlib in "${MULTILIBS[@]}"; do 116 | osdir="${mlib%;*}" 117 | opts="${mlib#*;}" 118 | opts=$(expand_opts $opts) 119 | 120 | mkdir -p "$osdir" 121 | 122 | # Build tiny C library. 123 | rm -f "$osdir"/*.o "$osdir/libtinyc.a" 124 | for obj in "${OBJECTS[@]}" 125 | do 126 | src="$(src_for_machine "$osdir" "$obj")" 127 | case "$src" in 128 | *.c) 129 | echo "$osdir: compile: $src" 130 | ;; 131 | *.S) 132 | echo "$osdir: assemble: $src" 133 | ;; 134 | *) 135 | echo "Unknown source type $src" 136 | exit 1 137 | ;; 138 | esac 139 | $TARGET-gcc -Os -Wall -nostdlib -I include $opts "$src" -c -o "$osdir/$obj.o" 140 | ${AR65_PATH} a "$osdir/libtinyc.a" "$osdir/$obj.o" 141 | done 142 | 143 | # Build tiny maths library. 144 | rm -f "$osdir"/libm.a 145 | src="$(src_for_machine "$osdir" "math")" 146 | $TARGET-gcc -Os -nostdlib $opts "$src" -c -o "$osdir/math.o" 147 | ${AR65_PATH} a "$osdir/libm.a" "$osdir/math.o" 148 | 149 | mkdir -p "$PREFIX/$TARGET/$osdir/usr/lib/" 150 | cp -f "$osdir/libtinyc.a" "$PREFIX/$TARGET/$osdir/usr/lib" 151 | cp -f "$osdir/libm.a" "$PREFIX/$TARGET/$osdir/usr/lib" 152 | done 153 | -------------------------------------------------------------------------------- /libtinyc/exit.c: -------------------------------------------------------------------------------- 1 | /* A tiny C library. */ 2 | 3 | __attribute__((noreturn)) void 4 | exit (int status) 5 | { 6 | register unsigned char retcode __asm__ ("a") = status; 7 | __asm__ __volatile__ ("jmp 0" : : "Aq" (retcode)); 8 | while (1) 9 | ; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /libtinyc/fflush.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int 4 | fflush (FILE *stream) 5 | { 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /libtinyc/fprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdio.h" 4 | 5 | int fprintf (FILE *f, const char *fmt, ...) 6 | { 7 | va_list ap; 8 | int retcode; 9 | 10 | va_start (ap, fmt); 11 | retcode = vfprintf (f, fmt, ap); 12 | va_end (ap); 13 | 14 | return retcode; 15 | } 16 | -------------------------------------------------------------------------------- /libtinyc/fputs.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int fputs (const char *str, FILE *f) 4 | { 5 | while (*str) 6 | { 7 | fputc (*str, f); 8 | str++; 9 | } 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /libtinyc/ftoa.S: -------------------------------------------------------------------------------- 1 | .importzp _sp0, _sp1, _fp0, _fp1 2 | .importzp _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7 3 | .importzp _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7 4 | .importzp _tmp0, _tmp1 5 | 6 | .importzp _m65x_fpe0_mant, _m65x_fpe0_exp, _m65x_fpe0_sign 7 | .importzp _m65x_fpe1_mant, _m65x_fpe1_exp, _m65x_fpe1_sign 8 | 9 | .import _m65x_renormalize_right 10 | 11 | #define s_mant _m65x_fpe0_mant 12 | #define s_exp _m65x_fpe0_exp 13 | #define s_sign _m65x_fpe0_sign 14 | 15 | #define s2_mant _m65x_fpe1_mant 16 | #define s2_exp _m65x_fpe1_exp 17 | #define s2_sign _m65x_fpe1_sign 18 | 19 | 20 | .segment "ZEROPAGE" 21 | bufptr: 22 | .word 0 23 | 24 | .segment "DATA" 25 | b_mant: 26 | .dword 0 27 | b_exp: 28 | .byte 0 29 | b_sign: 30 | .byte 0 31 | fpnum: 32 | .dword 0 33 | dec_exp: 34 | .byte 0 35 | 36 | sigfigs: 37 | .byte 8 38 | bufidx: 39 | .byte 0 40 | print_exp: 41 | .byte 0 42 | place: 43 | .byte 0 44 | lastplace: 45 | .byte 0 46 | 47 | .segment "CODE" 48 | ; Arguments: 49 | ; - r0-r3: floating-point value to unpack. 50 | unpack: 51 | .scope 52 | lda #0 53 | sta s_mant 54 | sta s_mant+4 55 | sta s_exp+1 56 | lda _r0 57 | sta s_mant+1 58 | lda _r1 59 | sta s_mant+2 60 | lda _r2 61 | tax 62 | and #$7f 63 | sta s_mant+3 64 | ; sign is stored in high bit of s_sign. 65 | txa 66 | and #$80 67 | sta s_sign 68 | 69 | lda _r3 70 | sta s_exp 71 | beq exp_zero 72 | lda s_mant+3 73 | ora #$80 74 | sta s_mant+3 75 | exp_zero: 76 | rts 77 | .endscope 78 | 79 | copy_s_to_s2: 80 | .scope 81 | lda s_mant 82 | sta s2_mant 83 | lda s_mant+1 84 | sta s2_mant+1 85 | lda s_mant+2 86 | sta s2_mant+2 87 | lda s_mant+3 88 | sta s2_mant+3 89 | lda s_mant+4 90 | sta s2_mant+4 91 | lda s_exp 92 | sta s2_exp 93 | lda s_sign 94 | sta s2_sign 95 | rts 96 | .endscope 97 | 98 | copy_bias_to_s2: 99 | lda b_mant 100 | sta s2_mant 101 | lda b_mant+1 102 | sta s2_mant+1 103 | lda b_mant+2 104 | sta s2_mant+2 105 | lda b_mant+3 106 | sta s2_mant+3 107 | lda #0 108 | sta s2_mant+4 109 | lda b_exp 110 | sta s2_exp 111 | lda b_sign 112 | sta s2_sign 113 | rts 114 | 115 | add_s2_mant_to_s: 116 | lda s_mant 117 | clc 118 | adc s2_mant 119 | sta s_mant 120 | lda s_mant+1 121 | adc s2_mant+1 122 | sta s_mant+1 123 | lda s_mant+2 124 | adc s2_mant+2 125 | sta s_mant+2 126 | lda s_mant+3 127 | adc s2_mant+3 128 | sta s_mant+3 129 | lda s_mant+4 130 | adc s2_mant+4 131 | sta s_mant+4 132 | rts 133 | 134 | div10: 135 | .scope 136 | lda s_exp 137 | sec 138 | sbc #4 139 | sta s_exp 140 | 141 | ; s2 = s >> 1 142 | lda s_mant+4 143 | lsr a 144 | sta s2_mant+4 145 | lda s_mant+3 146 | ror a 147 | sta s2_mant+3 148 | lda s_mant+2 149 | ror a 150 | sta s2_mant+2 151 | lda s_mant+1 152 | ror a 153 | sta s2_mant+1 154 | lda s_mant 155 | ror a 156 | sta s2_mant 157 | 158 | ; s = s + s2 159 | jsr add_s2_mant_to_s 160 | 161 | jsr copy_s_to_s2 162 | 163 | ; divide the s2 mantissa by 16 164 | lda s2_mant+4 165 | ldx #4 166 | div16: 167 | lsr a 168 | ror s2_mant+3 169 | ror s2_mant+2 170 | ror s2_mant+1 171 | ror s2_mant 172 | dex 173 | bne div16 174 | sta s2_mant+4 175 | 176 | jsr add_s2_mant_to_s 177 | 178 | ; s_mant+4 s_mant+3 s_mant+2 s_mant+1 s_mant 179 | ; + s_mant+4 s_mant+3 s_mant+2 s_mant+1 180 | ;-> s_mant+4 s_mant+3 s_mant+2 s_mant+1 s_mant 181 | 182 | lda s_mant 183 | clc 184 | adc s_mant+1 185 | sta s_mant 186 | lda s_mant+1 187 | adc s_mant+2 188 | sta s_mant+1 189 | lda s_mant+2 190 | adc s_mant+3 191 | sta s_mant+2 192 | lda s_mant+3 193 | adc s_mant+4 194 | sta s_mant+3 195 | bcc :+ 196 | inc s_mant+4 197 | : 198 | 199 | ; s_mant+4 s_mant+3 s_mant+2 s_mant+1 s_mant 200 | ; + s_mant+4 s_mant+3 s_mant+2 201 | ;-> s_mant+3 s_mant+2 s_mant+1 s_mant 202 | 203 | lda s_mant 204 | clc 205 | adc s_mant+2 206 | sta s_mant 207 | lda s_mant+1 208 | adc s_mant+3 209 | sta s_mant+1 210 | lda s_mant+2 211 | adc s_mant+4 212 | sta s_mant+2 213 | bcc :+ 214 | inc s_mant+3 215 | : 216 | 217 | jmp _m65x_renormalize_right 218 | .endscope 219 | 220 | ensure_less_than_10: 221 | ; Divide input value until input value < 10.0. 222 | ; continue while: 223 | ; s_exp > 130 || (s_exp == 130 && s_mant >= 0xa0000000) 224 | .scope 225 | div10_loop: 226 | lda s_exp 227 | cmp #131 228 | bcs do_div 229 | cmp #130 230 | bne less_than_10 231 | lda s_mant+3 232 | cmp #$a0 233 | bcc less_than_10 234 | do_div: 235 | jsr div10 236 | inc dec_exp 237 | jmp div10_loop 238 | less_than_10: 239 | rts 240 | .endscope 241 | 242 | mul10: 243 | .scope 244 | jsr copy_s_to_s2 245 | 246 | lda s_exp 247 | clc 248 | adc #3 249 | sta s_exp 250 | 251 | lda s2_mant+3 252 | lsr a 253 | ror s2_mant+2 254 | ror s2_mant+1 255 | ror s2_mant 256 | lsr a 257 | ror s2_mant+2 258 | ror s2_mant+1 259 | ror s2_mant 260 | sta s2_mant+3 261 | 262 | jsr add_s2_mant_to_s 263 | jmp _m65x_renormalize_right 264 | .endscope 265 | 266 | add_bias: 267 | .scope 268 | jsr copy_bias_to_s2 269 | 270 | ; exit if s2_exp+31 < s_exp 271 | lda s2_exp 272 | clc 273 | adc #31 274 | cmp s_exp 275 | bcc out 276 | 277 | lda s_exp 278 | sec 279 | sbc s2_exp 280 | tax 281 | beq done_shifting 282 | lda s2_mant+4 283 | rshift_s2: 284 | lsr a 285 | ror s2_mant+3 286 | ror s2_mant+2 287 | ror s2_mant+1 288 | ror s2_mant 289 | dex 290 | bne rshift_s2 291 | sta s2_mant+4 292 | done_shifting: 293 | 294 | jsr add_s2_mant_to_s 295 | jmp _m65x_renormalize_right 296 | out: 297 | rts 298 | .endscope 299 | 300 | denormalize: 301 | .scope 302 | ldx s_exp 303 | lda s_mant 304 | loop: 305 | cpx #130 306 | bcs done 307 | lsr s_mant+4 308 | ror s_mant+3 309 | ror s_mant+2 310 | ror s_mant+1 311 | ror a 312 | inx 313 | jmp loop 314 | done: 315 | sta s_mant 316 | stx s_exp 317 | rts 318 | .endscope 319 | 320 | .export __m65x_ftoa 321 | ; Arguments: 322 | ; - r0,r1: pointer to output string. 323 | ; - r2-r5: floating-point value to print. 324 | __m65x_ftoa: 325 | .scope 326 | 327 | lda _r0 328 | sta bufptr 329 | lda _r1 330 | sta bufptr+1 331 | lda _r2 332 | sta fpnum 333 | lda _r3 334 | sta fpnum+1 335 | lda _r4 336 | sta fpnum+2 337 | lda _r5 338 | sta fpnum+3 339 | 340 | ; Unpack the constant 5.0. 341 | lda #0 342 | sta _r0 343 | sta _r1 344 | lda #32 345 | sta _r2 346 | lda #129 347 | sta _r3 348 | jsr unpack 349 | 350 | ; Divide by 10 "sigfigs" times. 351 | .scope 352 | lda sigfigs 353 | lda #8 354 | sta _r6 355 | loop: 356 | jsr div10 357 | dec _r6 358 | bne loop 359 | .endscope 360 | 361 | ; Copy to "bias", b_mant/b_exp/b_sign 362 | lda s_mant 363 | sta b_mant 364 | lda s_mant+1 365 | sta b_mant+1 366 | lda s_mant+2 367 | sta b_mant+2 368 | lda s_mant+3 369 | sta b_mant+3 370 | lda s_exp 371 | sta b_exp 372 | ; Copy the sign of the input number. 373 | lda fpnum+2 374 | and #$80 375 | sta b_sign 376 | 377 | lda #0 378 | sta dec_exp 379 | 380 | ; Unpack input value 381 | lda fpnum 382 | sta _r0 383 | lda fpnum+1 384 | sta _r1 385 | lda fpnum+2 386 | sta _r2 387 | lda fpnum+3 388 | sta _r3 389 | jsr unpack 390 | 391 | ldy #0 392 | sty bufidx 393 | 394 | lda s_sign 395 | bpl no_sign_char 396 | lda #'-' 397 | sta (bufptr),y 398 | inc bufidx 399 | no_sign_char: 400 | 401 | ldy bufidx 402 | lda s_exp 403 | ora s_mant 404 | ora s_mant+1 405 | ora s_mant+2 406 | ora s_mant+3 407 | bne not_zero 408 | lda #'0' 409 | sta (bufptr),y 410 | inc bufidx 411 | jmp finished 412 | not_zero: 413 | 414 | ; Multiply input value until s_exp >= 127 (input value >= 1.0). 415 | .scope 416 | mul10_loop: 417 | lda s_exp 418 | cmp #127 419 | bcs greater_than_1 420 | jsr mul10 421 | dec dec_exp 422 | jmp mul10_loop 423 | greater_than_1: 424 | .endscope 425 | 426 | jsr ensure_less_than_10 427 | jsr add_bias 428 | jsr ensure_less_than_10 429 | 430 | ; if dec_exp < -3 || dec_exp > 8 then print ...E... 431 | 432 | lda #0 433 | sta print_exp 434 | lda dec_exp 435 | clc 436 | adc #4 437 | cmp #12 438 | bcc no_exp 439 | lda #1 440 | sta print_exp 441 | no_exp: 442 | 443 | ; Output '0.' + <-dec_exp-1> x '0' 444 | .scope 445 | lda dec_exp 446 | bpl no_zero_dot_leading_zeros 447 | lda print_exp 448 | bne no_zero_dot_leading_zeros 449 | ldy bufidx 450 | lda #'0' 451 | sta (bufptr),y 452 | iny 453 | lda #'.' 454 | sta (bufptr),y 455 | iny 456 | ldx dec_exp 457 | lda #'0' 458 | emit_zeros: 459 | cpx #255 460 | beq done 461 | sta (bufptr),y 462 | inx 463 | iny 464 | jmp emit_zeros 465 | done: 466 | sty bufidx 467 | no_zero_dot_leading_zeros: 468 | .endscope 469 | 470 | ; The main digit output loop! 471 | .scope 472 | lda #0 473 | sta place 474 | emit_digits: 475 | lda place 476 | cmp sigfigs 477 | bcc loop_body 478 | lda print_exp 479 | beq :+ 480 | jmp done 481 | : lda dec_exp 482 | sec 483 | sbc place 484 | bvc :+ 485 | eor #$80 486 | : bmi done 487 | loop_body: 488 | 489 | .scope 490 | lda #0 491 | sta lastplace 492 | lda sigfigs 493 | sec 494 | sbc place 495 | cmp #1 496 | bne notlastplace 497 | sta lastplace 498 | notlastplace: 499 | .endscope 500 | 501 | jsr denormalize 502 | 503 | lda s_mant+3 504 | lsr a 505 | lsr a 506 | lsr a 507 | lsr a 508 | ora #$30 509 | ldy bufidx 510 | sta (bufptr),y 511 | iny 512 | sty bufidx 513 | 514 | ldx #4 515 | lda s_mant 516 | renormalize: 517 | asl a 518 | rol s_mant+1 519 | rol s_mant+2 520 | rol s_mant+3 521 | dec s_exp 522 | dex 523 | bne renormalize 524 | sta s_mant 525 | 526 | ; print decimal point if appropriate 527 | .scope 528 | lda print_exp 529 | beq no_exponent 530 | lda place 531 | bne done 532 | lda lastplace 533 | beq emit_point 534 | jmp done 535 | no_exponent: 536 | lda place 537 | cmp dec_exp 538 | bne done 539 | lda lastplace 540 | bne done 541 | emit_point: 542 | ldy bufidx 543 | lda #'.' 544 | sta (bufptr),y 545 | iny 546 | sty bufidx 547 | done: 548 | .endscope 549 | 550 | jsr mul10 551 | 552 | inc place 553 | jmp emit_digits 554 | done: 555 | .endscope 556 | 557 | ; Strip trailing zeros and decimal point 558 | .scope 559 | dec place 560 | ldy bufidx 561 | dey 562 | strip_zeros: 563 | cpy #1 564 | bcc done_zeros 565 | lda (bufptr),y 566 | cmp #'0' 567 | bne done_zeros 568 | lda dec_exp 569 | cmp place 570 | bcs done_zeros 571 | sty bufidx 572 | dey 573 | dec place 574 | jmp strip_zeros 575 | done_zeros: 576 | 577 | lda (bufptr),y 578 | cmp #'.' 579 | bne done_point 580 | sty bufidx 581 | done_point: 582 | 583 | .endscope 584 | 585 | finished: 586 | lda #0 587 | ldy bufidx 588 | sta (bufptr),y 589 | 590 | .scope 591 | lda print_exp 592 | beq no_exp 593 | lda dec_exp 594 | sta _r0 595 | rts 596 | no_exp: 597 | lda #0 598 | sta _r0 599 | rts 600 | .endscope 601 | 602 | .endscope 603 | -------------------------------------------------------------------------------- /libtinyc/fwrite.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | size_t 4 | fwrite (const void *ptr, size_t size, size_t nmemb, FILE *f) 5 | { 6 | size_t memct, sizect; 7 | const char *ptrc = ptr; 8 | 9 | for (memct = 0; memct < nmemb; memct++) 10 | for (sizect = 0; sizect < size; sizect++) 11 | { 12 | fputc (*ptrc, f); 13 | ptrc++; 14 | } 15 | 16 | return memct; 17 | } 18 | -------------------------------------------------------------------------------- /libtinyc/include/alloca.h: -------------------------------------------------------------------------------- 1 | #ifndef _ALLOCA_H 2 | #define _ALLOCA_H 1 3 | 4 | extern void *alloca (size_t); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /libtinyc/include/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASSERT_H 2 | #define _ASSERT_H 1 3 | 4 | #include 5 | #include 6 | 7 | #ifndef NDEBUG 8 | 9 | #define _STRINGIFY(N) _STRINGIFY2(N) 10 | #define _STRINGIFY2(N) #N 11 | 12 | #define assert(N) \ 13 | do \ 14 | if (!(N)) \ 15 | { \ 16 | fputs (__FILE__ ":" _STRINGIFY(__LINE__) ": Assertion failed: '" \ 17 | #N "'\n", stderr); \ 18 | abort (); \ 19 | } \ 20 | while (0) 21 | 22 | #else 23 | 24 | #define assert(N) 25 | 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /libtinyc/include/errno.h: -------------------------------------------------------------------------------- 1 | #ifndef _ERRNO_H 2 | #define _ERRNO_H 1 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /libtinyc/include/math.h: -------------------------------------------------------------------------------- 1 | #ifndef _MATH_H 2 | #define _MATH_H 1 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /libtinyc/include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDDEF_H 2 | #define _STDDEF_H 1 3 | 4 | typedef unsigned int size_t; 5 | typedef int ssize_t; 6 | 7 | #ifndef NULL 8 | #define NULL (void *) 0 9 | #endif 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /libtinyc/include/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDINT_H 2 | #define _STDINT_H 1 3 | 4 | typedef signed char int8_t; 5 | typedef unsigned char uint8_t; 6 | 7 | typedef short int16_t; 8 | typedef unsigned short uint16_t; 9 | 10 | typedef long int32_t; 11 | typedef unsigned long uint32_t; 12 | 13 | typedef short intptr_t; 14 | typedef unsigned short uintptr_t; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /libtinyc/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDIO_H 2 | #define _STDIO_H 1 3 | 4 | #include 5 | #include 6 | 7 | typedef int FILE; 8 | 9 | extern FILE *stdin; 10 | extern FILE *stdout; 11 | extern FILE *stderr; 12 | 13 | #define SEEK_SET 0 14 | #define SEEK_CUR 1 15 | #define SEEK_END 2 16 | 17 | #define EOF (-1) 18 | 19 | extern char __m65x_char_to_file; 20 | 21 | extern int fputc (int, FILE *); 22 | extern int fputs (const char *, FILE *); 23 | #define putc(C, F) fputc ((C), (F)) 24 | extern int putchar (int); 25 | extern int puts (const char *); 26 | extern int vfprintf (FILE *, const char *, va_list); 27 | extern int fprintf (FILE *, const char *, ...); 28 | extern int printf (const char *, ...); 29 | extern int sprintf (char *, const char *, ...); 30 | extern int vsprintf (char *, const char *, va_list); 31 | extern int fflush (FILE *); 32 | extern int fseek (FILE *, long, int); 33 | extern size_t fwrite (const void *, size_t, size_t, FILE *); 34 | extern long ftell (FILE *); 35 | extern void rewind (FILE *); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /libtinyc/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDLIB_H 2 | #define _STDLIB_H 1 3 | 4 | #include 5 | 6 | extern void *malloc (size_t); 7 | extern void free (void *); 8 | extern void *calloc (size_t, size_t); 9 | extern void *realloc (void *, size_t); 10 | extern void exit (int); 11 | extern void abort (void); 12 | extern void srand (unsigned int); 13 | extern int rand (void); 14 | 15 | #define RAND_MAX 0x7fff 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /libtinyc/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRING_H 2 | #define _STRING_H 1 3 | 4 | #include 5 | 6 | extern void *memset (void *, int, size_t); 7 | extern void *memcpy (void *, const void *, size_t); 8 | extern int memcmp (const void *, const void *, size_t); 9 | extern int strcmp (const char *, const char *); 10 | extern size_t strlen (const char *s); 11 | extern char *strcpy (char *, const char *); 12 | extern void *memmove (void *, const void *, size_t); 13 | extern int strncmp (const char *, const char *, size_t); 14 | extern char *strncpy (char *, const char *, size_t); 15 | extern char *strchr (const char *s, int c); 16 | extern char *strrchr (const char *s, int c); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /libtinyc/include/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYS_TYPES_H 2 | #define _SYS_TYPES_H 1 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /libtinyc/include/time.h: -------------------------------------------------------------------------------- 1 | #ifndef _TIME_H 2 | #define _TIME_H 1 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /libtinyc/include/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNISTD_H 2 | #define _UNISTD_H 1 3 | 4 | typedef int pid_t; 5 | 6 | extern char **environ; 7 | 8 | extern pid_t fork (void); 9 | extern int execl (const char *, const char *, ...); 10 | extern int execlp (const char *, const char *, ...); 11 | extern int execle (const char *, const char *, ...); 12 | extern int execv (const char *path, char *const argv[]); 13 | extern int execvp (const char *, char *const argv[]); 14 | extern int execvpe (const char *, char *const argv[], char *const envp[]); 15 | extern int execve (const char *, char *const argv[], char *const envp[]); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /libtinyc/math.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itszor/gcc-6502-bits/15b26ddf7863e8a5d17678c6c11bac9cbe353138/libtinyc/math.c -------------------------------------------------------------------------------- /libtinyc/memcmp.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | int 4 | memcmp (const void *s1, const void *s2, size_t n) 5 | { 6 | const unsigned char *c1 = s1, *c2 = s2; 7 | unsigned int i; 8 | 9 | for (i = 0; i < n; i++) 10 | { 11 | int diff = c1[i] - c2[i]; 12 | if (diff != 0) 13 | return diff; 14 | } 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /libtinyc/memcpy.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | void * 4 | memcpy (void *dest, const void *src, size_t n) 5 | { 6 | unsigned char *d = dest; 7 | const unsigned char *s = src; 8 | unsigned int i; 9 | 10 | for (i = 0; i < n; i++) 11 | d[i] = s[i]; 12 | 13 | return dest; 14 | } 15 | -------------------------------------------------------------------------------- /libtinyc/memmove.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | void * 4 | memmove (void *dest, const void *src, size_t n) 5 | { 6 | unsigned char *d = dest; 7 | unsigned const char *s = src; 8 | int i; 9 | 10 | if (dest < src) 11 | { 12 | for (i = 0; i < n; i++) 13 | d[i] = s[i]; 14 | } 15 | else 16 | { 17 | for (i = n - 1; i >= 0; i--) 18 | d[i] = s[i]; 19 | } 20 | 21 | return dest; 22 | } 23 | -------------------------------------------------------------------------------- /libtinyc/memset.S: -------------------------------------------------------------------------------- 1 | .importzp _r0, _r1, _r2, _r3, _r4, _r5 2 | 3 | .segment "CODE" 4 | .export memset 5 | ; args: 6 | ; _r1, _r0: dst pointer 7 | ; _r3 (unused), _r2: character to write 8 | ; _r5, _r4: number of bytes to fill 9 | ; returns: 10 | ; _r1, _r0: dst pointer 11 | memset: 12 | lda _r1 13 | sta _r3 14 | 15 | lda _r2 16 | 17 | ldy #0 18 | ldx _r5 19 | beq lastpage 20 | 21 | fullpage: 22 | sta (_r0),y 23 | iny 24 | bne fullpage 25 | inc _r1 26 | dex 27 | bne fullpage 28 | 29 | lastpage: 30 | ldy _r4 31 | beq done 32 | lploop: 33 | dey 34 | sta (_r0),y 35 | bne lploop 36 | 37 | done: 38 | lda _r3 39 | sta _r1 40 | rts 41 | -------------------------------------------------------------------------------- /libtinyc/memset.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | void * 4 | memset (void *s, int c, size_t n) 5 | { 6 | int i; 7 | unsigned char cbyte = c; 8 | unsigned char *scp = s; 9 | 10 | for (i = 0; i < n; i++) 11 | scp[i] = cbyte; 12 | 13 | return s; 14 | } 15 | -------------------------------------------------------------------------------- /libtinyc/printf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdio.h" 4 | 5 | int printf (const char *fmt, ...) 6 | { 7 | va_list ap; 8 | int retcode; 9 | 10 | va_start (ap, fmt); 11 | retcode = vfprintf (stdout, fmt, ap); 12 | va_end (ap); 13 | 14 | return retcode; 15 | } 16 | -------------------------------------------------------------------------------- /libtinyc/putchar.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int putchar (int c) 4 | { 5 | return fputc (c, stdout); 6 | } 7 | -------------------------------------------------------------------------------- /libtinyc/puts.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int puts (const char *str) 4 | { 5 | fputs (str, stdout); 6 | fputc ('\n', stdout); 7 | return 1; 8 | } 9 | -------------------------------------------------------------------------------- /libtinyc/rand.c: -------------------------------------------------------------------------------- 1 | #include "stdlib.h" 2 | 3 | static unsigned long state = 1; 4 | 5 | void 6 | srand (unsigned int newstate) 7 | { 8 | state = (unsigned long) newstate + 17; 9 | } 10 | 11 | /* This is a basic implementation of xorshift32. The internal state is 32 12 | bits, but we're only returning the low-order 15 of those. */ 13 | 14 | int 15 | rand (void) 16 | { 17 | unsigned long lstate = state; 18 | lstate ^= lstate << 13; 19 | lstate ^= lstate >> 17; 20 | lstate ^= lstate << 5; 21 | state = lstate; 22 | return state & 0x7fff; 23 | } 24 | -------------------------------------------------------------------------------- /libtinyc/semi65x/fputc.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int fputc (int c, FILE *f) 4 | { 5 | volatile char *cp = (char*) 0xfff0; 6 | 7 | if (f == stdout || f == stderr) 8 | *cp = c; 9 | 10 | return c; 11 | } 12 | -------------------------------------------------------------------------------- /libtinyc/sprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdio.h" 4 | 5 | int 6 | sprintf (char *str, const char *fmt, ...) 7 | { 8 | va_list ap; 9 | int rc; 10 | 11 | __m65x_char_to_file = 0; 12 | va_start (ap, fmt); 13 | rc = vfprintf ((FILE *) &str, fmt, ap); 14 | va_end (ap); 15 | __m65x_char_to_file = 1; 16 | 17 | return rc; 18 | } 19 | -------------------------------------------------------------------------------- /libtinyc/stdfiles.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | FILE *stdin = (FILE *) 0; 4 | FILE *stdout = (FILE *) 1; 5 | FILE *stderr = (FILE *) 2; 6 | -------------------------------------------------------------------------------- /libtinyc/strchr.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | char * 4 | strchr (const char *s, int c) 5 | { 6 | char thechar; 7 | do 8 | { 9 | thechar = *s; 10 | if (thechar == c) 11 | return (char *) s; 12 | s++; 13 | } 14 | while (thechar != '\0'); 15 | 16 | return NULL; 17 | } 18 | -------------------------------------------------------------------------------- /libtinyc/strcmp.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | int 4 | strcmp (const char *s1, const char *s2) 5 | { 6 | for (; *s1 || *s2; s1++, s2++) 7 | { 8 | int diff; 9 | 10 | if (!*s1 || !*s2) 11 | return *(unsigned char *)s1 - *(unsigned const char *)s2; 12 | 13 | diff = *s1 - *s2; 14 | if (diff != 0) 15 | return diff; 16 | } 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /libtinyc/strcpy.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | char * 4 | strcpy (char *dest, const char *src) 5 | { 6 | char *odest = dest; 7 | 8 | while ((*dest++ = *src++)) 9 | ; 10 | 11 | return odest; 12 | } 13 | -------------------------------------------------------------------------------- /libtinyc/strlen.S: -------------------------------------------------------------------------------- 1 | .importzp _r0, _r1, _r2 2 | 3 | .segment "CODE" 4 | .export strlen 5 | strlen: 6 | ldy #0 7 | sty _r2 8 | page_loop: 9 | lda (_r0),y 10 | beq done 11 | iny 12 | bne page_loop 13 | 14 | inc _r1 15 | inc _r2 16 | #ifdef __CMOS__ 17 | bra page_loop 18 | #else 19 | jmp page_loop 20 | #endif 21 | done: 22 | sty _r0 23 | lda _r2 24 | sta _r1 25 | rts 26 | -------------------------------------------------------------------------------- /libtinyc/strlen.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | size_t 4 | strlen (const char *s) 5 | { 6 | unsigned int count = 0; 7 | 8 | while (*s++) 9 | count++; 10 | 11 | return count; 12 | } 13 | -------------------------------------------------------------------------------- /libtinyc/strncmp.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | int 4 | strncmp (const char *s1, const char *s2, size_t n) 5 | { 6 | unsigned int i; 7 | 8 | for (i = 0; i < n && (*s1 || *s2); i++, s1++, s2++) 9 | { 10 | int diff; 11 | 12 | if (!*s1 || !*s2) 13 | return *(unsigned char *)s1 - *(unsigned const char*)s2; 14 | 15 | diff = *s1 - *s2; 16 | if (diff != 0) 17 | return diff; 18 | } 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /libtinyc/strncpy.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | char * 4 | strncpy (char *dest, const char *src, size_t n) 5 | { 6 | unsigned int i; 7 | char *odest = dest; 8 | 9 | for (i = 0; i < n; dest++, src++, i++) 10 | { 11 | char c = *dest = *src; 12 | if (!c) 13 | break; 14 | } 15 | 16 | /* Pad with NUL chars. */ 17 | for (; i < n; dest++, i++) 18 | *dest = '\0'; 19 | 20 | return odest; 21 | } 22 | -------------------------------------------------------------------------------- /libtinyc/strrchr.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | char * 4 | strrchr (const char *s, int c) 5 | { 6 | char *last = NULL; 7 | char thechar; 8 | 9 | do 10 | { 11 | thechar = *s; 12 | if (thechar == c) 13 | last = (char *) s; 14 | s++; 15 | } 16 | while (thechar != '\0'); 17 | 18 | return last; 19 | } 20 | -------------------------------------------------------------------------------- /libtinyc/vfprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdio.h" 4 | #include "string.h" 5 | 6 | char __m65x_char_to_file = 1; 7 | 8 | static void 9 | emit_char (int c, FILE *f) 10 | { 11 | if (__m65x_char_to_file) 12 | fputc (c, f); 13 | else 14 | { 15 | char **ptr = (char **) f; 16 | **ptr = c; 17 | (*ptr)++; 18 | } 19 | } 20 | 21 | /* A version of fputs that knows about the __m65x_char_to_file hack. */ 22 | static void 23 | sfputs (const char *str, FILE *f) 24 | { 25 | const char *iter; 26 | for (iter = str; *iter; iter++) 27 | emit_char (*iter, f); 28 | } 29 | 30 | #define M65X_FLOAT_PRINT 31 | 32 | static int print_udec (FILE *f, unsigned long val) 33 | { 34 | char digits[10]; 35 | int c = 0; 36 | int printed = 0; 37 | 38 | do 39 | { 40 | digits[c++] = val % 10; 41 | val = val / 10; 42 | } 43 | while (val > 0); 44 | 45 | for (--c; c >= 0; c--) 46 | { 47 | emit_char (digits[c] + '0', f); 48 | printed++; 49 | } 50 | 51 | return printed; 52 | } 53 | 54 | static int print_sdec (FILE *f, long val) 55 | { 56 | int printed = 0; 57 | if (val < 0) 58 | { 59 | emit_char ('-', f); 60 | printed += print_udec (f, -val) + 1; 61 | } 62 | else 63 | printed += print_udec (f, val); 64 | 65 | return printed; 66 | } 67 | 68 | static int print_hex (FILE *f, unsigned long val) 69 | { 70 | unsigned char seen_nonzero = 0; 71 | int printed = 0; 72 | int i; 73 | 74 | for (i = 7; i >= 0; i--) 75 | { 76 | unsigned char nybble = (val >> 28) & 0xf; 77 | 78 | if (nybble > 0 || i == 0 || seen_nonzero) 79 | { 80 | emit_char (nybble < 10 ? nybble + '0' : nybble - 10 + 'a', f); 81 | printed++; 82 | } 83 | 84 | if (nybble != 0) 85 | seen_nonzero = 1; 86 | 87 | val <<= 4; 88 | } 89 | 90 | return printed; 91 | } 92 | 93 | #ifdef M65X_FLOAT_PRINT 94 | extern signed char __m65x_ftoa (char *, float); 95 | 96 | static int 97 | print_float (FILE *f, float x) 98 | { 99 | signed char exp; 100 | int printed = 0; 101 | char output[16]; 102 | exp = __m65x_ftoa (&output[0], x); 103 | sfputs (output, f); 104 | printed = strlen (output); 105 | if (exp != 0) 106 | printed += fprintf (f, "E%d", exp); 107 | return printed; 108 | } 109 | #endif 110 | 111 | #ifndef MAIN 112 | int vfprintf (FILE *f, const char *fmt, va_list ap) 113 | { 114 | int printed = 0; 115 | 116 | while (*fmt) 117 | { 118 | if (*fmt == '%') 119 | { 120 | retry: 121 | switch (*++fmt) 122 | { 123 | case 'c': 124 | { 125 | int val = va_arg (ap, int); 126 | emit_char (val, f); 127 | printed++; 128 | } 129 | break; 130 | 131 | case 'l': 132 | { 133 | switch (*++fmt) 134 | { 135 | case 'd': 136 | { 137 | long val = va_arg (ap, long); 138 | printed += print_sdec (f, val); 139 | } 140 | break; 141 | 142 | case 'u': 143 | { 144 | unsigned long val = va_arg (ap, unsigned long); 145 | printed += print_udec (f, val); 146 | } 147 | break; 148 | 149 | case 'x': 150 | { 151 | unsigned long val = va_arg (ap, unsigned long); 152 | printed += print_hex (f, val); 153 | } 154 | break; 155 | 156 | default: 157 | ; 158 | } 159 | } 160 | break; 161 | 162 | case 'd': 163 | { 164 | int val = va_arg (ap, int); 165 | printed += print_sdec (f, val); 166 | } 167 | break; 168 | 169 | case 'u': 170 | { 171 | unsigned int val = va_arg (ap, unsigned int); 172 | printed += print_udec (f, val); 173 | } 174 | break; 175 | 176 | case 's': 177 | { 178 | char *str = va_arg (ap, char *); 179 | sfputs (str, f); 180 | printed += strlen (str); 181 | } 182 | break; 183 | 184 | case 'p': 185 | case 'x': 186 | { 187 | unsigned int val = va_arg (ap, unsigned int); 188 | printed += print_hex (f, val); 189 | } 190 | break; 191 | 192 | case '%': 193 | emit_char ('%', f); 194 | printed++; 195 | break; 196 | 197 | #ifdef M65X_FLOAT_PRINT 198 | case 'f': 199 | { 200 | float val = va_arg (ap, double); 201 | printed += print_float (f, val); 202 | } 203 | break; 204 | #endif 205 | default: 206 | /* Just skip unknown % formatting codes. */ 207 | goto retry; 208 | } 209 | } 210 | else 211 | { 212 | emit_char (*fmt, f); 213 | printed++; 214 | } 215 | 216 | fmt++; 217 | } 218 | 219 | /* Zero-terminate if printing to string. */ 220 | if (!__m65x_char_to_file) 221 | emit_char (0, f); 222 | 223 | return printed; 224 | } 225 | #endif 226 | 227 | #ifdef MAIN 228 | void *ptr; 229 | 230 | __attribute__((noinline)) void 231 | little_vararg (int* unk, ...) 232 | { 233 | va_list ap; 234 | va_start (ap, unk); 235 | //ptr = (void*) ap; 236 | print_hex (stdout, va_arg (ap, int)); 237 | va_end (ap); 238 | } 239 | 240 | int main (int argc, char* argv[]) 241 | { 242 | int i; 243 | #if 0 244 | print_hex (stdout, 0xa0); 245 | #else 246 | for (i = 0; i < 257; i++) 247 | { 248 | #if 1 249 | little_vararg (0, i); 250 | #else 251 | print_hex (stdout, i); 252 | #endif 253 | fputc ('\n', stdout); 254 | } 255 | #endif 256 | } 257 | #endif 258 | -------------------------------------------------------------------------------- /libtinyc/vprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdio.h" 4 | 5 | int 6 | vprintf (const char *fmt, va_list ap) 7 | { 8 | return vfprintf (stdout, fmt, ap); 9 | } 10 | -------------------------------------------------------------------------------- /libtinyc/vsprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdio.h" 4 | 5 | int 6 | vsprintf (char *str, const char *fmt, va_list ap) 7 | { 8 | int rc; 9 | 10 | __m65x_char_to_file = 0; 11 | rc = vfprintf ((FILE *) &str, fmt, ap); 12 | __m65x_char_to_file = 1; 13 | 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /resultdb/compile.sh: -------------------------------------------------------------------------------- 1 | export PGHOST=localhost 2 | export PGPORT=5432 3 | export PGUSER=$(whoami) 4 | export PGPASSWORD=password 5 | #export UNIX_DOMAIN_SOCKET_DIR=/var/run/postgresql 6 | export PGDATABASE='gcc_results' 7 | ocamlfind ocamlc -package pgocaml,pgocaml.syntax,fileutils -linkpkg -syntax camlp4o resultdb.ml -o resultdb 8 | -------------------------------------------------------------------------------- /resultdb/db.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS results; 2 | DROP TABLE IF EXISTS xfails; 3 | DROP TABLE IF EXISTS tests; 4 | DROP TABLE IF EXISTS component_version; 5 | DROP TABLE IF EXISTS components; 6 | DROP TABLE IF EXISTS versions; 7 | DROP TABLE IF EXISTS testrun; 8 | DROP TABLE IF EXISTS testbundle; 9 | DROP TABLE IF EXISTS targets; 10 | DROP TABLE IF EXISTS multilibs; 11 | DROP TABLE IF EXISTS configs; 12 | DROP TABLE IF EXISTS expfiles; 13 | DROP TYPE IF EXISTS outcome; 14 | 15 | -- Name of .exp file for test -- compile.exp etc.. This can usually be found 16 | -- via parsing the .sum file. 17 | 18 | CREATE TABLE expfiles ( 19 | exp_id serial PRIMARY KEY, 20 | name text UNIQUE NOT NULL 21 | ); 22 | 23 | -- The component under test, 'gcc', 'binutils' or whatever. 24 | 25 | CREATE TABLE components ( 26 | comp_id serial PRIMARY KEY, 27 | component text UNIQUE NOT NULL 28 | ); 29 | 30 | -- One row for each test we have (or expect) a result for. A given component 31 | -- (gcc) and expfile (compile.exp) must only have one test of each name. The 32 | -- original test-result order is recorded in "test_collate", for use during 33 | -- eventual output. (This is expected to start from zero for each component, 34 | -- for example). 35 | 36 | CREATE TABLE tests ( 37 | test_id serial PRIMARY KEY, 38 | comp_id integer NOT NULL, 39 | exp_id integer NOT NULL, 40 | CONSTRAINT comp_fkey FOREIGN KEY (comp_id) 41 | REFERENCES components (comp_id) MATCH SIMPLE 42 | ON UPDATE NO ACTION ON DELETE NO ACTION, 43 | CONSTRAINT expfile_fkey FOREIGN KEY (exp_id) 44 | REFERENCES expfiles (exp_id) MATCH SIMPLE 45 | ON UPDATE NO ACTION ON DELETE NO ACTION, 46 | name text NOT NULL, 47 | UNIQUE (comp_id, exp_id, name) 48 | ); 49 | 50 | -- The target, 6502, arm-eabi, etc. 51 | 52 | CREATE TABLE targets ( 53 | target_id serial PRIMARY KEY, 54 | target text UNIQUE NOT NULL 55 | ); 56 | 57 | -- The multilib -- ".;", "thumb;@mthumb", whatever. A free-form text field. 58 | 59 | CREATE TABLE multilibs ( 60 | mlib_id serial PRIMARY KEY, 61 | multilib text UNIQUE NOT NULL 62 | ); 63 | 64 | -- The config used to build the release. Again a free-form text field. 65 | 66 | CREATE TABLE configs ( 67 | cfg_id serial PRIMARY KEY, 68 | config text UNIQUE NOT NULL 69 | ); 70 | 71 | -- A row represents a collection of tests -- several multilibs, sharing a 72 | -- target and a configuration. The whole collection is also given a datestamp. 73 | 74 | CREATE TABLE testbundle ( 75 | bundle_id serial PRIMARY KEY, 76 | target_id integer NOT NULL, 77 | cfg_id integer NOT NULL, 78 | date timestamp without time zone, 79 | CONSTRAINT target_fkey FOREIGN KEY (target_id) 80 | REFERENCES targets (target_id) MATCH SIMPLE 81 | ON UPDATE NO ACTION ON DELETE NO ACTION, 82 | CONSTRAINT cfg_fkey FOREIGN KEY (cfg_id) 83 | REFERENCES configs (cfg_id) MATCH SIMPLE 84 | ON UPDATE NO ACTION ON DELETE NO ACTION 85 | ); 86 | 87 | -- A test run. One row (a single run_id) represents (an index for) all the 88 | -- tests for a given multilib, i.e. all the different components under test. 89 | -- Not sure if that's sensible. 90 | 91 | CREATE TABLE testrun ( 92 | run_id serial PRIMARY KEY, 93 | bundle_id integer NOT NULL, 94 | mlib_id integer NOT NULL, 95 | CONSTRAINT bundle_fkey FOREIGN KEY (bundle_id) 96 | REFERENCES testbundle (bundle_id) MATCH SIMPLE 97 | ON UPDATE NO ACTION ON DELETE NO ACTION, 98 | CONSTRAINT mlib_fkey FOREIGN KEY (mlib_id) 99 | REFERENCES multilibs (mlib_id) MATCH SIMPLE 100 | ON UPDATE NO ACTION ON DELETE NO ACTION 101 | ); 102 | 103 | -- A free-form version for a particular component. Maybe a subversion or git 104 | -- revision, or an "official" release version number. 105 | 106 | CREATE TABLE versions ( 107 | vers_id serial PRIMARY KEY, 108 | version text UNIQUE NOT NULL 109 | ); 110 | 111 | -- A test bundle can record the versions of each of the components under test 112 | -- using rows of this table. As many or as few versions can be stored as 113 | -- appropriate. Whether the component's repository is "modified", i.e. 114 | -- contains uncommitted patches at the time of testing can also be recorded. 115 | 116 | CREATE TABLE component_version ( 117 | bundle_id integer, 118 | comp_id integer, 119 | vers_id integer, 120 | modified BOOLEAN NOT NULL, 121 | CONSTRAINT bundle_fkey FOREIGN KEY (bundle_id) 122 | REFERENCES testbundle (bundle_id) MATCH SIMPLE 123 | ON UPDATE NO ACTION ON DELETE NO ACTION, 124 | CONSTRAINT comp_fkey FOREIGN KEY (comp_id) 125 | REFERENCES components (comp_id) MATCH SIMPLE 126 | ON UPDATE NO ACTION ON DELETE NO ACTION, 127 | CONSTRAINT vers_fkey FOREIGN KEY (vers_id) 128 | REFERENCES versions (vers_id) MATCH SIMPLE 129 | ON UPDATE NO ACTION ON DELETE NO ACTION 130 | ); 131 | 132 | -- Outcome for a single test. Self-explanatory. 133 | 134 | CREATE TYPE outcome AS ENUM ( 135 | 'PASS', 136 | 'FAIL', 137 | 'XPASS', 138 | 'XFAIL', 139 | 'ERROR', 140 | 'UNSUPPORTED', 141 | 'UNRESOLVED', 142 | 'WARNING', 143 | 'UNTESTED', 144 | 'KFAIL', 145 | 'GDB_compile_failed', 146 | 'Misc_error' 147 | ); 148 | 149 | -- One row per test result. Basically three indices -- so probably 12 bytes of 150 | -- storage per result. 151 | 152 | CREATE TABLE results ( 153 | run_id integer NOT NULL, 154 | test_id integer NOT NULL, 155 | test_collate integer NOT NULL, 156 | -- enums don't work with pg'ocaml. Bah! 157 | result text, 158 | CONSTRAINT run_fkey FOREIGN KEY (run_id) 159 | REFERENCES testrun (run_id) MATCH SIMPLE 160 | ON UPDATE NO ACTION ON DELETE NO ACTION, 161 | CONSTRAINT test_fkey FOREIGN KEY (test_id) 162 | REFERENCES tests (test_id) MATCH SIMPLE 163 | ON UPDATE NO ACTION ON DELETE NO ACTION 164 | ); 165 | 166 | -- No constraints here for target, cfg or multilib, allowing them to be blank 167 | -- for "don't care"/all. 168 | 169 | CREATE TABLE xfails ( 170 | xfail_id serial PRIMARY KEY, 171 | test_id integer NOT NULL, 172 | target_id integer, 173 | cfg_id integer, 174 | mlib_id integer, 175 | reason text, 176 | CONSTRAINT test_fkey FOREIGN KEY (test_id) 177 | REFERENCES tests (test_id) MATCH SIMPLE 178 | ON UPDATE NO ACTION ON DELETE NO ACTION 179 | ); 180 | 181 | -- Test sanity. 182 | 183 | INSERT INTO components (component) VALUES ('gcc'); 184 | 185 | INSERT INTO expfiles (name) VALUES ('compile.exp'); 186 | 187 | INSERT INTO tests (comp_id, exp_id, name) VALUES ( 188 | (SELECT comp_id FROM components WHERE component = 'gcc'), 189 | (SELECT exp_id FROM expfiles WHERE name = 'compile.exp'), 190 | 'Check for foos and bars'); 191 | 192 | INSERT INTO tests (comp_id, exp_id, name) VALUES ( 193 | (SELECT comp_id FROM components WHERE component = 'gcc'), 194 | (SELECT exp_id FROM expfiles WHERE name = 'compile.exp'), 195 | 'Check for foos and bazzes'); 196 | 197 | INSERT INTO targets (target) VALUES ('6502'); 198 | INSERT INTO configs (config) VALUES ('build.sh'); 199 | INSERT INTO multilibs (multilib) VALUES ('.;'); 200 | 201 | INSERT INTO testbundle (target_id, cfg_id, date) VALUES ( 202 | (SELECT target_id FROM targets WHERE target = '6502'), 203 | (SELECT cfg_id FROM configs WHERE config = 'build.sh'), 204 | '2014-04-03 23:05:00'); 205 | 206 | INSERT INTO versions (version) VALUES ('SVN-r155'); 207 | 208 | INSERT INTO component_version (bundle_id, comp_id, vers_id, modified) VALUES ( 209 | (SELECT bundle_id FROM testbundle WHERE date = '2014-04-03 23:05:00'), 210 | (SELECT comp_id FROM components WHERE component = 'gcc'), 211 | (SELECT vers_id FROM versions WHERE version = 'SVN-r155'), 212 | FALSE); 213 | 214 | WITH rid AS ( 215 | INSERT INTO testrun (bundle_id, mlib_id) VALUES ( 216 | (SELECT bundle_id FROM testbundle WHERE date = '2014-04-03 23:05:00'), 217 | (SELECT mlib_id FROM multilibs WHERE multilib = '.;')) 218 | RETURNING run_id AS run_id 219 | ) 220 | INSERT INTO results (run_id, test_id, test_collate, result) VALUES ( 221 | (select run_id from rid), 222 | (SELECT test_id FROM tests WHERE name = 'Check for foos and bars'), 223 | 0, 224 | 'PASS' 225 | ); 226 | 227 | INSERT INTO xfails (test_id, target_id, reason) VALUES ( 228 | (SELECT test_id from tests WHERE name = 'Check for foos and bazzes'), 229 | (SELECT target_id from targets WHERE target = '6502'), 230 | 'This one plain doesn''t work!' 231 | ); 232 | -------------------------------------------------------------------------------- /resultdb/resultdb.ml: -------------------------------------------------------------------------------- 1 | type result = PASS | FAIL | XPASS | XFAIL | ERROR | UNSUPPORTED | UNRESOLVED 2 | | WARNING | UNTESTED | KFAIL | GDB_compile_failed | Misc_error 3 | 4 | type line_type = Result of result * string 5 | | Test_error of result * string 6 | | Begin_exp of string 7 | | Unknown 8 | 9 | let rec skip_header fh = 10 | try 11 | let line = input_line fh in 12 | if String.length line >= 7 && (String.sub line 0 7) = "Running" then () 13 | else skip_header fh 14 | with End_of_file -> () 15 | 16 | exception Bad_line 17 | 18 | let running_exp_file = Str.regexp "^Running \\([^ ]*\\)" 19 | 20 | let classify line = 21 | if Str.string_match running_exp_file line 0 then begin 22 | Begin_exp (Str.matched_group 1 line) 23 | end else begin 24 | try 25 | let idx = String.index line ':' in 26 | let res = String.sub line 0 idx 27 | and test = String.sub line (idx + 2) ((String.length line) - (idx + 2)) in 28 | let restype = match res with 29 | "PASS" -> PASS 30 | | "FAIL" -> FAIL 31 | | "XPASS" -> XPASS 32 | | "XFAIL" -> XFAIL 33 | | "ERROR" -> ERROR 34 | | "UNSUPPORTED" -> UNSUPPORTED 35 | | "UNRESOLVED" -> UNRESOLVED 36 | | "WARNING" -> WARNING 37 | | "UNTESTED" -> UNTESTED 38 | | "KFAIL" -> KFAIL 39 | | _ -> raise Bad_line in 40 | Result (restype, test) 41 | with 42 | Not_found -> Unknown 43 | | Invalid_argument "String.sub" -> raise Bad_line 44 | end 45 | 46 | let contains_regex regex str = 47 | try 48 | let _ = Str.search_forward regex str 0 in 49 | true 50 | with Not_found -> false 51 | 52 | let expfile_strip expfile testsuite_dir = 53 | let path = FilePath.DefaultPath.filename_of_string expfile in 54 | let rec scan p = 55 | if FilePath.basename p = testsuite_dir then 56 | FilePath.make_relative p path 57 | else 58 | let updir = FilePath.dirname p in 59 | if FilePath.is_updir updir p then scan updir else expfile in 60 | scan path 61 | 62 | exception Too_many 63 | 64 | let one_result = function 65 | [] -> raise Not_found 66 | | [x] -> x 67 | | _ -> raise Too_many 68 | 69 | let expfile_id dbh expfile = 70 | try 71 | one_result (PGSQL (dbh) "select exp_id from expfiles where name=$expfile") 72 | with Not_found -> 73 | one_result (PGSQL (dbh) "insert into expfiles (name) values ($expfile) \ 74 | returning exp_id") 75 | 76 | let component_id dbh component = 77 | try 78 | one_result (PGSQL (dbh) "select comp_id from components \ 79 | where component=$component") 80 | with Not_found -> 81 | one_result (PGSQL (dbh) "insert into components (component) \ 82 | values ($component) returning comp_id") 83 | 84 | let test_id dbh comp_id exp_id testname = 85 | try 86 | one_result (PGSQL (dbh) "select test_id from tests where \ 87 | comp_id=$comp_id and exp_id=$exp_id \ 88 | and name=$testname") 89 | with Not_found -> 90 | one_result (PGSQL (dbh) "insert into tests (comp_id, exp_id, name) \ 91 | values ($comp_id, $exp_id, $testname) \ 92 | returning test_id") 93 | 94 | let target_id dbh target = 95 | try 96 | one_result (PGSQL (dbh) "select target_id from targets \ 97 | where target=$target") 98 | with Not_found -> 99 | one_result (PGSQL (dbh) "insert into targets (target) values ($target) \ 100 | returning target_id") 101 | 102 | let multilib_id dbh mlib = 103 | try 104 | one_result (PGSQL (dbh) "select mlib_id from multilibs \ 105 | where multilib=$mlib") 106 | with Not_found -> 107 | one_result (PGSQL (dbh) "insert into multilibs (multilib) values ($mlib) \ 108 | returning mlib_id") 109 | 110 | let config_id dbh config = 111 | try 112 | one_result (PGSQL (dbh) "select cfg_id from configs \ 113 | where config=$config") 114 | with Not_found -> 115 | one_result (PGSQL (dbh) "insert into configs (config) values ($config) \ 116 | returning cfg_id") 117 | 118 | let create_bundle dbh target_id cfg_id datestamp = 119 | one_result (PGSQL (dbh) "insert into testbundle (target_id, cfg_id, date) \ 120 | values ($target_id, $cfg_id, $datestamp) \ 121 | returning bundle_id") 122 | 123 | let create_testrun dbh bundle_id mlib_id = 124 | one_result (PGSQL (dbh) "insert into testrun (bundle_id, mlib_id) \ 125 | values ($bundle_id, $mlib_id) 126 | returning run_id") 127 | 128 | let string_of_result = function 129 | PASS -> "PASS" 130 | | FAIL -> "FAIL" 131 | | XPASS -> "XPASS" 132 | | XFAIL -> "XFAIL" 133 | | ERROR -> "ERROR" 134 | | UNSUPPORTED -> "UNSUPPORTED" 135 | | UNRESOLVED -> "UNRESOLVED" 136 | | WARNING -> "WARNING" 137 | | UNTESTED -> "UNTESTED" 138 | | KFAIL -> "KFAIL" 139 | | GDB_compile_failed -> "GDB_compile_failed" 140 | | Misc_error -> "Misc_error" 141 | 142 | let add_result dbh run_id test_id test_collate result = 143 | let result_str = string_of_result result in 144 | PGSQL (dbh) "insert into results (run_id, test_id, test_collate, result) \ 145 | values ($run_id, $test_id, $test_collate, $result_str)" 146 | 147 | let read_sum_file dbh comp_id run_id sumfile = 148 | let gdb_comp_failed = Str.regexp "\\(^gdb compile failed, \\)" in 149 | let line_number = ref 0 150 | and current_expfile = ref "(unknown exp file)" in 151 | let current_expid = ref (expfile_id dbh !current_expfile) 152 | and fh = open_in sumfile in 153 | skip_header fh; 154 | try 155 | while true do 156 | let line = input_line fh in 157 | let classified = 158 | try 159 | classify line 160 | with Bad_line -> 161 | if Str.string_match gdb_comp_failed line 0 then 162 | let testname = Str.string_after line (Str.match_end ()) in 163 | Test_error (GDB_compile_failed, testname) 164 | else 165 | Test_error (Misc_error, line) in 166 | begin match classified with 167 | Unknown -> () 168 | | Begin_exp e -> 169 | let stripped = expfile_strip e "testsuite" in 170 | let exp_id = expfile_id dbh stripped in 171 | current_expfile := e; 172 | current_expid := exp_id 173 | | Result (res, test) 174 | | Test_error (res, test) -> 175 | let test_id = test_id dbh comp_id !current_expid test in 176 | add_result dbh run_id test_id (Int32.of_int !line_number) res 177 | end; 178 | incr line_number 179 | done 180 | with End_of_file -> close_in fh 181 | 182 | 183 | let _ = 184 | Unix.putenv "PGDATABASE" "gcc_results"; 185 | Unix.putenv "PGPASSWORD" "password"; 186 | Unix.putenv "PGHOST" "localhost"; 187 | Unix.putenv "PGPORT" "5432"; 188 | let dbh = PGOCaml.connect () in 189 | 190 | let bundle_id = create_bundle dbh (target_id dbh "6502") 191 | (config_id dbh "build.sh") (CalendarLib.Calendar.now ()) in 192 | 193 | let run_id = create_testrun dbh bundle_id (multilib_id dbh ".;") in 194 | 195 | read_sum_file dbh (component_id dbh "gcc") run_id 196 | "/home/jules/stuff-in-hiding/gcc-6502/testresults-2014-04-05-1/gcc.sum"; 197 | 198 | let print_comp c = 199 | Printf.printf "%s\n" c in 200 | 201 | let compos = PGSQL(dbh) "select component from components" in 202 | List.iter print_comp compos; 203 | 204 | PGOCaml.close dbh 205 | -------------------------------------------------------------------------------- /semi65x/6502core.h: -------------------------------------------------------------------------------- 1 | /**************************************************************** 2 | BeebEm - BBC Micro and Master 128 Emulator 3 | Copyright (C) 1994 David Alan Gilbert 4 | Copyright (C) 1997 Mike Wyatt 5 | Copyright (C) 2001 Richard Gellman 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public 18 | License along with this program; if not, write to the Free 19 | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | Boston, MA 02110-1301, USA. 21 | ****************************************************************/ 22 | 23 | /* 6502Core - header - David Alan Gilbert 16/10/94 */ 24 | 25 | #ifndef CORE6502_HEADER 26 | #define CORE6502_HEADER 27 | 28 | #ifndef SEMI65X 29 | #include "port.h" 30 | #endif 31 | #include "stdio.h" 32 | 33 | void DumpRegs(void); 34 | 35 | typedef enum IRQ_Nums { 36 | sysVia, 37 | userVia, 38 | serial, 39 | tube, 40 | teletext, 41 | hdc, 42 | } IRQ_Nums; 43 | 44 | typedef enum NMI_Nums{ 45 | nmi_floppy, 46 | nmi_econet, 47 | } NMI_Nums; 48 | 49 | typedef enum PSR_Flags 50 | { 51 | FlagC=1, 52 | FlagZ=2, 53 | FlagI=4, 54 | FlagD=8, 55 | FlagB=16, 56 | FlagV=64, 57 | FlagN=128 58 | } PSR_Flags; 59 | 60 | extern int trace; 61 | extern int trace_186; 62 | extern int IgnoreIllegalInstructions; 63 | extern int BeginDump; 64 | 65 | extern unsigned char intStatus; 66 | extern unsigned char NMIStatus; 67 | extern unsigned int Cycles; 68 | extern int ProgramCounter; 69 | extern int PrePC; 70 | extern CycleCountT TotalCycles; 71 | extern unsigned int NMILock; 72 | extern int DisplayCycles; 73 | 74 | extern int CyclesToInt; 75 | #define NO_TIMER_INT_DUE -1000000 76 | 77 | #define SetTrigger(after,var) var=TotalCycles+after; 78 | #define IncTrigger(after,var) var+=(after); 79 | 80 | #define ClearTrigger(var) var=CycleCountTMax; 81 | 82 | #define AdjustTrigger(var) if (var!=CycleCountTMax) var-=CycleCountWrap; 83 | 84 | /*-------------------------------------------------------------------------*/ 85 | /* Initialise 6502core */ 86 | void Init6502core(void); 87 | 88 | /*-------------------------------------------------------------------------*/ 89 | /* Execute one 6502 instruction, move program counter on */ 90 | void Exec6502Instruction(void); 91 | 92 | void DoNMI(void); 93 | void core_dumpstate(void); 94 | void DoInterrupt(void); 95 | void Save6502UEF(FILE *SUEF); 96 | void Load6502UEF(FILE *SUEF); 97 | void SyncIO(void); 98 | void AdjustForIORead(void); 99 | void AdjustForIOWrite(void); 100 | 101 | #ifdef M512COPRO_ENABLED 102 | int i186_execute(int num_cycles); 103 | #endif 104 | 105 | extern int SwitchOnCycles; // Reset delay 106 | extern int OpCodes; 107 | extern int BHardware; 108 | #endif 109 | -------------------------------------------------------------------------------- /semi65x/Makefile: -------------------------------------------------------------------------------- 1 | CXX := g++ -DSEMI65X 2 | CFLAGS = -g -O3 -Wall $(INCLUDE) 3 | CXXFLAGS = -g -O3 -Wall $(INCLUDE) 4 | INCLUDE := 5 | LIBS := -lboost_regex 6 | LD := $(CXX) 7 | 8 | OBJS := mapfile.o disas.o semi65x.o 6502core.o 9 | 10 | TARGET := semi65x 11 | 12 | .PHONY: .depend 13 | 14 | all: $(TARGET) 15 | 16 | clean: 17 | rm -f *.o $(TARGET) 18 | 19 | cleaner: clean 20 | rm -f *.d 21 | 22 | $(TARGET): $(OBJS) 23 | $(CXX) $(OBJS) -o $@ $(LIBS) 24 | 25 | %.o: %.cpp 26 | $(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@ 27 | 28 | %.o: %.c 29 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 30 | 31 | %.d: %.cpp 32 | $(CXX) $(CXXFLAGS) $(INCLUDE) -MM $< | ./dirify.sh "$@" > "$@" 33 | 34 | %.d: %.c 35 | $(CC) $(CFLAGS) $(INCLUDE) -MM $< | ./dirify.sh "$@" > "$@" 36 | 37 | ifneq ($(MAKECMDGOALS),clean) 38 | ifneq ($(MAKECMDGOALS),cleaner) 39 | include $(OBJS:.o=.d) 40 | endif 41 | endif 42 | 43 | -------------------------------------------------------------------------------- /semi65x/dirify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | DIR=$(dirname "$1") 3 | while read line; do 4 | echo $line | sed 's,\([^.]*.o\):,'"$DIR"'/\1:,g' 5 | done 6 | -------------------------------------------------------------------------------- /semi65x/disas.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mapfile.h" 5 | 6 | static const char *opcodes[] = 7 | { 8 | /* 0x00 */ 9 | "brk", "ora", "$02", "$03", "tsb", "ora", "asl", "$07", 10 | "php", "ora", "asl", "$0b", "tsb", "ora", "asl", "$0f", 11 | /* 0x10 */ 12 | "bpl", "ora", "ora", "$13", "trb", "ora", "asl", "$17", 13 | "clc", "ora", "inc", "$1b", "trb", "ora", "asl", "$1f", 14 | /* 0x20 */ 15 | "jsr", "and", "$22", "$23", "bit", "and", "rol", "$27", 16 | "plp", "and", "rol", "$2b", "bit", "and", "rol", "$2f", 17 | /* 0x30 */ 18 | "bmi", "and", "and", "$33", "bit", "and", "rol", "$37", 19 | "sec", "and", "dec", "$3b", "bit", "and", "rol", "$3f", 20 | /* 0x40 */ 21 | "rti", "eor", "$42", "$43", "bit", "eor", "lsr", "$47", 22 | "pha", "eor", "lsr", "$4b", "jmp", "eor", "lsr", "$4f", 23 | /* 0x50 */ 24 | "bvc", "eor", "eor", "$53", "$54", "eor", "lsr", "$57", 25 | "cli", "eor", "phy", "$5b", "jmp", "eor", "lsr", "$5f", 26 | /* 0x60 */ 27 | "rts", "adc", "$62", "$63", "stz", "adc", "ror", "$67", 28 | "pla", "adc", "ror", "$6b", "jmp", "adc", "ror", "$6f", 29 | /* 0x70 */ 30 | "bvs", "adc", "adc", "$73", "stz", "adc", "ror", "$77", 31 | "sei", "adc", "ply", "$7b", "jmp", "adc", "ror", "$7f", 32 | /* 0x80 */ 33 | "bra", "sta", "$82", "$83", "sty", "sta", "stx", "$87", 34 | "dey", "bit", "txa", "$8b", "sty", "sta", "stx", "$8f", 35 | /* 0x90 */ 36 | "bcc", "sta", "sta", "$93", "sty", "sta", "stx", "$97", 37 | "tya", "sta", "txs", "$9b", "stz", "sta", "stz", "$9f", 38 | /* 0xa0 */ 39 | "ldy", "lda", "ldx", "$a3", "ldy", "lda", "ldx", "$a7", 40 | "tay", "lda", "tax", "$ab", "ldy", "lda", "ldx", "$af", 41 | /* 0xb0 */ 42 | "bcs", "lda", "lda", "$b3", "ldy", "lda", "ldx", "$b7", 43 | "clv", "lda", "tsx", "$bb", "ldy", "lda", "ldx", "$bf", 44 | /* 0xc0 */ 45 | "cpy", "cmp", "$c2", "$c3", "cpy", "cmp", "dec", "$c7", 46 | "iny", "cmp", "dex", "$cb", "cpy", "cmp", "dec", "$cf", 47 | /* 0xd0 */ 48 | "bne", "cmp", "cmp", "$d3", "$d4", "cmp", "dec", "$d7", 49 | "cld", "cmp", "phx", "$db", "$dc", "cmp", "dec", "$df", 50 | /* 0xe0 */ 51 | "cpx", "sbc", "$e2", "$e3", "cpx", "sbc", "inc", "$e7", 52 | "inx", "sbc", "nop", "$eb", "cpx", "sbc", "inc", "$ef", 53 | /* 0xf0 */ 54 | "beq", "sbc", "sbc", "$f3", "$f4", "sbc", "inc", "$f7", 55 | "sed", "sbc", "plx", "$fb", "$fc", "sbc", "inc", "$ff" 56 | }; 57 | 58 | enum addrmode 59 | { 60 | UNKNOWN, 61 | IMPLIED, 62 | INDIRECT, 63 | INDEXED_INDIRECT, 64 | ZP, 65 | ACCUMULATOR, 66 | IMMEDIATE, 67 | ABSOLUTE, 68 | INDIRECT_INDEXED, 69 | ZP_X, 70 | ZP_Y, 71 | ABS_X, 72 | ABS_Y, 73 | IND_ABS_X, 74 | RELATIVE 75 | }; 76 | 77 | static const char *softregs[] = 78 | { 79 | "_sp0", "_sp1", "_fp0", "_fp1", 80 | "_r0", "_r1", "_r2", "_r3", "_r4", "_r5", "_r6", "_r7", 81 | "_s0", "_s1", "_s2", "_s3", "_s4", "_s5", "_s6", "_s7", 82 | "_e0", "_e1", "_e2", "_e3", "_e4", "_e5", "_e6", "_e7", 83 | "_e8", "_e9", "_e10", "_e11", "_e12", "_e13", "_e14", "_e15", 84 | "_e16", "_e17", "_e18", "_e19", "_e20", "_e21", "_e22", "_e23", 85 | "_e24", "_e25", "_e26", "_e27", "_e28", "_e29", "_e30", "_e31", 86 | "_tmp0", "_tmp1", "_sa", "_sx", "_sy" 87 | }; 88 | 89 | #define ARRAYLEN(X) (sizeof(X) / sizeof(X[0])) 90 | 91 | static unsigned softreg_base = 0; 92 | 93 | static const char *fancy_name (unsigned regnum) 94 | { 95 | if (regnum >= softreg_base && regnum < softreg_base + ARRAYLEN (softregs)) 96 | return softregs[regnum - softreg_base]; 97 | 98 | return NULL; 99 | } 100 | 101 | /* Print disassembled insn to OUTFILE. Return number of bytes consumed. */ 102 | 103 | int 104 | disassemble_insn (FILE *outfile, unsigned int pc, unsigned char *insn) 105 | { 106 | int opcode = insn[0]; 107 | addrmode am; 108 | const char *regname; 109 | 110 | switch (opcode & 0x3) 111 | { 112 | case 0x1: 113 | switch (opcode) 114 | { 115 | case 0x01: case 0x21: case 0x41: case 0x61: 116 | case 0x81: case 0xa1: case 0xc1: case 0xe1: 117 | am = INDEXED_INDIRECT; 118 | break; 119 | 120 | case 0x05: case 0x25: case 0x45: case 0x65: 121 | case 0x85: case 0xa5: case 0xc5: case 0xe5: 122 | am = ZP; 123 | break; 124 | 125 | case 0x09: case 0x29: case 0x49: case 0x69: 126 | case 0xa9: case 0xc9: case 0xe9: 127 | am = IMMEDIATE; 128 | break; 129 | 130 | case 0x0d: case 0x2d: case 0x4d: case 0x6d: 131 | case 0x8d: case 0xad: case 0xcd: case 0xed: 132 | am = ABSOLUTE; 133 | break; 134 | 135 | case 0x11: case 0x31: case 0x51: case 0x71: 136 | case 0x91: case 0xb1: case 0xd1: case 0xf1: 137 | am = INDIRECT_INDEXED; 138 | break; 139 | 140 | case 0x15: case 0x35: case 0x55: case 0x75: 141 | case 0x95: case 0xb5: case 0xd5: case 0xf5: 142 | am = ZP_X; 143 | break; 144 | 145 | case 0x19: case 0x39: case 0x59: case 0x79: 146 | case 0x99: case 0xb9: case 0xd9: case 0xf9: 147 | am = ABS_Y; 148 | break; 149 | 150 | case 0x1d: case 0x3d: case 0x5d: case 0x7d: 151 | case 0x9d: case 0xbd: case 0xdd: case 0xfd: 152 | am = ABS_X; 153 | break; 154 | 155 | default: 156 | am = UNKNOWN; 157 | } 158 | break; 159 | 160 | case 0x2: 161 | switch (opcode) 162 | { 163 | case 0xa2: 164 | am = IMMEDIATE; 165 | break; 166 | 167 | case 0x06: case 0x26: case 0x46: case 0x66: 168 | case 0x86: case 0xa6: case 0xc6: case 0xe6: 169 | am = ZP; 170 | break; 171 | 172 | case 0x0a: case 0x2a: case 0x4a: case 0x6a: 173 | am = ACCUMULATOR; 174 | break; 175 | 176 | case 0x0e: case 0x2e: case 0x4e: case 0x6e: 177 | case 0x8e: case 0xae: case 0xce: case 0xee: 178 | am = ABSOLUTE; 179 | break; 180 | 181 | case 0x16: case 0x36: case 0x56: case 0x76: 182 | case 0xd6: case 0xf6: 183 | am = ZP_X; 184 | break; 185 | 186 | case 0x96: case 0xb6: 187 | am = ZP_Y; 188 | break; 189 | 190 | case 0x1e: case 0x3e: case 0x5e: case 0x7e: 191 | case 0xde: case 0xfe: 192 | am = ABS_X; 193 | break; 194 | 195 | case 0xbe: 196 | am = ABS_Y; 197 | break; 198 | 199 | default: 200 | am = UNKNOWN; 201 | } 202 | break; 203 | 204 | case 0x0: 205 | switch (opcode) 206 | { 207 | case 0xa0: case 0xc0: case 0xe0: 208 | am = IMMEDIATE; 209 | break; 210 | 211 | case 0x24: case 0x84: case 0xa4: case 0xc4: case 0xe4: 212 | am = ZP; 213 | break; 214 | 215 | case 0x2c: case 0x4c: case 0x6c: case 0x8c: case 0xac: 216 | case 0xcc: case 0xec: 217 | am = ABSOLUTE; 218 | break; 219 | 220 | case 0x94: case 0xb4: 221 | am = ZP_X; 222 | break; 223 | 224 | case 0xbc: 225 | am = ABS_X; 226 | break; 227 | 228 | default: 229 | am = UNKNOWN; 230 | } 231 | break; 232 | 233 | case 0x3: 234 | am = UNKNOWN; 235 | } 236 | 237 | /* Branch instructions. */ 238 | if ((opcode & 0x1f) == 0x10) 239 | am = RELATIVE; 240 | 241 | switch (opcode) 242 | { 243 | case 0x00: 244 | case 0x40: 245 | case 0x60: 246 | case 0x08: case 0x28: case 0x48: case 0x68: 247 | case 0x88: case 0xa8: case 0xc8: case 0xe8: 248 | case 0x18: case 0x38: case 0x58: case 0x78: 249 | case 0x98: case 0xb8: case 0xd8: case 0xf8: 250 | case 0x8a: case 0x9a: case 0xaa: case 0xba: 251 | case 0xca: case 0xea: 252 | am = IMPLIED; 253 | break; 254 | 255 | case 0x20: 256 | am = ABSOLUTE; 257 | break; 258 | 259 | /* 65C02 insns. */ 260 | case 0x1a: case 0x3a: case 0x5a: case 0x7a: 261 | case 0xda: case 0xfa: 262 | am = IMPLIED; 263 | break; 264 | 265 | case 0x12: case 0x32: case 0x52: case 0x72: 266 | case 0x92: case 0xb2: case 0xd2: case 0xf2: 267 | am = INDIRECT; 268 | break; 269 | 270 | case 0x7c: 271 | am = IND_ABS_X; 272 | break; 273 | 274 | case 0x89: 275 | am = IMMEDIATE; 276 | break; 277 | 278 | case 0x34: case 0x74: 279 | am = ZP_X; 280 | break; 281 | 282 | case 0x3c: case 0x9e: 283 | am = ABS_X; 284 | break; 285 | 286 | case 0x04: 287 | case 0x14: case 0x64: 288 | /* Some 65C02s only. */ 289 | case 0x07: case 0x17: case 0x27: case 0x37: 290 | case 0x47: case 0x57: case 0x67: case 0x77: 291 | case 0x87: case 0x97: case 0xa7: case 0xb7: 292 | case 0xc7: case 0xd7: case 0xe7: case 0xf7: 293 | am = ZP; 294 | break; 295 | 296 | case 0x0c: case 0x1c: case 0x9c: 297 | am = ABSOLUTE; 298 | break; 299 | 300 | case 0x80: 301 | am = RELATIVE; 302 | break; 303 | 304 | default: 305 | ; 306 | } 307 | 308 | /*fprintf (outfile, "(%.2x) ", opcode);*/ 309 | 310 | switch (am) 311 | { 312 | case RELATIVE: 313 | { 314 | int addr = pc + (signed char) insn[1] + 2; 315 | const char *symbolic_name = find_symbol (addr).c_str(); 316 | fprintf (outfile, "%s %s", opcodes[opcode], symbolic_name); 317 | if (symbolic_name[0] != '$') 318 | fprintf (outfile, " ($%.4x)", addr); 319 | return 2; 320 | } 321 | 322 | case INDIRECT: 323 | if ((regname = fancy_name (insn[1]))) 324 | fprintf (outfile, "%s (%s)", opcodes[opcode], regname); 325 | else 326 | fprintf (outfile, "%s ($%.2x)", opcodes[opcode], insn[1]); 327 | return 2; 328 | 329 | case INDEXED_INDIRECT: 330 | if ((regname = fancy_name (insn[1]))) 331 | fprintf (outfile, "%s (%s,x)", opcodes[opcode], regname); 332 | else 333 | fprintf (outfile, "%s ($%.2x,x)", opcodes[opcode], insn[1]); 334 | return 2; 335 | 336 | case ZP: 337 | if ((regname = fancy_name (insn[1]))) 338 | fprintf (outfile, "%s %s", opcodes[opcode], regname); 339 | else 340 | fprintf (outfile, "%s $%.2x", opcodes[opcode], insn[1]); 341 | return 2; 342 | 343 | case ZP_X: 344 | if ((regname = fancy_name (insn[1]))) 345 | fprintf (outfile, "%s %s,x", opcodes[opcode], regname); 346 | else 347 | fprintf (outfile, "%s $%.2x,x", opcodes[opcode], insn[1]); 348 | return 2; 349 | 350 | case ZP_Y: 351 | if ((regname = fancy_name (insn[1]))) 352 | fprintf (outfile, "%s %s,y", opcodes[opcode], regname); 353 | else 354 | fprintf (outfile, "%s $%.2x,y", opcodes[opcode], insn[1]); 355 | return 2; 356 | 357 | case ACCUMULATOR: 358 | fprintf (outfile, "%s a", opcodes[opcode]); 359 | return 1; 360 | 361 | case IMPLIED: 362 | fprintf (outfile, "%s", opcodes[opcode]); 363 | return 1; 364 | 365 | case IMMEDIATE: 366 | fprintf (outfile, "%s #$%.2x", opcodes[opcode], insn[1]); 367 | return 2; 368 | 369 | case ABSOLUTE: 370 | { 371 | int addr = insn[1] + insn[2] * 256; 372 | const char *symbolic_name = find_symbol (addr).c_str(); 373 | fprintf (outfile, "%s %s", opcodes[opcode], symbolic_name); 374 | if (symbolic_name[0] != '$') 375 | fprintf (outfile, " ($%.4x)", addr); 376 | return 3; 377 | } 378 | 379 | case ABS_X: 380 | fprintf (outfile, "%s $%.4x,x", opcodes[opcode], 381 | insn[1] + insn[2] * 256); 382 | return 3; 383 | 384 | case ABS_Y: 385 | fprintf (outfile, "%s $%.4x,y", opcodes[opcode], 386 | insn[1] + insn[2] * 256); 387 | return 3; 388 | 389 | case INDIRECT_INDEXED: 390 | if ((regname = fancy_name (insn[1]))) 391 | fprintf (outfile, "%s (%s),y", opcodes[opcode], regname); 392 | else 393 | fprintf (outfile, "%s ($%.2x),y", opcodes[opcode], insn[1]); 394 | return 2; 395 | 396 | case IND_ABS_X: 397 | fprintf (outfile, "%s $%.4x,x", opcodes[opcode], 398 | insn[1] + insn[2] * 256); 399 | return 3; 400 | 401 | case UNKNOWN: 402 | fprintf (outfile, "%s ??", opcodes[opcode]); 403 | return 1; 404 | } 405 | 406 | return -1; 407 | } 408 | -------------------------------------------------------------------------------- /semi65x/disas.h: -------------------------------------------------------------------------------- 1 | #ifndef DISAS_H 2 | #define DISAS_H 1 3 | 4 | extern int disassemble_insn (FILE *, unsigned int, unsigned char *); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /semi65x/mapfile.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "mapfile.h" 13 | 14 | using namespace std; 15 | 16 | vector modules; 17 | vector segments; 18 | map exports; 19 | vector imports; 20 | 21 | enum filepart 22 | { 23 | UNKNOWN, 24 | MODULES_LIST, 25 | SEGMENT_LIST, 26 | EXPORTS_LIST, 27 | IMPORTS_LIST 28 | }; 29 | 30 | void 31 | add_symbol (uint16_t addr, string symname) 32 | { 33 | //cerr << "Adding symbol '" << symname << "' with value " << addr << endl; 34 | exports[addr] = symname; 35 | } 36 | 37 | string 38 | find_symbol (int addr) 39 | { 40 | map::iterator mi; 41 | mi = exports.upper_bound(addr); 42 | 43 | if (exports.empty() || mi == exports.begin()) 44 | { 45 | std::stringstream ss; 46 | ss << '$' << std::hex << addr; 47 | return ss.str(); 48 | } 49 | else 50 | { 51 | mi--; 52 | if (mi->first == addr) 53 | return mi->second; 54 | else 55 | { 56 | std::stringstream ss; 57 | ss << mi->second << "+" << addr - mi->first; 58 | return ss.str(); 59 | } 60 | } 61 | } 62 | 63 | void 64 | parse_map (const char *filename) 65 | { 66 | filepart part = UNKNOWN; 67 | bool seen_separator = false; 68 | 69 | modules.clear(); 70 | segments.clear(); 71 | exports.clear(); 72 | imports.clear(); 73 | 74 | ifstream ifs; 75 | 76 | boost::regex one_export_re("([A-Za-z_]+[A-Za-z0-9_$]*)\\s+([0-9A-F]+)\\s+" 77 | "([ALR]+)\\s+"); 78 | boost::regex two_exports_re("([A-Za-z_]+[A-Za-z0-9_$]*)\\s+([0-9A-F]+)\\s+" 79 | "([ALR]+)\\s+" 80 | "([A-Za-z_]+[A-Za-z0-9_$]*)\\s+([0-9A-F]+)\\s+" 81 | "([ALR]+)\\s+"); 82 | 83 | ifs.open (filename, ifstream::in); 84 | 85 | while (ifs.good()) 86 | { 87 | string line; 88 | 89 | getline (ifs, line); 90 | 91 | switch (part) 92 | { 93 | case UNKNOWN: 94 | if (line.compare("Modules list:") == 0) 95 | { 96 | part = MODULES_LIST; 97 | seen_separator = false; 98 | continue; 99 | } 100 | break; 101 | 102 | case MODULES_LIST: 103 | if (line.compare("Segment list:") == 0) 104 | { 105 | part = SEGMENT_LIST; 106 | seen_separator = false; 107 | continue; 108 | } 109 | 110 | if (line.compare("-------------") == 0) 111 | seen_separator = true; 112 | else 113 | { 114 | 115 | } 116 | break; 117 | 118 | case SEGMENT_LIST: 119 | if (line.compare("Exports list by name:") == 0) 120 | { 121 | part = EXPORTS_LIST; 122 | seen_separator = false; 123 | continue; 124 | } 125 | 126 | if (line.compare("-------------") == 0) 127 | seen_separator = true; 128 | else 129 | { 130 | 131 | } 132 | break; 133 | 134 | case EXPORTS_LIST: 135 | if (line.compare("Imports list:") == 0) 136 | { 137 | part = IMPORTS_LIST; 138 | seen_separator = false; 139 | continue; 140 | } 141 | 142 | if (line.compare("-------------") == 0) 143 | seen_separator = true; 144 | else 145 | { 146 | boost::smatch sm; 147 | if (boost::regex_match(line, sm, two_exports_re)) 148 | { 149 | std::stringstream ss; 150 | int addr1, addr2; 151 | 152 | ss << std::hex << sm[2] << ' ' << sm[5]; 153 | ss >> addr1 >> addr2; 154 | 155 | add_symbol (addr1, sm[1]); 156 | add_symbol (addr2, sm[4]); 157 | } 158 | else if (boost::regex_match(line, sm, one_export_re)) 159 | { 160 | std::stringstream ss; 161 | int addr; 162 | 163 | ss << std::hex << sm[2]; 164 | ss >> addr; 165 | add_symbol (addr, sm[1]); 166 | } 167 | } 168 | break; 169 | 170 | case IMPORTS_LIST: 171 | break; 172 | } 173 | } 174 | 175 | /*cerr << "Symbol at 529 is " << find_symbol(529) << endl; 176 | cerr << "Symbol at 530 is " << find_symbol(530) << endl; 177 | cerr << "Symbol at 531 is " << find_symbol(531) << endl;*/ 178 | 179 | ifs.close (); 180 | } 181 | -------------------------------------------------------------------------------- /semi65x/mapfile.h: -------------------------------------------------------------------------------- 1 | #ifndef MAPFILE_H 2 | #define MAPFILE_H 1 3 | 4 | extern void parse_map (const char *filename); 5 | extern std::string find_symbol (int addr); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /semi65x/semi65cx-sim.exp: -------------------------------------------------------------------------------- 1 | # This is a list of toolchains that are supported on this board. 2 | set_board_info target_install {6502} 3 | 4 | # Load the generic configuration for this board. This will define any 5 | # routines needed to communicate with the board. 6 | load_generic_config "sim" 7 | 8 | # Unset the slow_simulator flag; this simulator isn't slow. (I haven't 9 | # found documentation as to what constitutes a "slow" simulator and 10 | # there's no reference to that variable in the GCC test-suite, but all 11 | # tests I've found work.) 12 | unset_board_info slow_simulator 13 | 14 | # We don't use basic-sim.exp and setup_sim because the simulator, called 15 | # "mmix", is external to the build tree. If nobody set the simulator 16 | # name, we set it to "mmix", so the rest of the framework works. Let $SIM 17 | # override. 18 | set_board_info sim "semi65x" 19 | 20 | # No default multilib options are needed for this board. 21 | process_multilib_options "" 22 | 23 | set_board_info is_simulator 1 24 | 25 | # It isn't visible in the target triple, so we set it explicitly. The 26 | # *linked* format is currently mmo, but those cases where this matters we 27 | # can deal with separately. 28 | set_board_info obj_format "binary" 29 | 30 | # The compiler used to build for this board. This has *nothing* to do 31 | # with what compiler is tested if we're testing gcc. 32 | set_board_info compiler "[find_gcc]" 33 | 34 | # We only support newlib on this target. We assume that all multilib 35 | # options have been specified before we get here. 36 | set_board_info cflags "-mcpu=65C02" 37 | 38 | # We put the stack in the code segment, so trampolines work; the mmix 39 | # simulator does not allow code to be executed in the "normal" documented 40 | # data and stack segments. Use a somewhat magic number, so stack addresses 41 | # are easily recognized when debugging. 42 | set_board_info ldflags "" 43 | 44 | # No linker script needed - the simulator is the main environment for this 45 | # target. 46 | set_board_info ldscript "" 47 | 48 | # Pass remaining options directly to simulator 49 | set_board_info sim,options "-c 65C02 -l 0x200" 50 | 51 | # Return codes aren't supported by the simulator. 52 | unset_board_info needs_status_wrapper 53 | 54 | # FIXME: Some gdb board variables are usually here. I currently have 55 | # no clue what to set them to, so I won't. 56 | set_board_info gdb,nosignals 1 57 | 58 | # The simulator's going to crash. Try to make it at least do it quickly. 59 | set_board_info gcc,timeout 120 60 | 61 | # Setting this makes several tests use smaller data structures. Size is 62 | # arbitrary! 63 | set_board_info gcc,stack_size 8192 64 | -------------------------------------------------------------------------------- /semi65x/semi65x-sim.exp: -------------------------------------------------------------------------------- 1 | # This is a list of toolchains that are supported on this board. 2 | set_board_info target_install {6502} 3 | 4 | # Load the generic configuration for this board. This will define any 5 | # routines needed to communicate with the board. 6 | load_generic_config "sim" 7 | 8 | # Unset the slow_simulator flag; this simulator isn't slow. (I haven't 9 | # found documentation as to what constitutes a "slow" simulator and 10 | # there's no reference to that variable in the GCC test-suite, but all 11 | # tests I've found work.) 12 | unset_board_info slow_simulator 13 | 14 | # We don't use basic-sim.exp and setup_sim because the simulator, called 15 | # "mmix", is external to the build tree. If nobody set the simulator 16 | # name, we set it to "mmix", so the rest of the framework works. Let $SIM 17 | # override. 18 | set_board_info sim "semi65x" 19 | 20 | # No default multilib options are needed for this board. 21 | process_multilib_options "" 22 | 23 | set_board_info is_simulator 1 24 | 25 | # It isn't visible in the target triple, so we set it explicitly. The 26 | # *linked* format is currently mmo, but those cases where this matters we 27 | # can deal with separately. 28 | set_board_info obj_format "binary" 29 | 30 | # The compiler used to build for this board. This has *nothing* to do 31 | # with what compiler is tested if we're testing gcc. 32 | set_board_info compiler "[find_gcc]" 33 | 34 | # We only support newlib on this target. We assume that all multilib 35 | # options have been specified before we get here. 36 | set_board_info cflags "" 37 | 38 | # We put the stack in the code segment, so trampolines work; the mmix 39 | # simulator does not allow code to be executed in the "normal" documented 40 | # data and stack segments. Use a somewhat magic number, so stack addresses 41 | # are easily recognized when debugging. 42 | set_board_info ldflags "" 43 | 44 | # No linker script needed - the simulator is the main environment for this 45 | # target. 46 | set_board_info ldscript "" 47 | 48 | # Pass remaining options directly to simulator 49 | set_board_info sim,options "-c 6502 -l 0x200" 50 | 51 | # Return codes aren't supported by the simulator. 52 | unset_board_info needs_status_wrapper 53 | 54 | # FIXME: Some gdb board variables are usually here. I currently have 55 | # no clue what to set them to, so I won't. 56 | set_board_info gdb,nosignals 1 57 | 58 | # The simulator's going to crash. Try to make it at least do it quickly. 59 | set_board_info gcc,timeout 120 60 | 61 | # Setting this makes several tests use smaller data structures. Size is 62 | # arbitrary! 63 | set_board_info gcc,stack_size 8192 64 | -------------------------------------------------------------------------------- /semi65x/semi65x.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "semi65x.h" 11 | #include "6502core.h" 12 | #include "disas.h" 13 | #include "mapfile.h" 14 | 15 | #define RAMSIZE 65536 16 | #define IOPORT 0xfff0 17 | 18 | unsigned char WholeRam[RAMSIZE]; 19 | int MachineType; 20 | bool DebugEnabled = false; 21 | 22 | int 23 | BeebReadMem (int addr) 24 | { 25 | return WholeRam[addr]; 26 | } 27 | 28 | int 29 | DebugReadMem (int addr, bool host) 30 | { 31 | return BeebReadMem (addr); 32 | } 33 | 34 | void 35 | BeebWriteMem (int addr, unsigned char val) 36 | { 37 | if (addr == IOPORT) 38 | { 39 | fputc (val, stdout); 40 | fflush (stdout); 41 | } 42 | 43 | WholeRam[addr] = val; 44 | } 45 | 46 | void 47 | WriteLog (const char *fmt, ...) 48 | { 49 | /* Do nothing. */ 50 | } 51 | 52 | int 53 | DebugDisassembleInstruction (int addr, bool host, char *opstr) 54 | { 55 | /* Do nothing. */ 56 | return 0; 57 | } 58 | 59 | bool 60 | DebugDisassembler (int addr, int prevAddr, int Accumulator, int XReg, int Yreg, 61 | int PSR, int StackReg, bool host) 62 | { 63 | /* Do nothing. */ 64 | return true; 65 | } 66 | 67 | void 68 | beebmem_dumpstate (void) 69 | { 70 | /* Do nothing. */ 71 | } 72 | 73 | void 74 | Sleep (int) 75 | { 76 | /* Do nothing. */ 77 | } 78 | 79 | void 80 | print_flags (FILE *f, int flags) 81 | { 82 | fputc (flags & FlagN ? 'N' : 'n', f); 83 | fputc (flags & FlagV ? 'V' : 'v', f); 84 | fputc ('-', f); 85 | fputc (flags & FlagB ? 'B' : 'b', f); 86 | fputc (flags & FlagD ? 'D' : 'd', f); 87 | fputc (flags & FlagI ? 'I' : 'i', f); 88 | fputc (flags & FlagZ ? 'Z' : 'z', f); 89 | fputc (flags & FlagC ? 'C' : 'c', f); 90 | } 91 | 92 | class watchinfo 93 | { 94 | public: 95 | watchinfo(unsigned int size, unsigned long addr) : addr(addr), size(size) 96 | { 97 | prev = getmem(size, addr); 98 | } 99 | 100 | unsigned int getbyte(unsigned long addr) 101 | { 102 | return BeebReadMem(addr); 103 | } 104 | 105 | unsigned int getword(unsigned long addr) 106 | { 107 | return BeebReadMem(addr) | (BeebReadMem(addr + 1) << 8); 108 | } 109 | 110 | unsigned int getdword(unsigned long addr) 111 | { 112 | return BeebReadMem(addr) | (BeebReadMem(addr + 1) << 8) 113 | | (BeebReadMem(addr + 2) << 16) | (BeebReadMem(addr + 3) << 24); 114 | } 115 | 116 | unsigned int getmem(unsigned int size, unsigned long addr) 117 | { 118 | switch (size) 119 | { 120 | case 1: return getbyte(addr); 121 | case 2: return getword(addr); 122 | case 4: return getdword(addr); 123 | } 124 | return -1; 125 | } 126 | 127 | void update() 128 | { 129 | prev = getmem(size, addr); 130 | } 131 | 132 | void show_diff(FILE *f) 133 | { 134 | unsigned int curr = getmem(size, addr); 135 | if (curr != prev) 136 | { 137 | switch (size) 138 | { 139 | case 1: 140 | fprintf (f, " [%.4lx]=%.2x->%.2x", addr, prev, curr); 141 | break; 142 | case 2: 143 | fprintf (f, " [%.4lx]=%.4x->%.4x", addr, prev, curr); 144 | break; 145 | case 4: 146 | fprintf (f, " [%.4lx]=%.8x->%.8x", addr, prev, curr); 147 | break; 148 | } 149 | prev = curr; 150 | } 151 | } 152 | 153 | private: 154 | unsigned long addr; 155 | unsigned int prev; 156 | unsigned int size; 157 | }; 158 | 159 | int 160 | main (int argc, char* argv[]) 161 | { 162 | bool quit = false; 163 | int arg = 1; 164 | int load_addr = 0; 165 | int exec_addr = -1; 166 | struct stat statbuf; 167 | bool verbose = false; 168 | bool trace = false; 169 | bool watch = false; 170 | const char *mapfile = NULL; 171 | std::vector watchpoints; 172 | 173 | MachineType = 1; 174 | 175 | for (arg = 1; arg < argc;) 176 | { 177 | if (strcmp (argv[arg], "-c") == 0) 178 | { 179 | arg++; 180 | if (strcmp (argv[arg], "6502") == 0 181 | || strcmp (argv[arg], "6512") == 0) 182 | MachineType = 1; 183 | else if (strcasecmp (argv[arg], "65C02") == 0 184 | || strcasecmp (argv[arg], "65SC12") == 0) 185 | MachineType = 3; 186 | else 187 | { 188 | fprintf (stderr, "Unknown CPU '%s'\n", argv[arg]); 189 | exit (1); 190 | } 191 | } 192 | else if (strcmp (argv[arg], "-l") == 0) 193 | load_addr = strtol (argv[++arg], NULL, 0); 194 | else if (strcmp (argv[arg], "-e") == 0) 195 | exec_addr = strtol (argv[++arg], NULL, 0); 196 | else if (strcmp (argv[arg], "-v") == 0) 197 | verbose = true; 198 | else if (strcmp (argv[arg], "-t") == 0) 199 | trace = true; 200 | else if (strcmp (argv[arg], "-m") == 0) 201 | mapfile = argv[++arg]; 202 | else if (strncmp (argv[arg], "-w", 2) == 0) 203 | { 204 | int watchsize = 0; 205 | switch (argv[arg][2]) 206 | { 207 | case 'b': 208 | watchsize = 1; 209 | break; 210 | case 'w': 211 | case 'h': 212 | watchsize = 2; 213 | break; 214 | case 'l': 215 | case 'd': 216 | watchsize = 4; 217 | break; 218 | default: 219 | fprintf (stderr, "Watch what? (Use b/[wh]/[ld])\n"); 220 | exit (1); 221 | } 222 | unsigned long watchaddr = strtoul (argv[++arg], NULL, 0); 223 | if (verbose) 224 | fprintf (stderr, "Watching %s at 0x%.4lx\n", 225 | watchsize == 1 ? "byte" : 226 | watchsize == 2 ? "word" : 227 | watchsize == 4 ? "long" : "?", watchaddr); 228 | watch = true; 229 | watchpoints.emplace_back(watchsize, watchaddr); 230 | } 231 | else 232 | { 233 | FILE *f; 234 | int readbytes; 235 | 236 | if (stat (argv[arg], &statbuf) != 0) 237 | { 238 | perror ("main"); 239 | exit (1); 240 | } 241 | 242 | if (statbuf.st_size + load_addr >= RAMSIZE) 243 | { 244 | fprintf (stderr, "Program doesn't fit in RAM, exiting.\n"); 245 | exit (1); 246 | } 247 | 248 | f = fopen (argv[arg], "r"); 249 | 250 | if (!f) 251 | { 252 | fprintf (stderr, "Couldn't open binary '%s'\n", argv[arg]); 253 | exit (1); 254 | } 255 | 256 | readbytes = fread (&WholeRam[load_addr], 1, statbuf.st_size, f); 257 | 258 | if (verbose) 259 | fprintf (stderr, "Read %d bytes to 0x%.4x\n", readbytes, load_addr); 260 | 261 | fclose (f); 262 | } 263 | 264 | arg++; 265 | } 266 | 267 | if (mapfile) 268 | parse_map (mapfile); 269 | 270 | /* Start execution at beginning of the loaded executable if not otherwise 271 | specified. */ 272 | if (exec_addr == -1) 273 | exec_addr = load_addr; 274 | 275 | if (verbose) 276 | fprintf (stderr, "Load addr: 0x%.4x Exec addr: 0x%.4x\n", load_addr, 277 | exec_addr); 278 | 279 | /* Point reset vector to loaded binary's execution address. */ 280 | BeebWriteMem (0xfffc, exec_addr & 255); 281 | BeebWriteMem (0xfffd, (exec_addr >> 8) & 255); 282 | 283 | for (auto &wb : watchpoints) 284 | wb.update(); 285 | 286 | Init6502core (); 287 | 288 | /* Do the math! */ 289 | while (!quit) 290 | { 291 | if (trace) 292 | { 293 | extern int ProgramCounter, Accumulator, XReg, YReg; 294 | extern unsigned char StackReg, PSR; 295 | fprintf (stderr, "PC=%.4x A=%.2x X=%.2x Y=%.2x S=%.2x F=", 296 | ProgramCounter, Accumulator, XReg, YReg, StackReg); 297 | print_flags (stderr, PSR); 298 | fputc (' ', stderr); 299 | disassemble_insn (stderr, ProgramCounter, &WholeRam[ProgramCounter]); 300 | if (!watch) 301 | fprintf (stderr, "\n"); 302 | } 303 | Exec6502Instruction (); 304 | if (trace && watch) 305 | { 306 | for (auto &wp : watchpoints) 307 | wp.show_diff(stderr); 308 | fprintf (stderr, "\n"); 309 | } 310 | } 311 | 312 | return 0; 313 | } 314 | -------------------------------------------------------------------------------- /semi65x/semi65x.h: -------------------------------------------------------------------------------- 1 | #ifndef SEMI65X_H 2 | #define SEMI65X_H 1 3 | 4 | #include 5 | 6 | typedef uint64_t CycleCountT; 7 | 8 | typedef void CArm; 9 | 10 | extern unsigned char WholeRam[65536]; 11 | 12 | #define BEEBWRITEMEM_DIRECT(A,V) \ 13 | do { WholeRam[(A)] = (V); } while (0) 14 | 15 | extern int BeebReadMem (int); 16 | extern void BeebWriteMem (int, unsigned char); 17 | extern void beebmem_dumpstate (void); 18 | extern int DebugDisassembleInstruction (int addr, bool host, char *opstr); 19 | extern void WriteLog (const char *, ...); 20 | extern int DebugReadMem (int, bool); 21 | extern bool DebugDisassembler (int addr, int prevAddr, int Accumulator, int XReg, int YReg, int PSR, int StackReg, bool host); 22 | extern void Sleep (int); 23 | 24 | 25 | extern int MachineType; 26 | extern bool DebugEnabled; 27 | extern uint64_t CycleCountWrap; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /semi65x/site-orig.exp: -------------------------------------------------------------------------------- 1 | if ![info exists board_dir] { 2 | set boards_dir {} 3 | } 4 | lappend boards_dir "BOARD_DIR_LOCATION" 5 | 6 | global target_list 7 | 8 | case "$target_triplet" in { 9 | { "6502-*" } { 10 | set target_list "semi65x-sim" 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /semi65x/test/runtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | pasta test.s -o test 4 | ../semi65x -l 0xe00 test 5 | -------------------------------------------------------------------------------- /semi65x/test/test.s: -------------------------------------------------------------------------------- 1 | .org 0xe00 2 | start: 3 | ldx #0 4 | loop: 5 | lda message,x 6 | sta 0xfff0 7 | beq done 8 | inx 9 | jmp loop 10 | done: 11 | ; Exit emulator. 12 | jmp 0 13 | 14 | message: 15 | .asc "Hello world\n",0 16 | -------------------------------------------------------------------------------- /tests/args.c: -------------------------------------------------------------------------------- 1 | #if 0 2 | int foo (int a, int b, int c, int d) 3 | { 4 | return a+b+c+d; 5 | } 6 | #endif 7 | 8 | int bar (int a, int b, int c, int d, int e, int f) 9 | { 10 | return e+f; 11 | } 12 | -------------------------------------------------------------------------------- /tests/fpcmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float x[] = { 0.0, 1.0, -1.0, 1.0, -1.0, 2.0, 3.0, -2.0, -3.0, -2.0, 4 | 0.0, -0.5 }; 5 | float y[] = { 0.0, 1.0, -1.0, -1.0, 1.0, 3.0, 2.0, 3.0, -4.0, -1.0, 6 | 0.5, 0.0 }; 7 | 8 | int main (void) 9 | { 10 | int i; 11 | 12 | for (i = 0; i < sizeof(x) / sizeof(x[0]); i++) 13 | { 14 | printf ("%d ", x[i] < y[i]); 15 | printf ("%d ", x[i] <= y[i]); 16 | printf ("%d ", x[i] > y[i]); 17 | printf ("%d ", x[i] >= y[i]); 18 | printf ("%d ", x[i] == y[i]); 19 | printf ("%d\n", x[i] != y[i]); 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/hello.c: -------------------------------------------------------------------------------- 1 | static void 2 | myputc (char c) 3 | { 4 | volatile char *cp = (char*) 0xfff0; 5 | *cp = c; 6 | } 7 | 8 | static void 9 | myputs (const char *msg) 10 | { 11 | while (*msg) 12 | myputc (*msg++); 13 | } 14 | 15 | int main (int argc, char* argv) 16 | { 17 | int i; 18 | myputs ("Hello world!\n"); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /tests/retcode.c: -------------------------------------------------------------------------------- 1 | int main(void) 2 | { 3 | return 5; 4 | } 5 | -------------------------------------------------------------------------------- /tests/whatever.c: -------------------------------------------------------------------------------- 1 | int foo (int *arr) 2 | { 3 | arr[2]--; 4 | return arr[1]+1; 5 | } 6 | -------------------------------------------------------------------------------- /tests/whatever10.c: -------------------------------------------------------------------------------- 1 | int q = 2; 2 | 3 | void 4 | foo (int** w, int x) 5 | { 6 | w[2][3] = x; 7 | } 8 | -------------------------------------------------------------------------------- /tests/whatever11.c: -------------------------------------------------------------------------------- 1 | int q = 2; 2 | 3 | void 4 | foo (int* w, int x) 5 | { 6 | if (x == 5) 7 | w[3] = x; 8 | } 9 | -------------------------------------------------------------------------------- /tests/whatever12.c: -------------------------------------------------------------------------------- 1 | int q = 2; 2 | 3 | int 4 | foo_gt (int x) 5 | { 6 | if (x > 5u) 7 | return 1; 8 | return 0; 9 | } 10 | 11 | int 12 | foo_ge (int x) 13 | { 14 | if (x >= 5u) 15 | return 1; 16 | return 0; 17 | } 18 | 19 | int 20 | foo_lt (int x) 21 | { 22 | if (x < 5u) 23 | return 1; 24 | return 0; 25 | } 26 | 27 | int 28 | foo_le (int x) 29 | { 30 | if (x <= 5u) 31 | return 1; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/whatever13.c: -------------------------------------------------------------------------------- 1 | int q = 2; 2 | 3 | int 4 | foo_lt (int x) 5 | { 6 | if (x < 5) 7 | return 1; 8 | return 0; 9 | } 10 | 11 | int 12 | foo_le (int x) 13 | { 14 | if (x <= 5) 15 | return 1; 16 | return 0; 17 | } 18 | 19 | int 20 | foo_gt (int x) 21 | { 22 | if (x > 5) 23 | return 1; 24 | return 0; 25 | } 26 | 27 | int 28 | foo_ge (int x) 29 | { 30 | if (x >= 5) 31 | return 1; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/whatever14.c: -------------------------------------------------------------------------------- 1 | int 2 | character_things (int x) 3 | { 4 | return "Hello world\010"[x]; 5 | } 6 | -------------------------------------------------------------------------------- /tests/whatever15.c: -------------------------------------------------------------------------------- 1 | char *arr; 2 | 3 | void 4 | character_things (char *in, int x) 5 | { 6 | int i; 7 | for (i = 0; i < x; i++) 8 | arr[i] = in[i]; 9 | } 10 | -------------------------------------------------------------------------------- /tests/whatever2.c: -------------------------------------------------------------------------------- 1 | int foo (int *arr, int i) 2 | { 3 | return arr[1]+i; 4 | } 5 | -------------------------------------------------------------------------------- /tests/whatever3.c: -------------------------------------------------------------------------------- 1 | int foo (unsigned int *arr, int i) 2 | { 3 | return (arr[1] >> 1) + (arr[2] >> 2); 4 | } 5 | -------------------------------------------------------------------------------- /tests/whatever4.c: -------------------------------------------------------------------------------- 1 | int friendly_global = 1; 2 | int another_global = 2; 3 | int third_global; 4 | int fourth_global; 5 | 6 | static void __attribute__ ((used)) 7 | foo (unsigned int *arr, int i) 8 | { 9 | fourth_global = third_global; 10 | third_global = friendly_global + another_global; 11 | } 12 | -------------------------------------------------------------------------------- /tests/whatever5.c: -------------------------------------------------------------------------------- 1 | int friendly_global = 1; 2 | int another_global[3]; 3 | 4 | int 5 | foo (unsigned int *arr, int i) 6 | { 7 | return another_global[2] + friendly_global + arr[2]; 8 | } 9 | -------------------------------------------------------------------------------- /tests/whatever6.c: -------------------------------------------------------------------------------- 1 | int 2 | foo (int w) 3 | { 4 | return (w>>2) + (w>>1); 5 | } 6 | -------------------------------------------------------------------------------- /tests/whatever7.c: -------------------------------------------------------------------------------- 1 | int 2 | foo (int w, int v) 3 | { 4 | if (w == v) 5 | return 6; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /tests/whatever8.c: -------------------------------------------------------------------------------- 1 | int q = 2; 2 | 3 | int 4 | foo (int w, int v) 5 | { 6 | if (v == q && w != q) 7 | return 6; 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /tests/whatever9.c: -------------------------------------------------------------------------------- 1 | int q = 2; 2 | 3 | int 4 | foo (int** w) 5 | { 6 | return w[2][3]; 7 | } 8 | -------------------------------------------------------------------------------- /wrappers/6502-ar: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CC65_PATH=${CC65_PATH:-/usr/bin} 3 | AR65=${CC65_PATH}/ar65 4 | ARG=$1 5 | case "$ARG" in 6 | "rc"|"cr") 7 | ARG=a 8 | ;; 9 | *) 10 | ;; 11 | esac 12 | shift 13 | exec ${AR65} $ARG $@ 14 | -------------------------------------------------------------------------------- /wrappers/6502-ranlib: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This one doesn't really do anything! 3 | --------------------------------------------------------------------------------