aki_iic’s blog

己の欲せざる処人に施す事無かれ、狂人の真似するは即ち狂人なり

Fuzix-Compiler-Kit

 最近ちょこちょこFuzix環境を彷徨っておりまして、Fuzix専用のクロスコンパイラキットについて。

GitHUB

github.com

cc [option and file list]

options:

-c:    compile to object modules only
-D:    define a macro for the C preprocessor
-E:    preprocess only, to stdout
-i:    enable split I/D if supported by this target
-I:    add a directory to the include path
-l:    add a library name to link
-L:    add a path to the library search path
-m:    set the CPU to compile for
-M:    create a map file
-o:    specify the output file name of the complation (a.out default)
-O:    set optimization level 0-3, or for size '-Os'
-s:    build standalone. Do not include the OS libraries and include paths
-S:    compile to assembly source only
-t:    set the target OS
-T:    set the starting address of the text/code segment
-V:    verbosely print pass information
-X:    keep temporary files for debugging

long options:
--dlib:    build a loadable object module instead

processors:
-m8080: Intel 8080 (compatible 8085, Z80)
-m8085: Intel 8085
-mz80: Zilog Z80 (compatible Z180, Z280, eZ80)
-mz180: Zilog Z180

z80/z180 feature options:
-mz80-banked: Z80 with banked code
-mz80-noix: do not touch IX
-mz80-noiy: do not touch IY

processors (debug):
-m65c816: 65C816 16bit mode
-m6303: Hitachi 6303
-m6309: Hitachi 6309 (currently as 6809)
-m6800: Motorola 6800 (compatible 6303, 6803, 68HC11)
-m6803: Motorola 6803 (compatible 6303, 68HC11)
-m6809: Motorola 6809 (compatible 6309)
-m68hc11: Motorola 68HC11
-mnova: DG Nova
-mnova3: DG Nova 3 and later (with stack hardware)
-mthread: Generate threadcode tables
-msuper8: Zilog Super 8
-mz8: Zilog Z8

nova feature options:
-multiply: use the hardware multiply and divide option

processors (development only)
-m1802: bytecode for 1802 interpreter
-m1805: bytecode for 1805 interpreter
-m6502:    6502 8bit, NMOS legal instructions
-m65c02: 6502 8bit CMOS legal instructions
-m8086: Intel 8088/8086 (compatible 80186/286/..)
-m80186: Intel 80188/186 (compatible 80286/...)
-m8070: NS8070 series
-mnova3: DG Nova3, Nova4 or MicroNova

 ターゲットは何ともレトロなプロセサ(nova迄)がサポートされている様ですがcdp1802/cdp1805はCコンパイラfccという実行ファイル名)ではサポートされていない点には注意が必要かもしれません。

 オプションも昔(80年代頃の)cp/m-80のCコンパイラの如く色々(妙な)オプションがあったり(IX,IYを使うとか)、未定義命令(8085、6309等)と商用のコンパイラでは難しそう(というか21世紀にこれらレトロCPUのCコンパイラOSSで提供して下さるだけでも歓喜:)であります(ああ、個人の印象ですが)。

 別段当方ソフト屋さんではないしコンパイラのどうちゃらこうちゃら等言及できるスキルがある筈も無いのでとりあえず適当なCソースでアセンブラコードを生成させた行数でいくつか(知ってる)チップのコード生成を眺めてみようかと。

・Cソース:

fcc お試し用 Cソース

コンパイル

fcc -mターゲット t1.c -S

アセンブラコード生成迄)

・生成されたアセンブラコード行数

fccで生成されたアセンブラコード行数

 fcc(本Cコンパイラ)はint は16bit(なつかし)なのでDレジスタが無い6800は非常にコード効率が悪くなっている様です↓

    .setcpu 6800
    .code
    .export _main
    .code
_main:
    des
    des
    des
    des
    des
    des
;make local ptr off 0, rlim 254 noff 0
    tsx
    clr 1,x
    clr 0,x
;
L1_l:
;make local ptr off 0, rlim 254 noff 0
    tsx
    ldb 1,x
    lda 0,x
    pshb
    psha
    clra
    ldab #10
    jsr __cclt
;
    jeq L1_b
    jmp L1_n
L1_c:
;make local ptr off 0, rlim 252 noff 0
    tsx
    ldb 1,x
    lda 0,x
    addb #1
    adca #0
    stb 1,x
    sta 0,x
;
    jmp L1_l
L1_n:
;make local ptr off 0, rlim 254 noff 0
    tsx
    ldb 1,x
    lda 0,x
    lslb
    rola
;make local ptr off 2, rlim 254 noff 2
    stb 3,x
    sta 2,x
;
;make local ptr off 0, rlim 254 noff 0
    addb 1,x
    adca 0,x
;make local ptr off 4, rlim 254 noff 4
    stb 5,x
    sta 4,x
;
    jmp L1_c
L1_b:
    ins
    ins
    ins
    ins
    ins
    ins
    rts

 これは16bit演算が出来ない(Dレジスタとして使えない)6800なので仕方が無いしスタック操作命令も貧弱なのでこういうコードになるのでしょう(何か偉そう)。それでも21世紀に6800のCコンパイラが提供され且つFuzixがビルド出来るのだから感謝しかありません(心から)。

 今度はDレジスタが使える6803/68HC11の例↓

    .code
    .export _main
    .code
_main:
    pshx
    pshx
    pshx
;make local ptr off 0, rlim 254 noff 0
    tsx
    clr 1,x
    clr 0,x
;
L1_l:
;make local ptr off 0, rlim 254 noff 0
    tsx
    ldd 0,x
    subd #10
    jsr boollt
;
    jeq L1_b
    jmp L1_n
L1_c:
;make local ptr off 0, rlim 252 noff 0
    tsx
    ldd 0,x
    addd #1
    std 0,x
;
    jmp L1_l
L1_n:
;make local ptr off 0, rlim 254 noff 0
    tsx
    ldd 0,x
    lslb
    rola
;make local ptr off 2, rlim 254 noff 2
    std 2,x
;
;make local ptr off 0, rlim 254 noff 0
    addd 0,x
;make local ptr off 4, rlim 254 noff 4
    std 4,x
;
    jmp L1_c
L1_b:
    pulx
    pulx
    pulx
    rts

 Dレジスタで16bit演算が出来るので大分コードが少なくなっています。

 今度は8080の例↓

fcc 8080 code

 元々z80/8080が出発点(Fuzixの歴史上)からか?8080でdad命令をちゃんと使って効率の良いコードを生成している様です(80系詳しくないので見当違いかもしれません)。

 最後は80186の例。16bitですがレトロで知ってるチップという事で↓

fcc 80186 code

  流石に世代が違う16bitプロセサ故、短いコードで済んでおります(enter命令とか懐かしいですね)。enter/leaveは元々v20〜v5x(NEC)の命令セットだった様な・・・

 おまけで知る人ぞ知るSC/MP///(INS807X)です↓

fcc 8070(SC/MP3) code

 意外や意外と言っては失礼なのですが結構コード効率が良い印象。

 

 だらだら記して参りましたがこういった古きを訪ねて新しきを知る(或いは知らない?)も愉しきものでございます(たまには、ね)。