mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
RISCV: Correct auipc imm; clarify signed imm error; add imm negative t… (#1378)
RISCV: Correct auipc imm; claify signed imm error; add imm negative tests. Allow fitted int asm imm const in uints; add rv regs
This commit is contained in:
@@ -67,7 +67,11 @@ typedef enum
|
||||
RISCV_F31,
|
||||
RISCV_MIE,
|
||||
RISCV_MSTATUS,
|
||||
RISCV_MTVEC
|
||||
RISCV_MTVEC,
|
||||
RISCV_MCAUSE,
|
||||
RISCV_MEPC,
|
||||
RISCV_MTVAL,
|
||||
RISCV_MSIP
|
||||
} RISCVClobbers;
|
||||
|
||||
static const char *RISCVClobberNames[] = {
|
||||
@@ -138,6 +142,10 @@ static const char *RISCVClobberNames[] = {
|
||||
[RISCV_MIE] = "mie",
|
||||
[RISCV_MSTATUS] = "mstatus",
|
||||
[RISCV_MTVEC] = "mtvec",
|
||||
[RISCV_MCAUSE] = "mcause",
|
||||
[RISCV_MEPC] = "mepc",
|
||||
[RISCV_MTVAL] = "mtval",
|
||||
[RISCV_MSIP] = "msip",
|
||||
};
|
||||
|
||||
static const char *riscv_gp_integer_regs[] = { "$x0", "$x1", "$x2", "$x3", "$x4",
|
||||
@@ -160,5 +168,5 @@ static const char *riscv_float_regs[] = { "$f0", "$f1", "$f2", "$f3", "$f4",
|
||||
"$f20", "$f21", "$f22", "$f23", "$f24",
|
||||
"$f25", "$f26", "$f27", "$f28", "$f29",
|
||||
"$f30", "$f31" };
|
||||
static const char *riscv_machine_integer_regs[] = { "$mie", "$mstatus", "$mtvec" };
|
||||
static const char *riscv_machine_integer_regs[] = { "$mie", "$mstatus", "$mtvec", "$mcause", "$mepc", "$mtval", "$msip" };
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ static void init_asm_riscv(PlatformTarget *target)
|
||||
// load
|
||||
reg_instr(target, "li", "w:r64/mem, immi64");
|
||||
reg_instr(target, "lui", "w:r64, immu20");
|
||||
reg_instr(target, "auipc", "w:r64, immi20");
|
||||
reg_instr(target, "auipc", "w:r64, immu20");
|
||||
reg_instr(target, "mv", "w:r64/mem, r64/mem");
|
||||
reg_instr(target, "ld", "w:r64/mem, mem");
|
||||
reg_instr(target, "lw", "w:r64/mem, mem");
|
||||
@@ -394,7 +394,7 @@ static void init_asm_riscv(PlatformTarget *target)
|
||||
// load
|
||||
reg_instr(target, "li", "w:r32/mem, immi32");
|
||||
reg_instr(target, "lui", "w:r32, immu20");
|
||||
reg_instr(target, "auipc", "w:r32, immi20");
|
||||
reg_instr(target, "auipc", "w:r32, immu20");
|
||||
reg_instr(target, "mv", "w:r32/mem, r32/mem");
|
||||
reg_instr(target, "lw", "w:r32/mem, mem");
|
||||
reg_instr(target, "lh", "w:r32/mem, mem");
|
||||
|
||||
@@ -21,7 +21,12 @@ static inline Type *max_supported_imm_int(bool is_signed, AsmArgType arg)
|
||||
if (is_signed)
|
||||
{
|
||||
unsigned bits = arg_bits_max(arg.imm_arg_ibits, 64);
|
||||
if (!bits) return NULL;
|
||||
if (!bits)
|
||||
{
|
||||
bits = arg_bits_max(arg.imm_arg_ubits, 64);
|
||||
if (!bits) return NULL;
|
||||
return type_int_unsigned_by_bitsize(next_highest_power_of_2(bits));
|
||||
}
|
||||
return type_int_signed_by_bitsize(next_highest_power_of_2(bits));
|
||||
}
|
||||
unsigned bits = arg_bits_max(arg.imm_arg_ubits, 64);
|
||||
@@ -135,7 +140,7 @@ static inline bool sema_check_asm_arg_const_int(SemaContext *context, AsmInlineB
|
||||
return false;
|
||||
}
|
||||
Int i = int_expr->const_expr.ixx;
|
||||
unsigned max_bits = arg_bits_max(is_signed ? arg_type.imm_arg_ibits : arg_type.imm_arg_ubits, 0);
|
||||
unsigned max_bits = arg_bits_max(arg_type.imm_arg_ibits > arg_type.imm_arg_ubits ? arg_type.imm_arg_ibits : arg_type.imm_arg_ubits, 0);
|
||||
if (!type || !int_fits(i, type->type_kind) || !sema_check_npot_imm_fits(i, arg_type))
|
||||
{
|
||||
SEMA_ERROR(expr, "'%s' expected %s limited to %d bits.", instr->name, type_quoted_error_string(type), max_bits);
|
||||
|
||||
58
test/test_suite/asm/asm_imm_err_rv.c3
Normal file
58
test/test_suite/asm/asm_imm_err_rv.c3
Normal file
@@ -0,0 +1,58 @@
|
||||
// #target: elf-riscv32
|
||||
module test;
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
asm
|
||||
{
|
||||
andi $s1, $s2, -2049; // #error: 'andi' expected 'short' limited to 12 bits.
|
||||
}
|
||||
}
|
||||
|
||||
fn void test2()
|
||||
{
|
||||
asm
|
||||
{
|
||||
ori $t0, $t1, 2048; // #error: 'ori' expected 'short' limited to 12 bits.
|
||||
}
|
||||
}
|
||||
|
||||
fn void test3()
|
||||
{
|
||||
asm
|
||||
{
|
||||
slli $a0, $a1, 32u; // #error: 'slli' expected 'char' limited to 5 bits.
|
||||
}
|
||||
}
|
||||
|
||||
fn void test4()
|
||||
{
|
||||
asm
|
||||
{
|
||||
lui $a0, 0xFFFFFF; // #error: 'lui' expected 'uint' limited to 20 bits.
|
||||
}
|
||||
}
|
||||
|
||||
fn void test5()
|
||||
{
|
||||
asm
|
||||
{
|
||||
lui $a0, -1; // #error: 'lui' expected 'uint' limited to 20 bits.
|
||||
}
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
asm
|
||||
{
|
||||
auipc $a0, -1; // #error: 'auipc' expected 'uint' limited to 20 bits.
|
||||
}
|
||||
}
|
||||
|
||||
fn void test7()
|
||||
{
|
||||
asm
|
||||
{
|
||||
slli $a0, 1, 31u; // #error: 'slli' does not support a direct integer constant here.
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,10 @@ fn void main(String[] args)
|
||||
int x = 2;
|
||||
asm
|
||||
{
|
||||
li $s1, -65536;
|
||||
li $s1, -2147483648;
|
||||
lui $t0, 123456u;
|
||||
auipc $x15, -123456;
|
||||
auipc $x15, 123456u;
|
||||
auipc $a0, 1;
|
||||
mv $a0, $a1;
|
||||
lw $a4, [&x];
|
||||
lb $a5, [$a7 - 4];
|
||||
@@ -17,4 +18,4 @@ fn void main(String[] args)
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
"li s1, -65536\0Alui t0, 123456\0Aauipc x15, -123456\0Amv a0, a1\0Alw a4, $0\0Alb a5, -4(a7)\0A", "*m,~{x5},~{x9},~{x10},~{x14},~{x15}"(ptr elementtype(i32) %x)
|
||||
"li s1, -2147483648\0Alui t0, 123456\0Aauipc x15, 123456\0Aauipc a0, 1\0Amv a0, a1\0Alw a4, $0\0Alb a5, -4(a7)\0A", "*m,~{x5},~{x9},~{x10},~{x14},~{x15}"(ptr elementtype(i32) %x)
|
||||
Reference in New Issue
Block a user