stable
This commit is contained in:
21
linker/Makefile
Normal file
21
linker/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
CC = gcc
|
||||
CFLAGS = -g -Wall -I..
|
||||
# CLFAGS += -fsanitize=address
|
||||
|
||||
all: smcc
|
||||
smcc: cc asm lib
|
||||
$(CC) $(CFLAGS) riscv32_crt.c riscv32_linker.c test_main.c -L../assembler/riscv32 -lasm -L../ccompiler -lcc -L../lib -lcore -o smcc
|
||||
|
||||
lib:
|
||||
make -C ../lib
|
||||
|
||||
asm:
|
||||
make -C ../assembler/riscv32
|
||||
|
||||
cc:
|
||||
make -C ../ccompiler
|
||||
|
||||
clean:
|
||||
make -C ../lib clean
|
||||
make -C ../assembler/riscv32 clean
|
||||
make -C ../ccompiler clean
|
6
linker/header.h
Normal file
6
linker/header.h
Normal file
@ -0,0 +1,6 @@
|
||||
#include <assembler/riscv32/riscv32.h>
|
||||
#include <assembler/riscv32/riscv32_instr.h>
|
||||
#include <lib/core.h>
|
||||
|
||||
rv32_prog_t* gen_rv32_crt();
|
||||
rv32_prog_t* link_rv32_prog(rv32_prog_t* progs[]);
|
21
linker/riscv32_crt.c
Normal file
21
linker/riscv32_crt.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "header.h"
|
||||
// #include <assembler/riscv32/riscv32.c>
|
||||
|
||||
rv32_prog_t* gen_rv32_crt() {
|
||||
rv32_prog_t* crt = (rv32_prog_t*)salloc_alloc(sizeof(rv32_prog_t));
|
||||
init_rv32_prog(crt, NULL);
|
||||
rv32_li(crt, REG_SP, 0x1000);
|
||||
rv32_li(crt, REG_RA, 0x0);
|
||||
|
||||
// call main
|
||||
symasm_entry_t entry = {
|
||||
.name = "main",
|
||||
.attr = GLOBAL
|
||||
};
|
||||
rv32_call_l(crt, &entry);
|
||||
|
||||
// ecall exit2
|
||||
rv32_li(crt, REG_A7, 93);
|
||||
rv32_ecall(crt);
|
||||
return crt;
|
||||
}
|
65
linker/riscv32_linker.c
Normal file
65
linker/riscv32_linker.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include "header.h"
|
||||
|
||||
static u32_t text_addr = 0;
|
||||
#define FOREACH_PROGS(progs) for (rv32_prog_t **pprog = progs, *prog = *progs; \
|
||||
*pprog != NULL; prog = *(++pprog))
|
||||
int append(const void *key, void *value, void *context) {
|
||||
symtab_asm_t* symtab = (symtab_asm_t*) context;
|
||||
symasm_entry_t* entry = (symasm_entry_t*) key;
|
||||
u32_t* addr = (u32_t*) value;
|
||||
*addr += text_addr; // size to index
|
||||
salloc_alloc(16);
|
||||
if (entry->attr == GLOBAL) {
|
||||
symtab_asm_put(symtab, entry, *addr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
rv32_prog_t* link_rv32_prog(rv32_prog_t* progs[]) {
|
||||
symtab_asm_t symtab;
|
||||
init_symtab_asm(&symtab);
|
||||
|
||||
rv32_prog_t* exe = salloc_alloc(sizeof(rv32_prog_t));
|
||||
init_rv32_prog(exe, NULL);
|
||||
|
||||
FOREACH_PROGS(progs) {
|
||||
prog->text_base_address = text_addr;
|
||||
text_addr += prog->text.size;
|
||||
}
|
||||
exe->text.data = salloc_alloc(text_addr * sizeof(u32_t));
|
||||
exe->text.cap = text_addr;
|
||||
exe->text.size = text_addr;
|
||||
text_addr = 0;
|
||||
FOREACH_PROGS(progs) {
|
||||
rt_memcpy(exe->text.data + text_addr, prog->text.data, prog->text.size * sizeof(u32_t));
|
||||
// FIXME
|
||||
hashtable_foreach(&prog->symtab.symtab, append, &symtab);
|
||||
text_addr += prog->text.size;
|
||||
}
|
||||
|
||||
// find by self
|
||||
FOREACH_PROGS(progs) {
|
||||
for (int i = 0; i < prog->rinstrs.size; i++) {
|
||||
u32_t* paddr;
|
||||
u32_t addr;
|
||||
paddr = symtab_asm_get(&prog->symtab, &prog->rinstrs.data[i].target);
|
||||
if (paddr == NULL) {
|
||||
paddr = symtab_asm_get(&symtab, &prog->rinstrs.data[i].target);
|
||||
if (paddr == NULL) {
|
||||
LOG_FATAL("linker: %s not found", prog->rinstrs.data[i].target.name);
|
||||
}
|
||||
addr = *paddr;
|
||||
} else {
|
||||
addr = *paddr;
|
||||
// addr += prog->text_base_address;
|
||||
}
|
||||
// FIXME
|
||||
int cur_idx = prog->text_base_address + prog->rinstrs.data[i].address;
|
||||
prog->rinstrs.data[i].instr.imm += (addr - cur_idx) * sizeof(u32_t);
|
||||
emit_rv32_instr(exe, &prog->rinstrs.data[i].instr, cur_idx, NULL);
|
||||
|
||||
// symtab_get(&prog->symtab, &prog->rinstrs.data[i].target);
|
||||
}
|
||||
}
|
||||
return exe;
|
||||
}
|
58
linker/test_main.c
Normal file
58
linker/test_main.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include "header.h"
|
||||
#include <ccompiler/ccompiler.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// gcc rv32ima_codegen.c -o rv32gen.exe
|
||||
init_lib_core();
|
||||
log_set_level(NULL, LOG_LEVEL_ERROR | LOG_LEVEL_WARN | LOG_LEVEL_FATAL);
|
||||
|
||||
const char* infilename = "test.c";
|
||||
const char* outfilename = "flat.bin";
|
||||
if (argc >= 2) {
|
||||
infilename = argv[1];
|
||||
}
|
||||
if (argc >= 3) {
|
||||
outfilename = argv[2];
|
||||
}
|
||||
FILE* in = fopen(infilename, "r");
|
||||
FILE* out = fopen(outfilename, "wb");
|
||||
if (in == NULL || out == NULL) {
|
||||
printf("Failed to open file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
smcc_cc_t cc = {
|
||||
.file = infilename,
|
||||
.sread = (sread_fn)fread,
|
||||
.stream = in,
|
||||
};
|
||||
|
||||
asm_prog_t *prog = smcc_cc(&cc);
|
||||
// gen_rv32_instr(&prog->rv32);
|
||||
|
||||
rv32_prog_t* rv32_crt = gen_rv32_crt();
|
||||
rv32_prog_t* rv32_progs[3] = {
|
||||
rv32_crt,
|
||||
&prog->rv32,
|
||||
NULL,
|
||||
};
|
||||
// rv32_progs[0] = rv32_crt;
|
||||
// rv32_progs[1] = &prog->rv32;
|
||||
// rv32_progs[2] = NULL;
|
||||
|
||||
rv32_prog_t* code = link_rv32_prog(rv32_progs);
|
||||
|
||||
// for (int i = 0; i < code->instrs.size; i++) {
|
||||
// fwrite(&code->instrs.data[i].instr, 4, 1, out);
|
||||
// fflush(out);
|
||||
// }
|
||||
|
||||
// Flatbin fmt
|
||||
fwrite(code->text.data, sizeof(u32_t), code->text.size, out);
|
||||
// fwrite(code->data.data, sizeof(u8_t)code->text.size, 1, out);
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user