Message ID | 1380242934-20953-10-git-send-email-agraf@suse.de |
---|---|
State | New |
Headers | show |
Hi Alex, On 09/27/13 02:48, Alexander Graf wrote: > This adds handling for the b and bl instructions. > > Signed-off-by: Alexander Graf <agraf@suse.de> > --- > target-arm/translate-a64.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 61 insertions(+) > > diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c > index 73ccade..267fd4d 100644 > --- a/target-arm/translate-a64.c > +++ b/target-arm/translate-a64.c > @@ -133,6 +133,58 @@ static void real_unallocated_encoding(DisasContext *s) > real_unallocated_encoding(s); \ > } while (0) > > +static int get_bits(uint32_t inst, int start, int len) > +{ > + return (inst >> start) & ((1 << len) - 1); > +} > + do you think it makes sense to reuse extract32 from bitops here? > +static int get_sbits(uint32_t inst, int start, int len) > +{ > + int r = get_bits(inst, start, len); > + if (r & (1 << (len - 1))) { > + /* Extend the MSB 1 to the higher bits */ > + r |= -1 & ~((1ULL << len) - 1); > + } > + return r; > +} > + sextract32? > +static TCGv_i64 cpu_reg(int reg) > +{ > + if (reg == 31) { > + /* XXX leaks temps */ > + return tcg_const_i64(0); ... > + } else { > + return cpu_X[reg]; > + } > +} > + > +static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest) > +{ > + TranslationBlock *tb; > + > + tb = s->tb; > + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { > + tcg_gen_goto_tb(n); > + gen_a64_set_pc_im(dest); > + tcg_gen_exit_tb((tcg_target_long)tb + n); > + } else { > + gen_a64_set_pc_im(dest); > + tcg_gen_exit_tb(0); > + } > +} > + > +static void handle_b(DisasContext *s, uint32_t insn) > +{ > + uint64_t addr = s->pc - 4 + (get_sbits(insn, 0, 26) << 2); > + > + if (get_bits(insn, 31, 1)) { > + /* BL */ > + tcg_gen_movi_i64(cpu_reg(30), s->pc); > + } > + gen_goto_tb(s, 0, addr); > + s->is_jmp = DISAS_TB_JUMP; > +} > + > void disas_a64_insn(CPUARMState *env, DisasContext *s) > { > uint32_t insn; > @@ -141,12 +193,21 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s) > s->insn = insn; > s->pc += 4; > > + /* One-off branch instruction layout */ > + switch (insn >> 26) { > + case 0x25: > + case 0x5: > + handle_b(s, insn); > + goto insn_done; > + } > + > switch ((insn >> 24) & 0x1f) { > default: > unallocated_encoding(s); > break; > } > > +insn_done: > if (unlikely(s->singlestep_enabled) && (s->is_jmp == DISAS_TB_JUMP)) { > /* go through the main loop for single step */ > s->is_jmp = DISAS_JUMP; > Ciao, Claudio
On 09/26/2013 05:48 PM, Alexander Graf wrote: > +static int get_bits(uint32_t inst, int start, int len) > +{ > + return (inst >> start) & ((1 << len) - 1); > +} > + > +static int get_sbits(uint32_t inst, int start, int len) > +{ > + int r = get_bits(inst, start, len); > + if (r & (1 << (len - 1))) { > + /* Extend the MSB 1 to the higher bits */ > + r |= -1 & ~((1ULL << len) - 1); > + } > + return r; > +} extract32 and sextract32 please. > +static TCGv_i64 cpu_reg(int reg) > +{ > + if (reg == 31) { > + /* XXX leaks temps */ > + return tcg_const_i64(0); > + } else { > + return cpu_X[reg]; > + } > +} See how we treat temporaries in the sparc translator. We record them in the DisasContext to be freed at the end of the insn. > + tb = s->tb; > + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { Not the only conditions you need to check. In particular, no single-stepping or tb->flags & CF_LAST_IO. C.f. target-alpha's use_goto_tb function. r~
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 73ccade..267fd4d 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -133,6 +133,58 @@ static void real_unallocated_encoding(DisasContext *s) real_unallocated_encoding(s); \ } while (0) +static int get_bits(uint32_t inst, int start, int len) +{ + return (inst >> start) & ((1 << len) - 1); +} + +static int get_sbits(uint32_t inst, int start, int len) +{ + int r = get_bits(inst, start, len); + if (r & (1 << (len - 1))) { + /* Extend the MSB 1 to the higher bits */ + r |= -1 & ~((1ULL << len) - 1); + } + return r; +} + +static TCGv_i64 cpu_reg(int reg) +{ + if (reg == 31) { + /* XXX leaks temps */ + return tcg_const_i64(0); + } else { + return cpu_X[reg]; + } +} + +static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest) +{ + TranslationBlock *tb; + + tb = s->tb; + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { + tcg_gen_goto_tb(n); + gen_a64_set_pc_im(dest); + tcg_gen_exit_tb((tcg_target_long)tb + n); + } else { + gen_a64_set_pc_im(dest); + tcg_gen_exit_tb(0); + } +} + +static void handle_b(DisasContext *s, uint32_t insn) +{ + uint64_t addr = s->pc - 4 + (get_sbits(insn, 0, 26) << 2); + + if (get_bits(insn, 31, 1)) { + /* BL */ + tcg_gen_movi_i64(cpu_reg(30), s->pc); + } + gen_goto_tb(s, 0, addr); + s->is_jmp = DISAS_TB_JUMP; +} + void disas_a64_insn(CPUARMState *env, DisasContext *s) { uint32_t insn; @@ -141,12 +193,21 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s) s->insn = insn; s->pc += 4; + /* One-off branch instruction layout */ + switch (insn >> 26) { + case 0x25: + case 0x5: + handle_b(s, insn); + goto insn_done; + } + switch ((insn >> 24) & 0x1f) { default: unallocated_encoding(s); break; } +insn_done: if (unlikely(s->singlestep_enabled) && (s->is_jmp == DISAS_TB_JUMP)) { /* go through the main loop for single step */ s->is_jmp = DISAS_JUMP;
This adds handling for the b and bl instructions. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-arm/translate-a64.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)