Message ID | 1380242934-20953-15-git-send-email-agraf@suse.de |
---|---|
State | New |
Headers | show |
On 09/26/2013 05:48 PM, Alexander Graf wrote: > This patch adds emulation support for the orr instruction. > > Signed-off-by: Alexander Graf <agraf@suse.de> > --- > target-arm/helper-a64.c | 28 +++++++++++ > target-arm/helper-a64.h | 1 + > target-arm/translate-a64.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 149 insertions(+) > > diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c > index 8105fb5..da72b7f 100644 > --- a/target-arm/helper-a64.c > +++ b/target-arm/helper-a64.c > @@ -24,3 +24,31 @@ > #include "sysemu/sysemu.h" > #include "qemu/bitops.h" > > +uint32_t HELPER(pstate_add)(uint32_t pstate, uint64_t a1, uint64_t a2, > + uint64_t ar) > +{ > + int64_t s1 = a1; > + int64_t s2 = a2; > + int64_t sr = ar; > + > + pstate &= ~(PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V); > + > + if (sr < 0) { > + pstate |= PSTATE_N; > + } > + > + if (!ar) { > + pstate |= PSTATE_Z; > + } > + > + if (ar && (ar < a1)) { > + pstate |= PSTATE_C; > + } > + > + if ((s1 > 0 && s2 > 0 && sr < 0) || > + (s1 < 0 && s2 < 0 && sr > 0)) { > + pstate |= PSTATE_V; > + } > + > + return pstate; > +} Why are you not using the same split apart bits as A32? > + /* XXX carry_out */ > + switch (shift_type) { What carry out? I see no such in the ShiftReg description. > + case 3: > + tcg_gen_rotr_i64(r, cpu_reg(reg), tcg_shift); > + break; Incorrect rotate for 32bit? > +static void handle_orr(DisasContext *s, uint32_t insn) > +{ > + int is_32bit = !get_bits(insn, 31, 1); > + int dest = get_reg(insn); > + int source = get_bits(insn, 5, 5); > + int rm = get_bits(insn, 16, 5); > + int shift_amount = get_sbits(insn, 10, 6); > + int is_n = get_bits(insn, 21, 1); > + int shift_type = get_bits(insn, 22, 2); > + int opc = get_bits(insn, 29, 2); > + bool setflags = (opc == 0x3); > + TCGv_i64 tcg_op2; > + TCGv_i64 tcg_dest; > + > + if (is_32bit && (shift_amount < 0)) { > + /* reserved value */ > + unallocated_encoding(s); > + } Why are you extracting shift_amount signed? > + > + /* MOV is dest = xzr & (source & ~0) */ Comment is wrong. > + if (!shift_amount && source == 0x1f) { > + if (is_32bit) { > + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg(rm)); > + } else { > + tcg_gen_mov_i64(cpu_reg_sp(dest), cpu_reg(rm)); > + } > + if (is_n) { > + tcg_gen_not_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); > + } > + if (is_32bit) { > + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); > + } These are incorrect -- no sp in the logical ops, but xzr instead. And surely we can emit fewer opcodes for the simple cases here. Since these are the canonical aliases for mov/mvn, it'll pay off. TCGv src = cpu_reg(rm); TCGv dst = cpu_reg(rd); if (is_n) { tcg_gen_not_i64(dst, src); src = dst; } if (is_32bit) { tcg_gen_ext32u_i64(dst, src); } else { tcg_gen_mov_i64(dst, src); } Note that tcg_gen_mov_i64 does the src == dst check, so a simple 64-bit mvn will only emit the not. > + tcg_dest = cpu_reg(dest); > + switch (opc) { > + case 0x0: > + case 0x3: > + tcg_gen_and_i64(tcg_dest, cpu_reg(source), tcg_op2); > + break; > + case 0x1: > + tcg_gen_or_i64(tcg_dest, cpu_reg(source), tcg_op2); > + break; > + case 0x2: > + tcg_gen_xor_i64(tcg_dest, cpu_reg(source), tcg_op2); > + break; > + } > + > + if (is_32bit) { > + tcg_gen_ext32u_i64(tcg_dest, tcg_dest); > + } > + > + if (setflags) { > + gen_helper_pstate_add(pstate, pstate, tcg_dest, cpu_reg(31), tcg_dest); > + } Incorrect flags generated. They're different between add/sub and logical. In particular, C and V are always zero. > + handle_orr(s, insn); And please use a more proper name than ORR for something that handles all of the logical insns. r~
On 27.09.2013, at 11:25, Richard Henderson <rth@twiddle.net> wrote: > On 09/26/2013 05:48 PM, Alexander Graf wrote: >> This patch adds emulation support for the orr instruction. >> >> Signed-off-by: Alexander Graf <agraf@suse.de> >> --- >> target-arm/helper-a64.c | 28 +++++++++++ >> target-arm/helper-a64.h | 1 + >> target-arm/translate-a64.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 149 insertions(+) >> >> diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c >> index 8105fb5..da72b7f 100644 >> --- a/target-arm/helper-a64.c >> +++ b/target-arm/helper-a64.c >> @@ -24,3 +24,31 @@ >> #include "sysemu/sysemu.h" >> #include "qemu/bitops.h" >> >> +uint32_t HELPER(pstate_add)(uint32_t pstate, uint64_t a1, uint64_t a2, >> + uint64_t ar) >> +{ >> + int64_t s1 = a1; >> + int64_t s2 = a2; >> + int64_t sr = ar; >> + >> + pstate &= ~(PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V); >> + >> + if (sr < 0) { >> + pstate |= PSTATE_N; >> + } >> + >> + if (!ar) { >> + pstate |= PSTATE_Z; >> + } >> + >> + if (ar && (ar < a1)) { >> + pstate |= PSTATE_C; >> + } >> + >> + if ((s1 > 0 && s2 > 0 && sr < 0) || >> + (s1 < 0 && s2 < 0 && sr > 0)) { >> + pstate |= PSTATE_V; >> + } >> + >> + return pstate; >> +} > > Why are you not using the same split apart bits as A32? There is an architecturally defined register that specifies what pstate looks like and IIRC that includes system level state as well, similar to EFLAGS. So I figured it's more straight forward to use a single variable for it. I don't think it really makes much of a difference either way though. If we see that doing it in a split way makes more sense we can always just switch to that later. Alex
On 31 October 2013 00:29, Alexander Graf <agraf@suse.de> wrote: > > On 27.09.2013, at 11:25, Richard Henderson <rth@twiddle.net> wrote: >> Why are you not using the same split apart bits as A32? > > There is an architecturally defined register that specifies > what pstate looks like and IIRC that includes system level > state as well, similar to EFLAGS. No, the architecture goes out of its way to point out that pstate is not a register. There are a collection of different state bits which are generally accessible via different MSR/MRS instructions or in some cases not accessible at all. This is a difference from A32. In any case as Richard says we already split NZCV from the rest of CPSR in A32 -- the few places that want a complete 32 bit CPSR call a helper function that assembles it from the various separate parts. > I don't think it really makes much of a difference either way > though. If we see that doing it in a split way makes more > sense we can always just switch to that later. I think the split is less critical for A64 because of the severely reduced conditionality which means we're less likely to be making frequent NZCV checks. However it's probably still worth having because it's pretty nearly free. -- PMM
Hello, On 09/27/2013 08:25 PM, Richard Henderson wrote: > On 09/26/2013 05:48 PM, Alexander Graf wrote: >> This patch adds emulation support for the orr instruction. >> >> Signed-off-by: Alexander Graf <agraf@suse.de> >> --- >> target-arm/helper-a64.c | 28 +++++++++++ >> target-arm/helper-a64.h | 1 + >> target-arm/translate-a64.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 149 insertions(+) >> >> diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c >> index 8105fb5..da72b7f 100644 >> --- a/target-arm/helper-a64.c >> +++ b/target-arm/helper-a64.c >> @@ -24,3 +24,31 @@ >> #include "sysemu/sysemu.h" >> #include "qemu/bitops.h" >> >> +uint32_t HELPER(pstate_add)(uint32_t pstate, uint64_t a1, uint64_t a2, >> + uint64_t ar) >> +{ >> + int64_t s1 = a1; >> + int64_t s2 = a2; >> + int64_t sr = ar; >> + >> + pstate &= ~(PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V); >> + >> + if (sr < 0) { >> + pstate |= PSTATE_N; >> + } >> + >> + if (!ar) { >> + pstate |= PSTATE_Z; >> + } >> + >> + if (ar && (ar < a1)) { >> + pstate |= PSTATE_C; >> + } >> + >> + if ((s1 > 0 && s2 > 0 && sr < 0) || >> + (s1 < 0 && s2 < 0 && sr > 0)) { >> + pstate |= PSTATE_V; >> + } >> + >> + return pstate; >> +} > > Why are you not using the same split apart bits as A32? > >> + /* XXX carry_out */ >> + switch (shift_type) { > > What carry out? I see no such in the ShiftReg description. > >> + case 3: >> + tcg_gen_rotr_i64(r, cpu_reg(reg), tcg_shift); >> + break; > > Incorrect rotate for 32bit? > >> +static void handle_orr(DisasContext *s, uint32_t insn) >> +{ >> + int is_32bit = !get_bits(insn, 31, 1); >> + int dest = get_reg(insn); >> + int source = get_bits(insn, 5, 5); >> + int rm = get_bits(insn, 16, 5); >> + int shift_amount = get_sbits(insn, 10, 6); >> + int is_n = get_bits(insn, 21, 1); >> + int shift_type = get_bits(insn, 22, 2); >> + int opc = get_bits(insn, 29, 2); >> + bool setflags = (opc == 0x3); >> + TCGv_i64 tcg_op2; >> + TCGv_i64 tcg_dest; >> + >> + if (is_32bit && (shift_amount < 0)) { >> + /* reserved value */ >> + unallocated_encoding(s); >> + } > > Why are you extracting shift_amount signed? > >> + >> + /* MOV is dest = xzr & (source & ~0) */ > > Comment is wrong. > >> + if (!shift_amount && source == 0x1f) { Besides the comment, is this correct? I am trying to rework this patch, but this part seems incorrect to me. We land here for the AND as well, and if source(rn) is xzr, then I would expect the result to be zero for AND regardless of anything else, and not a MOV. Can we really do this optimization in general here for AND, OR, EOR? Thanks for any clarification, Claudio >> + if (is_32bit) { >> + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg(rm)); >> + } else { >> + tcg_gen_mov_i64(cpu_reg_sp(dest), cpu_reg(rm)); >> + } >> + if (is_n) { >> + tcg_gen_not_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); >> + } >> + if (is_32bit) { >> + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); >> + } > > These are incorrect -- no sp in the logical ops, but xzr instead. > > And surely we can emit fewer opcodes for the simple cases here. > Since these are the canonical aliases for mov/mvn, it'll pay off. > > TCGv src = cpu_reg(rm); > TCGv dst = cpu_reg(rd); > > if (is_n) { > tcg_gen_not_i64(dst, src); > src = dst; > } > if (is_32bit) { > tcg_gen_ext32u_i64(dst, src); > } else { > tcg_gen_mov_i64(dst, src); > } > > Note that tcg_gen_mov_i64 does the src == dst check, so a simple > 64-bit mvn will only emit the not. > > >> + tcg_dest = cpu_reg(dest); >> + switch (opc) { >> + case 0x0: >> + case 0x3: >> + tcg_gen_and_i64(tcg_dest, cpu_reg(source), tcg_op2); >> + break; >> + case 0x1: >> + tcg_gen_or_i64(tcg_dest, cpu_reg(source), tcg_op2); >> + break; >> + case 0x2: >> + tcg_gen_xor_i64(tcg_dest, cpu_reg(source), tcg_op2); >> + break; >> + } >> + >> + if (is_32bit) { >> + tcg_gen_ext32u_i64(tcg_dest, tcg_dest); >> + } >> + >> + if (setflags) { >> + gen_helper_pstate_add(pstate, pstate, tcg_dest, cpu_reg(31), tcg_dest); >> + } > > Incorrect flags generated. They're different between add/sub and logical. > In particular, C and V are always zero. > >> + handle_orr(s, insn); > > And please use a more proper name than ORR for something that handles all > of the logical insns. > > > r~ >
On Mon, Nov 18, 2013 at 11:15 AM, Claudio Fontana <claudio.fontana@linaro.org> wrote: > Hello, > > On 09/27/2013 08:25 PM, Richard Henderson wrote: >> On 09/26/2013 05:48 PM, Alexander Graf wrote: >>> This patch adds emulation support for the orr instruction. >>> >>> Signed-off-by: Alexander Graf <agraf@suse.de> >>> --- >>> target-arm/helper-a64.c | 28 +++++++++++ >>> target-arm/helper-a64.h | 1 + >>> target-arm/translate-a64.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ >>> 3 files changed, 149 insertions(+) >>> >>> diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c >>> index 8105fb5..da72b7f 100644 >>> --- a/target-arm/helper-a64.c >>> +++ b/target-arm/helper-a64.c >>> @@ -24,3 +24,31 @@ >>> #include "sysemu/sysemu.h" >>> #include "qemu/bitops.h" >>> >>> +uint32_t HELPER(pstate_add)(uint32_t pstate, uint64_t a1, uint64_t a2, >>> + uint64_t ar) >>> +{ >>> + int64_t s1 = a1; >>> + int64_t s2 = a2; >>> + int64_t sr = ar; >>> + >>> + pstate &= ~(PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V); >>> + >>> + if (sr < 0) { >>> + pstate |= PSTATE_N; >>> + } >>> + >>> + if (!ar) { >>> + pstate |= PSTATE_Z; >>> + } >>> + >>> + if (ar && (ar < a1)) { >>> + pstate |= PSTATE_C; >>> + } >>> + >>> + if ((s1 > 0 && s2 > 0 && sr < 0) || >>> + (s1 < 0 && s2 < 0 && sr > 0)) { >>> + pstate |= PSTATE_V; >>> + } >>> + >>> + return pstate; >>> +} >> >> Why are you not using the same split apart bits as A32? >> >>> + /* XXX carry_out */ >>> + switch (shift_type) { >> >> What carry out? I see no such in the ShiftReg description. >> >>> + case 3: >>> + tcg_gen_rotr_i64(r, cpu_reg(reg), tcg_shift); >>> + break; >> >> Incorrect rotate for 32bit? >> >>> +static void handle_orr(DisasContext *s, uint32_t insn) >>> +{ >>> + int is_32bit = !get_bits(insn, 31, 1); >>> + int dest = get_reg(insn); >>> + int source = get_bits(insn, 5, 5); >>> + int rm = get_bits(insn, 16, 5); >>> + int shift_amount = get_sbits(insn, 10, 6); >>> + int is_n = get_bits(insn, 21, 1); >>> + int shift_type = get_bits(insn, 22, 2); >>> + int opc = get_bits(insn, 29, 2); >>> + bool setflags = (opc == 0x3); >>> + TCGv_i64 tcg_op2; >>> + TCGv_i64 tcg_dest; >>> + >>> + if (is_32bit && (shift_amount < 0)) { >>> + /* reserved value */ >>> + unallocated_encoding(s); >>> + } >> >> Why are you extracting shift_amount signed? >> >>> + >>> + /* MOV is dest = xzr & (source & ~0) */ >> >> Comment is wrong. >> >>> + if (!shift_amount && source == 0x1f) { > > Besides the comment, is this correct? > I am trying to rework this patch, but this part seems incorrect to me. > > We land here for the AND as well, and if source(rn) is xzr, > then I would expect the result to be zero for AND regardless of anything else, > and not a MOV. > > Can we really do this optimization in general here for AND, OR, EOR? That part is definitely wrong: there's a missing check that opc = 1 (ORR/ORN for MOV/MVN). The comment also is very wrong :-) Also note that SP can't be accessed by the shifted reg logical ops as Richard wrote. Laurent > Thanks for any clarification, > > Claudio > >>> + if (is_32bit) { >>> + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg(rm)); >>> + } else { >>> + tcg_gen_mov_i64(cpu_reg_sp(dest), cpu_reg(rm)); >>> + } >>> + if (is_n) { >>> + tcg_gen_not_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); >>> + } >>> + if (is_32bit) { >>> + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); >>> + } >> >> These are incorrect -- no sp in the logical ops, but xzr instead. >> >> And surely we can emit fewer opcodes for the simple cases here. >> Since these are the canonical aliases for mov/mvn, it'll pay off. >> >> TCGv src = cpu_reg(rm); >> TCGv dst = cpu_reg(rd); >> >> if (is_n) { >> tcg_gen_not_i64(dst, src); >> src = dst; >> } >> if (is_32bit) { >> tcg_gen_ext32u_i64(dst, src); >> } else { >> tcg_gen_mov_i64(dst, src); >> } >> >> Note that tcg_gen_mov_i64 does the src == dst check, so a simple >> 64-bit mvn will only emit the not. >> >> >>> + tcg_dest = cpu_reg(dest); >>> + switch (opc) { >>> + case 0x0: >>> + case 0x3: >>> + tcg_gen_and_i64(tcg_dest, cpu_reg(source), tcg_op2); >>> + break; >>> + case 0x1: >>> + tcg_gen_or_i64(tcg_dest, cpu_reg(source), tcg_op2); >>> + break; >>> + case 0x2: >>> + tcg_gen_xor_i64(tcg_dest, cpu_reg(source), tcg_op2); >>> + break; >>> + } >>> + >>> + if (is_32bit) { >>> + tcg_gen_ext32u_i64(tcg_dest, tcg_dest); >>> + } >>> + >>> + if (setflags) { >>> + gen_helper_pstate_add(pstate, pstate, tcg_dest, cpu_reg(31), tcg_dest); >>> + } >> >> Incorrect flags generated. They're different between add/sub and logical. >> In particular, C and V are always zero. >> >>> + handle_orr(s, insn); >> >> And please use a more proper name than ORR for something that handles all >> of the logical insns. >> >> >> r~ >> >
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index 8105fb5..da72b7f 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -24,3 +24,31 @@ #include "sysemu/sysemu.h" #include "qemu/bitops.h" +uint32_t HELPER(pstate_add)(uint32_t pstate, uint64_t a1, uint64_t a2, + uint64_t ar) +{ + int64_t s1 = a1; + int64_t s2 = a2; + int64_t sr = ar; + + pstate &= ~(PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V); + + if (sr < 0) { + pstate |= PSTATE_N; + } + + if (!ar) { + pstate |= PSTATE_Z; + } + + if (ar && (ar < a1)) { + pstate |= PSTATE_C; + } + + if ((s1 > 0 && s2 > 0 && sr < 0) || + (s1 < 0 && s2 < 0 && sr > 0)) { + pstate |= PSTATE_V; + } + + return pstate; +} diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h index 30ecf78..1492b15 100644 --- a/target-arm/helper-a64.h +++ b/target-arm/helper-a64.h @@ -17,3 +17,4 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +DEF_HELPER_FLAGS_4(pstate_add, TCG_CALL_NO_RWG_SE, i32, i32, i64, i64, i64) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 039e73a..2a80715 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -484,6 +484,123 @@ static void handle_ldarx(DisasContext *s, uint32_t insn) tcg_temp_free_i64(tcg_addr); } +static TCGv_i64 get_shift(int reg, int shift_type, TCGv_i64 tcg_shift, + int is_32bit) +{ + TCGv_i64 r; + + r = tcg_temp_new_i64(); + + /* XXX carry_out */ + switch (shift_type) { + case 0: /* LSL */ + tcg_gen_shl_i64(r, cpu_reg(reg), tcg_shift); + break; + case 1: /* LSR */ + tcg_gen_shr_i64(r, cpu_reg(reg), tcg_shift); + break; + case 2: /* ASR */ + if (is_32bit) { + TCGv_i64 tcg_tmp = tcg_temp_new_i64(); + tcg_gen_ext32s_i64(tcg_tmp, cpu_reg(reg)); + tcg_gen_sar_i64(r, tcg_tmp, tcg_shift); + tcg_temp_free_i64(tcg_tmp); + } else { + tcg_gen_sar_i64(r, cpu_reg(reg), tcg_shift); + } + break; + case 3: + tcg_gen_rotr_i64(r, cpu_reg(reg), tcg_shift); + break; + } + + return r; +} + +static TCGv_i64 get_shifti(int reg, int shift_type, int shift, int is_32bit) +{ + TCGv_i64 tcg_shift; + TCGv_i64 r; + + if (!shift) { + r = tcg_temp_new_i64(); + tcg_gen_mov_i64(r, cpu_reg(reg)); + return r; + } + + tcg_shift = tcg_const_i64(shift); + r = get_shift(reg, shift_type, tcg_shift, is_32bit); + tcg_temp_free_i64(tcg_shift); + + return r; +} + +static void handle_orr(DisasContext *s, uint32_t insn) +{ + int is_32bit = !get_bits(insn, 31, 1); + int dest = get_reg(insn); + int source = get_bits(insn, 5, 5); + int rm = get_bits(insn, 16, 5); + int shift_amount = get_sbits(insn, 10, 6); + int is_n = get_bits(insn, 21, 1); + int shift_type = get_bits(insn, 22, 2); + int opc = get_bits(insn, 29, 2); + bool setflags = (opc == 0x3); + TCGv_i64 tcg_op2; + TCGv_i64 tcg_dest; + + if (is_32bit && (shift_amount < 0)) { + /* reserved value */ + unallocated_encoding(s); + } + + /* MOV is dest = xzr & (source & ~0) */ + if (!shift_amount && source == 0x1f) { + if (is_32bit) { + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg(rm)); + } else { + tcg_gen_mov_i64(cpu_reg_sp(dest), cpu_reg(rm)); + } + if (is_n) { + tcg_gen_not_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); + } + if (is_32bit) { + tcg_gen_ext32u_i64(cpu_reg_sp(dest), cpu_reg_sp(dest)); + } + return; + } + + tcg_op2 = get_shifti(rm, shift_type, shift_amount & (is_32bit ? 31 : 63), + is_32bit); + if (is_n) { + tcg_gen_not_i64(tcg_op2, tcg_op2); + } + + tcg_dest = cpu_reg(dest); + switch (opc) { + case 0x0: + case 0x3: + tcg_gen_and_i64(tcg_dest, cpu_reg(source), tcg_op2); + break; + case 0x1: + tcg_gen_or_i64(tcg_dest, cpu_reg(source), tcg_op2); + break; + case 0x2: + tcg_gen_xor_i64(tcg_dest, cpu_reg(source), tcg_op2); + break; + } + + if (is_32bit) { + tcg_gen_ext32u_i64(tcg_dest, tcg_dest); + } + + if (setflags) { + gen_helper_pstate_add(pstate, pstate, tcg_dest, cpu_reg(31), tcg_dest); + } + + tcg_temp_free_i64(tcg_op2); +} + void disas_a64_insn(CPUARMState *env, DisasContext *s) { uint32_t insn; @@ -516,6 +633,9 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s) handle_ldarx(s, insn); } break; + case 0x0a: + handle_orr(s, insn); + break; case 0x0c: if (get_bits(insn, 29, 1)) { handle_stp(s, insn);
This patch adds emulation support for the orr instruction. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-arm/helper-a64.c | 28 +++++++++++ target-arm/helper-a64.h | 1 + target-arm/translate-a64.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+)