From b28bf50d2b10d6af8c57c288bf587a1d467ff484 Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Tue, 6 Apr 2021 13:36:33 +0200 Subject: [PATCH] riscv64-asm: Add beq, bne, blt, bge, bltu, bgeu --- riscv64-asm.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ riscv64-tok.h | 9 +++++++ 2 files changed, 79 insertions(+) diff --git a/riscv64-asm.c b/riscv64-asm.c index 4abbc6e5..27ff2cb0 100644 --- a/riscv64-asm.c +++ b/riscv64-asm.c @@ -503,6 +503,67 @@ static void asm_data_transfer_opcode(TCCState* s1, int token) } } +static void asm_branch_opcode(TCCState* s1, int token) +{ + // Branch (RS1,RS2,IMM); SB-format + uint32_t opcode = (0x18 << 2) | 3; + uint32_t offset = 0; + Operand ops[3]; + parse_operand(s1, &ops[0]); + if (ops[0].type != OP_REG) { + expect("register"); + return; + } + if (tok == ',') + next(); + else + expect("','"); + parse_operand(s1, &ops[1]); + if (ops[1].type != OP_REG) { + expect("register"); + return; + } + if (tok == ',') + next(); + else + expect("','"); + parse_operand(s1, &ops[2]); + + if (ops[2].type != OP_IM12S) { + tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL)); + return; + } + offset = ops[2].e.v; + if (offset & 1) { + tcc_error("'%s': Expected third operand that is an even immediate value", get_tok_str(token, NULL)); + return; + } + + switch (token) { + case TOK_ASM_beq: + opcode |= 0 << 12; + break; + case TOK_ASM_bne: + opcode |= 1 << 12; + break; + case TOK_ASM_blt: + opcode |= 4 << 12; + break; + case TOK_ASM_bge: + opcode |= 5 << 12; + break; + case TOK_ASM_bltu: + opcode |= 6 << 12; + break; + case TOK_ASM_bgeu: + opcode |= 7 << 12; + break; + default: + expect("known branch instruction"); + } + asm_emit_opcode(opcode | ENCODE_RS1(ops[0].reg) | ENCODE_RS2(ops[1].reg) | (((offset >> 1) & 0xF) << 8) | (((offset >> 5) & 0x1f) << 25) | (((offset >> 11) & 1) << 7) | (((offset >> 12) & 1) << 31)); +} + ST_FUNC void asm_opcode(TCCState *s1, int token) { switch (token) { @@ -589,6 +650,15 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) asm_data_transfer_opcode(s1, token); return; + case TOK_ASM_beq: + case TOK_ASM_bne: + case TOK_ASM_blt: + case TOK_ASM_bge: + case TOK_ASM_bltu: + case TOK_ASM_bgeu: + asm_branch_opcode(s1, token); + return; + default: expect("known instruction"); } diff --git a/riscv64-tok.h b/riscv64-tok.h index 1261d95f..0b218412 100644 --- a/riscv64-tok.h +++ b/riscv64-tok.h @@ -155,6 +155,15 @@ DEF_ASM(sltu) DEF_ASM(sltiu) +/* Branch */ + + DEF_ASM(beq) + DEF_ASM(bne) + DEF_ASM(blt) + DEF_ASM(bge) + DEF_ASM(bltu) + DEF_ASM(bgeu) + /* Sync */ DEF_ASM(fence)