Skip to content

Commit

Permalink
Fix for RISC-V
Browse files Browse the repository at this point in the history
  • Loading branch information
tyfkda committed Dec 22, 2023
1 parent 1b1b066 commit 6266d33
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 111 deletions.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,14 @@ clean:

# Run tests on RISC-V simulator.
.PHONY: test-riscv64
test-riscv64:
$(MAKE) ARCHTYPE:=riscv64 PLATFORM:=posix HOST_CC_PREFIX=riscv64-unknown-elf-
test-riscv64: cross-compile-riscv64
$(MAKE) -C tests clean && \
$(MAKE) RUN_EXE="$(CURDIR)/tool/run-riscv64" NO_LINK_TEST=1 -C tests all

.PHONY: cross-compile-riscv64
cross-compile-riscv64:
$(MAKE) ARCHTYPE:=riscv64 PLATFORM:=posix HOST_CC_PREFIX=riscv64-unknown-elf-

### Library

.PHONY: libs
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ XCC

C compiler running on Linux or MacOS.

* Supporting architecture: x86-64, aarch64 (arm64), wasm
* Supporting architecture: x86-64, aarch64 (arm64), riscv64, wasm
* Binary format: ELF64


Expand Down
4 changes: 2 additions & 2 deletions src/cc/arch/aarch64/ir_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ static void ei_iofs(IR *ir) {
static void ei_sofs(IR *ir) {
assert(ir->opr1->flag & VRF_CONST);
const char *dst = kReg64s[ir->dst->phys];
int ofs = ir->opr1->frame.offset;
int ofs = ir->opr1->fixnum;
if (ofs < 4096 && ofs > -4096) {
ADD(dst, SP, IM(ir->opr1->fixnum));
ADD(dst, SP, IM(ofs));
} else {
mov_immediate(dst, ofs, true, false);
ADD(dst, dst, SP);
Expand Down
2 changes: 1 addition & 1 deletion src/cc/arch/riscv64/arch_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define MAX_FREG_ARGS (8)

#define PHYSICAL_REG_TEMPORARY (8)
#define PHYSICAL_REG_MAX (PHYSICAL_REG_TEMPORARY + 14)
#define PHYSICAL_REG_MAX (PHYSICAL_REG_TEMPORARY + 18)
#define PHYSICAL_FREG_TEMPORARY (8)
#define PHYSICAL_FREG_MAX (PHYSICAL_FREG_TEMPORARY + 24)

Expand Down
25 changes: 4 additions & 21 deletions src/cc/arch/riscv64/emit_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,6 @@ static void move_params_to_assigned(Function *func) {
extern const int ArchRegParamMapping[];
extern const char *kFReg64s[];

// static const char *kRegParam32s[] = {W0, W1, W2, W3, W4, W5, W6, W7};
// static const char **kRegParamTable[] = {kRegParam32s, kRegParam32s, kRegParam32s, kRegParam64s};
// const char *kFRegParam32s[] = {S0, S1, S2, S3, S4, S5, S6, S7};
const char *kFRegParam64s[] = {FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7};
static const int kPow2Table[] = {-1, 0, 1, -1, 2, -1, -1, -1, 3};
#define kPow2TableSize ((int)(sizeof(kPow2Table) / sizeof(*kPow2Table)))
Expand All @@ -416,13 +413,7 @@ static void move_params_to_assigned(Function *func) {
if (vreg->flag & VRF_SPILLED) {
int offset = vreg->frame.offset;
assert(offset != 0);
const char *dst;
// if (offset >= -256) {
dst = IMMEDIATE_OFFSET(offset, FP);
// } else {
// mov_immediate(X9, offset, true, false); // x9 broken.
// dst = REG_OFFSET(FP, X9, NULL);
// }
const char *dst = IMMEDIATE_OFFSET(offset, FP);
switch (pow) {
case 0: SB(src, dst); break;
case 1: SH(src, dst); break;
Expand Down Expand Up @@ -514,7 +505,6 @@ static void emit_defun(Function *func) {

// TODO: Handle fp_saved and ra_saved individually.
if (fp_saved || ra_saved) {
// STP(FP, LR, PRE_INDEX(SP, -16));
ADDI(SP, SP, IM(-16));
SD(RA, IMMEDIATE_OFFSET(8, SP));
SD(FP, IMMEDIATE_OFFSET0(SP));
Expand All @@ -529,14 +519,7 @@ static void emit_defun(Function *func) {
if (fp_saved) {
MV(FP, SP);
if (frame_size > 0) {
const char *value;
// if (frame_size <= 0x0fff) {
value = IM(-frame_size);
ADDI(SP, SP, value);
// } else {
// // Break x17
// mov_immediate(value = X17, frame_size, true, false);
// }
ADDI(SP, SP, IM(-frame_size));
}
}

Expand All @@ -556,11 +539,11 @@ static void emit_defun(Function *func) {
if (fp_saved || ra_saved) {
LD(FP, IMMEDIATE_OFFSET0(SP));
LD(RA, IMMEDIATE_OFFSET(8, SP));
ADD(SP, SP, IM(16));
ADDI(SP, SP, IM(16));
}
}
if (vaarg_params_saved > 0)
ADD(SP, SP, IM(vaarg_params_saved));
ADDI(SP, SP, IM(vaarg_params_saved));

RET();
}
Expand Down
112 changes: 32 additions & 80 deletions src/cc/arch/riscv64/ir_riscv64.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,21 @@ static void pop_caller_save_regs(Vector *saves);

// Register allocator

// AArch64: Calling Convention
// X8(XR): Indirect return value address.
// X16(IP0), X17(IP1): Intra-Procedure-call scratch registers.
// X18(PR): Platform register. Used for some operating-system-specific special purpose or an additional caller-saved register.
// X29(FP): Frame pointer (Callee save)

// static const char *kReg32s[PHYSICAL_REG_MAX] = {
// W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W16, // Temporary
// W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, // Callee save
// W10, W11, W12, W13, W14, W15, W18}; // Caller save
// static const char *kReg64s[PHYSICAL_REG_MAX] = {
// X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X16, // Temporary
// X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, // Callee save
// X10, X11, X12, X13, X14, X15, X18}; // Caller save
const char *kReg64s[PHYSICAL_REG_MAX] = {
A0, A1, A2, A3, A4, A5, A6, A7, // Temporary
S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, FP, // Callee save
T0, T1, T2}; // Caller save
T0, T1, T2, T3, T4, T5, T6}; // Caller save

#define GET_A0_INDEX() 0
// #define GET_X16_INDEX() 10

#define CALLEE_SAVE_REG_COUNT ((int)(sizeof(kCalleeSaveRegs) / sizeof(*kCalleeSaveRegs)))
static const int kCalleeSaveRegs[] = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};

#define CALLER_SAVE_REG_COUNT ((int)(sizeof(kCallerSaveRegs) / sizeof(*kCallerSaveRegs)))
static const int kCallerSaveRegs[] = {19, 20, 21};
static const int kCallerSaveRegs[] = {19, 20, 21, 22, 23, 24, 25};

const int ArchRegParamMapping[] = {0, 1, 2, 3, 4, 5, 6, 7};

// const char **kRegSizeTable[] = {kReg32s, kReg32s, kReg32s, kReg64s};
// static const char *kZeroRegTable[] = {WZR, WZR, WZR, XZR};

// Break s1 in store, mod and tjmp
static const char *kTmpReg = S1;

Expand All @@ -74,12 +56,6 @@ static const int kCallerSaveFRegs[] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 3
static unsigned long detect_extra_occupied(RegAlloc *ra, IR *ir) {
UNUSED(ir);
unsigned long ioccupy = 0;
// switch (ir->kind) {
// case IR_JMP: case IR_TJMP: case IR_CALL:
// ioccupy = 1UL << GET_X16_INDEX();
// break;
// default: break;
// }
if (ra->flag & RAF_STACK_FRAME)
ioccupy |= 1UL << GET_FPREG_INDEX();
return ioccupy;
Expand All @@ -102,20 +78,15 @@ bool is_im12(intptr_t x) {
return x <= ((1L << 11) - 1) && x >= -(1L << 11);
}

void mov_immediate(const char *dst, int64_t value, bool is_unsigned) {
UNUSED(is_unsigned);
LI(dst, IM(value));
}

static void ei_bofs(IR *ir) {
const char *dst = kReg64s[ir->dst->phys];
int ofs = ir->bofs.frameinfo->offset;
// if (ofs < 4096 && ofs > -4096) {
if (is_im12(ofs)) {
ADDI(dst, FP, IM(ofs));
// } else {
// mov_immediate(dst, ofs, true, false);
// ADD(dst, dst, FP);
// }
} else {
LI(dst, IM(ofs));
ADD(dst, dst, FP);
}
}

static void ei_iofs(IR *ir) {
Expand All @@ -124,25 +95,20 @@ static void ei_iofs(IR *ir) {
label = MANGLE(label);
label = quote_label(label);
const char *dst = kReg64s[ir->dst->phys];
// if (!is_got(ir->iofs.label)) {
LUI(dst, LABEL_OFFSET_HI(label));
ADDI(dst, dst, LABEL_OFFSET_LO(label));
// } else {
// ADRP(dst, LABEL_AT_GOTPAGE(label));
// LDR(dst, fmt("[%s,#%s]", dst, LABEL_AT_GOTPAGEOFF(label)));
// }
LUI(dst, LABEL_OFFSET_HI(label));
ADDI(dst, dst, LABEL_OFFSET_LO(label));
}

static void ei_sofs(IR *ir) {
assert(ir->opr1->flag & VRF_CONST);
const char *dst = kReg64s[ir->dst->phys];
// int ofs = ir->opr1->frame.offset;
// if (ofs < 4096 && ofs > -4096) {
ADDI(dst, SP, IM(ir->opr1->fixnum));
// } else {
// mov_immediate(dst, ofs, true, false);
// ADD(dst, dst, SP);
// }
int ofs = ir->opr1->fixnum;
if (is_im12(ofs)) {
ADDI(dst, SP, IM(ofs));
} else {
LI(dst, IM(ofs));
ADD(dst, dst, SP);
}
}

#define ei_load_s ei_load
Expand All @@ -154,10 +120,10 @@ static void ei_load(IR *ir) {
src = IMMEDIATE_OFFSET0(kReg64s[ir->opr1->phys]);
} else {
assert(ir->opr1->flag & VRF_SPILLED);
if (ir->opr1->frame.offset >= -4096 && ir->opr1->frame.offset <= 4096) {
if (is_im12(ir->opr1->frame.offset)) {
src = IMMEDIATE_OFFSET(ir->opr1->frame.offset, FP);
} else {
mov_immediate(kTmpReg, ir->opr1->frame.offset, false);
LI(kTmpReg, IM(ir->opr1->frame.offset));
ADD(kTmpReg, kTmpReg, FP);
src = IMMEDIATE_OFFSET0(kTmpReg);
}
Expand Down Expand Up @@ -204,10 +170,10 @@ static void ei_store(IR *ir) {
target = IMMEDIATE_OFFSET0(kReg64s[ir->opr2->phys]);
} else {
assert(ir->opr2->flag & VRF_SPILLED);
if (ir->opr2->frame.offset >= -4096 && ir->opr2->frame.offset <= 4096) {
if (is_im12(ir->opr2->frame.offset)) {
target = IMMEDIATE_OFFSET(ir->opr2->frame.offset, FP);
} else {
mov_immediate(kTmpReg, ir->opr2->frame.offset, false);
LI(kTmpReg, IM(ir->opr2->frame.offset));
ADD(kTmpReg, kTmpReg, FP);
target = IMMEDIATE_OFFSET0(kTmpReg);
}
Expand All @@ -224,7 +190,7 @@ static void ei_store(IR *ir) {
if (ir->opr1->fixnum == 0)
src = ZERO;
else
mov_immediate(src = kTmpReg, ir->opr1->fixnum, ir->flag & IRF_UNSIGNED);
LI(src = kTmpReg, IM(ir->opr1->fixnum));
} else {
src = kReg64s[ir->opr1->phys];
}
Expand Down Expand Up @@ -408,7 +374,7 @@ static void ei_result(IR *ir) {
int dstphys = ir->dst != NULL ? ir->dst->phys : GET_A0_INDEX();
const char *dst = kReg64s[dstphys];
if (ir->opr1->flag & VRF_CONST) {
mov_immediate(dst, ir->opr1->fixnum, ir->flag & IRF_UNSIGNED);
LI(dst, IM(ir->opr1->fixnum));
} else if (ir->opr1->phys != dstphys) { // Source is not return register.
MV(dst, kReg64s[ir->opr1->phys]);
}
Expand Down Expand Up @@ -444,7 +410,7 @@ static void ei_mov(IR *ir) {
assert(!(ir->dst->flag & VRF_CONST));
const char *dst = kReg64s[ir->dst->phys];
if (ir->opr1->flag & VRF_CONST) {
mov_immediate(dst, ir->opr1->fixnum, ir->flag & IRF_UNSIGNED);
LI(dst, IM(ir->opr1->fixnum));
} else {
if (ir->opr1->phys != ir->dst->phys) {
MV(dst, kReg64s[ir->opr1->phys]);
Expand Down Expand Up @@ -657,7 +623,7 @@ static void ei_precall(IR *ir) {
ir->precall.stack_aligned = align_stack;

if (align_stack > 0) {
SUB(SP, SP, IM(align_stack));
ADDI(SP, SP, IM(-align_stack));
}
}

Expand Down Expand Up @@ -703,7 +669,7 @@ static void ei_call(IR *ir) {
IR *precall = ir->call.precall;
int align_stack = precall->precall.stack_aligned + precall->precall.stack_args_size;
if (align_stack != 0) {
ADD(SP, SP, IM(align_stack));
ADDI(SP, SP, IM(align_stack));
}

// Resore caller save registers.
Expand Down Expand Up @@ -848,16 +814,15 @@ void pop_callee_save_regs(unsigned long used, unsigned long fused) {
}

int calculate_func_param_bottom(Function *func) {
const char *saves[(N + 1) & ~1];
const char *saves[ALIGN(N, 2)];
FuncBackend *fnbe = func->extra;
unsigned long used = fnbe->ra->used_reg_bits; //, fused = fnbe->ra->used_freg_bits;
unsigned long used = fnbe->ra->used_reg_bits, fused = fnbe->ra->used_freg_bits;
int count = enum_callee_save_regs(used, CALLEE_SAVE_REG_COUNT, kCalleeSaveRegs, kReg64s, saves);
// int fcount = enum_callee_save_regs(fused, CALLEE_SAVE_FREG_COUNT, kCalleeSaveFRegs, kFReg64s,
// saves);
int fcount = 0;
int callee_save_count = ALIGN(count, 2) + ALIGN(fcount, 2);
int fcount = enum_callee_save_regs(fused, CALLEE_SAVE_FREG_COUNT, kCalleeSaveFRegs, kFReg64s,
&saves[count]);
int total = count + fcount;

return (callee_save_count * POINTER_SIZE) + (POINTER_SIZE * 2); // Return address, saved base pointer.
return (ALIGN(total, 2) * POINTER_SIZE) + (POINTER_SIZE * 2); // Return address, saved base pointer.
}
#undef N

Expand Down Expand Up @@ -986,12 +951,6 @@ void tweak_irs(FuncBackend *fnbe) {
if (ir->opr1->flag & VRF_CONST)
swap_opr12(ir);
if (ir->opr2->flag & VRF_CONST) {
// if (ir->opr2->fixnum < 0) {
// ir->kind = IR_SUB;
// VReg *old = ir->opr2;
// ir->opr2 = reg_alloc_spawn_const(ra, -old->fixnum, old->vsize);
// ir->opr2->flag = old->flag;
// }
if (ir->opr2->fixnum > 0x0fff || ir->opr2->fixnum < -0x0fff)
insert_const_mov(&ir->opr2, ra, irs, j++);
}
Expand All @@ -1008,12 +967,6 @@ void tweak_irs(FuncBackend *fnbe) {
insert_const_mov(&ir->opr1, ra, irs, j++);
}
if (ir->opr2->flag & VRF_CONST) {
// if (ir->opr2->fixnum < 0) {
// ir->kind = IR_ADD;
// VReg *old = ir->opr2;
// ir->opr2 = reg_alloc_spawn_const(ra, -old->fixnum, old->vsize);
// ir->opr2->flag = old->flag;
// }
if (ir->opr2->fixnum > 0x0fff || ir->opr2->fixnum < -0x0fff)
insert_const_mov(&ir->opr2, ra, irs, j++);
}
Expand Down Expand Up @@ -1063,8 +1016,7 @@ void tweak_irs(FuncBackend *fnbe) {
insert_const_mov(&ir->opr2, ra, irs, j++);
break;
case COND_LT: case COND_GE:
if ((ir->opr2->flag & VRF_CONST) &&
(ir->opr2->fixnum < -4096 || ir->opr2->fixnum > 4096))
if ((ir->opr2->flag & VRF_CONST) && !is_im12(ir->opr2->fixnum))
insert_const_mov(&ir->opr2, ra, irs, j++);
break;
default:
Expand Down
10 changes: 6 additions & 4 deletions src/cc/arch/riscv64/riscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
#define T0 "t0"
#define T1 "t1"
#define T2 "t2"
#define T3 "t3"
#define T4 "t4"
#define T5 "t5"
#define T6 "t6"

#define FA0 "fa0"
#define FA1 "fa1"
Expand Down Expand Up @@ -212,14 +216,12 @@
#define FCVT_D_S(o1, o2) EMIT_ASM("fcvt.d.s", o1, o2) // double <- float
#define FCVT_S_D(o1, o2) EMIT_ASM("fcvt.s.d", o1, o2) // float <- double

#define FMV_X_W(o1, o2) EMIT_ASM("fmv.x.w", o1, o2) // int <- float(hex)
#define FMV_X_D(o1, o2) EMIT_ASM("fmv.x.d", o1, o2) // int <- double(hex)
#define FMV_X_W(o1, o2) EMIT_ASM("fmv.x.w", o1, o2) // int <- float(hex)
#define FMV_X_D(o1, o2) EMIT_ASM("fmv.x.d", o1, o2) // int <- double(hex)

#define FEQ_D(o1, o2, o3) EMIT_ASM("feq.d", o1, o2, o3)
#define FEQ_S(o1, o2, o3) EMIT_ASM("feq.s", o1, o2, o3)
#define FLT_D(o1, o2, o3) EMIT_ASM("flt.d", o1, o2, o3)
#define FLT_S(o1, o2, o3) EMIT_ASM("flt.s", o1, o2, o3)
#define FLE_D(o1, o2, o3) EMIT_ASM("fle.d", o1, o2, o3)
#define FLE_S(o1, o2, o3) EMIT_ASM("fle.s", o1, o2, o3)

void mov_immediate(const char *dst, int64_t value, bool is_unsigned);

0 comments on commit 6266d33

Please sign in to comment.