Skip to content

Commit

Permalink
Merge branch 'feature/riscv-call'
Browse files Browse the repository at this point in the history
  • Loading branch information
tyfkda committed Apr 12, 2024
2 parents e8778c5 + 71f15d3 commit a4c49c9
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 20 deletions.
3 changes: 3 additions & 0 deletions include/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ typedef struct {
#define R_X86_64_PC32 (2) /* PC relative 32 bit signed */
#define R_X86_64_PLT32 (4) /* 32 bit PLT address */

#define R_RISCV_CALL (18)
#define R_RISCV_RELAX (51)

#define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((Elf64_Word)(info))
#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
Expand Down
72 changes: 68 additions & 4 deletions src/as/arch/aarch64/ir_asm.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
#include "../../../config.h"
#include "ir_asm.h"

#include <assert.h>

#include "gen_section.h"
#include "table.h"
#include "util.h"

#define BYTE_SIZE (1)
#define SHORT_SIZE (2)
#define LONG_SIZE (4)
#define QUAD_SIZE (8)

static LabelInfo *new_label(int section, uintptr_t address) {
LabelInfo *info = malloc_or_die(sizeof(*info));
info->section = section;
Expand Down Expand Up @@ -79,11 +86,68 @@ IR *new_ir_expr(enum IrKind kind, const Expr *expr) {
return ir;
}

static uintptr_t align_next_section(enum SectionType sec, uintptr_t address) {
size_t align = section_aligns[sec];
if (align > 1)
address = ALIGN(address, align);
return address;
}

bool calc_label_address(uintptr_t start_address, Vector **section_irs, Table *label_table) {
UNUSED(start_address);
UNUSED(section_irs);
UNUSED(label_table);
return true;
bool settle = true;
uintptr_t address = start_address;
for (int sec = 0; sec < SECTION_COUNT; ++sec) {
address = align_next_section(sec, address);
section_start_addresses[sec] = address;

Vector *irs = section_irs[sec];
for (int i = 0, len = irs->len; i < len; ++i) {
IR *ir = irs->data[i];
ir->address = address;
switch (ir->kind) {
case IR_LABEL:
{
LabelInfo *info;
if (!table_try_get(label_table, ir->label, (void**)&info)) {
fprintf(stderr, "[%.*s] not found\n", NAMES(ir->label));
assert(!"Unexpected");
} else {
info->address = address;
}
}
break;
case IR_CODE:
address += ir->code.len;
break;
case IR_DATA:
address += ir->data.len;
break;
case IR_BSS:
address += ir->bss;
break;
case IR_ALIGN:
ir->address = address = ALIGN(address, ir->align);
if ((size_t)ir->align > section_aligns[sec]) {
section_aligns[sec] = ir->align;
settle = false;
}
break;
case IR_EXPR_BYTE:
address += BYTE_SIZE;
break;
case IR_EXPR_SHORT:
address += SHORT_SIZE;
break;
case IR_EXPR_LONG:
address += LONG_SIZE;
break;
case IR_EXPR_QUAD:
address += QUAD_SIZE;
break;
}
}
}
return settle;
}

bool resolve_relative_address(Vector **section_irs, Table *label_table, Vector *unresolved) {
Expand Down
87 changes: 79 additions & 8 deletions src/as/arch/riscv64/asm_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,30 @@ inline bool assemble_error(const ParseInfo *info, const char *message) {
//

#define ZERO 0

#define C_LI(rd, imm) MAKE_CODE16(inst, code, 0x4001 | ((imm & 0x20) << 12) | (rd << 7) | ((imm & 0x1f) << 2))
#define C_LUI(rd, imm) MAKE_CODE16(inst, code, 0x6001 | ((imm & 0x20) << 12) | (rd << 7) | ((imm & 0x1f) << 2))
#define C_ADDIW(rd, imm) MAKE_CODE16(inst, code, 0x2001 | ((imm & 0x20) << 12) | (rd << 7) | ((imm & 0x1f) << 2))

#define ADDIW(rd, rs, imm) MAKE_CODE32(inst, code, 0x00000019 | ((int32_t)imm << 20) | (rs << 15) | (rd << 7))
#define ADDI(rd, rs, imm) MAKE_CODE32(inst, code, 0x00000013 | ((int32_t)imm << 20) | (rd << 7))
#define RA 1
#define SP 2

#define IMM(imm, t, b) (((imm) >> (b)) & ((1 << (t - b + 1)) - 1))
#define RTYPE(funct7, rs2, rs1, funct3, rd, opcode) MAKE_CODE32(inst, code, ((funct7) << 25) | ((rs2) << 20) | ((rs1) << 15) | ((funct3) << 12) | ((rd) << 7) | (opcode)) // R-type
#define ITYPE(imm, rs1, funct3, rd, opcode) MAKE_CODE32(inst, code, (IMM(imm, 11, 0) << 20) | ((rs1) << 15) | ((funct3) << 12) | ((rd) << 7) | (opcode)) // I-type
#define STYPE(imm, rs2, rs1, funct3, opcode) MAKE_CODE32(inst, code, (IMM(imm, 11, 5) << 25) | ((rs2) << 20) | ((rs1) << 15) | ((funct3) << 12) | (IMM(imm, 4, 0) << 7) | (opcode)) // S-type
#define BTYPE(imm, rs2, rs1, funct3, opcode) MAKE_CODE32(inst, code, (IMM(imm, 12, 12) << 31) | (IMM(imm, 10, 5) << 25) | ((rs2) << 20) | ((rs1) << 15) | ((funct3) << 12) | (IMM(imm, 4, 0) << 7) | (opcode)) // B-type
#define UTYPE(imm, rd, opcode) MAKE_CODE32(inst, code, (IMM(imm, 31, 12) << 12) | ((rd) << 7) | (opcode)) // U-type
#define JTYPE(imm, rd, opcode) MAKE_CODE32(inst, code, (IMM(imm, 20, 20) << 31) | (IMM(imm, 10, 1) << 20) | (IMM(imm, 11, 11) << 19) | (IMM(imm, 19, 12) << 12) | ((rd) << 7) | (opcode)) // J-type

#define C_LI(rd, imm) MAKE_CODE16(inst, code, 0x4001 | (IMM(imm, 5, 5) << 12) | (rd << 7) | (IMM(imm, 4, 0) << 2))
#define C_LUI(rd, imm) MAKE_CODE16(inst, code, 0x6001 | (IMM(imm, 5, 5) << 12) | (rd << 7) | (IMM(imm, 4, 0) << 2))
#define C_ADDI(rd, imm) MAKE_CODE16(inst, code, 0x0001 | (IMM(imm, 5, 5) << 12) | (rd << 7) | (IMM(imm, 4, 0) << 2))
#define C_ADDIW(rd, imm) MAKE_CODE16(inst, code, 0x2001 | (IMM(imm, 5, 5) << 12) | (rd << 7) | (IMM(imm, 4, 0) << 2))
#define C_LDSP(rd, imm) MAKE_CODE16(inst, code, 0xe002 | (IMM(imm, 5, 5) << 12) | (rd << 7) | (IMM(imm, 4, 3) << 5) | (IMM(imm, 8, 6) << 2))
#define C_SDSP(rs, imm) MAKE_CODE16(inst, code, 0xe002 | (IMM(imm, 5, 3) << 10) | (IMM(imm, 8, 6) << 7) | (rs << 2))
#define C_JR(rs) MAKE_CODE16(inst, code, 0x8002 | (rs << 7))

#define ADDI(rd, rs, imm) ITYPE(imm, rs, 0x00, rd, 0x13)
#define ADDIW(rd, rs, imm) ITYPE(imm, rs, 0x00, rd, 0x1b)
#define AUIPC(rd, imm) UTYPE(imm, rd, 0x17)
#define JALR(rd, rs, imm) ITYPE(imm, rs, 0x00, rd, 0x67)
#define RET() C_JR(RA)

#define LI(rd, imm) ADDI(rd, ZERO, imm)
#define MV(rd, rs) ADDI(rd, rs, 0)
Expand Down Expand Up @@ -88,8 +105,58 @@ static unsigned char *asm_li(Inst *inst, Code *code) {
return code->buf;
}

static unsigned char *asm_addi(Inst *inst, Code *code) {
int rd = inst->opr1.reg.no;
int rs = inst->opr2.reg.no;
int64_t imm =inst->opr3.immediate;
if (rd == rs && is_im6(imm) && imm != 0) {
C_ADDI(rd, imm);
} else {
// TODO:
return NULL;
}
return code->buf;
}

static unsigned char *asm_ld(Inst *inst, Code *code) {
int rd = inst->opr1.reg.no;
Expr *offset = inst->opr2.indirect.offset;
if (offset == NULL || offset->kind == EX_FIXNUM) {
int64_t imm = offset != NULL ? offset->fixnum : 0;
int base_reg = inst->opr2.indirect.reg.no;
if (imm >= 0 && imm < (1 << 9) && (imm & 7) == 0 && base_reg == SP) {
imm >>= 3;
C_LDSP(rd, imm);
return code->buf;
}
}
return NULL;
}

static unsigned char *asm_sd(Inst *inst, Code *code) {
int rd = inst->opr1.reg.no;
Expr *offset = inst->opr2.indirect.offset;
if (offset == NULL || offset->kind == EX_FIXNUM) {
int64_t imm = offset != NULL ? offset->fixnum : 0;
int base_reg = inst->opr2.indirect.reg.no;
if (imm >= 0 && imm < (1 << 9) && (imm & 7) == 0 && base_reg == SP) {
imm >>= 3;
C_SDSP(rd, imm);
return code->buf;
}
}
return NULL;
}

static unsigned char *asm_call_d(Inst *inst, Code *code) {
UNUSED(inst);
AUIPC(RA, 0);
JALR(RA, RA, 0);
return code->buf;
}

static unsigned char *asm_ret(Inst *inst, Code *code) {
MAKE_CODE16(inst, code, 0x8082);
RET();
return code->buf;
}

Expand All @@ -107,6 +174,10 @@ typedef struct {
static const AsmInstTable *table[] = {
[NOOP] = (const AsmInstTable[]){ {asm_noop, NOOPERAND, NOOPERAND, NOOPERAND}, {NULL} },
[LI] = (const AsmInstTable[]){ {asm_li, REG, IMMEDIATE, NOOPERAND}, {NULL} },
[ADDI] = (const AsmInstTable[]){ {asm_addi, REG, REG, IMMEDIATE}, {NULL} },
[LD] = (const AsmInstTable[]){ {asm_ld, REG, INDIRECT, NOOPERAND}, {NULL} },
[SD] = (const AsmInstTable[]){ {asm_sd, REG, INDIRECT, NOOPERAND}, {NULL} },
[CALL] = (const AsmInstTable[]){ {asm_call_d, DIRECT, NOOPERAND, NOOPERAND}, {NULL} },
[RET] = (const AsmInstTable[]){ {asm_ret, NOOPERAND, NOOPERAND, NOOPERAND}, {NULL} },
};

Expand Down
13 changes: 13 additions & 0 deletions src/as/arch/riscv64/inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ typedef struct Expr Expr;
enum Opcode {
NOOP,
LI,
ADDI,
LD,
SD,
CALL,
RET,
};

Expand All @@ -28,13 +32,22 @@ enum OperandType {
NOOPERAND,
REG, // reg
IMMEDIATE, // 1234
DIRECT, // foobar
INDIRECT, // ofs(reg)
};

typedef struct {
enum OperandType type;
union {
Reg reg;
int64_t immediate;
struct {
Expr *expr;
} direct;
struct {
Expr *offset;
Reg reg;
} indirect;
};
} Operand;

Expand Down
Loading

0 comments on commit a4c49c9

Please sign in to comment.