Skip to content

OpeLa Language Specification

Kota UCHIDA edited this page Aug 28, 2020 · 41 revisions

OpeLa 言語仕様

OpeLa メインページ

プログラム例:割り込み

IDT の 21 に割り込みハンドラを登録し,割り込み許可(sti)する例です。

// パディングを絶対に入れない構造体の定義
// foo'bar は特別な構文で,接頭辞 foo が共通するメンバがグループ化される
type idtEntry packed_struct {
  Offset'Low       address16[15:0]
  SegmentSelector  uint16
  IST              uint3
  _                uint5
  Type             uint4
  _                uint1
  DPL              uint2
  P                uint1
  Offset'Middle    address16[31:16]
  Offset'High      address32[63:32]
  _                uint32
}

// こちらは適切にパディングが入る構造体
type stackFrame struct {
  SS    uint16
  SP    address
  Flags uint64
  CS    uint16
  IP    address
}

// グローバル変数
var (
  idt idtEntry[256]
)

func notifyEndOfInterrupt() {
  // 組み込みの Atomic 型を使ってレジスタアクセス
  eoi *Atomic<uint32> := address(0xfee000b0)
  eoi->Store(0);
  // same as: *Atomic<uint32>(address(0xfee000b0))->Store(0)
}

// interrupt service routine
isr intHandler21(stackFrame *stackFrame) {
  Printk("INT21 CS:RIP = {:02x}:{:08x}\n", stackFrame->CS, stackFrame->IP)
  notifyEndOfInterrupt()
}

func main(argc int, argv *byte) {
  idt[21] = {
    .offset = &intHandler21, .segment_selector = 1 * 8,
    .type = 14, .dpl = 0, .p = 1
  }
  idtr packed_struct { _ uint16, _ address } := { sizeof(idt) - 1, &idt }
  intrin.Lidt(&idtr)
  intrin.Sti()

  for {
    intrin.Hlt()
  }
}

組み込み型

  • intN/uintN: N ビット幅の符号付き/符号無し整数
  • byte: uint8 の別名
  • address: ネイティブ幅のアドレス型
  • addressN: N ビット幅のアドレス型

アドレス型

他の言語にない特徴的な型として address がある。アドレスはポインタから型情報を取り除いたものである。C の void* に近い。

任意のポインタと address は相互に暗黙的に変換可能。 address から整数へは暗黙的に変換可能。 整数から address へは明示的なキャスト address(整数) が必要。

ユーザー定義型

  • type Name T: T という型に Name と言う名前を付ける。Name は T とは異なる型となる。
  • struct {..}: 構造体型
  • packed_struct {..}: パディングが無い構造体型

パディング

8 ビット以上で,かつ 2 の累乗のビット幅を持つ整数型(int8, int16, int32, int64)は,自身のバイト数によってアラインされる。 8 ビット未満か,2 の累乗ではないビット幅の整数型はアラインされない(= 前のメンバに連続して配置される)

マスクフィールド

ページエントリのアドレスフィールドのように,下位 N ビットをマスクして読み書きすべきフィールドを定義できる。

type PageEntry struct {
  P    uint1
  RW   uint1
  US   uint1
  PWT  uint1
  PCD  uint1
  A    uint1
  D    uint1
  PAT  uint1
  G    uint1
  _    uint3
  Addr address64[63:12]
}

func f() {
  var e PageEntry
  e.Addr = 0x12345
  assert(e.Addr == 0x12000)
}

レジスタ差分定義

Clone this wiki locally