diff mbox

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

Message ID 1473373930-31547-3-git-send-email-mrolnik@gmail.com
State New
Headers show

Commit Message

Michael Rolnik Sept. 8, 2016, 10:31 p.m. UTC
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 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

Comments

Richard Henderson Sept. 20, 2016, 8:51 p.m. UTC | #1
On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> ---
>  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.

> +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.

> +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~
diff mbox

Patch

diff --git a/target-arc/Makefile.objs b/target-arc/Makefile.objs
index a3475dd..6fdb000 100644
--- a/target-arc/Makefile.objs
+++ b/target-arc/Makefile.objs
@@ -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
diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
new file mode 100644
index 0000000..50119bf
--- /dev/null
+++ b/target-arc/translate-inst.c
@@ -0,0 +1,170 @@ 
+/*
+ *  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>
+ */
+
+/*
+    see http://me.bios.io/images/d/dd/ARCompactISA_ProgrammersReference.pdf
+*/
+
+#include "translate.h"
+#include "qemu/bitops.h"
+#include "tcg/tcg.h"
+#include "translate-inst.h"
+
+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)                         */
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_add_Vf(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(cpu_Vf, t1, 31);/*  Vf = t1(31)                         */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+/*
+    ADC
+*/
+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();
+    }
+
+    tcg_gen_add_tl(rslt, src1, src2);
+    tcg_gen_add_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_add_Cf(rslt, src1, src2);
+        gen_add_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ADD
+*/
+int arc_gen_ADD(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_add_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_add_Cf(rslt, src1, src2);
+        gen_add_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ADD1
+*/
+int arc_gen_ADD1(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 1);
+    arc_gen_ADD(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ADD2
+*/
+int arc_gen_ADD2(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 2);
+    arc_gen_ADD(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ADD3
+*/
+int arc_gen_ADD3(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 3);
+    arc_gen_ADD(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
new file mode 100644
index 0000000..08e23c7
--- /dev/null
+++ b/target-arc/translate-inst.h
@@ -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);
+