tags: RCWT Wiki

RCWT Wiki

最終更新2020/03/28
github: C++, Rust
(注) C++での実装とRustでの実装ではフォーマットおよび命令セットが異なっている。TODO 統一

期限

次回のプラサミ

Summary

RCWTは言語処理系における使用を目的としたVMであり

  • レジスタマシン
  • CISC

の特徴を持つ。また命令セットは

  • 32bit
  • 3番地コード

を基本としている。RCWTは Resister Machine, CISC, Word Code, Three-Address Codeの頭文字をとったものである。設計方針はsimple and friendly。フロントエンドとしてrlispおよびincrementalを開発している(未完成)。

How to use

必要なツールは以下

  • Git
  • Gnu Make
  • Clang
  • a processor for Rust
  • a processor for Java
commands start with '$', but comments don't

clone
$ git clone https://github.com/sKyrBBit/RRCWT
$ cd RRCWT

build
$ make build

windows help
$ rrcwt -h

linux help
$ ./rrcwt -h

ロード

以下の手続きを順に実行する

  • initialize
  • load
  • setup

initialize

目的:直前にロードしたファイルが実行中のロードに影響を与えないようにする
機能:ロード時に使用されるメモリやレジスタを初期化する

load

目的:プログラムをVMにとって実行可能な形式にする、アドレスをメモリに対する一意な添字にする
機能:プログラムをファイルからメモリに読み込む、シンボルを再配置しリンクする
(注) 読み込み時にリンクするのが望ましいが、不可能または何らかの目的でリンクすべきでないという場合は、実行時そのシンボルが初めて参照されるまでに解決することが保障されていればよい(実行時リンクはdirect-threading codeでは実現不可能?)

setup

目的:円滑にプログラムを実行できる状態に整える
機能:エントリーポイントを調整する、セットアップコードを生成する

リンク

以下の手続きを順に実行する

  • load
  • resolve

resolve

目的:シンボルが実際のアドレスを指すことを保証する
機能:シンボルテーブル、再配置アドレスにパッチをあてる

命令

32bitの固定長であり、3番地コードを基本としている。0xaabbccddという命令の場合、aaが命令の種類を定め、bb, cc, ddは命令の引数として扱われる。引数の個数が3より少ない場合、00が与えられることが求められる。
例:r1 = r2 + r30x10010203 というaddr命令で表せる。

型を表す文字を加える場合は接頭詞、機能を表す文字を加える場合は接尾詞とする。

接尾詞

  • Register 右辺がレジスタ
  • Immediate 右辺が即値
  • Lock Free 他の処理が割り込まない

命令セット

/* 00 */ &&L_NOP,   /* 01 */ &&L_EXIT, /* 02 */ &&L_BP,   /* 03 */ &&L_NOP,
/* 04 */ &&L_STORE, /* 05 */ &&L_LOAD, /* 06 */ &&L_PUSH, /* 07 */ &&L_POP,
/* 08 */ &&L_COPY,  /* 09 */ &&L_NOP,  /* 0a */ &&L_SOUT, /* 0b */ &&L_CASL,
/* 0c */ &&L_ADDL,  /* 0d */ &&L_SUBL, /* 0e */ &&L_ANDL, /* 0f */ &&L_ORL,

/* 10 */ &&L_ADDR,  /* 11 */ &&L_SUBR, /* 12 */ &&L_MULR, /* 13 */ &&L_DIVR,
/* 14 */ &&L_ADDI,  /* 15 */ &&L_SUBI, /* 16 */ &&L_MULI, /* 17 */ &&L_DIVI,
/* 18 */ &&L_GT,    /* 19 */ &&L_GE,   /* 1a */ &&L_EQ,   /* 1b */ &&L_CONST,
/* 1c */ &&L_AND,   /* 1d */ &&L_OR,   /* 1e */ &&L_NOT,  /* 1f */ &&L_NOP,

/* 20 */ &&L_GOTO,  /* 21 */ &&L_BACK, /* 22 */ &&L_NOP,  /* 23 */ &&L_NOP,
/* 24 */ &&L_IFGT,  /* 25 */ &&L_IFGE, /* 26 */ &&L_IFEQ, /* 27 */ &&L_IOUT,
/* 28 */ &&L_IIN,   /* 29 */ &&L_NEW,  /* 2a */ &&L_SET,  /* 2b */ &&L_GET,
/* 2c */ &&L_CALL,  /* 2d */ &&L_RET,  /* 2e */ &&L_NOP,  /* 2f */ &&L_NOP,

/* 30 */ &&L_SHLR,  /* 31 */ &&L_SHRR, /* 32 */ &&L_NOP,  /* 33 */ &&L_NOP,
/* 34 */ &&L_SHLI,  /* 35 */ &&L_SHRI, /* 36 */ &&L_NOP,  /* 37 */ &&L_NOP,

Note

  • リトルエンディアンを優先してサポートしている。
  • JITコンパイルにはClangが必要である。

TODO

  • 関数・クラスの実装
  • ネイティブ呼び出し(dll)
  • コメントを増やす
  • DOC 目的
  • DOC 動機/背景
  • DOC Constrains
# option
{ "-d": "--debug",
  "-e": "--error",
  "-w": "--warning",
  "-p": "--prompt",
  "-i": "--interpreter" }
# grammar
{ "atom": ["NUMBER", "SYMBOL", "boolean"],
  "tuple": ["(s . s)"],
  "boolean": ["#t", "#f"],
  "s": ["atom", "tuple"] }

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

TableGen

文献が少ないため仕様不明。以下はきつねさんのほぼ写経。

// registers
class RCWTReg<bits<4> num, string n>: Register<n> {
  field bits<4> num;
  let Namespace = "RCWT";
}

def R0: RCWTReg<0x0, "R0">, DwarfRegNum<[0x0]>;
def R1: RCWTReg<0x1, "R1">, DwarfRegNum<[0x1]>;
def R2: RCWTReg<0x2, "R2">, DwarfRegNum<[0x2]>;
def R3: RCWTReg<0x3, "R3">, DwarfRegNum<[0x3]>;
def R4: RCWTReg<0x4, "R4">, DwarfRegNum<[0x4]>;
def R5: RCWTReg<0x5, "R5">, DwarfRegNum<[0x5]>;
def R6: RCWTReg<0x6, "R6">, DwarfRegNum<[0x6]>;
def R7: RCWTReg<0x7, "R7">, DwarfRegNum<[0x7]>;
def R8: RCWTReg<0x8, "R8">, DwarfRegNum<[0x8]>;
def R9: RCWTReg<0x9, "R9">, DwarfRegNum<[0x9]>;
def Ra: RCWTReg<0xa, "Ra">, DwarfRegNum<[0xa]>;
def Rb: RCWTReg<0xb, "Rb">, DwarfRegNum<[0xb]>;
def Rc: RCWTReg<0xc, "Rc">, DwarfRegNum<[0xc]>;
def Rd: RCWTReg<0xd, "Rd">, DwarfRegNum<[0xd]>;
def Re: RCWTReg<0xd, "Re">, DwarfRegNum<[0xe]>;
def Rf: RCWTReg<0xf, "Rf">, DwarfRegNum<[0xf]>;

def RCWTRegClass: RegisterClass<"RCWT", [i32], 32, (add
  R0, R1, R2, R3,
  R4, R5, R6, R7,
  R8, R9, Ra, Rb,
  Rc, Rd, Re, Rf
)>;

// function unit
def ALU: FuncUnit;

def IICAlu:    InstrItinclass;
def IICLoad:   InstrItinClass;
def IICStore:  InstrItinClass;
def IICBranch: InstrItinClass;
def IICPseudo: InstrItinClass;

def RCWTGenericItineraries: ProcessorItineraries<[ALU], [], [
  InstrItinData<IICAlu,    [InstrStage<1, [ALU]>]>
  InstrItinData<IICLoad,   [InstrStage<1, [ALU]>]>
  InstrItinData<IICStore,  [InstrStage<1, [ALU]>]>
  InstrItinData<IICBranch, [InstrStage<1, [ALU]>]>
  InstrItinData<IICPseudo, [InstrStage<1, [ALU]>]>
]

// calling convention
def CC_RCWT: ConllingConv<[
  CCIfType<[i8, i16], CCPromoteToType<i32>>
]>

// target
def RCWTInstrInfo: InstrInfo;

def :Processor<"rcwt0.1.0", RCWTGenericItineraries, []>;

def RCWTAsmWriter: AsmWriter {
  string AsmWriterClassName = "InstrPrinter";
  bit isMCAsmWriter = 1;
}

def RCWT: target {
  let InstructionSet = RCWTInstrInfo;
  let AssemblyWriter = [RCWTAsmWriter];
}

// instruction
class Format<bit val> {
  bit Value = val;
}

def Pseudo:       Format<0>;
def ThreeAddress: Format<1>;

class RCWTInstr<dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin,
  Format f>: Instruction {
  field bits<32> Instr;
  Format Form = f;

  bits<8> Opcode = 0;

  let Namespace = "RCWT";
  let Size = 4;
  let Instr{31-24} = Opcode;
  OutOperandList = outs;
  InOperandList = ins;
  let AsmString = asmstr;
  let pattern = pattern;
  let Itinerary = itin;

  bit FormBit = Form.Value;

  let DecoderNamespace = "RCWT";

  field bits<32> SoftFail = 0;
}

class RCWTInstrThreeAddress<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern,
  InstrItinClass itin>: RCWTInstr<outs, ins, asmstr, pattern, itin, ThreeAddress> {
  bits<8> op0;
  bits<8> op1;
  bits<8> op2;

  let Opcode = op;

  let Instr{23-16} = op0;
  let Instr{15-8}  = op1;
  let Instr{7-0}   = op2;
}

class RCWTPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>: RCWTInstr<outs, ins,
  asmstr, pattern, IICPseudo, Pseudo> {
  let isCodeGenOnly = 1;
  let isPseudo = 1;
}

class ArithLogicInstr<bits<8> op, string asmstr, SDNode OpNode, InstrItinClass itin,
  RegisterClass rc>: RCWTInstrThreeAddress<op, (outs rc:$op0), (ins rc:$op1, rc:$op2),
  !strconcat(asmstr, "\t$op0, $op1, $op2"), [(set rc:$op0, (OpNode rc:$op1, rc:$op2))], itin> {
}

def ADDR: ArithLogicInstr<0x10, "addr", add, IICAlu, RCWTRegClass>;
def SUBR: ArithLogicInstr<0x11, "subr", add, IICAlu, RCWTRegClass>;
def MULR: ArithLogicInstr<0x12, "mulr", add, IICAlu, RCWTRegClass>;
def DIVR: ArithLogicInstr<0x13, "divr", add, IICAlu, RCWTRegClass>;

def GT: ArithLogicInstr<0x14, "gt", add, IICAlu, RCWTRegClass>;
def GE: ArithLogicInstr<0x15, "ge", add, IICAlu, RCWTRegClass>;
def EQ: ArithLogicInstr<0x16, "eq", add, IICAlu, RCWTRegClass>;