Skip to content

Commit d5242ac

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 d5242ac

File tree

4 files changed

+51
-15
lines changed

4 files changed

+51
-15
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
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__)
@@ -771,6 +772,9 @@ static inline void emit_alu64_imm8(struct jit_state *state,
771772
if (op == 0xc1) {
772773
emit_load_imm(state, R10, imm);
773774
emit_dataproc_2source(state, true, DP2_LSRV, dst, dst, R10);
775+
} else if (src == 0) {
776+
emit_load_imm(state, temp_reg, 0x1);
777+
emit_addsub_register(state, true, AS_ADD, dst, dst, temp_reg);
774778
}
775779
#endif
776780
}
@@ -914,6 +918,9 @@ static inline void emit_load(struct jit_state *state,
914918
case S32:
915919
emit_loadstore_imm(state, LS_LDRW, dst, src, offset);
916920
break;
921+
case S64:
922+
emit_loadstore_imm(state, LS_LDRX, dst, src, offset);
923+
break;
917924
default:
918925
assert(NULL);
919926
__UNREACHABLE;
@@ -1104,6 +1111,9 @@ static inline void emit_store(struct jit_state *state,
11041111
case S32:
11051112
emit_loadstore_imm(state, LS_STRW, src, dst, offset);
11061113
break;
1114+
case S64:
1115+
emit_loadstore_imm(state, LS_STRX, src, dst, offset);
1116+
break;
11071117
default:
11081118
assert(NULL);
11091119
__UNREACHABLE;
@@ -2026,11 +2036,29 @@ void parse_branch_history_table(struct jit_state *state,
20262036
}
20272037
}
20282038

2039+
void emit_jit_update_timer(struct jit_state *state)
2040+
{
2041+
#if defined(__x86_64__)
2042+
/* Increment rv->timer. *rv pointer is stored in RDI register */
2043+
/* INC RDI, [rv + offsetof(riscv_t, timer)] */
2044+
emit_rex(state, 1, 0, 0, 0);
2045+
emit1(state, 0xff);
2046+
emit1(state, 0x87);
2047+
emit4(state, offsetof(riscv_t, timer));
2048+
#elif defined(__aarch64__)
2049+
emit_load(state, S64, parameter_reg[0], temp_reg, offsetof(riscv_t, timer));
2050+
emit_alu64_imm8(state, 0, 0, temp_reg, 1);
2051+
emit_store(state, S64, temp_reg, parameter_reg[0],
2052+
offsetof(riscv_t, timer));
2053+
#endif
2054+
}
2055+
20292056
#define GEN(inst, code) \
20302057
static void do_##inst(struct jit_state *state UNUSED, riscv_t *rv UNUSED, \
20312058
rv_insn_t *ir UNUSED) \
20322059
{ \
20332060
code; \
2061+
emit_jit_update_timer(state); \
20342062
}
20352063
#include "rv32_jit.c"
20362064
#undef GEN

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+
code; \
61+
LLVMValueRef timer_ptr = t2c_gen_timer_addr(start, builder, ir); \
62+
LLVMValueRef timer = \
63+
LLVMBuildLoad2(*builder, LLVMInt64Type(), timer_ptr, ""); \
64+
timer = LLVMBuildAdd(*builder, timer, \
65+
LLVMConstInt(LLVMInt64Type(), 1, false), ""); \
66+
LLVMBuildStore(*builder, timer, timer_ptr); \
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)