mirror of https://repo.or.cz/tinycc.git
Compare commits
2 Commits
2b0a663df9
...
8cbbd2b88a
Author | SHA1 | Date |
---|---|---|
Ekaitz Zarraga | 8cbbd2b88a | |
Ekaitz Zarraga | 019d10fc12 |
184
riscv64-asm.c
184
riscv64-asm.c
|
@ -62,6 +62,8 @@ static void asm_ternary_opcode(TCCState *s1, int token);
|
|||
static void asm_unary_opcode(TCCState *s1, int token);
|
||||
ST_FUNC void gen_expr32(ExprValue *pe);
|
||||
static void parse_operand(TCCState *s1, Operand *op);
|
||||
static void parse_operands(TCCState *s1, Operand *ops, int count);
|
||||
static void parse_mem_access_operands(TCCState *s1, Operand* ops);
|
||||
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
|
||||
/* C extension */
|
||||
static void asm_emit_ca(int token, uint16_t opcode, const Operand *rd, const Operand *rs2);
|
||||
|
@ -209,13 +211,63 @@ static void parse_operand(TCCState *s1, Operand *op)
|
|||
}
|
||||
}
|
||||
|
||||
static void parse_operands(TCCState *s1, Operand* ops, int count){
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if ( i != 0 ) {
|
||||
if ( tok == ',')
|
||||
next();
|
||||
else
|
||||
expect("','");
|
||||
}
|
||||
parse_operand(s1, &ops[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* parse `X, imm(Y)` to {X, Y, imm} operands */
|
||||
static void parse_mem_access_operands(TCCState *s1, Operand* ops){
|
||||
static const Operand zimm = {.type = OP_IM12S};
|
||||
|
||||
Operand op;
|
||||
int i;
|
||||
|
||||
parse_operand(s1, &ops[0]);
|
||||
if ( tok == ',')
|
||||
next();
|
||||
else
|
||||
expect("','");
|
||||
|
||||
if ( tok == '(') {
|
||||
/* `X, (Y)` case*/
|
||||
next();
|
||||
parse_operand(s1, &ops[1]);
|
||||
if ( tok == ')') next(); else expect("')'");
|
||||
ops[2] = zimm;
|
||||
} else {
|
||||
parse_operand(s1, &ops[2]);
|
||||
if ( tok == '('){
|
||||
/* `X, imm(Y)` case*/
|
||||
next();
|
||||
parse_operand(s1, &ops[1]);
|
||||
if ( tok == ')') next(); else expect("')'");
|
||||
} else {
|
||||
/* `X, Y` case*/
|
||||
/* we parsed Y thinking it was imm, swap and default imm to zero */
|
||||
op = ops[2];
|
||||
ops[1] = ops[2];
|
||||
ops[2] = op;
|
||||
ops[2] = zimm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void asm_unary_opcode(TCCState *s1, int token)
|
||||
{
|
||||
uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
|
||||
Operand op;
|
||||
static const Operand nil = {.type = OP_REG};
|
||||
|
||||
parse_operand(s1, &op);
|
||||
parse_operands(s1, &op, 1);
|
||||
/* Note: Those all map to CSR--so they are pseudo-instructions. */
|
||||
opcode |= ENCODE_RD(op.reg);
|
||||
|
||||
|
@ -280,12 +332,7 @@ static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Oper
|
|||
static void asm_binary_opcode(TCCState* s1, int token)
|
||||
{
|
||||
Operand ops[2];
|
||||
parse_operand(s1, &ops[0]);
|
||||
if (tok == ',')
|
||||
next();
|
||||
else
|
||||
expect("','");
|
||||
parse_operand(s1, &ops[1]);
|
||||
parse_operands(s1, &ops[0], 2);
|
||||
|
||||
switch (token) {
|
||||
case TOK_ASM_lui:
|
||||
|
@ -496,20 +543,56 @@ static void asm_emit_j(int token, uint32_t opcode, const Operand* rd, const Oper
|
|||
gen_le32(opcode | ENCODE_RD(rd->reg) | (((imm >> 20) & 1) << 31) | (((imm >> 1) & 0x3ff) << 21) | (((imm >> 11) & 1) << 20) | (((imm >> 12) & 0xff) << 12));
|
||||
}
|
||||
|
||||
static void asm_mem_access_opcode(TCCState *s1, int token)
|
||||
{
|
||||
|
||||
Operand ops[3];
|
||||
parse_mem_access_operands(s1, &ops[0]);
|
||||
|
||||
// l{b|h|w|d}[u] rd, imm(rs1); I-format
|
||||
switch (token) {
|
||||
case TOK_ASM_lb:
|
||||
asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lh:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lw:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_ld:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lbu:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lhu:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lwu:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
|
||||
// s{b|h|w|d} rs2, imm(rs1); S-format (with rsX swapped)
|
||||
case TOK_ASM_sb:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (0 << 12), &ops[1], &ops[0], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_sh:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (1 << 12), &ops[1], &ops[0], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_sw:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (2 << 12), &ops[1], &ops[0], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_sd:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (3 << 12), &ops[1], &ops[0], &ops[2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void asm_ternary_opcode(TCCState *s1, int token)
|
||||
{
|
||||
Operand ops[3];
|
||||
parse_operand(s1, &ops[0]);
|
||||
if (tok == ',')
|
||||
next();
|
||||
else
|
||||
expect("','");
|
||||
parse_operand(s1, &ops[1]);
|
||||
if (tok == ',')
|
||||
next();
|
||||
else
|
||||
expect("','");
|
||||
parse_operand(s1, &ops[2]);
|
||||
parse_operands(s1, &ops[0], 3);
|
||||
|
||||
switch (token) {
|
||||
case TOK_ASM_sll:
|
||||
|
@ -631,46 +714,6 @@ static void asm_ternary_opcode(TCCState *s1, int token)
|
|||
asm_emit_b(token, 0x63 | (7 << 12), ops, ops + 1, ops + 2);
|
||||
return;
|
||||
|
||||
// Loads (RD,RS1,I); I-format
|
||||
|
||||
case TOK_ASM_lb:
|
||||
asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lh:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lw:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lbu:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lhu:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
// 64 bit
|
||||
case TOK_ASM_ld:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_lwu:
|
||||
asm_emit_i(token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
|
||||
// Stores (RS1,RS2,I); S-format
|
||||
|
||||
case TOK_ASM_sb:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_sh:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_sw:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
case TOK_ASM_sd:
|
||||
asm_emit_s(token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
||||
return;
|
||||
|
||||
/* M extension */
|
||||
case TOK_ASM_div:
|
||||
asm_emit_r(token, 0x33 | (4 << 12) | (1 << 25), ops, ops + 1, ops + 2);
|
||||
|
@ -857,6 +900,20 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||
asm_binary_opcode(s1, token);
|
||||
return;
|
||||
|
||||
case TOK_ASM_lb:
|
||||
case TOK_ASM_lh:
|
||||
case TOK_ASM_lw:
|
||||
case TOK_ASM_ld:
|
||||
case TOK_ASM_lbu:
|
||||
case TOK_ASM_lhu:
|
||||
case TOK_ASM_lwu:
|
||||
case TOK_ASM_sb:
|
||||
case TOK_ASM_sh:
|
||||
case TOK_ASM_sw:
|
||||
case TOK_ASM_sd:
|
||||
asm_mem_access_opcode(s1, token);
|
||||
break;
|
||||
|
||||
case TOK_ASM_add:
|
||||
case TOK_ASM_addi:
|
||||
case TOK_ASM_addiw:
|
||||
|
@ -870,18 +927,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||
case TOK_ASM_bltu:
|
||||
case TOK_ASM_bne:
|
||||
case TOK_ASM_jalr:
|
||||
case TOK_ASM_lb:
|
||||
case TOK_ASM_lbu:
|
||||
case TOK_ASM_ld:
|
||||
case TOK_ASM_lh:
|
||||
case TOK_ASM_lhu:
|
||||
case TOK_ASM_lw:
|
||||
case TOK_ASM_lwu:
|
||||
case TOK_ASM_or:
|
||||
case TOK_ASM_ori:
|
||||
case TOK_ASM_sb:
|
||||
case TOK_ASM_sd:
|
||||
case TOK_ASM_sh:
|
||||
case TOK_ASM_sll:
|
||||
case TOK_ASM_slli:
|
||||
case TOK_ASM_slliw:
|
||||
|
@ -900,7 +947,6 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||
case TOK_ASM_srlw:
|
||||
case TOK_ASM_sub:
|
||||
case TOK_ASM_subw:
|
||||
case TOK_ASM_sw:
|
||||
case TOK_ASM_xor:
|
||||
case TOK_ASM_xori:
|
||||
/* M extension */
|
||||
|
|
Loading…
Reference in New Issue