summaryrefslogtreecommitdiffhomepage
path: root/ir/be/riscv/riscv_spec.pl
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2018-03-31 12:12:43 +0200
committerChristoph Mallon <christoph.mallon@gmx.de>2018-08-15 12:05:18 +0200
commitb031096c75829e287eb18942542ebcd4c6daa8a9 (patch)
tree5e27a38e506a6c4cfe3ff3e3f0513fb79866b36f /ir/be/riscv/riscv_spec.pl
parentd87cbba82fd6596a233f3bf2910d1eaa80f23bb5 (diff)
riscv: Implement a basic RISC-V 32 backend.
Diffstat (limited to 'ir/be/riscv/riscv_spec.pl')
-rw-r--r--ir/be/riscv/riscv_spec.pl240
1 files changed, 240 insertions, 0 deletions
diff --git a/ir/be/riscv/riscv_spec.pl b/ir/be/riscv/riscv_spec.pl
new file mode 100644
index 0000000..1488eaf
--- /dev/null
+++ b/ir/be/riscv/riscv_spec.pl
@@ -0,0 +1,240 @@
+# This file is part of libFirm.
+# Copyright (C) 2018 Christoph Mallon.
+
+$arch = "riscv";
+
+my $mode_gp = "mode_Iu";
+
+%reg_classes = (
+ gp => {
+ mode => $mode_gp,
+ registers => [
+ { name => "zero", encoding => 0 },
+ { name => "ra", encoding => 1 },
+ { name => "sp", encoding => 2 },
+ { name => "gp", encoding => 3 },
+ { name => "tp", encoding => 4 },
+ { name => "t0", encoding => 5 },
+ { name => "t1", encoding => 6 },
+ { name => "t2", encoding => 7 },
+ { name => "s0", encoding => 8 },
+ { name => "s1", encoding => 9 },
+ { name => "a0", encoding => 10 },
+ { name => "a1", encoding => 11 },
+ { name => "a2", encoding => 12 },
+ { name => "a3", encoding => 13 },
+ { name => "a4", encoding => 14 },
+ { name => "a5", encoding => 15 },
+ { name => "a6", encoding => 16 },
+ { name => "a7", encoding => 17 },
+ { name => "s2", encoding => 18 },
+ { name => "s3", encoding => 19 },
+ { name => "s4", encoding => 20 },
+ { name => "s5", encoding => 21 },
+ { name => "s6", encoding => 22 },
+ { name => "s7", encoding => 23 },
+ { name => "s8", encoding => 24 },
+ { name => "s9", encoding => 25 },
+ { name => "s10", encoding => 26 },
+ { name => "s11", encoding => 27 },
+ { name => "t3", encoding => 28 },
+ { name => "t4", encoding => 29 },
+ { name => "t5", encoding => 30 },
+ { name => "t6", encoding => 31 },
+ ]
+ },
+);
+
+%init_attr = (
+ riscv_attr_t => "",
+ riscv_cond_attr_t =>
+ "attr->cond = cond;",
+ riscv_immediate_attr_t =>
+ "attr->ent = ent;\n".
+ "\tattr->val = val;",
+ riscv_switch_attr_t =>
+ "be_switch_attr_init(res, &attr->swtch, table, table_entity);",
+);
+
+my $binOp = {
+ irn_flags => [ "rematerializable" ],
+ in_reqs => [ "cls-gp", "cls-gp" ],
+ out_reqs => [ "cls-gp" ],
+ ins => [ "left", "right" ],
+ outs => [ "res" ],
+ emit => "{name}\t%D0, %S0, %S1",
+};
+
+my $callOp = {
+ state => "exc_pinned",
+ in_reqs => "...",
+ out_reqs => "...",
+ ins => [ "mem", "stack", "first_argument" ],
+ outs => [ "M", "stack", "first_result" ],
+};
+
+my $immediateOp = {
+ irn_flags => [ "rematerializable" ],
+ in_reqs => [ "cls-gp" ],
+ out_reqs => [ "cls-gp" ],
+ ins => [ "left" ],
+ outs => [ "res" ],
+ attr_type => "riscv_immediate_attr_t",
+ attr => "ir_entity *const ent, int32_t const val",
+ emit => "{name}\t%D0, %S0, %I",
+};
+
+my $loadOp = {
+ state => "exc_pinned",
+ in_reqs => [ "mem", "cls-gp" ],
+ out_reqs => [ "mem", "cls-gp" ],
+ ins => [ "mem", "base" ],
+ outs => [ "M", "res" ],
+ attr_type => "riscv_immediate_attr_t",
+ attr => "ir_entity *const ent, int32_t const val",
+ emit => "{name}\t%D1, %A",
+};
+
+my $storeOp = {
+ state => "exc_pinned",
+ in_reqs => [ "mem", "cls-gp", "cls-gp" ],
+ out_reqs => [ "mem" ],
+ ins => [ "mem", "base", "value" ],
+ outs => [ "M" ],
+ attr_type => "riscv_immediate_attr_t",
+ attr => "ir_entity *const ent, int32_t const val",
+ emit => "{name}\t%S2, %A",
+};
+
+%nodes = (
+
+add => { template => $binOp },
+
+addi => { template => $immediateOp },
+
+and => { template => $binOp },
+
+andi => { template => $immediateOp },
+
+bcc => {
+ state => "pinned",
+ op_flags => [ "cfopcode", "forking" ],
+ in_reqs => [ "cls-gp", "cls-gp" ],
+ ins => [ "left", "right" ],
+ out_reqs => [ "exec", "exec" ],
+ outs => [ "false", "true" ],
+ attr_type => "riscv_cond_attr_t",
+ attr => "riscv_cond_t const cond",
+},
+
+div => { template => $binOp, },
+
+divu => { template => $binOp, },
+
+ijmp => {
+ state => "pinned",
+ op_flags => [ "cfopcode", "unknown_jump" ],
+ in_reqs => [ "cls-gp" ],
+ out_reqs => [ "exec" ],
+ emit => "jr\t%S0",
+},
+
+j => {
+ state => "pinned",
+ irn_flags => [ "simple_jump", "fallthrough" ],
+ op_flags => [ "cfopcode" ],
+ out_reqs => [ "exec" ],
+},
+
+jal => {
+ template => $callOp,
+ attr_type => "riscv_immediate_attr_t",
+ attr => "ir_entity *const ent, int32_t const val",
+ emit => "jal\t%J",
+},
+
+jalr => {
+ template => $callOp,
+ emit => "jalr\t%S2",
+},
+
+lb => { template => $loadOp },
+
+lbu => { template => $loadOp },
+
+lh => { template => $loadOp },
+
+lhu => { template => $loadOp },
+
+lui => {
+ template => $immediateOp,
+ in_reqs => [],
+ ins => [],
+ emit => "lui\t%D0, %H",
+},
+
+lw => { template => $loadOp },
+
+mul => { template => $binOp, },
+
+mulh => { template => $binOp, },
+
+mulhu => { template => $binOp, },
+
+or => { template => $binOp },
+
+ori => { template => $immediateOp },
+
+rem => { template => $binOp, },
+
+remu => { template => $binOp, },
+
+ret => {
+ state => "pinned",
+ op_flags => [ "cfopcode" ],
+ in_reqs => "...",
+ out_reqs => [ "exec" ],
+ ins => [ "mem", "stack", "addr", "first_result" ],
+ emit => "ret",
+},
+
+sb => { template => $storeOp },
+
+sh => { template => $storeOp },
+
+sll => { template => $binOp },
+
+slli => { template => $immediateOp },
+
+slt => { template => $binOp },
+
+sltiu => { template => $immediateOp },
+
+sltu => { template => $binOp },
+
+sra => { template => $binOp },
+
+srai => { template => $immediateOp },
+
+srl => { template => $binOp },
+
+srli => { template => $immediateOp },
+
+sub => { template => $binOp },
+
+sw => { template => $storeOp },
+
+switch => {
+ op_flags => [ "cfopcode", "forking" ],
+ state => "pinned",
+ in_reqs => [ "cls-gp" ],
+ out_reqs => "...",
+ attr_type => "riscv_switch_attr_t",
+ attr => "const ir_switch_table *table, ir_entity *table_entity",
+},
+
+xor => { template => $binOp },
+
+xori => { template => $immediateOp },
+
+);