Skip to contentSkip to conversation

ARC cores

RFC PATCH In review Michael Rolnik 5 participants 55 messages Sep 8, 2016 – Sep 27, 2016 Synopsys ARC architecture

lore
Share & tools
lore
#0 lore raw

cover ARC cores

This series of patches adds ARC target to QEMU. It indends to support
- ARCtangent-A5 processor
- ARC 600 processor
- ARC 700 processor

All instructions except ASLS are implemented. Not fully tested yet. However I was able to execute correctly recursive fibonacci calculation. Reset vector is assumed to be some hardcoded value which worked for my test. I am planning to get FreeRTOS for ARC, once I get it, I will able to verify and complete interrupt support.

Michael Rolnik (29):
target-arc: initial commit
target-arc: ADC, ADD, ADD1, ADD2, ADD3
target-arc: SUB, SUB1, SUB2, SUB3, SBC, RSUB, CMP
target-arc: AND, OR, XOR, BIC, TST
target-arc: ASL(m), ASR(m), LSR(m), ROR(m)
target-arc: EX, LD, ST, SYNC, PREFETCH
target-arc: MAX, MIN
target-arc: MOV, EXT, SEX, SWAP
target-arc: NEG, ABS, NOT
target-arc: POP, PUSH
target-arc: BCLR, BMSK, BSET, BTST, BXOR
target-arc: RLC, RRC
target-arc: NORM, NORMW
target-arc: MPY, MPYH, MPYHU, MPYU
target-arc: MUL64, MULU64, DIVAW
target-arc: BBIT0, BBIT1, BR
target-arc: B, BL
target-arc: J, JL
target-arc: LR, SR
target-arc: ADDS, ADDSDW, SUBS, SUBSDW
target-arc: ABSS, ABSSW, NEGS, NEGSW, RND16, SAT16
target-arc: ASLS, ASRS
target-arc: FLAG, BRK, SLEEP
target-arc: NOP, UNIMP
target-arc: TRAP, SWI
target-arc: RTIE
target-arc: LP
target-arc: decode
target-arc: sample board

 .gitignore                      |    2 +
 MAINTAINERS                     |    6 +
 arch_init.c                     |    2 +
 configure                       |    5 +
 default-configs/arc-softmmu.mak |    0
 hw/arc/Makefile.objs            |   21 +
 hw/arc/sample.c                 |   80 ++
 include/sysemu/arch_init.h      |    1 +
 target-arc/Makefile.objs        |   28 +
 target-arc/cpu-qom.h            |   84 ++
 target-arc/cpu.c                |  269 ++++
 target-arc/cpu.h                |  174 +++
 target-arc/decode.c             | 2212 ++++++++++++++++++++++++++++++
 target-arc/gdbstub.c            |  138 ++
 target-arc/helper.c             |   74 +
 target-arc/helper.h             |   29 +
 target-arc/machine.c            |   35 +
 target-arc/machine.h            |   21 +
 target-arc/op_helper.c          |  443 ++++++
 target-arc/translate-inst.c     | 2855 +++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h     |  175 +++
 target-arc/translate.c          |  424 ++++++
 target-arc/translate.h          |  223 +++
 23 files changed, 7301 insertions(+)
 create mode 100644 default-configs/arc-softmmu.mak
 create mode 100644 hw/arc/Makefile.objs
 create mode 100644 hw/arc/sample.c
 create mode 100644 target-arc/Makefile.objs
 create mode 100644 target-arc/cpu-qom.h
 create mode 100644 target-arc/cpu.c
 create mode 100644 target-arc/cpu.h
 create mode 100644 target-arc/decode.c
 create mode 100644 target-arc/gdbstub.c
 create mode 100644 target-arc/helper.c
 create mode 100644 target-arc/helper.h
 create mode 100644 target-arc/machine.c
 create mode 100644 target-arc/machine.h
 create mode 100644 target-arc/op_helper.c
 create mode 100644 target-arc/translate-inst.c
 create mode 100644 target-arc/translate-inst.h
 create mode 100644 target-arc/translate.c
 create mode 100644 target-arc/translate.h
Signature · 1 line
2.4.9 (Apple Git-60)
#1 lore raw

RFC PATCH 1/29 target-arc: initial commit

---
 .gitignore                      |   2 +
 MAINTAINERS                     |   5 +
 arch_init.c                     |   2 +
 configure                       |   5 +
 default-configs/arc-softmmu.mak |   0
 include/sysemu/arch_init.h      |   1 +
 target-arc/Makefile.objs        |  26 +++
 target-arc/cpu-qom.h            |  84 ++++++++
 target-arc/cpu.c                | 269 +++++++++++++++++++++++++
 target-arc/cpu.h                | 174 +++++++++++++++++
 target-arc/decode.c             |   7 +
 target-arc/gdbstub.c            | 138 +++++++++++++
 target-arc/helper.c             |  74 +++++++
 target-arc/helper.h             |  21 ++
 target-arc/machine.c            |  35 ++++
 target-arc/machine.h            |  21 ++
 target-arc/translate.c          | 424 ++++++++++++++++++++++++++++++++++++++++
 target-arc/translate.h          | 223 +++++++++++++++++++++
 18 files changed, 1511 insertions(+)
 create mode 100644 default-configs/arc-softmmu.mak
 create mode 100644 target-arc/Makefile.objs
 create mode 100644 target-arc/cpu-qom.h
 create mode 100644 target-arc/cpu.c
 create mode 100644 target-arc/cpu.h
 create mode 100644 target-arc/decode.c
 create mode 100644 target-arc/gdbstub.c
 create mode 100644 target-arc/helper.c
 create mode 100644 target-arc/helper.h
 create mode 100644 target-arc/machine.c
 create mode 100644 target-arc/machine.h
 create mode 100644 target-arc/translate.c
 create mode 100644 target-arc/translate.h
.gitignore +2 -0
index 88ec249..37a71af 100644
@@ -58,6 +58,8 @@
 /fsdev/virtfs-proxy-helper
 *.[1-9]
 *.a
+*.swp
+*.swo
 *.aux
 *.cp
 *.dvi
MAINTAINERS +5 -0
index b6fb84e..0500cf5 100644
@@ -99,6 +99,11 @@ F: hw/alpha/
 F: tests/tcg/alpha/
 F: disas/alpha.c
 
+ARC
+M: Michael Rolnik <[email protected]>
+S: Maintained
+F: target-arc/
+
 ARM
 M: Peter Maydell <[email protected]>
 L: [email protected]
arch_init.c +2 -0
index fa05973..04b51f5 100644
@@ -80,6 +80,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_UNICORE32
 #elif defined(TARGET_TRICORE)
 #define QEMU_ARCH QEMU_ARCH_TRICORE
+#elif defined(TARGET_ARC)
+#define QEMU_ARCH QEMU_ARCH_ARC
 #endif
 
 const uint32_t arch_type = QEMU_ARCH;
configure +5 -0
index 5a9bda1..8aee641 100755
@@ -5672,6 +5672,8 @@ case "$target_name" in
   ;;
   alpha)
   ;;
+  arc)
+  ;;
   arm|armeb)
     TARGET_ARCH=arm
     bflt="yes"
@@ -5874,6 +5876,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
       disas_config "ARM_A64"
     fi
   ;;
+  arc)
+    disas_config "ARC"
+  ;;
   arm)
     disas_config "ARM"
     if test -n "${cxx}"; then
default-configs/arc-softmmu.mak new file +0 -0
new file mode 100644
index 0000000..e69de29
include/sysemu/arch_init.h +1 -0
index 1c9dad1..35148a6 100644
@@ -23,6 +23,7 @@ enum {
     QEMU_ARCH_UNICORE32 = (1 << 14),
     QEMU_ARCH_MOXIE = (1 << 15),
     QEMU_ARCH_TRICORE = (1 << 16),
+    QEMU_ARCH_ARC = (1 << 16),
 };
 
 extern const uint32_t arch_type;
target-arc/Makefile.objs new file +26 -0
new file mode 100644
index 0000000..a3475dd
@@ -0,0 +1,26 @@
+#
+#  QEMU ARC CPU
+#
+#  Copyright (c) 2016 Michael Rolnik
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, see
+#  <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+obj-y   += translate.o
+obj-y   += helper.o
+obj-y   += cpu.o
+obj-y   += gdbstub.o
+obj-y   += decode.o
+obj-$(CONFIG_SOFTMMU) += machine.o
target-arc/cpu-qom.h new file +84 -0

84 lines not on this page · raw message

target-arc/cpu.c new file +269 -0

269 lines not on this page · raw message

target-arc/cpu.h new file +174 -0

174 lines not on this page · raw message

target-arc/decode.c new file +7 -0
new file mode 100644
index 0000000..1bb859a
@@ -0,0 +1,7 @@
+#include "translate.h"
+
+int arc_decode(DisasCtxt *ctx)
+{
+    return BS_STOP;
+}
+
target-arc/gdbstub.c new file +138 -0

138 lines not on this page · raw message

target-arc/helper.c new file +74 -0

74 lines not on this page · raw message

target-arc/helper.h new file +21 -0
new file mode 100644
index 0000000..69c91fb
@@ -0,0 +1,21 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+DEF_HELPER_1(debug, void, env)
target-arc/machine.c new file +35 -0
new file mode 100644
index 0000000..b008942
@@ -0,0 +1,35 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "cpu.h"
+#include "hw/boards.h"
+#include "machine.h"
+#include "migration/qemu-file.h"
+
+const VMStateDescription vms_arc_cpu = {
+    .name               = "cpu",
+    .version_id         = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_END_OF_LIST()
+    }
+};
target-arc/machine.h new file +21 -0
new file mode 100644
index 0000000..6190f3d
@@ -0,0 +1,21 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+extern const VMStateDescription vmstate_arc_cpu;
target-arc/translate.c new file +424 -0

424 lines not on this page · raw message

target-arc/translate.h new file +223 -0

223 lines not on this page · raw message

Signature · 1 line
2.4.9 (Apple Git-60)
#2 lore raw

Re: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit

target-arc/cpu.h line 63

Quoted 2 lines · Michael Rolnik
target-arc/cpu.h new file +2 -0
+#define CPU_IMM(env)    ((env)->r[62])
+#define CPU_PCL(env)    ((env)->r[63])

You don't need to represent these as actual registers. These are better considered placeholder regnums to be filled in with actual values during translation.

Quoted 9 lines
target-arc/cpu.h new file +9 -0
+struct CPUARCState {
+    uint32_t        r[64];
+
+    struct {
+        uint32_t    Lf;
+        uint32_t    Zf;     /*  zero                    */
+        uint32_t    Nf;     /*  negative                */
+        uint32_t    Cf;     /*  carry                   */
+        uint32_t    Vf;     /*  overflow                */

target-arc/cpu.h line 84

Quoted 10 lines
target-arc/cpu.h new file +10 -0
+        uint32_t    Uf;
+
+        uint32_t    DEf;
+        uint32_t    AEf;
+        uint32_t    A2f;    /*  interrupt 1 is active   */
+        uint32_t    A1f;    /*  interrupt 2 is active   */
+        uint32_t    E2f;    /*  interrupt 1 mask        */
+        uint32_t    E1f;    /*  interrupt 2 mask        */
+        uint32_t    Hf;     /*  halt                    */
+    } stat, stat_l1, stat_l2, stat_er;

There is no reason to represent each bit as a whole word, and even less to have four copies.

Only the current NZCV bits are relevant for expansion to a word, and even then you should consider not canonicalizing N, Z and V to a pure boolean value.

target-arc/cpu.h line 90

Quoted 6 lines
target-arc/cpu.h new file +6 -0
+
+    struct {
+        uint32_t    S2;
+        uint32_t    S1;
+        uint32_t    CS;
+    } macmod;

Does CS really need to be represented at all? It appears to me to be a field that you write to that clears S1 and S2.

target-arc/gdbstub.c line 78

Quoted 5 lines
target-arc/gdbstub.c new file +5 -0
+    switch (n) {
+        case 0x00 ... 0x3f: {
+            val = env->r[n];
+            break;
+        }

Please use the proper format for all switch statements.

    switch (n) {
    case 0x00 ... 0x3f:
        val = env->r[n];
        break;

target-arc/translate.c line 37

Quoted 12 lines
target-arc/translate.c new file +12 -0
+
+TCGv_env cpu_env;
+
+TCGv     cpu_gp;        /*  Global Pointer                      */
+TCGv     cpu_fp;        /*  Frame Pointer                       */
+TCGv     cpu_sp;        /*  Stack Pointer                       */
+TCGv     cpu_ilink1;    /*  Level 1 interrupt link register     */
+TCGv     cpu_ilink2;    /*  Level 2 interrupt link register     */
+TCGv     cpu_blink;     /*  Branch link register                */
+TCGv     cpu_mlo;       /*  Multiply low 32 bits, read only     */
+TCGv     cpu_mmi;       /*  Multiply middle 32 bits, read only  */
+TCGv     cpu_mhi;       /*  Multiply high 32 bits, read only    */

Why are these separate variables? They overlap cpu_r[N]. If you want them as names for clarity in translation, #define seems good enough.

target-arc/translate.c line 258

Quoted 3 lines
target-arc/translate.c new file +3 -0
+int arc_gen_INVALID(DisasCtxt *ctx)
+{
+    printf("invalid inst @:%08x\n", ctx->cpc);

No printf. It's not useful, even temporarily.

target-arc/translate.c line 295

Quoted 8 lines
target-arc/translate.c new file +8 -0
+    ctx.zero = tcg_const_local_i32(0);
+    ctx.one = tcg_const_local_i32(1);
+    ctx.msb32 = tcg_const_local_i32(0x80000000);
+    ctx.msb16 = tcg_const_local_i32(0x00008000);
+    ctx.smax16 = tcg_const_local_i32(0x7fffffff);
+    ctx.smax32 = tcg_const_local_i32(0x00007fff);
+    ctx.smax5 = tcg_const_local_i32(0x0000001f);
+    ctx.smin5 = tcg_const_local_i32(0xffffffe1);

Why are you creating all of these? Creating local temps containing immediates is a horrible waste.

Quoted 1 line

+ if (ctx.npc == env->lpe) {

You can't look at the contents of ENV during translation.

You'll need to implement this feature similar to how it's done for xtensa. See helper_wsr_lbeg, helper_wsr_lend, and gen_check_loop_end.

r~

#3 lore raw

Re: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit

Hello,

Quoted 5 lines · Richard Henderson
Quoted 1 line

+ if (ctx.npc == env->lpe) {

You can't look at the contents of ENV during translation.

You'll need to implement this feature similar to how it's done for xtensa. See helper_wsr_lbeg, helper_wsr_lend, and gen_check_loop_end.

I think it's fairly expensive solution, as it allows to have only one TB with zero overhead loop at a time. I'm looking at ways to optimize it, perhaps recording lbeg in the TB's cs_base.

Signature · 2 lines
Thanks.
-- Max
#4 lore raw

Re: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit

Quoted 4 lines · Max Filippov

Hello,

Quoted 1 line · Richard Henderson
Quoted 1 line

+ if (ctx.npc == env->lpe) {

Quoted 9 lines
Quoted 4 lines

You can't look at the contents of ENV during translation.

You'll need to implement this feature similar to how it's done for xtensa. See helper_wsr_lbeg, helper_wsr_lend, and gen_check_loop_end.

I think it's fairly expensive solution, as it allows to have only one TB with zero overhead loop at a time. I'm looking at ways to optimize it, perhaps recording lbeg in the TB's cs_base.

It may be expensive, but at least it works. Unlike the mechanism quoted above, which doesn't work at all.

r~

#5 lore raw

RFC PATCH 2/29 target-arc: ADC, ADD, ADD1, ADD2, ADD3

In reply to Michael Rolnik
---
 target-arc/Makefile.objs    |   1 +
 target-arc/translate-inst.c | 170 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  30 ++++++++
 3 files changed, 201 insertions(+)
 create mode 100644 target-arc/translate-inst.c
 create mode 100644 target-arc/translate-inst.h
target-arc/Makefile.objs +1 -0
index a3475dd..6fdb000 100644
@@ -21,6 +21,7 @@
 obj-y   += translate.o
 obj-y   += helper.o
 obj-y   += cpu.o
+obj-y   += translate-inst.o
 obj-y   += gdbstub.o
 obj-y   += decode.o
 obj-$(CONFIG_SOFTMMU) += machine.o
target-arc/translate-inst.c new file +170 -0

170 lines not on this page · raw message

target-arc/translate-inst.h new file +30 -0
new file mode 100644
index 0000000..08e23c7
@@ -0,0 +1,30 @@
+/*
+ *  QEMU ARC CPU
+ *
+ *  Copyright (c); 2016 Michael Rolnik
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option); any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR dest PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, see
+ *  <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "translate.h"
+#include "qemu/bitops.h"
+#include "tcg/tcg.h"
+
+int arc_gen_ADC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD2(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD3(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#6 lore raw

Re: [Qemu-devel] [PATCH RFC v1 02/29] target-arc: ADC, ADD, ADD1, ADD2, ADD3

Quoted 8 lines · Michael Rolnik
---
 target-arc/Makefile.objs    |   1 +
 target-arc/translate-inst.c | 170 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  30 ++++++++
 3 files changed, 201 insertions(+)
 create mode 100644 target-arc/translate-inst.c
 create mode 100644 target-arc/translate-inst.h

Please don't split translate.c into translate-inst.* and decode.c like you did for AVR. Since you're not generating any source from a template, there's even less call for it here than before.

target-arc/translate-inst.c line 42

Quoted 13 lines
target-arc/translate-inst.c new file +13 -0
+static void gen_add_Cf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    tcg_gen_and_tl(t1, src1, src2); /*  t1 = src1 & src2                    */
+    tcg_gen_andc_tl(t2, src1, dest);/*  t2 = src1 & ~dest                   */
+    tcg_gen_andc_tl(t3, src2, dest);/*  t3 = src2 & ~dest                   */
+    tcg_gen_or_tl(t1, t1, t2);      /*  t1 = t1 | t2 | t3                   */
+    tcg_gen_or_tl(t1, t1, t3);
+
+    tcg_gen_shri_tl(cpu_Cf, t1, 31);/*  Cf = t1(31)                         */

I've shown you before how to generate a carry bit from tcg_gen_add2_tl.

target-arc/translate-inst.c line 78

Quoted 7 lines
target-arc/translate-inst.c new file +7 -0
+int arc_gen_ADC(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }

It would be cleaner to simply always use a temporary. The tcg optimizer will generate the same code either way.

r~

#7 lore raw

RFC PATCH 3/29 target-arc: SUB, SUB1, SUB2, SUB3, SBC, RSUB, CMP

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 165 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   8 +++
 2 files changed, 173 insertions(+)
target-arc/translate-inst.c +165 -0
index 50119bf..7389e5c 100644
@@ -66,6 +66,44 @@ static void gen_add_Vf(TCGv dest, TCGv src1, TCGv src2)
     tcg_temp_free_i32(t1);
 }
 
+static void gen_sub_Cf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    tcg_gen_not_tl(t1, src1);       /*  t1 = ~src1                          */
+    tcg_gen_and_tl(t2, t1, src2);   /*  t2 = ~src1 & src2                   */
+    tcg_gen_or_tl(t3, t1, src2);    /*  t3 = (~src1 | src2) & dest          */
+    tcg_gen_and_tl(t3, t3, dest);
+    tcg_gen_or_tl(t2, t2, t3);      /*  t2 = ~src1 & src2
+                                           | ~src1 & dest
+                                           | dest & src2                    */
+    tcg_gen_shri_tl(cpu_Cf, t2, 31);/*  Cf = t2(31)                         */
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_sub_Vf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /*
+        t1 = src1 & ~src2 & ~dest
+           | ~src1 & src2 & dest
+           = (src1 ^ dest) & (src1 ^ dest)*/
+    tcg_gen_xor_tl(t1, src1, dest);
+    tcg_gen_xor_tl(t2, src1, src2);
+    tcg_gen_and_tl(t1, t1, t2);
+    tcg_gen_shri_tl(cpu_Vf, t1, 31);/*  Vf = t1(31) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
 /*
     ADC
 */
@@ -168,3 +206,130 @@ int arc_gen_ADD3(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    SUB
+*/
+int arc_gen_SUB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_sub_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        gen_sub_Cf(rslt, src1, src2);
+        gen_sub_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SBC
+*/
+int arc_gen_SBC(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_sub_tl(rslt, src1, src2);
+    tcg_gen_sub_tl(rslt, rslt, cpu_Cf);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        gen_sub_Cf(rslt, src1, src2);
+        gen_sub_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+/*
+    SUB1
+*/
+int arc_gen_SUB1(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 1);
+    arc_gen_SUB(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    SUB2
+*/
+int arc_gen_SUB2(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 2);
+    arc_gen_SUB(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    SUB3
+*/
+int arc_gen_SUB3(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 3);
+    arc_gen_SUB(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    RSUB
+*/
+int arc_gen_RSUB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    return arc_gen_SUB(ctx, dest, src2, src1);
+}
+
+/*
+    CMP
+*/
+int arc_gen_CMP(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv rslt = tcg_temp_new_i32();
+
+    tcg_gen_sub_tl(rslt, src1, src2);
+
+    tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+    tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    gen_sub_Cf(rslt, src1, src2);
+    gen_sub_Vf(rslt, src1, src2);
+
+    tcg_temp_free_i32(rslt);
+
+    return  BS_NONE;
+}
target-arc/translate-inst.h +8 -0
index 08e23c7..40ed8a0 100644
@@ -28,3 +28,11 @@ int arc_gen_ADD1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD2(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD3(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_SUB(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUB1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUB2(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUB3(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SBC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_RSUB(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_CMP(DisasCtxt *c, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#8 lore raw

Re: [Qemu-devel] [PATCH RFC v1 03/29] target-arc: SUB, SUB1, SUB2, SUB3, SBC, RSUB, CMP

Quoted 4 lines · Michael Rolnik
target-arc/translate-inst.c +4 -0
+static void gen_sub_Cf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();

target-arc/translate-inst.c static void gen_add_Vf(TCGv dest, TCGv src1, TCGv src2) · line 82

Quoted 10 lines
target-arc/translate-inst.c +10 -0
+    TCGv t3 = tcg_temp_new_i32();
+
+    tcg_gen_not_tl(t1, src1);       /*  t1 = ~src1                          */
+    tcg_gen_and_tl(t2, t1, src2);   /*  t2 = ~src1 & src2                   */
+    tcg_gen_or_tl(t3, t1, src2);    /*  t3 = (~src1 | src2) & dest          */
+    tcg_gen_and_tl(t3, t3, dest);
+    tcg_gen_or_tl(t2, t2, t3);      /*  t2 = ~src1 & src2
+                                           | ~src1 & dest
+                                           | dest & src2                    */
+    tcg_gen_shri_tl(cpu_Cf, t2, 31);/*  Cf = t2(31)                         */

Again, this can be done with tcg_gen_sub2_tl.

r~

#9 lore raw

RFC PATCH 4/29 target-arc: AND, OR, XOR, BIC, TST

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 119 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   6 +++
 2 files changed, 125 insertions(+)
target-arc/translate-inst.c +119 -0
index 7389e5c..5192f41 100644
@@ -333,3 +333,122 @@ int arc_gen_CMP(DisasCtxt *ctx, TCGv src1, TCGv src2)
 
     return  BS_NONE;
 }
+
+/*
+    TST
+*/
+int arc_gen_TST(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    ctx->opt.f = 1;
+    arc_gen_AND(ctx, temp, src1, src2);
+    tcg_temp_free_i32(temp);
+
+    return BS_NONE;
+}
+
+/*
+    AND
+*/
+int arc_gen_AND(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_and_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    OR
+*/
+int arc_gen_OR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_or_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    BIC
+*/
+int arc_gen_BIC(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andc_tl(rslt, src1, src2);  /*  rslt = src1 & ~src2             */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    XOR
+*/
+int arc_gen_XOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_xor_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +6 -0
index 40ed8a0..40ce696 100644
@@ -36,3 +36,9 @@ int arc_gen_SBC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_RSUB(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_CMP(DisasCtxt *c, TCGv src1, TCGv src2);
 
+int arc_gen_AND(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_OR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BIC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_XOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_TST(DisasCtxt *c, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#10 lore raw

Re: [Qemu-devel] [PATCH RFC v1 04/29] target-arc: AND, OR, XOR, BIC, TST

Quoted 9 lines · Michael Rolnik
target-arc/translate-inst.c +9 -0
+int arc_gen_AND(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_and_tl(rslt, src1, src2);

target-arc/translate-inst.c int arc_gen_CMP(DisasCtxt *ctx, TCGv src1, TCGv src2) · line 372

Quoted 10 lines
target-arc/translate-inst.c +10 -0
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }

There is no reason for this rslt temporary stuff.
Unlike with add & sub, src1 & src2 are not used after the operation, for any of the logical operations.

r~

#11 lore raw

RFC PATCH 5/29 target-arc: ASL(m), ASR(m), LSR(m), ROR(m)

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 212 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   9 ++
 2 files changed, 221 insertions(+)
target-arc/translate-inst.c +212 -0
index 5192f41..2032823 100644
@@ -452,3 +452,215 @@ int arc_gen_XOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    ASL
+*/
+int arc_gen_ASL(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    arc_gen_ADD(ctx, dest, src1, src1);
+
+    return  BS_NONE;
+}
+
+/*
+    ASLm
+*/
+int arc_gen_ASLm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(t0, src2, 31);
+    tcg_gen_shl_tl(rslt, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_rotl_tl(cpu_Cf, src1, t0);
+        tcg_gen_andi_tl(cpu_Cf, cpu_Cf, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ASR
+*/
+int arc_gen_ASR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_sari_tl(rslt, src1, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_andi_tl(cpu_Cf, src1, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ASRm
+*/
+int arc_gen_ASRm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(t0, src2, 31);
+    tcg_gen_sar_tl(rslt, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_rotr_tl(cpu_Cf, src1, src2);
+        tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    LSR
+*/
+int arc_gen_LSR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_shri_tl(rslt, src1, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+        tcg_gen_andi_tl(cpu_Cf, src1, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    LSRm
+*/
+int arc_gen_LSRm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(t0, src2, 31);
+    tcg_gen_shr_tl(rslt, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_rotr_tl(cpu_Cf, src1, t0);
+        tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ROR
+*/
+int arc_gen_ROR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_rotri_tl(rslt, src1, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Cf, cpu_Nf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    RORm
+*/
+int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x1f);
+    tcg_gen_rotr_tl(rslt, src1, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Cf, cpu_Nf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +9 -0
index 40ce696..325f708 100644
@@ -42,3 +42,12 @@ int arc_gen_BIC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_XOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_TST(DisasCtxt *c, TCGv src1, TCGv src2);
 
+int arc_gen_ASL(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ASLm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ASR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ASRm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_LSR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_LSRm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ROR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_RORm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#12 lore raw

RFC PATCH 6/29 target-arc: EX, LD, ST, SYNC, PREFETCH

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 230 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  10 ++
 2 files changed, 240 insertions(+)
target-arc/translate-inst.c +230 -0
index 2032823..ac13c86 100644
@@ -664,3 +664,233 @@ int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    EX
+*/
+int arc_gen_EX(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    tcg_gen_mov_tl(temp, dest);
+
+    tcg_gen_qemu_ld_tl(dest, src1, ctx->memidx, MO_UL);
+    tcg_gen_qemu_st_tl(temp, src1, ctx->memidx, MO_UL);
+
+    tcg_temp_free_i32(temp);
+
+    return BS_NONE;
+}
+
+/*
+    LD
+*/
+int arc_gen_LD(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv addr = tcg_temp_new_i32();
+
+    /*  address             */
+    switch (ctx->opt.aa) {
+        case 0x00: {
+            tcg_gen_add_tl(addr, src1, src2);
+        } break;
+
+        case 0x01: {
+            tcg_gen_add_tl(addr, src1, src2);
+        } break;
+
+        case 0x02: {
+            tcg_gen_mov_tl(addr, src1);
+        } break;
+
+        case 0x03: {
+            if (ctx->opt.zz == 0x02) {
+                tcg_gen_shli_tl(addr, src2, 1);
+            } else if (ctx->opt.zz == 0x00) {
+                tcg_gen_shli_tl(addr, src2, 2);
+            } else {
+                assert(!"bad format");
+            }
+
+            tcg_gen_add_tl(addr, src1, addr);
+        } break;
+    }
+
+    /*  memory read         */
+    switch (ctx->opt.zz) {
+        case 0x00: {
+            tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_UL);
+        } break;
+
+        case 0x01: {
+            if (ctx->opt.x) {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_SB);
+            } else {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_UB);
+            }
+        } break;
+
+        case 0x02: {
+            if (ctx->opt.x) {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_SW);
+            } else {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_UW);
+            }
+        } break;
+
+        case 0x03: {
+            assert(!"reserved");
+        } break;
+    }
+
+    /*  address write back      */
+    if (ctx->opt.aa == 0x01 || ctx->opt.aa == 0x02) {
+        tcg_gen_add_tl(src1, src1, src2);
+    }
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+    LDB
+*/
+int arc_gen_LDB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 1;    /*  byte                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_LD(ctx, dest, src1, src2);
+}
+
+/*
+    LDW
+*/
+int arc_gen_LDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 2;    /*  word                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_LD(ctx, dest, src1, src2);
+}
+
+/*
+    ST
+*/
+int arc_gen_ST(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv src3)
+{
+    TCGv addr = tcg_temp_new_i32();
+
+    /*  address         */
+    switch (ctx->opt.aa) {
+        case 0x00: {
+            tcg_gen_add_tl(addr, src2, src3);
+        } break;
+
+        case 0x01: {
+            tcg_gen_add_tl(addr, src2, src3);
+        } break;
+
+        case 0x02: {
+            tcg_gen_mov_tl(addr, src2);
+        } break;
+
+        case 0x03: {
+            if (ctx->opt.zz == 0x02) {
+                tcg_gen_shli_tl(addr, src3, 1);
+            } else if (ctx->opt.zz == 0x00) {
+                tcg_gen_shli_tl(addr, src3, 2);
+            } else {
+                assert(!"bad format");
+            }
+
+            tcg_gen_add_tl(addr, src2, addr);
+        } break;
+    }
+
+    /*  write               */
+    switch (ctx->opt.zz) {
+        case 0x00: {
+            tcg_gen_qemu_st_tl(src1, addr, ctx->memidx, MO_UL);
+        } break;
+
+        case 0x01: {
+            tcg_gen_qemu_st_tl(src1, addr, ctx->memidx, MO_UB);
+        } break;
+
+        case 0x02: {
+            tcg_gen_qemu_st_tl(src1, addr, ctx->memidx, MO_UW);
+        } break;
+
+        case 0x03: {
+            assert(!"reserved");
+        } break;
+    }
+
+    /*  address write back  */
+    if (ctx->opt.aa == 0x01 || ctx->opt.aa == 0x02) {
+        tcg_gen_add_tl(src2, src2, src3);
+    }
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+/*
+    STB
+*/
+int arc_gen_STB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 1;    /*  byte                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_ST(ctx, dest, src1, src2);
+}
+
+/*
+    STW
+*/
+int arc_gen_STW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 2;    /*  word                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_ST(ctx, dest, src1, src2);
+}
+
+/*
+    PREFETCH
+*/
+int arc_gen_PREFETCH(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    arc_gen_LD(ctx, temp, src1, src2);
+
+    tcg_temp_free_i32(temp);
+
+    return BS_NONE;
+}
+
+/*
+    SYNC
+*/
+int arc_gen_SYNC(DisasCtxt *ctx)
+{
+    /*  nothing to do*/
+
+    return BS_NONE;
+}
target-arc/translate-inst.h +10 -0
index 325f708..0038645 100644
@@ -51,3 +51,13 @@ int arc_gen_LSRm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ROR(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_RORm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_EX(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_LD(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_LDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_LDB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ST(DisasCtxt *c, TCGv src1, TCGv src2, TCGv src3);
+int arc_gen_STW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_STB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_PREFETCH(DisasCtxt *c, TCGv src1, TCGv src2);
+int arc_gen_SYNC(DisasCtxt *c);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#13 lore raw

Re: [Qemu-devel] [PATCH RFC v1 06/29] target-arc: EX, LD, ST, SYNC, PREFETCH

Quoted 17 lines · Michael Rolnik
---
 target-arc/translate-inst.c | 230 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  10 ++
 2 files changed, 240 insertions(+)
target-arc/translate-inst.c +3 -0
index 2032823..ac13c86 100644
@@ -664,3 +664,233 @@ int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    EX
+*/

target-arc/translate-inst.c int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2) · line 679

Quoted 10 lines
target-arc/translate-inst.c +10 -0
+int arc_gen_EX(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    tcg_gen_mov_tl(temp, dest);
+
+    tcg_gen_qemu_ld_tl(dest, src1, ctx->memidx, MO_UL);
+    tcg_gen_qemu_st_tl(temp, src1, ctx->memidx, MO_UL);
+
+    tcg_temp_free_i32(temp);

You need to load into temp and store directly from dest. Otherwise you incorrectly clobber dest when the page is read-only.

target-arc/translate-inst.c int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2) · line 692

Quoted 6 lines
target-arc/translate-inst.c +6 -0
+int arc_gen_LD(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv addr = tcg_temp_new_i32();
+
+    /*  address             */
+    switch (ctx->opt.aa) {

You should have a common subroutine for computing addresses. And probably for implementing all loads and all stores. Use TCGMemOp to distinguish the cases.

target-arc/translate-inst.c int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2) · line 881

Quoted 5 lines
target-arc/translate-inst.c +5 -0
+int arc_gen_PREFETCH(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    arc_gen_LD(ctx, temp, src1, src2);

A prefetch should be implemented as a NOP. Otherwise you'll generate exceptions when you shouldn't.

r~

#14 lore raw

RFC PATCH 7/29 target-arc: MAX, MIN

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 29 +++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  3 +++
 2 files changed, 32 insertions(+)
target-arc/translate-inst.c +29 -0
index ac13c86..5404f35 100644
@@ -894,3 +894,32 @@ int arc_gen_SYNC(DisasCtxt *ctx)
 
     return BS_NONE;
 }
+
+/*
+    MAX
+*/
+int arc_gen_MAX(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    if (ctx->opt.f) {
+        arc_gen_CMP(ctx, src1, src2);
+    }
+
+    tcg_gen_movcond_tl(TCG_COND_GEU, dest, src1, src2, src1, src2);
+
+    return  BS_NONE;
+}
+
+/*
+    MIN
+*/
+int arc_gen_MIN(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    if (ctx->opt.f) {
+        arc_gen_CMP(ctx, src1, src2);
+    }
+
+    tcg_gen_movcond_tl(TCG_COND_GEU, dest, src1, src2, src2, src1);
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +3 -0
index 0038645..0dc7f4c 100644
@@ -61,3 +61,6 @@ int arc_gen_STB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_PREFETCH(DisasCtxt *c, TCGv src1, TCGv src2);
 int arc_gen_SYNC(DisasCtxt *c);
 
+int arc_gen_MAX(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MIN(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#15 lore raw

Re: [Qemu-devel] [PATCH RFC v1 07/29] target-arc: MAX, MIN

target-arc/translate-inst.c int arc_gen_SYNC(DisasCtxt *ctx) · line 907

Quoted 7 lines · Michael Rolnik
target-arc/translate-inst.c +7 -0
+int arc_gen_MAX(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    if (ctx->opt.f) {
+        arc_gen_CMP(ctx, src1, src2);
+    }
+
+    tcg_gen_movcond_tl(TCG_COND_GEU, dest, src1, src2, src1, src2);

These are supposed to be signed comparisons.

r~

#16 lore raw

RFC PATCH 8/29 target-arc: MOV, EXT, SEX, SWAP

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 156 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   7 ++
 2 files changed, 163 insertions(+)
target-arc/translate-inst.c +156 -0
index 5404f35..4d756a9 100644
@@ -923,3 +923,159 @@ int arc_gen_MIN(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    MOV
+*/
+int arc_gen_MOV(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_mov_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    EXTB
+*/
+int arc_gen_EXTB(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext8u_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return BS_NONE;
+}
+
+/*
+    EXTW
+*/
+int arc_gen_EXTW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext16u_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return BS_NONE;
+}
+
+/*
+    SEXB
+*/
+int arc_gen_SEXB(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext8s_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SEXW
+*/
+int arc_gen_SEXW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext16s_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SWAP
+*/
+int arc_gen_SWAP(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_rotli_tl(rslt, src1, 16);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +7 -0
index 0dc7f4c..916d94e 100644
@@ -64,3 +64,10 @@ int arc_gen_SYNC(DisasCtxt *c);
 int arc_gen_MAX(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MIN(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_MOV(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_EXTB(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_EXTW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SEXB(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SEXW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SWAP(DisasCtxt *c, TCGv dest, TCGv src1);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#17 lore raw

RFC PATCH 9/29 target-arc: NEG, ABS, NOT

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  4 +++
 2 files changed, 72 insertions(+)
target-arc/translate-inst.c +68 -0
index 4d756a9..7f7e951 100644
@@ -1079,3 +1079,71 @@ int arc_gen_SWAP(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return  BS_NONE;
 }
 
+/*
+    ABS
+*/
+int arc_gen_ABS(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_neg_i32(t0, src1);
+    tcg_gen_movcond_tl(TCG_COND_GEU, rslt, src1, ctx->msb32, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Cf, src1, 31);
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Nf, src1, ctx->msb32);
+        tcg_gen_mov_tl(cpu_Vf, cpu_Nf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    NEG
+*/
+int arc_gen_NEG(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    arc_gen_SUB(ctx, dest, ctx->zero, src1);
+
+    return  BS_NONE;
+}
+
+/*
+    NOT
+*/
+int arc_gen_NOT(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_not_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +4 -0
index 916d94e..36ce19b 100644
@@ -71,3 +71,7 @@ int arc_gen_SEXB(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_SEXW(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_SWAP(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_NEG(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ABS(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NOT(DisasCtxt *c, TCGv dest, TCGv src1);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#18 lore raw

Re: [Qemu-devel] [PATCH RFC v1 09/29] target-arc: NEG, ABS, NOT

Quoted 1 line · Michael Rolnik

+ tcg_gen_movcond_tl(TCG_COND_GEU, rslt, src1, ctx->msb32, src1, t0);

Better as a signed comparison vs zero.

r~

#19 lore raw

RFC PATCH 10/29 target-arc: POP, PUSH

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 22 ++++++++++++++++++++++
 target-arc/translate-inst.h |  3 +++
 2 files changed, 25 insertions(+)
target-arc/translate-inst.c +22 -0
index 7f7e951..2a579f8 100644
@@ -1147,3 +1147,25 @@ int arc_gen_NOT(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return  BS_NONE;
 }
 
+/*
+    POP
+*/
+int arc_gen_POP(DisasCtxt *ctx, TCGv src1)
+{
+    tcg_gen_qemu_ld_tl(src1, cpu_sp, ctx->memidx, MO_UL);
+    tcg_gen_addi_tl(cpu_sp, cpu_sp, 4);
+
+    return BS_NONE;
+}
+
+/*
+    PUSH
+*/
+int arc_gen_PUSH(DisasCtxt *ctx, TCGv src1)
+{
+    tcg_gen_subi_tl(cpu_sp, cpu_sp, 4);
+    tcg_gen_qemu_st_tl(src1, cpu_sp, ctx->memidx, MO_UL);
+
+    return BS_NONE;
+}
+
target-arc/translate-inst.h +3 -0
index 36ce19b..d088a43 100644
@@ -75,3 +75,6 @@ int arc_gen_NEG(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_ABS(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NOT(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_POP(DisasCtxt *c, TCGv src1);
+int arc_gen_PUSH(DisasCtxt *c, TCGv src1);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#20 lore raw

Re: [Qemu-devel] [PATCH RFC v1 10/29] target-arc: POP, PUSH

target-arc/translate-inst.c int arc_gen_NOT(DisasCtxt *ctx, TCGv dest, TCGv src1) · line 1167

Quoted 2 lines · Michael Rolnik
target-arc/translate-inst.c +2 -0
+    tcg_gen_subi_tl(cpu_sp, cpu_sp, 4);
+    tcg_gen_qemu_st_tl(src1, cpu_sp, ctx->memidx, MO_UL);

You need to delay the write to the stack pointer until after the store, otherwise sp will have the incorrect contents if the page is not writable.

r~

#21 lore raw

RFC PATCH 11/29 target-arc: BCLR, BMSK, BSET, BTST, BXOR

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 139 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   6 ++
 2 files changed, 145 insertions(+)
target-arc/translate-inst.c +139 -0
index 2a579f8..91b7037 100644
@@ -1169,3 +1169,142 @@ int arc_gen_PUSH(DisasCtxt *ctx, TCGv src1)
     return BS_NONE;
 }
 
+/*
+    BCLR
+*/
+int arc_gen_BCLR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_andc_tl(rslt, src1, rslt);  /*  rslt = src1 & ~(1 << src2)      */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    BMSK
+*/
+int arc_gen_BMSK(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv mask = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(mask, src2, 0x3f);
+    tcg_gen_add_tl(mask, mask, ctx->one);
+    tcg_gen_shr_tl(mask, ctx->one, mask);
+    tcg_gen_sub_tl(mask, mask, ctx->one);
+
+    tcg_gen_and_tl(rslt, src1, mask);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free_i32(mask);
+
+    return  BS_NONE;
+}
+
+/*
+    BSET
+*/
+int arc_gen_BSET(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_or_tl(rslt, src1, rslt);    /*  rslt = src1 | (1 << src2)   */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    BTST
+*/
+int arc_gen_BTST(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv rslt = tcg_temp_new_i32();
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_and_tl(rslt, src1, rslt);       /*  rslt = src1 & (1 << src2)   */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    tcg_temp_free_i32(rslt);
+
+    return  BS_NONE;
+}
+
+/*
+    BXOR
+*/
+int arc_gen_BXOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_xor_tl(rslt, src1, rslt);       /*  rslt = src1 ^ (1 << src2)   */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +6 -0
index d088a43..88cae1c 100644
@@ -78,3 +78,9 @@ int arc_gen_NOT(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_POP(DisasCtxt *c, TCGv src1);
 int arc_gen_PUSH(DisasCtxt *c, TCGv src1);
 
+int arc_gen_BCLR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BMSK(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BSET(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BTST(DisasCtxt *c, TCGv src1, TCGv src2);
+int arc_gen_BXOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#22 lore raw

Re: [Qemu-devel] [PATCH RFC v1 11/29] target-arc: BCLR, BMSK, BSET, BTST, BXOR

target-arc/translate-inst.c int arc_gen_PUSH(DisasCtxt *ctx, TCGv src1) · line 1183

Quoted 9 lines · Michael Rolnik
target-arc/translate-inst.c +9 -0
+int arc_gen_BCLR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);

0x1f, in all of the functions.

target-arc/translate-inst.c int arc_gen_PUSH(DisasCtxt *ctx, TCGv src1) · line 1215

Quoted 3 lines
target-arc/translate-inst.c +3 -0
+    tcg_gen_add_tl(mask, mask, ctx->one);
+    tcg_gen_shr_tl(mask, ctx->one, mask);
+    tcg_gen_sub_tl(mask, mask, ctx->one);

I know this is the description in the manual, but this will produce a shift of 32 with an input of 31, which is illegal in tcg.

You need to use

mask = -1u >> (src2 ^ 31)

r~

#23 lore raw

RFC PATCH 12/29 target-arc: RLC, RRC

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  2 ++
 2 files changed, 59 insertions(+)
target-arc/translate-inst.c +57 -0
index 91b7037..a0d601e 100644
@@ -1308,3 +1308,60 @@ int arc_gen_BXOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    RLC
+*/
+int arc_gen_RLC(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_shli_tl(rslt, src1, 1);
+    tcg_gen_or_tl(rslt, rslt, cpu_Cf);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_shri_tl(cpu_Cf, src1, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    RRC
+*/
+int arc_gen_RRC(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src1, 0xfffffffe);
+    tcg_gen_or_tl(rslt, rslt, cpu_Cf);
+    tcg_gen_rotri_tl(rslt, rslt, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_andi_tl(cpu_Cf, src1, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +2 -0
index 88cae1c..5e1c52d 100644
@@ -84,3 +84,5 @@ int arc_gen_BSET(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_BTST(DisasCtxt *c, TCGv src1, TCGv src2);
 int arc_gen_BXOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_RRC(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_RLC(DisasCtxt *c, TCGv dest, TCGv src1);
Signature · 1 line
2.4.9 (Apple Git-60)
#24 lore raw

RFC PATCH 13/29 target-arc: NORM, NORMW

In reply to Michael Rolnik
---
 target-arc/Makefile.objs    |  1 +
 target-arc/helper.h         |  3 ++
 target-arc/op_helper.c      | 91 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.c | 52 ++++++++++++++++++++++++++
 target-arc/translate-inst.h |  4 ++
 5 files changed, 151 insertions(+)
 create mode 100644 target-arc/op_helper.c
target-arc/Makefile.objs +1 -0
index 6fdb000..cd3eebc 100644
@@ -21,6 +21,7 @@
 obj-y   += translate.o
 obj-y   += helper.o
 obj-y   += cpu.o
+obj-y   += op_helper.o
 obj-y   += translate-inst.o
 obj-y   += gdbstub.o
 obj-y   += decode.o
target-arc/helper.h +3 -0
index 69c91fb..d480052 100644
@@ -19,3 +19,6 @@
  */
 
 DEF_HELPER_1(debug, void, env)
+DEF_HELPER_2(norm, i32, env, i32)
+DEF_HELPER_2(normw, i32, env, i32)
+
target-arc/op_helper.c new file +91 -0

91 lines not on this page · raw message

target-arc/translate-inst.c +52 -0

55 lines not on this page · raw message

target-arc/translate-inst.h +4 -0
index 5e1c52d..811c914 100644
@@ -86,3 +86,7 @@ int arc_gen_BXOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
 int arc_gen_RRC(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_RLC(DisasCtxt *c, TCGv dest, TCGv src1);
+
+int arc_gen_NORMW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NORM(DisasCtxt *c, TCGv dest, TCGv src1);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#25 lore raw

Re: [Qemu-devel] [PATCH RFC v1 13/29] target-arc: NORM, NORMW

target-arc/op_helper.c line 75

Quoted 10 lines · Michael Rolnik
target-arc/op_helper.c new file +10 -0
+target_ulong helper_norm(CPUARCState *env, uint32_t src1)
+{
+    if (src1 == 0x00000000 || src1 == 0xffffffff) {
+        return 31;
+    } else {
+        if ((src1 & 0x80000000) == 0x80000000) {
+            src1 = ~src1;
+        }
+        return clz32(src1) - 1;
+    }

This is clrsb32.

target-arc/op_helper.c line 89

Quoted 12 lines
target-arc/op_helper.c new file +12 -0
+target_ulong helper_normw(CPUARCState *env, uint32_t src1)
+{
+    src1 &= 0xffff;
+
+    if (src1 == 0x0000 || src1 == 0xffff) {
+        return 15;
+    } else {
+        if ((src1 & 0x8000) == 0x8000) {
+            src1 = ~src1 & 0xffff;
+        }
+        return clz32(src1) - 17;
+    }

clrsb32((int16_t)src1) - 16

r~

#26 lore raw

RFC PATCH 14/29 target-arc: MPY, MPYH, MPYHU, MPYU

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 129 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   5 ++
 2 files changed, 134 insertions(+)
target-arc/translate-inst.c +129 -0
index 00785bf..92c75ac 100644
@@ -1417,3 +1417,132 @@ int arc_gen_NORM(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return BS_NONE;
 }
 
+/*
+    MPY
+*/
+int arc_gen_MPY(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64 rslt = tcg_temp_new_i64();
+    TCGv_i64 srcA = tcg_temp_new_i64();
+    TCGv_i64 srcB = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(srcA, src1);
+    tcg_gen_ext_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        TCGv_i64 temp = tcg_temp_new_i64();
+
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+
+        tcg_gen_trunc_i64_tl(cpu_Nf, rslt);
+        tcg_gen_shri_tl(cpu_Nf, cpu_Nf, 31);
+
+        tcg_gen_ext_i32_i64(temp, dest);
+        tcg_gen_setcond_i64(TCG_COND_NE, temp, temp, rslt);
+        tcg_gen_trunc_i64_tl(cpu_Cf, temp);
+
+        tcg_temp_free_i64(temp);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MPYH
+*/
+int arc_gen_MPYH(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(srcA, src1);
+    tcg_gen_ext_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_sari_i64(rslt, rslt, 32);
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, dest, 31);
+        tcg_gen_movi_tl(cpu_Vf, 0);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MPYHU
+*/
+int arc_gen_MPYHU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(srcA, src1);
+    tcg_gen_extu_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_shri_i64(rslt, rslt, 32);
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+        tcg_gen_movi_tl(cpu_Vf, 0);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MPYU
+*/
+int arc_gen_MPYU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(srcA, src1);
+    tcg_gen_extu_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+        tcg_gen_shri_i64(rslt, rslt, 32);
+        tcg_gen_trunc_i64_tl(cpu_Vf, rslt);
+        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_Vf, cpu_Vf, 0);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
target-arc/translate-inst.h +5 -0
index 811c914..084c282 100644
@@ -90,3 +90,8 @@ int arc_gen_RLC(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NORMW(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NORM(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_MPY(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MPYH(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MPYHU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MPYU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#27 lore raw

Re: [Qemu-devel] [PATCH RFC v1 14/29] target-arc: MPY, MPYH, MPYHU, MPYU

Quoted 11 lines · Michael Rolnik
target-arc/translate-inst.c +11 -0
+    tcg_gen_ext_i32_i64(srcA, src1);
+    tcg_gen_ext_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        TCGv_i64 temp = tcg_temp_new_i64();
+
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);

target-arc/translate-inst.c int arc_gen_NORM(DisasCtxt *ctx, TCGv dest, TCGv src1) · line 1449

Quoted 10 lines
target-arc/translate-inst.c +10 -0
+
+        tcg_gen_trunc_i64_tl(cpu_Nf, rslt);
+        tcg_gen_shri_tl(cpu_Nf, cpu_Nf, 31);
+
+        tcg_gen_ext_i32_i64(temp, dest);
+        tcg_gen_setcond_i64(TCG_COND_NE, temp, temp, rslt);
+        tcg_gen_trunc_i64_tl(cpu_Cf, temp);
+
+        tcg_temp_free_i64(temp);
+    }

It's probably easier to do this with tcg_gen_muls2_tl.

r~

#28 lore raw

RFC PATCH 15/29 target-arc: MUL64, MULU64, DIVAW

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 ++
 2 files changed, 109 insertions(+)
target-arc/translate-inst.c +105 -0
index 92c75ac..c3795fe 100644
@@ -1546,3 +1546,108 @@ int arc_gen_MPYU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return BS_NONE;
 }
 
+/*
+    DIVAW
+*/
+int arc_gen_DIVAW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+    TCGv rslt = dest;
+    TCGv temp = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    /*
+        if (src1 == 0)
+            dest = 0
+        else
+        {
+            src1_temp = src1 << 1
+            if (src1_temp >= src2)
+                dest = ((src1_temp - src2) | 0x0000_0001)
+            else
+                dest = src1_temp
+        }
+    */
+
+    tcg_gen_brcondi_tl(TCG_COND_NE, src1, 0, label_else);
+
+    tcg_gen_xor_tl(rslt, rslt, rslt);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_else);
+    tcg_gen_shli_tl(temp, src1, 1);
+    tcg_gen_mov_tl(rslt, temp);
+    tcg_gen_brcond_tl(TCG_COND_LT, temp, src2, label_done);
+        tcg_gen_sub_tl(rslt, temp, src2);
+        tcg_gen_ori_tl(rslt, rslt, 1);
+
+gen_set_label(label_done);
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free_i32(temp);
+
+    return  BS_NONE;
+}
+
+/*
+    MUL64
+*/
+int arc_gen_MUL64(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(srcA, src1);
+    tcg_gen_ext_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(cpu_mlo, rslt);
+    tcg_gen_sari_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mmi, rslt);
+    tcg_gen_sari_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mhi, rslt);
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MULU64
+*/
+int arc_gen_MULU64(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(srcA, src1);
+    tcg_gen_extu_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(cpu_mlo, rslt);
+    tcg_gen_shri_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mmi, rslt);
+    tcg_gen_shri_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mhi, rslt);
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
target-arc/translate-inst.h +4 -0
index 084c282..e017237 100644
@@ -95,3 +95,7 @@ int arc_gen_MPYH(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MPYHU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MPYU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_DIVAW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MUL64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MULU64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#29 lore raw

Re: [Qemu-devel] [PATCH RFC v1 15/29] target-arc: MUL64, MULU64, DIVAW

Quoted 30 lines · Michael Rolnik
---
 target-arc/translate-inst.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 ++
 2 files changed, 109 insertions(+)
target-arc/translate-inst.c +16 -0
index 92c75ac..c3795fe 100644
@@ -1546,3 +1546,108 @@ int arc_gen_MPYU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return BS_NONE;
 }
 
+/*
+    DIVAW
+*/
+int arc_gen_DIVAW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+    TCGv rslt = dest;
+    TCGv temp = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    /*
+        if (src1 == 0)

target-arc/translate-inst.c int arc_gen_MPYU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2) · line 1574

Quoted 10 lines
target-arc/translate-inst.c +10 -0
+            dest = 0
+        else
+        {
+            src1_temp = src1 << 1
+            if (src1_temp >= src2)
+                dest = ((src1_temp - src2) | 0x0000_0001)
+            else
+                dest = src1_temp
+        }
+    */

Probably better with two movcond instead of branches.

r~

#30 lore raw

RFC PATCH 16/29 target-arc: BBIT0, BBIT1, BR

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 136 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  35 ++++++++++++
 2 files changed, 171 insertions(+)
target-arc/translate-inst.c +136 -0
index c3795fe..8288edd 100644
@@ -104,6 +104,42 @@ static void gen_sub_Vf(TCGv dest, TCGv src1, TCGv src2)
     tcg_temp_free_i32(t1);
 }
 
+static void arc_gen_exec_delayslot(DisasCtxt *ctx)
+{
+    if (ctx->opt.limm == 0) {
+        uint32_t cpc = ctx->cpc;
+        uint32_t npc = ctx->npc;
+        uint32_t dpc = ctx->dpc;
+        uint32_t pcl = ctx->pcl;
+        options_t opt = ctx->opt;
+        int bstate = ctx->bstate;
+
+        ctx->cpc = ctx->npc;
+        ctx->pcl = ctx->cpc & 0xfffffffc;
+
+        ++ctx->ds;
+
+        /* TODO: check for illegal instruction sequence */
+
+        memset(&ctx->opt, 0, sizeof(ctx->opt));
+        arc_decode(ctx);
+
+        --ctx->ds;
+
+        ctx->cpc = cpc;
+        ctx->npc = npc;
+        ctx->dpc = dpc;
+        ctx->pcl = pcl;
+        ctx->opt = opt;
+        ctx->bstate = bstate;
+    }
+}
+
+static void arc_gen_kill_delayslot(DisasCtxt *ctx)
+{
+    /*  nothing to do   */
+}
+
 /*
     ADC
 */
@@ -1651,3 +1687,103 @@ int arc_gen_MULU64(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return BS_NONE;
 }
 
+/*
+    BBIT0
+*/
+int arc_gen_BBIT0(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv rd)
+{
+    TCGv mask = tcg_temp_new_i32();
+    TCGv cond = tcg_temp_new_i32();
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_jump = gen_new_label();
+
+    tcg_gen_andi_tl(mask, src2, 0x31);
+    tcg_gen_shr_tl(mask, ctx->one, mask);
+    tcg_gen_andc_tl(cond, src1, mask);      /*  cond = src1 & ~(1 << src2)   */
+
+    tcg_gen_brcond_tl(TCG_COND_EQ, cond, ctx->zero, label_jump);
+
+    tcg_gen_movi_tl(cpu_pc, ctx->npc);
+    arc_gen_exec_delayslot(ctx);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_jump);
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+
+gen_set_label(label_done);
+    tcg_temp_free_i32(cond);
+    tcg_temp_free_i32(mask);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    BBIT1
+*/
+int arc_gen_BBIT1(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv rd)
+{
+    TCGv mask = tcg_temp_new_i32();
+    TCGv cond = tcg_temp_new_i32();
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_jump = gen_new_label();
+
+    tcg_gen_andi_tl(mask, src2, 0x31);
+    tcg_gen_shr_tl(mask, ctx->one, mask);
+    tcg_gen_and_tl(cond, src1, mask);       /*  cond = src1 & (1 << src2)   */
+
+    tcg_gen_brcond_tl(TCG_COND_EQ, cond, ctx->zero, label_jump);
+
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_jump);
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+
+gen_set_label(label_done);
+    tcg_temp_free_i32(cond);
+    tcg_temp_free_i32(mask);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    BR
+*/
+int arc_gen_BR(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv Rd, TCGCond cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_jump = gen_new_label();
+
+    tcg_gen_brcond_tl(cond, src1, src2, label_jump);
+
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_jump);
+    tcg_gen_shli_tl(cpu_pc, Rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
target-arc/translate-inst.h +35 -0
index e017237..c78ed24 100644
@@ -22,6 +22,37 @@
 #include "qemu/bitops.h"
 #include "tcg/tcg.h"
 
+typedef enum ARC_COND {
+    ARC_COND_AL      = 0x00,
+    ARC_COND_RA      = 0x00,
+    ARC_COND_EQ      = 0x01,
+    ARC_COND_Z       = 0x01,
+    ARC_COND_NE      = 0x02,
+    ARC_COND_NZ      = 0x02,
+    ARC_COND_PL      = 0x03,
+    ARC_COND_P       = 0x03,
+    ARC_COND_MI      = 0x04,
+    ARC_COND_N       = 0x04,
+    ARC_COND_CS      = 0x05,
+    ARC_COND_C       = 0x05,
+    ARC_COND_LO      = 0x05,
+    ARC_COND_CC      = 0x06,
+    ARC_COND_NC      = 0x06,
+    ARC_COND_HS      = 0x06,
+    ARC_COND_VS      = 0x07,
+    ARC_COND_V       = 0x07,
+    ARC_COND_VC      = 0x08,
+    ARC_COND_NV      = 0x08,
+    ARC_COND_GT      = 0x09,
+    ARC_COND_GE      = 0x0a,
+    ARC_COND_LT      = 0x0b,
+    ARC_COND_LE      = 0x0c,
+    ARC_COND_HI      = 0x0d,
+    ARC_COND_LS      = 0x0e,
+    ARC_COND_PNZ     = 0x0f,
+} ARC_COND;
+
+
 int arc_gen_ADC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
@@ -99,3 +130,7 @@ int arc_gen_DIVAW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MUL64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MULU64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_BBIT0(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
+int arc_gen_BBIT1(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
+int arc_gen_BR(DisasCtxt *c, TCGv src1, TCGv src2, TCGv Rd, TCGCond cond);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#31 lore raw

Re: [Qemu-devel] [PATCH RFC v1 16/29] target-arc: BBIT0, BBIT1, BR

Quoted 20 lines · Michael Rolnik
target-arc/translate-inst.c +20 -0
+static void arc_gen_exec_delayslot(DisasCtxt *ctx)
+{
+    if (ctx->opt.limm == 0) {
+        uint32_t cpc = ctx->cpc;
+        uint32_t npc = ctx->npc;
+        uint32_t dpc = ctx->dpc;
+        uint32_t pcl = ctx->pcl;
+        options_t opt = ctx->opt;
+        int bstate = ctx->bstate;
+
+        ctx->cpc = ctx->npc;
+        ctx->pcl = ctx->cpc & 0xfffffffc;
+
+        ++ctx->ds;
+
+        /* TODO: check for illegal instruction sequence */
+
+        memset(&ctx->opt, 0, sizeof(ctx->opt));
+        arc_decode(ctx);
+

target-arc/translate-inst.c static void gen_sub_Vf(TCGv dest, TCGv src1, TCGv src2) · line 136

Quoted 10 lines
target-arc/translate-inst.c +10 -0
+        --ctx->ds;
+
+        ctx->cpc = cpc;
+        ctx->npc = npc;
+        ctx->dpc = dpc;
+        ctx->pcl = pcl;
+        ctx->opt = opt;
+        ctx->bstate = bstate;
+    }
+}

It might be easier to put the delay slot into a TB by itself. That will avoid having to duplicate the decoding here.

r~

#32 lore raw

RFC PATCH 17/29 target-arc: B, BL

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 189 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 +
 2 files changed, 193 insertions(+)
target-arc/translate-inst.c +189 -0
index 8288edd..ed2ced0 100644
@@ -140,6 +140,137 @@ static void arc_gen_kill_delayslot(DisasCtxt *ctx)
     /*  nothing to do   */
 }
 
+#define ARC_COND_IF_1(flag, label) \
+                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_ ## flag ## f, 0, label)
+#define ARC_COND_IF_0(flag, label) \
+                    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_ ## flag ## f, 0, label)
+
+void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip)
+{
+    TCGLabel *label_cont = gen_new_label();
+
+    switch (cond) {
+        /*
+            Always
+        */
+        case    ARC_COND_AL: {
+        } break;
+
+        /*
+            Zero
+        */
+        case    ARC_COND_Z: {
+            ARC_COND_IF_0(Z, label_skip);
+        } break;
+
+        /*
+            Non-Zero
+        */
+        case    ARC_COND_NZ: {
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+
+        /*
+            Positive
+        */
+        case    ARC_COND_P: {
+            tcg_gen_brcondi_tl(TCG_COND_LT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Negative
+        */
+        case    ARC_COND_N: {
+            tcg_gen_brcondi_tl(TCG_COND_GE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Carry set, lower than (unsigned)
+        */
+        case    ARC_COND_C: {
+            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Carry clear, higher or same (unsigned)
+        */
+        case    ARC_COND_CC: {
+            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Over-flow set
+        */
+        case    ARC_COND_VS: {
+            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Over-flow clear
+        */
+        case    ARC_COND_VC: {
+            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Greater than (signed)
+        */
+        case    ARC_COND_GT: {
+            tcg_gen_brcondi_tl(TCG_COND_LE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Greater than or equal to (signed)
+        */
+        case    ARC_COND_GE: {
+            tcg_gen_brcondi_tl(TCG_COND_LT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Less than (signed)
+        */
+        case    ARC_COND_LT: {
+            tcg_gen_brcondi_tl(TCG_COND_GE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Less than or equal to (signed)
+        */
+        case    ARC_COND_LE: {
+            tcg_gen_brcondi_tl(TCG_COND_GT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Higher than (unsigned)
+            !C and !Z
+        */
+        case    ARC_COND_HI: {
+            ARC_COND_IF_1(C, label_skip);
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+
+        /*
+            Lower than
+            C or Z
+        */
+        case    ARC_COND_LS: {
+            ARC_COND_IF_1(C, label_cont);
+            ARC_COND_IF_0(Z, label_skip);
+        } break;
+
+        /*
+            Positive non-zero
+            !N and !Z
+        */
+        case    ARC_COND_PNZ: {
+            ARC_COND_IF_1(N, label_skip);
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+    }
+
+    gen_set_label(label_cont);
+}
+
 /*
     ADC
 */
@@ -1787,3 +1918,61 @@ gen_set_label(label_done);
     return  BS_BRANCH_DS;
 }
 
+/*
+    B
+*/
+int arc_gen_B(DisasCtxt *ctx, TCGv rd, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    BL
+*/
+int arc_gen_BL(DisasCtxt *ctx, TCGv Rd, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_shli_tl(cpu_pc, Rd, 2);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        tcg_gen_movi_tl(cpu_blink, ctx->npc);
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        tcg_gen_movi_tl(cpu_blink, ctx->dpc);
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
target-arc/translate-inst.h +4 -0
index c78ed24..065570e 100644
@@ -134,3 +134,7 @@ int arc_gen_BBIT0(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
 int arc_gen_BBIT1(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
 int arc_gen_BR(DisasCtxt *c, TCGv src1, TCGv src2, TCGv Rd, TCGCond cond);
 
+void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip);
+int arc_gen_B(DisasCtxt *c, TCGv rd, ARC_COND cond);
+int arc_gen_BL(DisasCtxt *c, TCGv Rd, ARC_COND cond);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#33 lore raw

Re: [Qemu-devel] [PATCH RFC v1 17/29] target-arc: B, BL

target-arc/translate-inst.c static void arc_gen_kill_delayslot(DisasCtxt *ctx) · line 250

Quoted 4 lines · Michael Rolnik
target-arc/translate-inst.c +4 -0
+        case    ARC_COND_HI: {
+            ARC_COND_IF_1(C, label_skip);
+            ARC_COND_IF_1(Z, label_skip);
+        } break;

Why aren't you using AND / OR to combine these conditions?

r~

#34 lore raw

RFC PATCH 18/29 target-arc: J, JL

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  3 ++
 2 files changed, 96 insertions(+)
target-arc/translate-inst.c +93 -0
index ed2ced0..fd49a16 100644
@@ -1976,3 +1976,96 @@ gen_set_label(label_done);
     return  BS_BRANCH_DS;
 }
 
+/*
+    J
+*/
+int arc_gen_J(DisasCtxt *ctx, TCGv src1, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    if (ctx->opt.f) {
+        if (TCGV_EQUAL(src1, cpu_ilink1)) {
+            tcg_gen_mov_tl(cpu_Lf, cpu_l1_Lf);
+            tcg_gen_mov_tl(cpu_Zf, cpu_l1_Zf);
+            tcg_gen_mov_tl(cpu_Nf, cpu_l1_Nf);
+            tcg_gen_mov_tl(cpu_Cf, cpu_l1_Cf);
+            tcg_gen_mov_tl(cpu_Vf, cpu_l1_Vf);
+            tcg_gen_mov_tl(cpu_Uf, cpu_l1_Uf);
+
+            tcg_gen_mov_tl(cpu_DEf, cpu_l1_DEf);
+            tcg_gen_mov_tl(cpu_AEf, cpu_l1_AEf);
+            tcg_gen_mov_tl(cpu_A2f, cpu_l1_A2f);
+            tcg_gen_mov_tl(cpu_A1f, cpu_l1_A1f);
+            tcg_gen_mov_tl(cpu_E2f, cpu_l1_E2f);
+            tcg_gen_mov_tl(cpu_E1f, cpu_l1_E1f);
+
+            tcg_gen_mov_tl(cpu_bta, cpu_bta_l1);
+        }
+        if (TCGV_EQUAL(src1, cpu_ilink2)) {
+            tcg_gen_mov_tl(cpu_Lf, cpu_l2_Lf);
+            tcg_gen_mov_tl(cpu_Zf, cpu_l2_Zf);
+            tcg_gen_mov_tl(cpu_Nf, cpu_l2_Nf);
+            tcg_gen_mov_tl(cpu_Cf, cpu_l2_Cf);
+            tcg_gen_mov_tl(cpu_Vf, cpu_l2_Vf);
+            tcg_gen_mov_tl(cpu_Uf, cpu_l2_Uf);
+
+            tcg_gen_mov_tl(cpu_DEf, cpu_l2_DEf);
+            tcg_gen_mov_tl(cpu_AEf, cpu_l2_AEf);
+            tcg_gen_mov_tl(cpu_A2f, cpu_l2_A2f);
+            tcg_gen_mov_tl(cpu_A1f, cpu_l2_A1f);
+            tcg_gen_mov_tl(cpu_E2f, cpu_l2_E2f);
+            tcg_gen_mov_tl(cpu_E1f, cpu_l2_E1f);
+
+            tcg_gen_mov_tl(cpu_bta, cpu_bta_l2);
+        }
+    }
+
+    tcg_gen_mov_tl(cpu_pc, src1);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    JL
+*/
+int arc_gen_JL(DisasCtxt *ctx, TCGv src1, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_mov_tl(cpu_pc, src1);
+    if (ctx->opt.d == 0) {
+        tcg_gen_movi_tl(cpu_blink, ctx->npc);
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        tcg_gen_movi_tl(cpu_blink, ctx->dpc);
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
target-arc/translate-inst.h +3 -0
index 065570e..7d76707 100644
@@ -138,3 +138,6 @@ void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip);
 int arc_gen_B(DisasCtxt *c, TCGv rd, ARC_COND cond);
 int arc_gen_BL(DisasCtxt *c, TCGv Rd, ARC_COND cond);
 
+int arc_gen_J(DisasCtxt *c, TCGv src1, ARC_COND cond);
+int arc_gen_JL(DisasCtxt *c, TCGv src1, ARC_COND cond);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#35 lore raw

RFC PATCH 19/29 target-arc: LR, SR

In reply to Michael Rolnik
---
 target-arc/helper.h         |   2 +
 target-arc/op_helper.c      | 322 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.c |  26 ++++
 target-arc/translate-inst.h |   3 +
 4 files changed, 353 insertions(+)
target-arc/helper.h +2 -0
index d480052..1d84935 100644
@@ -21,4 +21,6 @@
 DEF_HELPER_1(debug, void, env)
 DEF_HELPER_2(norm, i32, env, i32)
 DEF_HELPER_2(normw, i32, env, i32)
+DEF_HELPER_2(lr, tl, env, i32)
+DEF_HELPER_2(sr, void, i32, i32)
 
target-arc/op_helper.c +322 -0

325 lines not on this page · raw message

target-arc/translate-inst.c +26 -0
index fd49a16..603a0a8 100644
@@ -2069,3 +2069,29 @@ gen_set_label(label_done);
     return  BS_BRANCH_DS;
 }
 
+/*
+    LR
+*/
+int arc_gen_LR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv cpc = tcg_const_local_i32((ctx->cpc + 3) & 0xfffffffc);
+    TCGv npc = tcg_const_local_i32((ctx->npc + 3) & 0xfffffffc);
+
+    gen_helper_lr(dest, cpu_env, src1);
+
+    tcg_temp_free_i32(cpc);
+    tcg_temp_free_i32(npc);
+
+    return BS_NONE;
+}
+
+/*
+    SR
+*/
+int arc_gen_SR(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    gen_helper_sr(src1, src2);
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +3 -0
index 7d76707..74beb33 100644
@@ -141,3 +141,6 @@ int arc_gen_BL(DisasCtxt *c, TCGv Rd, ARC_COND cond);
 int arc_gen_J(DisasCtxt *c, TCGv src1, ARC_COND cond);
 int arc_gen_JL(DisasCtxt *c, TCGv src1, ARC_COND cond);
 
+int arc_gen_LR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SR(DisasCtxt *c, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#36 lore raw

Re: [Qemu-devel] [PATCH RFC v1 19/29] target-arc: LR, SR

target-arc/translate-inst.c gen_set_label(label_done); · line 2078

Quoted 4 lines · Michael Rolnik
target-arc/translate-inst.c +4 -0
+int arc_gen_LR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv cpc = tcg_const_local_i32((ctx->cpc + 3) & 0xfffffffc);
+    TCGv npc = tcg_const_local_i32((ctx->npc + 3) & 0xfffffffc);

No need for _local here.

r~

#37 lore raw

RFC PATCH 20/29 target-arc: ADDS, ADDSDW, SUBS, SUBSDW

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 227 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 +
 2 files changed, 231 insertions(+)
target-arc/translate-inst.c +227 -0
index 603a0a8..d5c739e 100644
@@ -271,6 +271,45 @@ void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip)
     gen_set_label(label_cont);
 }
 
+static void gen_add16_Vf(TCGv v, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /*
+
+    src1 & src2 & ~dest | ~src1 & ~src2 & dest = (src1 ^ dest) & ~(src1 ^ src2)
+
+    */
+    tcg_gen_xor_tl(t1, src1, dest); /*  t1 = src1 ^ dest                    */
+    tcg_gen_xor_tl(t2, src1, src2); /*  t2 = src1 ^ src2                    */
+    tcg_gen_andc_tl(t1, t1, t2);    /*  t1 = (src1 ^ src2) & ~(src1 ^ src2) */
+
+    tcg_gen_shri_tl(v, t1, 15);/*  Vf = t1(15)                         */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+
+static void gen_sub16_Vf(TCGv v, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /*
+        t1 = src1 & ~src2 & ~dest
+           | ~src1 & src2 & dest
+           = (src1 ^ dest) & (src1 ^ dest)*/
+    tcg_gen_xor_tl(t1, src1, dest);
+    tcg_gen_xor_tl(t2, src1, src2);
+    tcg_gen_and_tl(t1, t1, t2);
+    tcg_gen_shri_tl(v, t1, 15);     /*  Vf = t1(15) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
 /*
     ADC
 */
@@ -2095,3 +2134,191 @@ int arc_gen_SR(DisasCtxt *ctx, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    ADDS
+*/
+int arc_gen_ADDS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv sat = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_add_tl(rslt, src1, src2);
+
+    /*
+        src1 & src2 & ~dest | ~src1 & ~src2 & dest
+                            = (src1 ^ dest) & ~(src1 ^ src2)
+    */
+    tcg_gen_xor_tl(t1, src1, rslt); /*  t1 = src1 ^ dest                    */
+    tcg_gen_xor_tl(t2, src1, src2); /*  t2 = src1 ^ src2                    */
+    tcg_gen_andc_tl(t1, t1, t2);    /*  t1 = (src1 ^ src2) & ~(src1 ^ src2) */
+
+    tcg_gen_shri_tl(sat, t1, 31);   /*  sat= t1(31)                         */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+
+    tcg_gen_movcond_tl(TCG_COND_LTU, rslt, dest, ctx->msb32, dest, ctx->smax32);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Cf, ctx->zero);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S1f, cpu_S2f, sat);
+        tcg_gen_or_tl(cpu_S1f, cpu_S2f, sat);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ADDSDW
+*/
+int arc_gen_ADDSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv loB = tcg_temp_new_i32();
+    TCGv hiB = tcg_temp_new_i32();
+    TCGv loC = tcg_temp_new_i32();
+    TCGv hiC = tcg_temp_new_i32();
+    TCGv loA = tcg_temp_new_i32();
+    TCGv hiA = tcg_temp_new_i32();
+    TCGv hiS = tcg_temp_new_i32();
+    TCGv loS = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(loB, src1, 0xffff);
+    tcg_gen_shri_tl(hiB, src1, 16);
+
+    tcg_gen_andi_tl(loC, src2, 0xffff);
+    tcg_gen_shri_tl(hiC, src2, 16);
+
+    tcg_gen_add_tl(loA, loB, loC);
+    tcg_gen_add_tl(hiA, hiB, hiC);
+
+    tcg_gen_movcond_tl(TCG_COND_LTU, loA, loA, ctx->msb16, loA, ctx->smax16);
+    tcg_gen_movcond_tl(TCG_COND_LTU, hiA, hiA, ctx->msb16, hiA, ctx->smax16);
+
+    tcg_gen_deposit_tl(rslt, loA, hiA, 16, 16);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_movi_tl(cpu_Cf, 0);
+
+        gen_add16_Vf(hiS, hiA, hiB, hiC);
+        gen_add16_Vf(loS, loA, loB, loC);
+
+        tcg_gen_or_tl(cpu_Vf, hiS, loS);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, hiS);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, loS);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(loA);
+    tcg_temp_free_i32(hiA);
+    tcg_temp_free_i32(loB);
+    tcg_temp_free_i32(hiB);
+    tcg_temp_free_i32(loC);
+    tcg_temp_free_i32(hiC);
+    tcg_temp_free_i32(hiS);
+    tcg_temp_free_i32(loS);
+
+    return  BS_NONE;
+}
+
+/*
+    SUBS
+*/
+int arc_gen_SUBS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    tcg_gen_mov_tl(temp, src2);
+
+    arc_gen_ADDS(ctx, dest, src1, temp);
+
+    tcg_temp_free_i32(temp);
+
+    return  BS_NONE;
+}
+
+/*
+    SUBSDW
+*/
+int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv loB = tcg_temp_new_i32();
+    TCGv hiB = tcg_temp_new_i32();
+    TCGv loC = tcg_temp_new_i32();
+    TCGv hiC = tcg_temp_new_i32();
+    TCGv loA = tcg_temp_new_i32();
+    TCGv hiA = tcg_temp_new_i32();
+    TCGv hiS = tcg_temp_new_i32();
+    TCGv loS = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(loB, src1, 0xffff);
+    tcg_gen_shri_tl(hiB, src1, 16);
+
+    tcg_gen_andi_tl(loC, src2, 0xffff);
+    tcg_gen_shri_tl(hiC, src2, 16);
+
+    tcg_gen_sub_tl(loA, loB, loC);
+    tcg_gen_sub_tl(hiA, hiB, hiC);
+
+    tcg_gen_movcond_tl(TCG_COND_LTU, loA, loA, ctx->msb16, loA, ctx->smax16);
+    tcg_gen_movcond_tl(TCG_COND_LTU, hiA, hiA, ctx->msb16, hiA, ctx->smax16);
+
+    tcg_gen_deposit_tl(rslt, loA, hiA, 16, 16);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_movi_tl(cpu_Cf, 0);
+
+        gen_sub16_Vf(hiS, hiA, hiB, hiC);
+        gen_sub16_Vf(loS, loA, loB, loC);
+
+        tcg_gen_or_tl(cpu_Vf, hiS, loS);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, hiS);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, loS);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(loA);
+    tcg_temp_free_i32(hiA);
+    tcg_temp_free_i32(loB);
+    tcg_temp_free_i32(hiB);
+    tcg_temp_free_i32(loC);
+    tcg_temp_free_i32(hiC);
+    tcg_temp_free_i32(hiS);
+    tcg_temp_free_i32(loS);
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +4 -0
index 74beb33..a4699e3 100644
@@ -144,3 +144,7 @@ int arc_gen_JL(DisasCtxt *c, TCGv src1, ARC_COND cond);
 int arc_gen_LR(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_SR(DisasCtxt *c, TCGv src1, TCGv src2);
 
+int arc_gen_ADDS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADDSDW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUBS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
Signature · 1 line
2.4.9 (Apple Git-60)
#38 lore raw

RFC PATCH 21/29 target-arc: ABSS, ABSSW, NEGS, NEGSW, RND16, SAT16

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 238 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   8 ++
 2 files changed, 246 insertions(+)
target-arc/translate-inst.c +238 -0
index d5c739e..2a62f30 100644
@@ -2322,3 +2322,241 @@ int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    ABSS
+*/
+int arc_gen_ABSS(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_neg_i32(t0, src1);
+    tcg_gen_movcond_tl(TCG_COND_LEU, rslt, src1, ctx->smax16, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, src1, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, src1, 31);
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Vf, src1, ctx->msb32);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, cpu_Vf);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ABSSW
+*/
+int arc_gen_ABSSW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 lo = tcg_temp_new_i32();
+    TCGv_i32 neg = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(lo, src1, 0x0000ffff);
+    tcg_gen_neg_tl(neg, lo);
+
+    tcg_gen_movcond_tl(TCG_COND_LEU, rslt, lo, ctx->smax16, lo, neg);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, src1, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, src1, 31);
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Vf, lo, ctx->msb16);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, cpu_Vf);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(lo);
+    tcg_temp_free_i32(neg);
+
+    return  BS_NONE;
+}
+
+/*
+    NEGS
+*/
+int arc_gen_NEGS(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 sat = tcg_temp_new_i32();
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+
+    tcg_gen_brcondi_tl(TCG_COND_NE, src1, 0x80000000, label_else);
+
+    tcg_gen_movi_tl(sat, 1);
+    tcg_gen_movi_tl(rslt, 0x7fffffff);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_else);
+    tcg_gen_movi_tl(sat, 0);
+    tcg_gen_neg_tl(rslt, src1);
+
+gen_set_label(label_done);
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, cpu_Vf);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free(sat);
+
+    return  BS_NONE;
+}
+
+/*
+    NEGSW
+*/
+int arc_gen_NEGSW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 src16 = tcg_temp_new_i32();
+    TCGv_i32 sat = tcg_temp_new_i32();
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+
+    tcg_gen_andi_tl(src16, src1, 0x0000ffff);
+
+    tcg_gen_brcondi_tl(TCG_COND_NE, src1, 0x8000, label_else);
+
+    tcg_gen_movi_tl(sat, 1);
+    tcg_gen_movi_tl(rslt, 0x7fff);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_else);
+    tcg_gen_movi_tl(sat, 0);
+    tcg_gen_neg_tl(rslt, src1);
+
+gen_set_label(label_done);
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free(src16);
+    tcg_temp_free(sat);
+
+    return  BS_NONE;
+}
+
+/*
+    RND16
+*/
+int arc_gen_RND16(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 hi = tcg_const_local_i32(0x00007fff);    /*  max sint16  */
+    TCGv_i32 lo = tcg_const_local_i32(0xffff8000);    /*  min sint16  */
+    TCGv_i32 sat = tcg_temp_new_i32();
+    TCGv_i32 temp = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_addi_tl(temp, src1, 0x00008000);
+    tcg_gen_shri_tl(temp, temp, 16);
+
+    tcg_gen_movcond_tl(TCG_COND_LT, rslt, src1, lo, hi, temp);
+    tcg_gen_movcond_tl(TCG_COND_GT, rslt, src1, hi, hi, temp);
+    tcg_gen_setcond_tl(TCG_COND_NE, sat, rslt, temp);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, sat);
+    }
+
+    tcg_temp_free_i32(temp);
+    tcg_temp_free_i32(sat);
+    tcg_temp_free_i32(lo);
+    tcg_temp_free_i32(hi);
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SAT16
+*/
+int arc_gen_SAT16(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 hi = tcg_const_local_i32(0x00007fff);    /*  max sint16  */
+    TCGv_i32 lo = tcg_const_local_i32(0xffff8000);    /*  min sint16  */
+    TCGv_i32 sat = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_movcond_tl(TCG_COND_LT, rslt, src1, lo, lo, src1);
+    tcg_gen_movcond_tl(TCG_COND_GT, rslt, src1, hi, hi, src1);
+    tcg_gen_setcond_tl(TCG_COND_NE, sat, rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, sat);
+    }
+
+    tcg_temp_free_i32(sat);
+    tcg_temp_free_i32(lo);
+    tcg_temp_free_i32(hi);
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
target-arc/translate-inst.h +8 -0
index a4699e3..c84d989 100644
@@ -148,3 +148,11 @@ int arc_gen_ADDS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADDSDW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_SUBS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+
+int arc_gen_ABSS(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ABSSW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SAT16(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_RND16(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NEGS(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NEGSW(DisasCtxt *c, TCGv dest, TCGv src1);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#39 lore raw

RFC PATCH 22/29 target-arc: ASLS, ASRS

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  3 +++
 2 files changed, 60 insertions(+)
target-arc/translate-inst.c +57 -0
index 2a62f30..524b213 100644
@@ -2560,3 +2560,60 @@ int arc_gen_SAT16(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return  BS_NONE;
 }
 
+/*
+    ASLS
+*/
+int arc_gen_ASLS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    /* TODO */
+
+    return  BS_NONE;
+}
+
+
+/*
+    ASRS
+*/
+int arc_gen_ASRS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    /* TODO: check */
+    TCGv rslt = dest;
+    TCGv shft = tcg_temp_new_i32();
+    TCGLabel *label_pos = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_brcond_tl(TCG_COND_LEU, src2, ctx->smax32, label_pos);
+
+    /*  negative    */
+    tcg_gen_movcond_tl(TCG_COND_GT, shft, src2, ctx->smin5, src2, ctx->smin5);
+    tcg_gen_neg_tl(shft, shft);
+    tcg_gen_shl_tl(rslt, src1, shft);
+
+    tcg_gen_br(label_done);
+
+gen_set_label(label_pos);
+    /*  positive    */
+    tcg_gen_movcond_tl(TCG_COND_LT, shft, src2, ctx->smax5, src2, ctx->smax5);
+    tcg_gen_sar_tl(rslt, src1, shft);
+
+gen_set_label(label_done);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_sari_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free_i32(shft);
+
+    return BS_NONE;
+}
+
target-arc/translate-inst.h +3 -0
index c84d989..e2b76d4 100644
@@ -156,3 +156,6 @@ int arc_gen_RND16(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NEGS(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NEGSW(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_ASLS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ASRS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#40 lore raw

Re: [Qemu-devel] [PATCH RFC v1 22/29] target-arc: ASLS, ASRS

Quoted 1 line · Michael Rolnik

+int arc_gen_ASLS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)

Just do these as helpers.

r~

#41 lore raw

RFC PATCH 23/29 target-arc: FLAG, BRK, SLEEP

In reply to Michael Rolnik
---
 target-arc/helper.h         |  1 +
 target-arc/op_helper.c      |  6 +++++
 target-arc/translate-inst.c | 61 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  4 +++
 4 files changed, 72 insertions(+)
target-arc/helper.h +1 -0
index 1d84935..14769b1 100644
@@ -23,4 +23,5 @@ DEF_HELPER_2(norm, i32, env, i32)
 DEF_HELPER_2(normw, i32, env, i32)
 DEF_HELPER_2(lr, tl, env, i32)
 DEF_HELPER_2(sr, void, i32, i32)
+DEF_HELPER_1(halt, void, env)
 
target-arc/op_helper.c +6 -0
index 3cf9080..b07939c 100644
@@ -411,3 +411,9 @@ target_ulong helper_lr(CPUARCState *env, uint32_t aux)
     return  result;
 }
 
+void helper_halt(CPUARCState *env)
+{
+    /* TODO: implement */
+}
+
+
target-arc/translate-inst.c +61 -0

64 lines not on this page · raw message

target-arc/translate-inst.h +4 -0
index e2b76d4..5794cad 100644
@@ -159,3 +159,7 @@ int arc_gen_NEGSW(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_ASLS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ASRS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_SLEEP(DisasCtxt *c, TCGv src1);
+int arc_gen_BRK(DisasCtxt *c);
+int arc_gen_FLAG(DisasCtxt *c, TCGv src1);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#42 lore raw

RFC PATCH 24/29 target-arc: NOP, UNIMP

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 20 ++++++++++++++++++++
 target-arc/translate-inst.h |  2 ++
 2 files changed, 22 insertions(+)
target-arc/translate-inst.c +20 -0
index 9d0f195..4c4318f 100644
@@ -2678,3 +2678,23 @@ int arc_gen_SLEEP(DisasCtxt *ctx, TCGv src1)
     return  BS_BREAK;
 }
 
+/*
+    NOP
+*/
+int arc_gen_NOP(DisasCtxt *ctx)
+{
+    /*  literally no operation  */
+    return  BS_NONE;
+}
+
+/*
+    UNIMP
+*/
+int arc_gen_UNIMP(DisasCtxt *ctx)
+{
+    /* PC = INT_VECTOR_BACE + 0x10 */
+    tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x10);
+
+    return  BS_EXCP;
+}
target-arc/translate-inst.h +2 -0
index 5794cad..9f88d03 100644
@@ -163,3 +163,5 @@ int arc_gen_SLEEP(DisasCtxt *c, TCGv src1);
 int arc_gen_BRK(DisasCtxt *c);
 int arc_gen_FLAG(DisasCtxt *c, TCGv src1);
 
+int arc_gen_NOP(DisasCtxt *c);
+int arc_gen_UNIMP(DisasCtxt *c);
Signature · 1 line
2.4.9 (Apple Git-60)
#43 lore raw

Re: [Qemu-devel] [PATCH RFC v1 24/29] target-arc: NOP, UNIMP

target-arc/translate-inst.c int arc_gen_SLEEP(DisasCtxt *ctx, TCGv src1) · line 2700

Quoted 8 lines · Michael Rolnik
target-arc/translate-inst.c +8 -0
+int arc_gen_UNIMP(DisasCtxt *ctx)
+{
+    /* PC = INT_VECTOR_BACE + 0x10 */
+    tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x10);
+
+    return  BS_EXCP;
+}

This should be done via an exception, with the pc change done in do_interrupt.

r~

#44 lore raw

RFC PATCH 25/29 target-arc: TRAP, SWI

In reply to Michael Rolnik
---
 target-arc/translate-inst.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 ++
 2 files changed, 109 insertions(+)
target-arc/translate-inst.c +105 -0
index 4c4318f..87a00ca 100644
@@ -2698,3 +2698,108 @@ int arc_gen_UNIMP(DisasCtxt *ctx)
 
     return  BS_EXCP;
 }
+
+/*
+    TRAP
+*/
+int arc_gen_TRAP(DisasCtxt *ctx, TCGv src1)
+{
+    if (arc_feature(ctx->env, ARC_FEATURE_ARC700)) {
+        tcg_gen_mov_tl(cpu_er_Lf, cpu_Lf);
+        tcg_gen_mov_tl(cpu_er_Zf, cpu_Zf);
+        tcg_gen_mov_tl(cpu_er_Nf, cpu_Nf);
+        tcg_gen_mov_tl(cpu_er_Cf, cpu_Cf);
+        tcg_gen_mov_tl(cpu_er_Vf, cpu_Vf);
+        tcg_gen_mov_tl(cpu_er_Uf, cpu_Uf);
+
+        tcg_gen_mov_tl(cpu_er_DEf, cpu_DEf);
+        tcg_gen_mov_tl(cpu_er_AEf, cpu_AEf);
+        tcg_gen_mov_tl(cpu_er_A2f, cpu_A2f);
+        tcg_gen_mov_tl(cpu_er_A1f, cpu_A1f);
+        tcg_gen_mov_tl(cpu_er_E2f, cpu_E2f);
+        tcg_gen_mov_tl(cpu_er_E1f, cpu_E1f);
+        tcg_gen_mov_tl(cpu_er_Hf, cpu_Hf);
+
+        tcg_gen_movi_tl(cpu_E1f, 0);
+        tcg_gen_movi_tl(cpu_E2f, 0);
+        tcg_gen_movi_tl(cpu_AEf, 1);
+        tcg_gen_movi_tl(cpu_Uf, 0);
+
+        tcg_gen_movi_tl(cpu_eret, ctx->npc);
+        tcg_gen_movi_tl(cpu_efa, ctx->cpc);
+        tcg_gen_andi_tl(cpu_ecr, src1, 0x000000ff);
+        tcg_gen_ori_tl(cpu_ecr, cpu_ecr, 0x00250000);
+        tcg_gen_movcond_tl(TCG_COND_NE, cpu_erbta, cpu_DEf, ctx->zero,
+                                                    cpu_bta, cpu_erbta);
+
+        tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+        tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x128);
+    } else {
+        arc_gen_UNIMP(ctx);
+    }
+
+    return  BS_EXCP;
+}
+
+/*
+    SWI
+*/
+int arc_gen_SWI(DisasCtxt *ctx)
+{
+    if (arc_feature(ctx->env, ARC_FEATURE_ARC700)) {
+        tcg_gen_mov_tl(cpu_er_Lf, cpu_Lf);
+        tcg_gen_mov_tl(cpu_er_Zf, cpu_Zf);
+        tcg_gen_mov_tl(cpu_er_Nf, cpu_Nf);
+        tcg_gen_mov_tl(cpu_er_Cf, cpu_Cf);
+        tcg_gen_mov_tl(cpu_er_Vf, cpu_Vf);
+        tcg_gen_mov_tl(cpu_er_Uf, cpu_Uf);
+
+        tcg_gen_mov_tl(cpu_er_DEf, cpu_DEf);
+        tcg_gen_mov_tl(cpu_er_AEf, cpu_AEf);
+        tcg_gen_mov_tl(cpu_er_A2f, cpu_A2f);
+        tcg_gen_mov_tl(cpu_er_A1f, cpu_A1f);
+        tcg_gen_mov_tl(cpu_er_E2f, cpu_E2f);
+        tcg_gen_mov_tl(cpu_er_E1f, cpu_E1f);
+        tcg_gen_mov_tl(cpu_er_Hf, cpu_Hf);
+
+        tcg_gen_movi_tl(cpu_E1f, 0);
+        tcg_gen_movi_tl(cpu_E2f, 0);
+        tcg_gen_movi_tl(cpu_AEf, 1);
+        tcg_gen_movi_tl(cpu_Uf, 0);
+
+        tcg_gen_movi_tl(cpu_eret, ctx->npc);
+        tcg_gen_movi_tl(cpu_efa, ctx->cpc);
+        tcg_gen_movi_tl(cpu_ecr, 0x00250000);
+        tcg_gen_movcond_tl(TCG_COND_NE, cpu_erbta, cpu_DEf, ctx->zero,
+                                                    cpu_bta, cpu_erbta);
+
+        tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+        tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x128);
+    } else {
+        tcg_gen_movi_tl(cpu_ilink2, ctx->npc);
+
+        tcg_gen_mov_tl(cpu_l2_Lf, cpu_Lf);
+        tcg_gen_mov_tl(cpu_l2_Zf, cpu_Zf);
+        tcg_gen_mov_tl(cpu_l2_Nf, cpu_Nf);
+        tcg_gen_mov_tl(cpu_l2_Cf, cpu_Cf);
+        tcg_gen_mov_tl(cpu_l2_Vf, cpu_Vf);
+        tcg_gen_mov_tl(cpu_l2_Uf, cpu_Uf);
+
+        tcg_gen_mov_tl(cpu_l2_DEf, cpu_DEf);
+        tcg_gen_mov_tl(cpu_l2_AEf, cpu_AEf);
+        tcg_gen_mov_tl(cpu_l2_A2f, cpu_A2f);
+        tcg_gen_mov_tl(cpu_l2_A1f, cpu_A1f);
+        tcg_gen_mov_tl(cpu_l2_E2f, cpu_E2f);
+        tcg_gen_mov_tl(cpu_l2_E1f, cpu_E1f);
+        tcg_gen_mov_tl(cpu_l2_Hf, cpu_Hf);
+
+        tcg_gen_movi_tl(cpu_E1f, 0);
+        tcg_gen_movi_tl(cpu_E2f, 0);
+
+        tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+        tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x10);
+    }
+
+    return  BS_EXCP;
+}
+
target-arc/translate-inst.h +4 -0
index 9f88d03..f7f988b 100644
@@ -165,3 +165,7 @@ int arc_gen_FLAG(DisasCtxt *c, TCGv src1);
 
 int arc_gen_NOP(DisasCtxt *c);
 int arc_gen_UNIMP(DisasCtxt *c);
+
+int arc_gen_SWI(DisasCtxt *c);
+int arc_gen_TRAP(DisasCtxt *c, TCGv src1);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#45 lore raw

RFC PATCH 26/29 target-arc: RTIE

In reply to Michael Rolnik
---
 target-arc/helper.h         |  1 +
 target-arc/op_helper.c      | 21 +++++++++++++++++++++
 target-arc/translate-inst.c | 10 ++++++++++
 target-arc/translate-inst.h |  2 ++
 4 files changed, 34 insertions(+)
target-arc/helper.h +1 -0
index 14769b1..abfd0d2 100644
@@ -24,4 +24,5 @@ DEF_HELPER_2(normw, i32, env, i32)
 DEF_HELPER_2(lr, tl, env, i32)
 DEF_HELPER_2(sr, void, i32, i32)
 DEF_HELPER_1(halt, void, env)
+DEF_HELPER_1(rtie, void, env)
 
target-arc/op_helper.c +21 -0
index b07939c..a3f6a46 100644
@@ -416,4 +416,25 @@ void helper_halt(CPUARCState *env)
     /* TODO: implement */
 }
 
+void helper_rtie(CPUARCState *env)
+{
+    if (env->stat.AEf) {
+        CPU_PCL(env) = env->eret;
+        env->stat = env->stat_er;
+        env->bta = env->erbta;
+    } else if (env->stat.A2f) {
+        CPU_PCL(env) = CPU_ILINK2(env);
+        env->stat = env->stat_l2;
+        env->bta = env->bta_l2;
+    } else if (env->stat.A1f) {
+        CPU_PCL(env) = CPU_ILINK1(env);
+        env->stat = env->stat_l1;
+        env->bta = env->bta_l1;
+    } else {
+        CPU_PCL(env) = env->eret;
+        env->stat = env->stat_er;
+        env->bta = env->stat.AEf;
+    }
+}
+
 
target-arc/translate-inst.c +10 -0
index 87a00ca..743f2be 100644
@@ -2803,3 +2803,13 @@ int arc_gen_SWI(DisasCtxt *ctx)
     return  BS_EXCP;
 }
 
+/*
+    RTIE
+*/
+int arc_gen_RTIE(DisasCtxt *ctx)
+{
+    gen_helper_rtie(cpu_env);
+
+    return  BS_BRANCH;
+}
+
target-arc/translate-inst.h +2 -0
index f7f988b..8bbac4f 100644
@@ -169,3 +169,5 @@ int arc_gen_UNIMP(DisasCtxt *c);
 int arc_gen_SWI(DisasCtxt *c);
 int arc_gen_TRAP(DisasCtxt *c, TCGv src1);
 
+int arc_gen_RTIE(DisasCtxt *c);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#46 lore raw

RFC PATCH 27/29 target-arc: LP

In reply to Michael Rolnik
---
 target-arc/helper.h         |  1 +
 target-arc/op_helper.c      |  5 ++++-
 target-arc/translate-inst.c | 40 ++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  2 ++
 4 files changed, 47 insertions(+), 1 deletion(-)
target-arc/helper.h +1 -0
index abfd0d2..ef5c12e 100644
@@ -25,4 +25,5 @@ DEF_HELPER_2(lr, tl, env, i32)
 DEF_HELPER_2(sr, void, i32, i32)
 DEF_HELPER_1(halt, void, env)
 DEF_HELPER_1(rtie, void, env)
+DEF_HELPER_1(flush, void, env)
 
target-arc/op_helper.c +4 -1
index a3f6a46..61e790e 100644
@@ -437,4 +437,7 @@ void helper_rtie(CPUARCState *env)
     }
 }
 
-
+void helper_flush(CPUARCState *env)
+{
+    tb_flush((CPUState *)arc_env_get_cpu(env));
+}
target-arc/translate-inst.c +40 -0
index 743f2be..87940ed 100644
@@ -2813,3 +2813,43 @@ int arc_gen_RTIE(DisasCtxt *ctx)
     return  BS_BRANCH;
 }
 
+/*
+    LPcc
+*/
+int arc_gen_LPcc(DisasCtxt *ctx, TCGv rd, unsigned Q)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGv t0 = tcg_const_local_i32(ctx->npc);
+
+    /*
+        if cc is false, pc will be updated here
+        pc = pcl + rd
+    */
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+
+    /*
+        if cc is false we will jump to done label
+    */
+    arc_gen_jump_ifnot(ctx, Q, label_done);
+
+    /*
+        cc is true
+    */
+    tcg_gen_movi_tl(t0, ctx->lpe);
+
+    tcg_gen_movi_tl(cpu_lps, ctx->npc);
+    tcg_gen_mov_tl(cpu_lpe, cpu_pc);
+    tcg_gen_movi_tl(cpu_pc, ctx->npc);
+
+    tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lpe, label_done);
+
+    gen_helper_flush(cpu_env);
+
+gen_set_label(label_done);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_BRANCH;
+}
+
target-arc/translate-inst.h +2 -0
index 8bbac4f..7ea20a0 100644
@@ -171,3 +171,5 @@ int arc_gen_TRAP(DisasCtxt *c, TCGv src1);
 
 int arc_gen_RTIE(DisasCtxt *c);
 
+int arc_gen_LPcc(DisasCtxt *ctx, TCGv Rd, unsigned Q);
+
Signature · 1 line
2.4.9 (Apple Git-60)
#47 lore raw

RFC PATCH 28/29 target-arc: decode

In reply to Michael Rolnik
---
 target-arc/decode.c | 2209 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 2207 insertions(+), 2 deletions(-)
target-arc/decode.c +2207 -2
index 1bb859a..0efc23d 100644
@@ -1,7 +1,2212 @@
 #include "translate.h"
+#include "translate-inst.h"
 
-int arc_decode(DisasCtxt *ctx)
+typedef int (*decode_f)(DisasCtxt *ctx, uint32_t opcode);
+
+static void arc_decode_src(DisasCtxt *ctx, TCGv src)
+{
+    if (TCGV_EQUAL(src, cpu_limm)   /* register refers to limm  */
+        && ctx->opt.limm == 0) {    /* limm is not yet decoded  */
+        uint32_t limm;
+
+        limm    = cpu_ldl_code(ctx->env, ctx->npc);
+        limm    = (limm & 0xffff0000) >> 16
+                | (limm & 0x0000ffff) << 16;
+
+        tcg_gen_movi_tl(cpu_limm, limm);
+
+        ctx->npc += sizeof(limm);
+        ctx->opt.limm = 1;
+        ctx->opt.d = 0;
+    }
+
+    if (TCGV_EQUAL(src, cpu_pcl)) {
+        tcg_gen_movi_tl(cpu_pcl, ctx->pcl);
+    }
+}
+
+static int arc_decode_invalid(DisasCtxt *ctx, uint32_t opcode)
+{
+    return BS_EXCP;
+}
+
+
+/*
+    Branch Conditionally
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-------------------|-|-------------------|-|----------+
+    | major   |S[10:1]            |0|S[20:11]           |N|Q[4:0]    |
+    +---------|-------------------|-|-------------------|-|----------+
+    |0 0 0 0 0|s s s s s s s s s s|0|S S S S S S S S S S|N|Q Q Q Q Q |
+    +---------+-------------------+-+-------------------+-+----------+
+
+    Branch Unconditional Far
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-------------------|-|-------------------|-|-|--------+
+    | major   |S[10:1]            |1|S[20:11]           |N|R|S[24:21]|
+    +---------|-------------------|-|-------------------|-|-|--------+
+    |0 0 0 0 0|s s s s s s s s s s|1|S S S S S S S S S S|N|0|T T T T |
+    +---------+-------------------+-+-------------------+-+-+--------+
+*/
+static int arc_decode_major00(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret;
+    TCGv s;
+
+    if (extract32(opcode, 16, 1) == 0) {
+        unsigned _Q = extract32(opcode, 0, 5);
+        unsigned _N = extract32(opcode, 5, 1);
+        unsigned _S = extract32(opcode, 6, 10);
+        unsigned _s = extract32(opcode, 17, 10);
+
+        s = tcg_const_local_i32(sextract32((_S << 10) | _s, 0, 20));
+        ctx->opt.d = _N;
+
+        ret = arc_gen_B(ctx, s, _Q);
+
+    } else {
+        unsigned _T = extract32(opcode, 0, 4);
+        unsigned _N = extract32(opcode, 5, 1);
+        unsigned _S = extract32(opcode, 6, 10);
+        unsigned _s = extract32(opcode, 17, 10);
+
+        s = tcg_const_local_i32(sextract32((((_T << 10) | _S) << 10) | _s, 0,
+                                                                           24));
+        ctx->opt.d = _N;
+
+        ret = arc_gen_B(ctx, s, ARC_COND_AL);
+    }
+
+    tcg_temp_free_i32(s);
+
+    return ret;
+}
+
+/*
+
+    Branch and Link Conditionally
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    | major   |S[10:2]          |0|0|S[20:11]           |N|Q[4:0]    |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    |0 0 0 0 1|s s s s s s s s s|0|0|S S S S S S S S S S|N|Q Q Q Q Q |
+    +---------+-----------------+-+-+-------------------+-+----------+
+
+    Branch and Link Unconditional Far
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    | major   |S[10:2]          |0|0|S[20:11]           |N|Q[4:0]    |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    |0 0 0 0 1|s s s s s s s s s|0|0|S S S S S S S S S S|N|Q Q Q Q Q |
+    +---------+-----------------+-+-+-------------------+-+----------+
+
+    Branch on Compare Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    | major   |b    |S[7:1]       |1|S|B    |C[5:0]     |N|0| minor  |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    |0 0 0 0 1|b b b|s s s s s s s|1|S|B B B|C C C C C C|N|0|i i i i |
+    +---------+-----+-------------+-+-+-----+-----------+-+-+--------+
+
+    Branch on Compare/Bit Test Register-Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    | major   |b    |S[7:1]       |1|S|B    |U[5:0]     |N|1| minor  |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    |0 0 0 0 1|b b b|s s s s s s s|1|S|B B B|U U U U U U|N|1|i i i i |
+    +---------+-----+-------------+-+-+-----+-----------+-+-+--------+
+*/
+static int arc_decode_major01_body(DisasCtxt *ctx,
+                                        unsigned minor, TCGv a, TCGv b, TCGv c)
+{
+    int ret;
+
+    switch (minor) {
+        case 0x00: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_EQ);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_NE);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_LT);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_GE);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_LTU);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_GEU);
+            break;
+        }
+
+        case 0x06 ... 0x0d: {
+            ret = arc_gen_INVALID(ctx);
+            break;
+        }
+
+        case 0x0E: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BBIT0(ctx, a, b, c);
+            break;
+        }
+        case 0x0F: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BBIT1(ctx, a, b, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major01(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret;
+
+    if (extract32(opcode, 16, 1) == 0) {
+
+        if (extract32(opcode, 17, 1) == 0) {
+            /*  Branch and Link Conditionally   */
+            unsigned _Q = extract32(opcode, 0, 5);
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _S = extract32(opcode, 6, 10);
+            unsigned _s = extract32(opcode, 18, 9);
+            TCGv s = tcg_const_local_i32(sextract32((_S << 9) | _s, 0, 19));
+
+            ctx->opt.d = _N;
+
+            ret = arc_gen_BL(ctx, s, _Q);
+
+            tcg_temp_free_i32(s);
+        } else {
+            /*  Branch and Link Unconditional Far   */
+            unsigned _T = extract32(opcode, 0, 4);
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _S = extract32(opcode, 6, 10);
+            unsigned _s = extract32(opcode, 18, 9);
+            TCGv s = tcg_const_local_i32(sextract32((((_T << 10) | _S) << 9) |
+                                                                    _s, 0, 23));
+
+            ctx->opt.d = _N;
+
+            ret = arc_gen_BL(ctx, s, ARC_COND_AL);
+
+            tcg_temp_free_i32(s);
+        }
+    } else {
+        unsigned minor;
+
+        minor = extract32(opcode, 0, 4);
+
+        if (extract32(opcode, 4, 1) == 0) {
+            /*  Branch on Compare Register-Register */
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _C = extract32(opcode, 6, 6);
+            unsigned _B = extract32(opcode, 12, 3);
+            unsigned _S = extract32(opcode, 15, 1);
+            unsigned _s = extract32(opcode, 17, 7);
+            unsigned _b = extract32(opcode, 24, 3);
+
+            TCGv b = cpu_r[(_B << 3) | _b];
+            TCGv c = cpu_r[_C];
+            TCGv s = tcg_const_local_i32(sextract32((_S << 7) | _s, 0, 8));
+
+            ctx->opt.d = _N;
+
+            ret = arc_decode_major01_body(ctx, minor, b, c, s);
+
+            tcg_temp_free_i32(s);
+        } else {
+            /*  Branch on Compare/Bit Test Register-Immediate   */
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _u = extract32(opcode, 6, 6);
+            unsigned _B = extract32(opcode, 12, 3);
+            unsigned _S = extract32(opcode, 15, 1);
+            unsigned _s = extract32(opcode, 17, 7);
+            unsigned _b = extract32(opcode, 24, 3);
+
+            TCGv b = cpu_r[(_B << 3) | _b];
+            TCGv u = tcg_const_local_i32(_u);
+            TCGv s = tcg_const_local_i32(sextract32((_S << 7) | _s, 0, 8));
+            ctx->opt.d = _N;
+
+            ret = arc_decode_major01_body(ctx, minor, b, u, s);
+
+            tcg_temp_free_i32(s);
+            tcg_temp_free_i32(u);
+        }
+    }
+
+    return ret;
+}
+
+
+/*
+    Load Register with Offset
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---------------+-+-----+-+---+---+-+------------+
+    | major   | b   |S[7:0]         |S|B    |D|aa |zz |x| A[5:0]     |
+    +---------+-----+---------------+-+-----+-+---+---+-+------------+
+    |0 0 0 1 0|b b b|s s s s s s s s|S|B B B|D|a a|Z Z|X|A A A A A A |
+    +---------+-----+---------------+-+-----+-+---+---+-+------------+
+*/
+static int arc_decode_major02(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _X = extract32(opcode, 6, 1);
+    unsigned _ZZ = extract32(opcode, 7, 2);
+    unsigned _AA = extract32(opcode, 9, 2);
+    unsigned _DI = extract32(opcode, 11, 1);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _S = extract32(opcode, 15, 1);
+    unsigned _s = extract32(opcode, 16, 8);
+    unsigned _b = extract32(opcode, 24, 3);
+
+    TCGv a = cpu_r[_A];
+    TCGv b = cpu_r[(_B << 3) | _b];
+    TCGv s = tcg_const_local_i32(sextract32((_S << 8) | _s, 0, 9));
+    ctx->opt.zz = _ZZ;
+    ctx->opt.x = _X;
+    ctx->opt.aa = _AA;
+    ctx->opt.di = _DI;
+
+    arc_decode_src(ctx, b);
+    ret = arc_gen_LD(ctx, a, b, s);
+
+    tcg_temp_free_i32(s);
+
+    return ret;
+}
+
+/*
+    Store Register with Offset
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---------------+-+-----+-----------+-+---+---+--+
+    | major   | b   | S[7:0]        |S| B   | C[5:0]    |D|aa |zz |R |
+    +---------+-----+---------------+-+-----+-----------+-+---+---+--+
+    |0 0 0 1 1|b b b|s s s s s s s s|S|B B B|C C C C C C|D|a a|Z Z|0 |
+    +---------+-----+---------------+-+-----+-----------+-+---+---+--+
+*/
+static int arc_decode_major03(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _ZZ = extract32(opcode, 1, 2);
+    unsigned _AA = extract32(opcode, 3, 2);
+    unsigned _DI = extract32(opcode, 5, 1);
+    unsigned _C = extract32(opcode, 6, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _S = extract32(opcode, 15, 1);
+    unsigned _s = extract32(opcode, 16, 8);
+    unsigned _b = extract32(opcode, 24, 3);
+
+    TCGv b = cpu_r[(_B << 3) | _b];
+    TCGv c = cpu_r[_C];
+    TCGv s = tcg_const_local_i32(sextract32((_S << 8) | _s, 0, 9));
+    ctx->opt.zz = _ZZ;
+    ctx->opt.aa = _AA;
+    ctx->opt.di = _DI;
+
+    arc_decode_src(ctx, b);
+    arc_decode_src(ctx, c);
+    ret = arc_gen_ST(ctx, c, b, s);
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    General Operations Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   | b   |P  | minor     |F| B   | C[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|0 0|i i i i i i|F|B B B|C C C C C C|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    General Operations Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   | b   |P  | minor     |F| B   | U[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|0 1|i i i i i i|F|B B B|U U U U U U|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    General Operations Register with Signed 12-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   | b   |P  | minor     |F| B   | S[5:0]    | S[11:6]    |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|0 1|i i i i i i|F|B B B|s s s s s s|S S S S S S |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    General Operations Conditional Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    | major   | b   |P  | minor     |F| B   | C[5:0]    |M|Q[4:0]    |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 0|b b b|1 1|i i i i i i|F|B B B|C C C C C C|0|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+    General Operations Conditional Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    | major   | b   |P  | minor     |F| B   | U[5:0]    |M|Q[4:0]    |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 0|b b b|1 1|i i i i i i|F|B B B|U U U U U U|1|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+    Load Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+---+-+---+-+-+-----+-----------+------------+
+    | major   | b   |aa |1 1 0|zz |x|d|B    | C[5:0]    | A[5:0]     |
+    +---------+-----+---+-----+---+-+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|a a|1 1 0|Z Z|X|D|B B B|C C C C C C|A A A A A A |
+    +---------+-----+---+---+-+---+-+-+-----+-----------+------------+
+
+*/
+static int arc_decode_major04_zop(DisasCtxt *ctx,
+                                        unsigned _B, TCGv c)
+{
+    int ret = BS_NONE;
+
+    switch (_B) {
+        case 0x01: {
+            ret = arc_gen_SLEEP(ctx, c);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_SWI(ctx);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_SYNC(ctx);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_RTIE(ctx);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_BRK(ctx);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major04_sop(DisasCtxt *ctx,
+                                    unsigned _A, unsigned _B, TCGv b, TCGv c)
+{
+    int ret = BS_NONE;
+
+    switch (_A) {
+        case 0x00: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASL(ctx, b, c);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASR(ctx, b, c);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LSR(ctx, b, c);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ROR(ctx, b, c);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RRC(ctx, b, c);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SEXB(ctx, b, c);
+            break;
+        }
+        case 0x06: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SEXW(ctx, b, c);
+            break;
+        }
+        case 0x07: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_EXTB(ctx, b, c);
+            break;
+        }
+        case 0x08: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_EXTW(ctx, b, c);
+            break;
+        }
+        case 0x09: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ABS(ctx, b, c);
+            break;
+        }
+        case 0x0A: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NOT(ctx, b, c);
+            break;
+        }
+        case 0x0B: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RLC(ctx, b, c);
+            break;
+        }
+        case 0x0C: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_EX(ctx, b, c);
+            break;
+        }
+        case 0x3F: {
+            ret = arc_decode_major04_zop(ctx, _B, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+static int arc_decode_major04_op(DisasCtxt *ctx,
+                           uint32_t opcode, TCGv a, TCGv b, TCGv c, unsigned _Q)
+{
+    int ret = BS_NONE;
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _b = extract32(opcode, 24, 3);
+    unsigned minor = extract32(opcode, 16, 6);
+    TCGLabel *skip = gen_new_label();
+
+    _B = (_B << 3) | _b;
+
+    switch (minor) {
+        case    0x00: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD(ctx, a, b, c);
+            break;
+        }
+        case    0x01: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADC(ctx, a, b, c);
+            break;
+        }
+        case    0x02: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB(ctx, a, b, c);
+            break;
+        }
+        case    0x03: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SBC(ctx, a, b, c);
+            break;
+        }
+        case    0x04: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_AND(ctx, a, b, c);
+            break;
+        }
+        case    0x05: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_OR(ctx, a, b, c);
+            break;
+        }
+        case    0x06: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BIC(ctx, a, b, c);
+            break;
+        }
+        case    0x07: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_XOR(ctx, a, b, c);
+            break;
+        }
+        case    0x08: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MAX(ctx, a, b, c);
+            break;
+        }
+        case    0x09: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MIN(ctx, a, b, c);
+            break;
+        }
+        case    0x0A: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MOV(ctx, b, c);
+            break;
+        }
+        case    0x0B: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_TST(ctx, b, c);
+            break;
+        }
+        case    0x0C: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_CMP(ctx, b, c);
+            break;
+        }
+        case    0x0D: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_CMP(ctx, c, b);
+            break;
+        }
+        case    0x0E: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RSUB(ctx, a, b, c);
+            break;
+        }
+        case    0x0F: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BSET(ctx, a, b, c);
+            break;
+        }
+        case    0x10: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BCLR(ctx, a, b, c);
+            break;
+        }
+        case    0x11: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BTST(ctx, b, c);
+            break;
+        }
+        case    0x12: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BXOR(ctx, a, b, c);
+            break;
+        }
+        case    0x13: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BMSK(ctx, a, b, c);
+            break;
+        }
+        case    0x14: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD1(ctx, a, b, c);
+            break;
+        }
+        case    0x15: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD2(ctx, a, b, c);
+            break;
+        }
+        case    0x16: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD3(ctx, a, b, c);
+            break;
+        }
+        case    0x17: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB1(ctx, a, b, c);
+            break;
+        }
+        case    0x18: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB2(ctx, a, b, c);
+            break;
+        }
+        case    0x19: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB3(ctx, a, b, c);
+            break;
+        }
+        case    0x1A: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPY(ctx, a, b, c);
+            break;
+        }
+        case    0x1B: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPYH(ctx, a, b, c);
+            break;
+        }
+        case    0x1C: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPYHU(ctx, a, b, c);
+            break;
+        }
+        case    0x1D: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPYU(ctx, a, b, c);
+            break;
+        }
+        case    0x20: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_J(ctx, c, ARC_COND_AL);
+            break;
+        }
+        case    0x21: {
+            ctx->opt.d = 1;
+            arc_decode_src(ctx, c);
+            ret = arc_gen_J(ctx, c, ARC_COND_AL);
+            break;
+        }
+        case    0x22: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_JL(ctx, c, _Q);
+            break;
+        }
+        case    0x23: {
+            ctx->opt.d = 1;
+            arc_decode_src(ctx, c);
+            ret = arc_gen_JL(ctx, c, _Q);
+            break;
+        }
+        case    0x28: {
+            ret = arc_gen_LPcc(ctx, c, _Q);
+            break;
+        }
+        case    0x29: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_FLAG(ctx, c);
+            break;
+        }
+        case    0x2A: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LR(ctx, b, c);
+            break;
+        }
+        case    0x2B: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SR(ctx, b, c);
+            break;
+        }
+        case    0x2F: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            ret = arc_decode_major04_sop(ctx, _A, _B, b, c);
+            break;
+        }
+        case    0x30 ... 0x37: {
+            unsigned _DI = extract32(opcode, 15, 1);
+            unsigned _X = extract32(opcode, 16, 1);
+            unsigned _ZZ = extract32(opcode, 17, 2);
+            unsigned _AA = extract32(opcode, 22, 2);
+
+            ctx->opt.zz = _ZZ;
+            ctx->opt.x = _X;
+            ctx->opt.aa = _AA;
+            ctx->opt.di = _DI;
+
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    gen_set_label(skip);
+
+    return ret;
+}
+
+static int arc_decode_major04(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _C = extract32(opcode, 6, 6);
+    unsigned _F = extract32(opcode, 15, 1);
+    unsigned _Q = extract32(opcode, 0, 5);
+    unsigned _S = extract32(opcode, 0, 6);
+    unsigned _b = extract32(opcode, 24, 3);
+    unsigned _s = extract32(opcode, 6, 6);
+    unsigned _u = extract32(opcode, 6, 6);
+
+    _B = (_B << 3) | _b;
+
+    switch (extract32(opcode, 22, 2)) {
+        case 0x00: {
+            /*  General Operations Register-Register    */
+
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv c = cpu_r[_C];
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major04_op(ctx, opcode, a, b, c, ARC_COND_AL);
+
+            break;
+        }
+        case 0x01: {
+            /*  General Operations Register with Unsigned 6-bit Immediate   */
+
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv u = tcg_const_local_i32(_u);
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major04_op(ctx, opcode, a, b, u, ARC_COND_AL);
+
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x02: {
+            /*  General Operations Register with Signed 12-bit Immediate    */
+
+            TCGv b = cpu_r[_B];
+            TCGv s = tcg_const_local_i32(sextract32((_S << 6) | _s, 0, 12));
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major04_op(ctx, opcode, b, b, s, ARC_COND_AL);
+
+            tcg_temp_free_i32(s);
+            break;
+        }
+        case 0x03: {
+            if (extract32(opcode, 5, 1) == 0) {
+                /*  General Operations Conditional Register */
+
+                TCGv b = cpu_r[_B];
+                TCGv c = cpu_r[_C];
+                ctx->opt.f = _F;
+
+                ret = arc_decode_major04_op(ctx, opcode, b, b, c, _Q);
+            } else {
+                TCGv b = cpu_r[_B];
+                TCGv u = tcg_const_local_i32(_u);
+
+                ctx->opt.f = _F;
+
+                ret = arc_decode_major04_op(ctx, opcode, b, b, u, _Q);
+            }
+
+            break;
+        }
+    }
+    return ret;
+}
+
+/*
+    Extension ALU Operation, Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | C[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 1|b b b|0 0|i i i i i i|F|B B B|C C C C C C|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    Extension ALU Operation, Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | U[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 1|b b b|0 1|i i i i i i|F|B B B|U U U U U U|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    Extension ALU Operation, Register with Signed 12-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | S[5:0]    | S[11:6]    |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 1|b b b|1 0|i i i i i i|F|B B B|s s s s s s|S S S S S S |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    Extension ALU Operation, Conditional Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | C[5:0]    |M| Q[5:0]   |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 1|b b b|1 1|i i i i i i|F|B B B|C C C C C C|0|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+    Extension ALU Operation, Conditional Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | U[5:0]    |M| Q[5:0]   |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 1|b b b|1 1|i i i i i i|F|B B B|U U U U U U|1|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+*/
+static int arc_decode_major05_zop(DisasCtxt *ctx,
+                                                            unsigned _B, TCGv c)
 {
-    return BS_STOP;
+    int ret = BS_NONE;
+
+    ret = arc_gen_INVALID(ctx);
+
+    return ret;
 }
 
+static int arc_decode_major05_sop(DisasCtxt *ctx,
+                                       unsigned _A, unsigned _B, TCGv b, TCGv c)
+{
+    int ret = BS_NONE;
+    switch (_A) {
+        case 0x00: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SWAP(ctx, b, c);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NORM(ctx, b, c);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SAT16(ctx, b, c);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RND16(ctx, b, c);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ABSSW(ctx, b, c);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ABSS(ctx, b, c);
+            break;
+        }
+        case 0x06: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NEGSW(ctx, b, c);
+            break;
+        }
+        case 0x07: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NEGS(ctx, b, c);
+            break;
+        }
+        case 0x08: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NORMW(ctx, b, c);
+            break;
+        }
+        case 0x3F: {
+            ret = arc_decode_major05_zop(ctx, _B, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+    return ret;
+}
+static int arc_decode_major05_op(DisasCtxt *ctx,
+                                        uint32_t opcode, TCGv a, TCGv b, TCGv c)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 16, 6);
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _b = extract32(opcode, 24, 3);
+
+    _B = (_B << 3) | _b;
+
+    switch (_i) {
+        case 0x00: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASLm(ctx, a, b, c);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LSRm(ctx, a, b, c);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASRm(ctx, a, b, c);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RORm(ctx, a, b, c);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MUL64(ctx, a, b, c);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MULU64(ctx, a, b, c);
+            break;
+        }
+        case 0x06: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADDS(ctx, a, b, c);
+            break;
+        }
+        case 0x07: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUBS(ctx, a, b, c);
+            break;
+        }
+        case 0x08: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_DIVAW(ctx, a, b, c);
+            break;
+        }
+        case 0x0A: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASLS(ctx, a, b, c);
+            break;
+        }
+        case 0x0B: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASRS(ctx, a, b, c);
+            break;
+        }
+        case 0x28: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADDSDW(ctx, a, b, c);
+            break;
+        }
+        case 0x29: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUBSDW(ctx, a, b, c);
+            break;
+        }
+        case 0x2F: {
+            ret = arc_decode_major05_sop(ctx, _A, _B, b, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major05(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _C = extract32(opcode, 6, 6);
+    unsigned _F = extract32(opcode, 15, 1);
+    unsigned _Q = extract32(opcode, 0, 5);
+    unsigned _S = extract32(opcode, 0, 6);
+    unsigned _b = extract32(opcode, 24, 3);
+    unsigned _s = extract32(opcode, 6, 6);
+    unsigned _u = extract32(opcode, 6, 6);
+
+    _B = (_B << 3) | _b;
+
+    switch (extract32(opcode, 22, 2)) {
+        case 0x00: {
+            /*
+                Extension ALU Operation, Register-Register
+            */
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv c = cpu_r[_C];
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major05_op(ctx, opcode, a, b, c);
+            break;
+        }
+        case 0x01: {
+            /*
+                Extension ALU Operation, Register with Unsigned 6-bit Immediate
+            */
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv u = tcg_const_local_i32(_u);
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major05_op(ctx, opcode, a, b, u);
+
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x02: {
+            /*
+                Extension ALU Operation, Register with Signed 12-bit Immediate
+            */
+            TCGv b = cpu_r[_B];
+            TCGv s = tcg_const_local_i32(sextract32((_S << 6) | _s, 0, 12));
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major05_op(ctx, opcode, b, b, s);
+
+            tcg_temp_free_i32(s);
+            break;
+        }
+        case 0x03: {
+            ctx->opt.f = _F;
+            TCGLabel *skip = gen_new_label();
+
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+
+            if (extract32(opcode, 5, 1) == 0) {
+                /*
+                    Extension ALU Operation, Conditional Register
+                */
+                TCGv b = cpu_r[_B];
+                TCGv c = cpu_r[_C];
+
+                ret = arc_decode_major05_op(ctx, opcode, b, b, c);
+
+            } else {
+                /*
+                    Extension ALU Operation, Conditional Register with
+                    Unsigned 6-bit Immediate
+                */
+                TCGv b = cpu_r[_B];
+                TCGv u = tcg_const_local_i32(_u);
+
+                ret = arc_decode_major05_op(ctx, opcode, b, b, u);
+
+                tcg_temp_free_i32(u);
+            }
+
+            gen_set_label(skip);
+            break;
+        }
+    }
+    return ret;
+}
+
+/*
+
+    Load /Add Register-Register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+---+------+
+    | major   | b   | c   | i | a    |
+    +---------+-----+-----+---+------+
+    |0 1 1 0 0|b b b|c c c|i i|a a a |
+    +---------+-----+-----+---+------+
+*/
+static int arc_decode_major0C(DisasCtxt *ctx, uint32_t opcode)
+{
+    unsigned _a = extract32(opcode, 0, 3);
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 3, 2);
+    int ret = BS_NONE;
+
+    TCGv a = cpu_r[(_a / 4) * 12 + _a % 4];
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+
+    switch (_i) {
+        case 0x00: {
+            ctx->opt.zz = 0;
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.zz = 1;
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        case 0x02: {
+            ctx->opt.zz = 2;
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_ADD(ctx, a, b, c);
+            break;
+        }
+    }
+    return ret;
+}
+
+/*
+
+    Load /Add Register-Register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+---+------+
+    | major   | b   | c   | i | u    |
+    +---------+-----+-----+---+------+
+    |0 1 1 0 1|b b b|c c c|i i|u u u |
+    +---------+-----+-----+---+------+
+*/
+static int arc_decode_major0D(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 3);
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 3, 2);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_ADD(ctx, c, b, u);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_SUB(ctx, c, b, u);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_ASLm(ctx, c, b, u);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_ASRm(ctx, c, b, u);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+
+    Mov/Cmp/Add with High Register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+---+------+
+    | major   | b   | h   | i | H    |
+    +---------+-----+-----+---+------+
+    |0 1 1 1 0|b b b|h h h|i i|H H H |
+    +---------+-----+-----+---+------+
+*/
+static int arc_decode_major0E(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _H = extract32(opcode, 0, 3);
+    unsigned _h = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 3, 2);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv h = cpu_r[(_H << 3) | _h];
+
+    switch (_i) {
+        case 0x00: {
+            arc_decode_src(ctx, h);
+            ret = arc_gen_ADD(ctx, b, b, h);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, h);
+            ret = arc_gen_MOV(ctx, b, h);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, h);
+            ret = arc_gen_CMP(ctx, b, h);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_MOV(ctx, h, b);
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/*
+
+    General Operations, register-register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | c   | i        |
+    +---------+-----+-----+----------+
+    |0 1 1 1 1|b b b|c c c|i i i i i |
+    +---------+-----+-----+----------+
+
+    General Operations, register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | i   | 0        |
+    +---------+-----+-----+----------+
+    |0 1 1 1 1|b b b|i i i|0 0 0 0 0 |
+    +---------+-----+-----+----------+
+
+    General Operations, no register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | i   | 7   | 0        |
+    +---------+-----+-----+----------+
+    |0 1 1 1 1|i i i|1 1 1|0 0 0 0 0 |
+    +---------+-----+-----+----------+
+*/
+static int arc_decode_major0F_zop(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 8, 3);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_NOP(ctx);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_UNIMP(ctx);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_EQ);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_NE);
+            break;
+        }
+        case 0x06: {
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_AL);
+            break;
+        }
+        case 0x07: {
+            ctx->opt.d = 1;
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_AL);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major0F_sop(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_J(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.d = 1;
+            ret = arc_gen_J(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_JL(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x03: {
+            ctx->opt.d = 1;
+            ret = arc_gen_JL(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x06: {
+            TCGLabel *skip = gen_new_label();
+
+            arc_gen_jump_ifnot(ctx, ARC_COND_NE, skip);
+
+            ret = arc_gen_SUB(ctx, b, b, b);
+
+            gen_set_label(skip);
+
+            break;
+        }
+        case 0x07: {
+            ret = arc_decode_major0F_zop(ctx, opcode);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major0F(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 0, 5);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_decode_major0F_sop(ctx, opcode);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_SUB(ctx, b, b, c);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_AND(ctx, b, b, c);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_OR(ctx, b, b, c);
+            break;
+        }
+        case 0x06: {
+            ret = arc_gen_BIC(ctx, b, b, c);
+            break;
+        }
+        case 0x07: {
+            ret = arc_gen_XOR(ctx, b, b, c);
+            break;
+        }
+        case 0x0B: {
+            ret = arc_gen_TST(ctx, b, c);
+            break;
+        }
+        case 0x0C: {
+            ret = arc_gen_MUL64(ctx, b, b, c);
+            break;
+        }
+        case 0x0D: {
+            ret = arc_gen_SEXB(ctx, b, c);
+            break;
+        }
+        case 0x0E: {
+            ret = arc_gen_SEXW(ctx, b, c);
+            break;
+        }
+        case 0x0F: {
+            ret = arc_gen_EXTB(ctx, b, c);
+            break;
+        }
+        case 0x10: {
+            ret = arc_gen_EXTW(ctx, b, c);
+            break;
+        }
+        case 0x11: {
+            ret = arc_gen_ABS(ctx, b, c);
+            break;
+        }
+        case 0x12: {
+            ret = arc_gen_NOT(ctx, b, c);
+            break;
+        }
+        case 0x13: {
+            ret = arc_gen_NEG(ctx, b, c);
+            break;
+        }
+        case 0x14: {
+            ret = arc_gen_ADD1(ctx, b, b, c);
+            break;
+        }
+        case 0x15: {
+            ret = arc_gen_ADD2(ctx, b, b, c);
+            break;
+        }
+        case 0x16: {
+            ret = arc_gen_ADD3(ctx, b, b, c);
+            break;
+        }
+        case 0x18: {
+            ret = arc_gen_ASLm(ctx, b, b, c);
+            break;
+        }
+        case 0x19: {
+            ret = arc_gen_LSRm(ctx, b, b, c);
+            break;
+        }
+        case 0x1A: {
+            ret = arc_gen_ASRm(ctx, b, b, c);
+            break;
+        }
+        case 0x1B: {
+            ret = arc_gen_ASL(ctx, b, c);
+            break;
+        }
+        case 0x1C: {
+            ret = arc_gen_ASR(ctx, b, c);
+            break;
+        }
+        case 0x1D: {
+            ret = arc_gen_LSR(ctx, b, c);
+            break;
+        }
+        case 0x1E: {
+            unsigned _u = extract32(opcode, 5, 6);
+            TCGv u = tcg_const_local_i32(_u);
+            ret = arc_gen_TRAP(ctx, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x1F: {
+            ret = arc_gen_BRK(ctx);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+/*
+    Load/Store with Offset
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | c   | u        |
+    +---------+-----+-----+----------+
+    |I I I I I|b b b|c c c|u u u u u |
+    +---------+-----+-----+----------+
+
+*/
+static int arc_decode_major10_16(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 11, 5);
+    unsigned _u = extract32(opcode, 0, 5);
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+    TCGv u;
+
+    switch (_i) {
+        case 0x10: {
+            ctx->opt.zz = 0;
+            u = tcg_const_local_i32(_u << 2);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x11: {
+            ctx->opt.zz = 1;
+            u = tcg_const_local_i32(_u);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x12: {
+            ctx->opt.zz = 2;
+            u = tcg_const_local_i32(_u << 1);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x13: {
+            ctx->opt.zz = 2;
+            ctx->opt.x = 1;
+            u = tcg_const_local_i32(_u << 1);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x14: {
+            ctx->opt.zz = 0;
+            u = tcg_const_local_i32(_u << 2);
+            ret = arc_gen_ST(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x15: {
+            ctx->opt.zz = 1;
+            u = tcg_const_local_i32(_u);
+            ret = arc_gen_ST(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x16: {
+            ctx->opt.zz = 2;
+            u = tcg_const_local_i32(_u << 1);
+            ret = arc_gen_ST(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+    }
+
+
+    return ret;
+}
+
+/*
+    Shift/Subtract/Bit Immediate
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | i   | u        |
+    +---------+-----+-----+----------+
+    |1 0 1 1 1|b b b|i i i|u u u u u |
+    +---------+-----+-----+----------+
+
+*/
+static int arc_decode_major17(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 5, 3);
+    unsigned _u = extract32(opcode, 0, 5);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_ASLm(ctx, b, b, u);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_LSRm(ctx, b, b, u);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_ASRm(ctx, b, b, u);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_SUB(ctx, b, b, u);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_BSET(ctx, b, b, u);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_BCLR(ctx, b, b, u);
+            break;
+        }
+        case 0x06: {
+            ret = arc_gen_BMSK(ctx, b, b, u);
+            break;
+        }
+        case 0x07: {
+            ret = arc_gen_BTST(ctx, b, u);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(u);
+
+    return ret;
+}
+
+/*
+    Stack Pointer Based Instructions
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | i   | u        |
+    +---------+-----+-----+----------+
+    |1 1 0 0 0|b b b|i i i|u u u u u |
+    +---------+-----+-----+----------+
+
+*/
+static int arc_decode_major18(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 5, 3);
+    unsigned _u = extract32(opcode, 0, 5);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u << 2);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_LD(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.zz = 1;
+            ret = arc_gen_LD(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_ST(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x03: {
+            ctx->opt.zz = 1;
+            ret = arc_gen_ST(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_ADD(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x05: {
+            switch (_b) {
+                case 0x00: {
+                    ret = arc_gen_ADD(ctx, cpu_sp, cpu_sp, u);
+                    break;
+                }
+                case 0x01: {
+                    ret = arc_gen_SUB(ctx, cpu_sp, cpu_sp, u);
+                    break;
+                }
+                default: {
+                    ret = arc_gen_INVALID(ctx);
+                }
+            }
+            break;
+        }
+        case 0x06: {
+            switch (_u) {
+                case 0x01: {
+                    ret = arc_gen_POP(ctx, b);
+                    break;
+                }
+                case 0x11: {
+                    ret = arc_gen_POP(ctx, cpu_blink);
+                    break;
+                }
+                default: {
+                    ret = arc_gen_INVALID(ctx);
+                }
+            }
+            break;
+        }
+        case 0x07: {
+            switch (_u) {
+                case 0x01: {
+                    ret = arc_gen_PUSH(ctx, b);
+                    break;
+                }
+                case 0x11: {
+                    ret = arc_gen_PUSH(ctx, cpu_blink);
+                    break;
+                }
+                default: {
+                    ret = arc_gen_INVALID(ctx);
+                }
+            }
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(u);
+
+    return ret;
+}
+
+/*
+    Stack Pointer Based Instructions
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+---+------------------+
+    | major   | i | s                |
+    +---------+---+------------------+
+    |1 1 0 0 1|i i|s s s s s s s s s |
+    +---------+---+------------------+
+*/
+static int arc_decode_major19(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 9);
+    unsigned _i = extract32(opcode, 9, 2);
+    TCGv s;
+
+    switch (_i) {
+        case 0x00: {
+            ctx->opt.zz = 0;
+            s = tcg_const_local_i32(_s << 2);
+            ret = arc_gen_LD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.zz = 1;
+            s = tcg_const_local_i32(_s);
+            ret = arc_gen_LD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+        case 0x02: {
+            ctx->opt.zz = 2;
+            s = tcg_const_local_i32(_s << 1);
+            ret = arc_gen_LD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+        case 0x03: {
+            s = tcg_const_local_i32(_s << 2);
+            ret = arc_gen_ADD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    Load PCL-Relative
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+----------------+
+    | major   | b   | s              |
+    +---------+-----+----------------+
+    |1 1 0 1 0|b b b|s s s s s s s s |
+    +---------+-----+----------------+
+
+*/
+static int arc_decode_major1A(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 8);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u << 2);
+
+    ret = arc_gen_LD(ctx, b, cpu_pcl, u);
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+    Move Immediate
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+----------------+
+    | major   | b   | u              |
+    +---------+-----+----------------+
+    |1 1 0 1 1|b b b|u u u u u u u u |
+    +---------+-----+----------------+
+*/
+static int arc_decode_major1B(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 8);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    ret = arc_gen_MOV(ctx, b, u);
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+    ADD/CMP Immediate
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-+--------------+
+    | major   | b   |i| u            |
+    +---------+-----+-+--------------+
+    |1 1 1 0 0|b b b|i|u u u u u u u |
+    +---------+-----+-+--------------+
+*/
+static int arc_decode_major1C(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 7);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 7, 1);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    if (_i == 0) {
+        ret = arc_gen_ADD(ctx, b, b, u);
+    } else {
+        ret = arc_gen_CMP(ctx, b, u);
+    }
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+    Branch on Compare Register with Zero
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-+--------------+
+    | major   | b   |i| s            |
+    +---------+-----+-+--------------+
+    |1 1 1 0 1|b b b|i|s s s s s s s |
+    +---------+-----+-+--------------+
+*/
+static int arc_decode_major1D(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 7);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 7, 1);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv s = tcg_const_local_i32(_s);
+
+    if (_i == 0) {
+        ret = arc_gen_BR(ctx, b, ctx->zero, s, TCG_COND_EQ);
+    } else {
+        ret = arc_gen_BR(ctx, b, ctx->zero, s, TCG_COND_NE);
+    }
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    Branch on Compare Register with Zero
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+---+------------------+
+    | major   | b | s                |
+    +---------+---+------------------+
+    |1 1 1 1 0|i i|s s s s s s s s s |
+    +---------+---+------------------+
+*/
+static int arc_decode_major1E(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 9);
+    unsigned _i = extract32(opcode, 9, 2);
+    TCGv s = tcg_const_local_i32(_s);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_B(ctx, s, ARC_COND_AL);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_B(ctx, s, ARC_COND_EQ);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_B(ctx, s, ARC_COND_NE);
+            break;
+        }
+        case 0x03: {
+            signed _s = sextract32(opcode, 0, 6);
+            unsigned _i = extract32(opcode, 5, 3);
+            TCGv s = tcg_const_local_i32(_s);
+
+            switch (_i) {
+                case 0x00: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_GT);
+                    break;
+                }
+                case 0x01: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_GE);
+                    break;
+                }
+                case 0x02: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LT);
+                    break;
+                }
+                case 0x03: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LE);
+                    break;
+                }
+                case 0x04: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_HI);
+                    break;
+                }
+                case 0x05: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_HS);
+                    break;
+                }
+                case 0x06: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LO);
+                    break;
+                }
+                case 0x07: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LS);
+                    break;
+                }
+            }
+
+            tcg_temp_free_i32(s);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    Branch on Compare Register with Zero
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+----------------------+
+    | major   | s                    |
+    +---------+----------------------+
+    |1 1 1 1 1|s s s s s s s s s s s |
+    +---------+----------------------+
+*/
+static int arc_decode_major1F(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 11);
+
+    TCGv s = tcg_const_local_i32(_s);
+
+    ret = arc_gen_BL(ctx, s, ARC_COND_AL);
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+int arc_decode(DisasCtxt *ctx)
+{
+    unsigned curr_major;
+    uint32_t curr_opcode;
+
+    unsigned next_major;
+    uint32_t next_opcode;
+
+    decode_f    decode[32] = {
+        [0x00]  = arc_decode_major00,
+        [0x01]  = arc_decode_major01,
+        [0x02]  = arc_decode_major02,
+        [0x03]  = arc_decode_major03,
+        [0x04]  = arc_decode_major04,
+        [0x05]  = arc_decode_major05,
+
+        [0x06]  = arc_decode_invalid,
+        [0x07]  = arc_decode_invalid,
+        [0x08]  = arc_decode_invalid,
+        [0x09]  = arc_decode_invalid,
+        [0x0a]  = arc_decode_invalid,
+        [0x0b]  = arc_decode_invalid,
+
+        [0x0c]  = arc_decode_major0C,
+        [0x0d]  = arc_decode_major0D,
+        [0x0e]  = arc_decode_major0E,
+        [0x0f]  = arc_decode_major0F,
+
+        [0x10]  = arc_decode_major10_16,
+        [0x11]  = arc_decode_major10_16,
+        [0x12]  = arc_decode_major10_16,
+        [0x13]  = arc_decode_major10_16,
+        [0x14]  = arc_decode_major10_16,
+        [0x15]  = arc_decode_major10_16,
+        [0x16]  = arc_decode_major10_16,
+
+        [0x17]  = arc_decode_major17,
+        [0x18]  = arc_decode_major18,
+        [0x19]  = arc_decode_major19,
+        [0x1a]  = arc_decode_major1A,
+        [0x1b]  = arc_decode_major1B,
+        [0x1c]  = arc_decode_major1C,
+        [0x1d]  = arc_decode_major1D,
+        [0x1e]  = arc_decode_major1E,
+        [0x1f]  = arc_decode_major1F,
+
+    };
+    memset(&ctx->opt, 0, sizeof(ctx->opt));
+
+    /*
+        1. get current opcode
+        2. set npc
+    */
+    curr_opcode = cpu_ldl_code(ctx->env, ctx->cpc);
+    curr_major  = extract32(curr_opcode, 11, 5);
+
+    if (curr_major <= 5) {
+        curr_opcode = (curr_opcode << 16) | (curr_opcode >> 16);
+        ctx->npc = ctx->cpc + 4;
+    } else {
+        ctx->npc = ctx->cpc + 2;
+    }
+
+    /*
+        3. set dpc (used by BL)
+    */
+    next_opcode = cpu_ldl_code(ctx->env, ctx->npc);
+    next_major  = extract32(next_opcode, 11, 5);
+    if (next_major <= 5) {
+        ctx->dpc = ctx->npc + 4;
+    } else {
+        ctx->dpc = ctx->npc + 2;
+    }
+
+    ctx->pcl = ctx->cpc & 0xfffffffc;
+
+    return  decode[curr_major](ctx, curr_opcode);
+}
Signature · 1 line
2.4.9 (Apple Git-60)
#48 lore raw

Re: [Qemu-devel] [PATCH RFC v1 28/29] target-arc: decode

Quoted 1 line · Michael Rolnik

+ decode_f decode[32] = {

There's no reason to use an array here, and worse, a non-static non-const array. Just use a switch here

Quoted 1 line

+ return decode[curr_major](ctx, curr_opcode);

r~

#49 lore raw

RFC PATCH 29/29 target-arc: sample board

In reply to Michael Rolnik
---
 MAINTAINERS          |  1 +
 hw/arc/Makefile.objs | 21 ++++++++++++++
 hw/arc/sample.c      | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 hw/arc/Makefile.objs
 create mode 100644 hw/arc/sample.c
MAINTAINERS +1 -0
index 0500cf5..6d7ce0b 100644
@@ -103,6 +103,7 @@ ARC
 M: Michael Rolnik <[email protected]>
 S: Maintained
 F: target-arc/
+F: hw/arc
 
 ARM
 M: Peter Maydell <[email protected]>
hw/arc/Makefile.objs new file +21 -0
new file mode 100644
index 0000000..5ac5cb7
@@ -0,0 +1,21 @@
+#
+#  QEMU ARC CPU
+#
+#  Copyright (c) 2016 Michael Rolnik
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, see
+#  <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+obj-y   += sample.o
hw/arc/sample.c new file +80 -0

80 lines not on this page · raw message

Signature · 1 line
2.4.9 (Apple Git-60)
#50 lore raw

cover ARC cores

In reply to Michael Rolnik

Hi Michael,

Quoted 10 lines · Michael Rolnik

This series of patches adds ARC target to QEMU. It indends to support ????- ARCtangent-A5 processor
????- ARC 600 processor
????- ARC 700 processor

All instructions except ASLS are implemented. Not fully tested yet. However I was able to execute correctly recursive fibonacci calculation. Reset vector is assumed to be some hardcoded value which worked for my test. I am planning to get FreeRTOS for ARC, once I get it, I will able to verify and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
?a) Builds for ARC
?b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:

	mov	r0, 1
	mov	r1, 2
	mov	r1, r0

--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble?
Dump of assembler code for function _start:
=> 0x00000100 <+0>: mov r0,0x1
???0x00000104 <+4>: mov r1,0x2
???0x00000108 <+8>: mov r1,r0
End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey

#51 lore raw

H Alexey.

Thanks.

I need some help in getting a small code that exercises interrupts. For several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it seems I forgot some of the things related to interrupts. I compiled FreeRTOS demo from embARC, however I could not find interrupt vectors there, I assume their board has ROM.
So, if you can help me with such a code, it would be great.

thanks,
Michael

On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <[email protected]

Quoted 69 lines

wrote:

Hi Michael,

Quoted 8 lines · Michael Rolnik

This series of patches adds ARC target to QEMU. It indends to support
- ARCtangent-A5 processor
- ARC 600 processor
- ARC 700 processor

All instructions except ASLS are implemented. Not fully tested yet. However I was able to execute correctly recursive fibonacci calculation. Reset vector is assumed to be some hardcoded value which worked for my

test.

Quoted 1 line

I am planning to get FreeRTOS for ARC, once I get it, I will able to

verify

Quoted 1 line

and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
a) Builds for ARC
b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:

        mov     r0, 1
        mov     r1, 2
        mov     r1, r0

--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble
Dump of assembler code for function _start:

=> 0x00000100 <+0>:     mov     r0,0x1
   0x00000104 <+4>:     mov     r1,0x2
   0x00000108 <+8>:     mov     r1,r0

End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from
this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start
playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey

Signature · 2 lines
Best Regards,
Michael Rolnik
#52 lore raw

Hi Michael,

I'm pretty sure embARC was not meant to be run on ARCompact (AKA ISAv1 cores like ARC600 & ARC700) instead targets were ARCv2 cores like ARC EM and ARC HS. Unfortunately I have no experience with embARC so adding more experienced person in the thread (Igor Guryanov) who may shed some light on interrupts in embARC.

-Alexey

On Sat, 2016-09-17 at 21:26 +0300, Michael Rolnik wrote:
H Alexey.

Thanks.

I need some help in getting a small code that exercises interrupts. For several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it seems I forgot some of the things related to interrupts. I compiled FreeRTOS demo from embARC, however I could not find interrupt vectors there, I assume their board has ROM. So, if you can help me with such a code, it would be great.

thanks,
Michael

On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <[email protected]<mailto:[email protected]>> wrote:
Hi Michael,

Quoted 10 lines · Michael Rolnik

This series of patches adds ARC target to QEMU. It indends to support
- ARCtangent-A5 processor
- ARC 600 processor
- ARC 700 processor

All instructions except ASLS are implemented. Not fully tested yet. However I was able to execute correctly recursive fibonacci calculation. Reset vector is assumed to be some hardcoded value which worked for my test. I am planning to get FreeRTOS for ARC, once I get it, I will able to verify and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
a) Builds for ARC
b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:

        mov     r0, 1
        mov     r1, 2
        mov     r1, r0

--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble
Dump of assembler code for function _start:

=> 0x00000100 <+0>:     mov     r0,0x1
   0x00000104 <+4>:     mov     r1,0x2
   0x00000108 <+8>:     mov     r1,r0

End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey

--
Best Regards,
Michael Rolnik

#53 lore raw

Hi Michael,

Long time ago debugged one problem with embARC and I remember I was also puzzled with itss interrupt handling approach. The board itself can fit only prebootloader in the ROM, and interrupt handling is kept in embARC itself.

But, the projects is aimed to support several different RTOS. As I remember, BSP was separated and made ‘universal’.
In other words, not very transparent and obvious ☺. If I recall it there were a single entry for interrupt/exceptions which scanned OS defined data structure in a search for pointers for actual handlers. i.e. it was very different from what you can find in simple baremetal example (like this one - https://github.com/foss-for-synopsys-dwc-arc-processors/ARC-Development-Systems-Forum/tree/master/examples/EMSK/timer_IRQ )

Let me refresh my memory on embARC internals which might have already evolved and I give you overview in a day or two.

Regards,
Igor.

From: Alexey Brodkin
Sent: Monday, September 19, 2016 3:41 PM
To: [email protected]
Cc: [email protected]; Igor Guryanov <[email protected]>; [email protected]
Subject: Re: [PATCH RFC v1 00/29] ARC cores

Hi Michael,

I'm pretty sure embARC was not meant to be run on ARCompact (AKA ISAv1 cores like ARC600 & ARC700) instead targets were ARCv2 cores like ARC EM and ARC HS. Unfortunately I have no experience with embARC so adding more experienced person in the thread (Igor Guryanov) who may shed some light on interrupts in embARC.

-Alexey

On Sat, 2016-09-17 at 21:26 +0300, Michael Rolnik wrote:
H Alexey.

Thanks.

I need some help in getting a small code that exercises interrupts. For several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it seems I forgot some of the things related to interrupts. I compiled FreeRTOS demo from embARC, however I could not find interrupt vectors there, I assume their board has ROM. So, if you can help me with such a code, it would be great.

thanks,
Michael

On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <[email protected]<mailto:[email protected]>> wrote:

Hi Michael,

Quoted 10 lines · Michael Rolnik

This series of patches adds ARC target to QEMU. It indends to support
- ARCtangent-A5 processor
- ARC 600 processor
- ARC 700 processor

All instructions except ASLS are implemented. Not fully tested yet. However I was able to execute correctly recursive fibonacci calculation. Reset vector is assumed to be some hardcoded value which worked for my test. I am planning to get FreeRTOS for ARC, once I get it, I will able to verify and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
a) Builds for ARC
b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:

        mov     r0, 1
        mov     r1, 2
        mov     r1, r0

--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble
Dump of assembler code for function _start:

=> 0x00000100 <+0>:     mov     r0,0x1
   0x00000104 <+4>:     mov     r1,0x2
   0x00000108 <+8>:     mov     r1,r0

End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey

--
Best Regards,
Michael Rolnik

#54 lore raw

Hi Igor,

I will try to compile this example and test my implementations.

Thank you,
Michael

Quoted 170 lines · Igor Guryanov

Hi Michael,

Long time ago debugged one problem with embARC and I remember I was also puzzled with itss interrupt handling approach.

The board itself can fit only prebootloader in the ROM, and interrupt handling is kept in embARC itself.

But, the projects is aimed to support several different RTOS. As I remember, BSP was separated and made ‘universal’.
In other words, not very transparent and obvious J. If I recall it there were a single entry for interrupt/exceptions which scanned OS defined data structure in a search for pointers for actual handlers. i.e. it was very different from what you can find in simple baremetal example (like this one
- https://github.com/foss-for-synopsys-dwc-arc-processors/
ARC-Development-Systems-Forum/tree/master/examples/EMSK/timer_IRQ )

Let me refresh my memory on embARC internals which might have already evolved and I give you overview in a day or two.

Regards,

Igor.

*From:* Alexey Brodkin
*Sent:* Monday, September 19, 2016 3:41 PM
*To:* [email protected]
*Cc:* [email protected]; Igor Guryanov <[email protected]>; [email protected]
*Subject:* Re: [PATCH RFC v1 00/29] ARC cores

Hi Michael,

I'm pretty sure embARC was not meant to be run on ARCompact (AKA ISAv1 cores like ARC600 & ARC700) instead targets were ARCv2 cores like ARC EM and ARC HS. Unfortunately I have no experience with embARC so adding more experienced person in the thread (Igor Guryanov) who may shed some light on interrupts in embARC.

-Alexey

On Sat, 2016-09-17 at 21:26 +0300, Michael Rolnik wrote:

H Alexey.

Thanks.

I need some help in getting a small code that exercises interrupts. For several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it seems I forgot some of the things related to interrupts. I compiled FreeRTOS demo from embARC, however I could not find interrupt vectors there, I assume their board has ROM.

So, if you can help me with such a code, it would be great.

thanks,

Michael

On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <
[email protected]> wrote:

Hi Michael,

Quoted 8 lines · Michael Rolnik

This series of patches adds ARC target to QEMU. It indends to support
- ARCtangent-A5 processor
- ARC 600 processor
- ARC 700 processor

All instructions except ASLS are implemented. Not fully tested yet. However I was able to execute correctly recursive fibonacci calculation. Reset vector is assumed to be some hardcoded value which worked for my

test.

Quoted 1 line

I am planning to get FreeRTOS for ARC, once I get it, I will able to

verify

Quoted 1 line

and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
a) Builds for ARC
b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:

        mov     r0, 1
        mov     r1, 2
        mov     r1, r0

--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble
Dump of assembler code for function _start:

=> 0x00000100 <+0>:     mov     r0,0x1
   0x00000104 <+4>:     mov     r1,0x2
   0x00000108 <+8>:     mov     r1,r0

End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from
this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start
playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey

--

Best Regards,
Michael Rolnik

Signature · 2 lines
Best Regards,
Michael Rolnik