Skip to content

Commit f478189

Browse files
committed
Update timer correctly
In the current implementation, the timer would not be updated untill the control flow exits the JIT-ed code. This commit updates the timer correctly after every instruction has been dispatched.
1 parent 1821908 commit f478189

File tree

4 files changed

+51
-17
lines changed

4 files changed

+51
-17
lines changed

src/emulate.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,10 @@ static void __trap_handler(riscv_t *rv);
8282

8383
/* FIXME: use more precise methods for updating time, e.g., RTC */
8484
#if RV32_HAS(Zicsr)
85-
static uint64_t ctr = 0;
8685
static inline void update_time(riscv_t *rv)
8786
{
88-
rv->csr_time[0] = ctr & 0xFFFFFFFF;
89-
rv->csr_time[1] = ctr >> 32;
87+
rv->csr_time[0] = rv->timer & 0xFFFFFFFF;
88+
rv->csr_time[1] = rv->timer >> 32;
9089
}
9190

9291
/* get a pointer to a CSR */
@@ -379,7 +378,7 @@ static uint32_t peripheral_update_ctr = 64;
379378
static bool do_##inst(riscv_t *rv, const rv_insn_t *ir, uint64_t cycle, \
380379
uint32_t PC) \
381380
{ \
382-
IIF(RV32_HAS(SYSTEM))(ctr++;, ) cycle++; \
381+
IIF(RV32_HAS(SYSTEM))(rv->timer++;, ) cycle++; \
383382
code; \
384383
IIF(RV32_HAS(SYSTEM)) \
385384
( \
@@ -1015,7 +1014,7 @@ static void rv_check_interrupt(riscv_t *rv)
10151014
emu_update_uart_interrupts(rv);
10161015
}
10171016

1018-
if (ctr > attr->timer)
1017+
if (rv->timer > attr->timer)
10191018
rv->csr_sip |= RV_INT_STI;
10201019
else
10211020
rv->csr_sip &= ~RV_INT_STI;

src/jit.c

+28-2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ enum operand_size {
211211
S8,
212212
S16,
213213
S32,
214+
S64,
214215
};
215216

216217
#if defined(__x86_64__)
@@ -756,7 +757,6 @@ static inline void emit_alu64(struct jit_state *state, int op, int src, int dst)
756757
#endif
757758
}
758759

759-
#if RV32_HAS(EXT_M)
760760
static inline void emit_alu64_imm8(struct jit_state *state,
761761
int op,
762762
int src UNUSED,
@@ -771,10 +771,12 @@ static inline void emit_alu64_imm8(struct jit_state *state,
771771
if (op == 0xc1) {
772772
emit_load_imm(state, R10, imm);
773773
emit_dataproc_2source(state, true, DP2_LSRV, dst, dst, R10);
774+
} else if (src == 0) {
775+
emit_load_imm(state, temp_reg, 0x1);
776+
emit_addsub_register(state, true, AS_ADD, dst, dst, temp_reg);
774777
}
775778
#endif
776779
}
777-
#endif
778780

779781
/* Register to register mov */
780782
static inline void emit_mov(struct jit_state *state, int src, int dst)
@@ -914,6 +916,9 @@ static inline void emit_load(struct jit_state *state,
914916
case S32:
915917
emit_loadstore_imm(state, LS_LDRW, dst, src, offset);
916918
break;
919+
case S64:
920+
emit_loadstore_imm(state, LS_LDRX, dst, src, offset);
921+
break;
917922
default:
918923
assert(NULL);
919924
__UNREACHABLE;
@@ -1104,6 +1109,9 @@ static inline void emit_store(struct jit_state *state,
11041109
case S32:
11051110
emit_loadstore_imm(state, LS_STRW, src, dst, offset);
11061111
break;
1112+
case S64:
1113+
emit_loadstore_imm(state, LS_STRX, src, dst, offset);
1114+
break;
11071115
default:
11081116
assert(NULL);
11091117
__UNREACHABLE;
@@ -2026,10 +2034,28 @@ void parse_branch_history_table(struct jit_state *state,
20262034
}
20272035
}
20282036

2037+
void emit_jit_update_timer(struct jit_state *state)
2038+
{
2039+
#if defined(__x86_64__)
2040+
/* Increment rv->timer. *rv pointer is stored in RDI register */
2041+
/* INC RDI, [rv + offsetof(riscv_t, timer)] */
2042+
emit_rex(state, 1, 0, 0, 0);
2043+
emit1(state, 0xff);
2044+
emit1(state, 0x87);
2045+
emit4(state, offsetof(riscv_t, timer));
2046+
#elif defined(__aarch64__)
2047+
emit_load(state, S64, parameter_reg[0], temp_reg, offsetof(riscv_t, timer));
2048+
emit_alu64_imm8(state, 0, 0, temp_reg, 1);
2049+
emit_store(state, S64, temp_reg, parameter_reg[0],
2050+
offsetof(riscv_t, timer));
2051+
#endif
2052+
}
2053+
20292054
#define GEN(inst, code) \
20302055
static void do_##inst(struct jit_state *state UNUSED, riscv_t *rv UNUSED, \
20312056
rv_insn_t *ir UNUSED) \
20322057
{ \
2058+
emit_jit_update_timer(state); \
20332059
code; \
20342060
}
20352061
#include "rv32_jit.c"

src/riscv_private.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ struct riscv_internal {
130130
riscv_word_t X[N_RV_REGS];
131131
riscv_word_t PC;
132132

133-
#if RV32_HAS(JIT) && RV32_HAS(SYSTEM)
133+
uint64_t timer; /* strictly increment timer */
134+
135+
#if RV32_HAS(JIT)
134136
/*
135137
* Aarch64 encoder only accepts 9 bits signed offset. Do not put this
136138
* structure below the section.

src/t2c.c

+16-9
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,21 @@ FORCE_INLINE LLVMBasicBlockRef t2c_block_map_search(struct LLVM_block_map *map,
4949
return NULL;
5050
}
5151

52-
#define T2C_OP(inst, code) \
53-
static void t2c_##inst( \
54-
LLVMBuilderRef *builder UNUSED, LLVMTypeRef *param_types UNUSED, \
55-
LLVMValueRef start UNUSED, LLVMBasicBlockRef *entry UNUSED, \
56-
LLVMBuilderRef *taken_builder UNUSED, \
57-
LLVMBuilderRef *untaken_builder UNUSED, riscv_t *rv UNUSED, \
58-
uint64_t mem_base UNUSED, rv_insn_t *ir UNUSED) \
59-
{ \
60-
code; \
52+
#define T2C_OP(inst, code) \
53+
static void t2c_##inst( \
54+
LLVMBuilderRef *builder UNUSED, LLVMTypeRef *param_types UNUSED, \
55+
LLVMValueRef start UNUSED, LLVMBasicBlockRef *entry UNUSED, \
56+
LLVMBuilderRef *taken_builder UNUSED, \
57+
LLVMBuilderRef *untaken_builder UNUSED, riscv_t *rv UNUSED, \
58+
uint64_t mem_base UNUSED, rv_insn_t *ir UNUSED) \
59+
{ \
60+
LLVMValueRef timer_ptr = t2c_gen_timer_addr(start, builder, ir); \
61+
LLVMValueRef timer = \
62+
LLVMBuildLoad2(*builder, LLVMInt64Type(), timer_ptr, ""); \
63+
timer = LLVMBuildAdd(*builder, timer, \
64+
LLVMConstInt(LLVMInt64Type(), 1, false), ""); \
65+
LLVMBuildStore(*builder, timer, timer_ptr); \
66+
code; \
6167
}
6268

6369
#define T2C_LLVM_GEN_ADDR(reg, rv_member, ir_member) \
@@ -79,6 +85,7 @@ T2C_LLVM_GEN_ADDR(ra, X, rv_reg_ra);
7985
T2C_LLVM_GEN_ADDR(sp, X, rv_reg_sp);
8086
#endif
8187
T2C_LLVM_GEN_ADDR(PC, PC, 0);
88+
T2C_LLVM_GEN_ADDR(timer, timer, 0);
8289

8390
#define T2C_LLVM_GEN_STORE_IMM32(builder, val, addr) \
8491
LLVMBuildStore(builder, LLVMConstInt(LLVMInt32Type(), val, true), addr)

0 commit comments

Comments
 (0)