Open Design Computer Project

オリジナルCPUから作る本格的自作コンピューター

ユーザ用ツール

サイト用ツール


software:porting_cgen

CGEN の移植

CGEN, the Cpu tools GENerator を利用することで、binutils の移植を比較的楽にすすめることができます。

CGEN について

CGEN は、アセンブラやシミュレータなどの CPU に依存するツールを開発するためのフレームワークです。(しーじぇんと読むらしい)

CPU の概要を書いた CGEN 用の定義ファイルを書くことで、binutils の移植を CGEN フレームワークを利用して書くことができます。

GNU Guile の元で動く Scheme で CGEN は書かれており、定義ファイルも Scheme を利用します。

CGEN CPU 定義ファイルの概要

CGEN は、binutils, gas を移植するために必要な opcodes に関する移植を手助けしてくれます。

それ以外にもシミュレータを作成を支援してくれる機能などがあります。

CGEN を利用するには、今から移植するプロセッサの情報を技術した CPU 定義ファイルを作成する必要があります。

まずは、他の CPU の定義ファイルを見てみることをおすすめします。

CPU 定義ファイルは、.cpu という拡張子で、binutils のソースツリーの cpu フォルダ内に格納されています。

ファミリーがたくさんある CPU や、大規模で複雑な CPU の定義ファイルは理解しづらいので、簡単なものから読んでいくとよいでしょう。

私は、m32r, fr30, openrisc などを参考にしました。

上からざっと見ていくと、define-arch や define-isa といった CPU のアーキテクチャ・命令セット定義から、define-cpu, define-mach, define-model といった CPU ファミリーの定義、その下にフィールドやレジスタ・ハードウェアの定義があり、オペランド・各種命令の定義が続いています。

これらを、マニュアルとともに見様見真似で移植していく事になります。

基本的には同じようなプロセッサの同じような命令を参考に移植してくと便利でしょう。

CPU 定義ファイルの移植

define-arch, define-isa, define-cpu, define-mach

define-model

フィールドの定義

http://sourceware.org/cgen/docs/cgen_5.html#SEC251

命令を格納するフィールドを定義します。

mist32 アーキテクチャを例にとって説明します。

mist32 アーキテクチャは、以下のような命令フォーマットを持っています。

基本的には、dnf (define-normal-field) を利用して定義していきます。

; opcode フィールドの例, 30bit から 10bit 分のフィールド
(dnf f-op    "opcode"             () 30 10)

insn-lsb0? の定義により、bit 指定方法が逆になるので、気をつけましょう。

複数のフィールドにまたがるフィールドは、dnmf (define-normal-multi-field) を利用して定義します。

; i11 フォーマットの即値フィールドの例
(dnf  f-i11h "11 bit immediate high"       () 15 6)
(dnf  f-i11l "11 bit immediate low"        () 4 5)
(dnmf f-i11  "11 bit immediate"            () INT
      (f-i11h f-i11l)
      (sequence () ; insert
                (set (ifield f-i11h) (and (sra (ifield f-i11) (const 5))
                                          (const #x3f)))
                (set (ifield f-i11l) (and (ifield f-i11) (const #x1f))))
      (sequence () ; extract           
                (set (ifield f-i11) (sub (xor (const #x400)
                                              (or (sll (ifield f-i11h) (const 5))
                                                  (ifield f-i11l)))
                                         (const #x400))))
)

レジスタ・ハードウェアの定義

http://sourceware.org/cgen/docs/cgen_5.html#SEC250

dnh (define-normal-hardware) で定義します。

汎用レジスタ、プログラムカウンタ、条件コード、即値の整数などを定義します。

; プログラムカウンタと汎用レジスタ
(dnh h-pc "program counter" (PC) (pc SI) () () ())
(dnh h-gr "general registers" ()
     (register WI (32))
     (keyword "" ((rglobl 28) (rtmp 29) (rbase 30) (rret 31)
                  (r0 0) (r1 1) (r2 2) (r3 3)
                  (r4 4) (r5 5) (r6 6) (r7 7)
                  (r8 8) (r9 9) (r10 10) (r11 11)
                  (r12 12) (r13 13) (r14 14) (r15 15)
                  (r16 16) (r17 17) (r18 18) (r19 19)
                  (r20 20) (r21 21) (r22 22) (r23 23)
                  (r24 24) (r25 25) (r26 26) (r27 27)
                  (r28 28) (r29 29) (r30 30) (r31 31)))
     () ()
)

オペランドの定義

http://sourceware.org/cgen/docs/cgen_5.html#SEC253

dnop (define-normal-operand) で定義します。

そのオペランドが指すハードウェアとフィールドを指定します。

(dnop rd    "destination register"            () h-gr     f-rd)
(dnop rs    "source register"                 () h-gr     f-rs)
(dnop cc    "condition code"                  () h-cc     f-cc)
(dnop p16   "16bit absolute unsigned address" () h-iaddr  f-p16)
(dnop i11   "11bit immediate"                 () h-int11  f-i11)
 
; handlers を設定すると特定のハンドラをパース時に噛ますことができる
; RISC マシンよくある hi() lo() などのマクロはこれを使う
(define-operand (name i16l)
  (comment "16 bit immediate, lo")
  (attrs)
  (type h-int16)
  (index f-i16)
  (handlers (parse "lo16"))
)

命令マクロの定義

http://sourceware.org/cgen/docs/cgen_5.html#SEC256

http://sourceware.org/cgen/docs/cgen_5.html#SEC254

命令を定義するためのマクロを define-pmacro で定義します。

その中で dni (define-normal-insn) を定義して、実際の命令定義をしています。

; O2 / I11 フォーマットの命令を定義するためのマクロ
; reg/reg にも reg/imm11 にも対応できる命令のマクロを作れる
(define-pmacro (o2-i11-op mnemonic opcode)
  (begin
    (dni mnemonic
         (.str mnemonic " reg/reg")
         ()
         (.str mnemonic " $rd,$rs")
         (+ EXT_0 opcode ISIMM_0 AFE_0 (f-reserve1 0) rd rs)
         ()
         ()
         )
    (dni (.sym mnemonic "i")
         (.str mnemonic " reg/imm11")
         ()
         (.str mnemonic " $rd,$i11")
         (+ EXT_0 opcode ISIMM_1 AFE_0 i11 rd)
         ()
         ()
         )
    )
)
 
; こんな感じで呼び出す
(o2-i11-op  add             OP_0)

opc ファイル

.cpu ファイル以外に .opc ファイルも移植をする必要がある。

例えば、handler で指定した parse 関数などをここで定義する。

参考資料

software/porting_cgen.txt · 最終更新: 2013/07/06 19:17 by hktechno