All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2)
@ 2017-06-26 22:03 Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 1/7] target/m68k: add fscc Laurent Vivier
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

Second part of patches submitted in the v3.

This series adds a subset of single precision and
double precision instructions using
set_floatx80_rounding_precision() to round the result.

For some other instructions, we introduce a new
function, floatx80_round(), to round them manually.

It also adds instructions fsglmul, fsgldiv,
fmovecr and fscc (since v3, use tcg_gen_setcond())

fmovem manages static and dynamic register list,
all the code has been moved to an helper.

v2:
  Fix gen_fcc_cond(): g[12] mark global variables,
  not variables to free.
  use floatx80_round() to compute fsglmul and fsgldiv
  split fmovem helper into 6 helpers

Laurent Vivier (7):
  target/m68k: add fscc.
  target/m68k: add fmovecr
  target/m68k: add explicit single and double precision operations
  softfloat: define floatx80_round()
  target/m68k: add fsglmul and fsgldiv
  target/m68k: add explicit single and double precision operations (part
    2)
  target/m68k: add fmovem

 fpu/softfloat.c          |  15 ++
 include/fpu/softfloat.h  |   1 +
 target/m68k/fpu_helper.c | 300 +++++++++++++++++++++++++++++++++++-
 target/m68k/helper.h     |  27 +++-
 target/m68k/translate.c  | 391 ++++++++++++++++++++++++++++++++---------------
 5 files changed, 611 insertions(+), 123 deletions(-)

-- 
2.9.4

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 1/7] target/m68k: add fscc.
  2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
@ 2017-06-26 22:03 ` Laurent Vivier
  2017-06-26 22:55   ` Richard Henderson
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr Laurent Vivier
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

use DisasCompare with FPU conditions in fscc and fbcc.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target/m68k/translate.c | 213 ++++++++++++++++++++++++++++++------------------
 1 file changed, 134 insertions(+), 79 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 7aa0fdc..8824f81 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -4633,142 +4633,196 @@ undef:
     disas_undef_fpu(env, s, insn);
 }
 
-DISAS_INSN(fbcc)
+static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond)
 {
-    uint32_t offset;
-    uint32_t addr;
-    TCGLabel *l1;
-    TCGv tmp, fpsr;
-
-    addr = s->pc;
-    offset = cpu_ldsw_code(env, s->pc);
-    s->pc += 2;
-    if (insn & (1 << 6)) {
-        offset = (offset << 16) | read_im16(env, s);
-    }
+    TCGv fpsr;
 
+    c->g1 = 1;
+    c->v2 = tcg_const_i32(0);
+    c->g2 = 0;
+    /* TODO: Raise BSUN exception.  */
     fpsr = tcg_temp_new();
     gen_load_fcr(s, fpsr, M68K_FPSR);
-    l1 = gen_new_label();
-    /* TODO: Raise BSUN exception.  */
-    /* Jump to l1 if condition is true.  */
-    switch (insn & 0x3f)  {
+    switch (cond) {
     case 0:  /* False */
     case 16: /* Signaling False */
+        c->v1 = c->v2;
+        c->tcond = TCG_COND_NEVER;
         break;
     case 1:  /* EQual Z */
     case 17: /* Signaling EQual Z */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_Z);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
+        c->tcond = TCG_COND_NE;
         break;
     case 2:  /* Ordered Greater Than !(A || Z || N) */
     case 18: /* Greater Than !(A || Z || N) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr,
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr,
                          FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
+        c->tcond = TCG_COND_EQ;
         break;
     case 3:  /* Ordered Greater than or Equal Z || !(A || N) */
     case 19: /* Greater than or Equal Z || !(A || N) */
-        assert(FPSR_CC_A == (FPSR_CC_N >> 3));
-        tmp = tcg_temp_new();
-        tcg_gen_shli_i32(tmp, fpsr, 3);
-        tcg_gen_or_i32(tmp, tmp, fpsr);
-        tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N);
-        tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_Z);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        g_assert(FPSR_CC_A == (FPSR_CC_N >> 3));
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_shli_i32(c->v1, fpsr, 3);
+        tcg_gen_or_i32(c->v1, c->v1, fpsr);
+        tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
+        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_Z);
+        c->tcond = TCG_COND_NE;
         break;
     case 4:  /* Ordered Less Than !(!N || A || Z); */
     case 20: /* Less Than !(!N || A || Z); */
-        tmp = tcg_temp_new();
-        tcg_gen_xori_i32(tmp, fpsr, FPSR_CC_N);
-        tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_N);
+        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z);
+        c->tcond = TCG_COND_EQ;
         break;
     case 5:  /* Ordered Less than or Equal Z || (N && !A) */
     case 21: /* Less than or Equal Z || (N && !A) */
-        assert(FPSR_CC_A == (FPSR_CC_N >> 3));
-        tmp = tcg_temp_new();
-        tcg_gen_xori_i32(tmp, fpsr, FPSR_CC_A);
-        tcg_gen_shli_i32(tmp, tmp, 3);
-        tcg_gen_ori_i32(tmp, tmp, FPSR_CC_Z);
-        tcg_gen_and_i32(tmp, tmp, fpsr);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        g_assert(FPSR_CC_A == (FPSR_CC_N >> 3));
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_A);
+        tcg_gen_shli_i32(c->v1, c->v1, 3);
+        tcg_gen_ori_i32(c->v1, c->v1, FPSR_CC_Z);
+        tcg_gen_and_i32(c->v1, c->v1, fpsr);
+        c->tcond = TCG_COND_NE;
         break;
     case 6:  /* Ordered Greater or Less than !(A || Z) */
     case 22: /* Greater or Less than !(A || Z) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z);
+        c->tcond = TCG_COND_EQ;
         break;
     case 7:  /* Ordered !A */
     case 23: /* Greater, Less or Equal !A */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
+        c->tcond = TCG_COND_EQ;
         break;
     case 8:  /* Unordered A */
     case 24: /* Not Greater, Less or Equal A */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
+        c->tcond = TCG_COND_NE;
         break;
     case 9:  /* Unordered or Equal A || Z */
     case 25: /* Not Greater or Less then A || Z */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z);
+        c->tcond = TCG_COND_NE;
         break;
     case 10: /* Unordered or Greater Than A || !(N || Z)) */
     case 26: /* Not Less or Equal A || !(N || Z)) */
-        assert(FPSR_CC_Z == (FPSR_CC_N >> 1));
-        tmp = tcg_temp_new();
-        tcg_gen_shli_i32(tmp, fpsr, 1);
-        tcg_gen_or_i32(tmp, tmp, fpsr);
-        tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N);
-        tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_A);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        g_assert(FPSR_CC_Z == (FPSR_CC_N >> 1));
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_shli_i32(c->v1, fpsr, 1);
+        tcg_gen_or_i32(c->v1, c->v1, fpsr);
+        tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
+        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A);
+        c->tcond = TCG_COND_NE;
         break;
     case 11: /* Unordered or Greater or Equal A || Z || !N */
     case 27: /* Not Less Than A || Z || !N */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
-        tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
+        tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
+        c->tcond = TCG_COND_NE;
         break;
     case 12: /* Unordered or Less Than A || (N && !Z) */
     case 28: /* Not Greater than or Equal A || (N && !Z) */
-        assert(FPSR_CC_Z == (FPSR_CC_N >> 1));
-        tmp = tcg_temp_new();
-        tcg_gen_xori_i32(tmp, fpsr, FPSR_CC_Z);
-        tcg_gen_shli_i32(tmp, tmp, 1);
-        tcg_gen_ori_i32(tmp, tmp, FPSR_CC_A);
-        tcg_gen_and_i32(tmp, tmp, fpsr);
-        tcg_gen_andi_i32(tmp, tmp, FPSR_CC_A | FPSR_CC_N);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        g_assert(FPSR_CC_Z == (FPSR_CC_N >> 1));
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_Z);
+        tcg_gen_shli_i32(c->v1, c->v1, 1);
+        tcg_gen_ori_i32(c->v1, c->v1, FPSR_CC_A);
+        tcg_gen_and_i32(c->v1, c->v1, fpsr);
+        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_A | FPSR_CC_N);
+        c->tcond = TCG_COND_NE;
         break;
     case 13: /* Unordered or Less or Equal A || Z || N */
     case 29: /* Not Greater Than A || Z || N */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
+        c->tcond = TCG_COND_NE;
         break;
     case 14: /* Not Equal !Z */
     case 30: /* Signaling Not Equal !Z */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_Z);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
+        c->v1 = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
+        c->tcond = TCG_COND_EQ;
         break;
     case 15: /* True */
     case 31: /* Signaling True */
-        tcg_gen_br(l1);
+        c->v1 = c->v2;
+        c->tcond = TCG_COND_ALWAYS;
         break;
     }
     tcg_temp_free(fpsr);
+}
+
+static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1)
+{
+    DisasCompare c;
+
+    gen_fcc_cond(&c, s, cond);
+    tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
+    free_cond(&c);
+}
+
+DISAS_INSN(fbcc)
+{
+    uint32_t offset;
+    uint32_t base;
+    TCGLabel *l1;
+
+    base = s->pc;
+    offset = (int16_t)read_im16(env, s);
+    if (insn & (1 << 6)) {
+        offset = (offset << 16) | read_im16(env, s);
+    }
+
+    l1 = gen_new_label();
+    update_cc_op(s);
+    gen_fjmpcc(s, insn & 0x3f, l1);
     gen_jmp_tb(s, 0, s->pc);
     gen_set_label(l1);
-    gen_jmp_tb(s, 1, addr + offset);
+    gen_jmp_tb(s, 1, base + offset);
+}
+
+DISAS_INSN(fscc)
+{
+    DisasCompare c;
+    int cond;
+    TCGv tmp;
+    uint16_t ext;
+
+    ext = read_im16(env, s);
+    cond = ext & 0x3f;
+    gen_fcc_cond(&c, s, cond);
+
+    tmp = tcg_temp_new();
+    tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2);
+    free_cond(&c);
+
+    tcg_gen_neg_i32(tmp, tmp);
+    DEST_EA(env, insn, OS_BYTE, tmp, NULL);
+    tcg_temp_free(tmp);
 }
 
 DISAS_INSN(frestore)
@@ -5349,6 +5403,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(frestore,  f340, ffc0, CF_FPU);
     INSN(fsave,     f300, ffc0, CF_FPU);
     INSN(fpu,       f200, ffc0, FPU);
+    INSN(fscc,      f240, ffc0, FPU);
     INSN(fbcc,      f280, ff80, FPU);
     INSN(frestore,  f340, ffc0, FPU);
     INSN(fsave,     f300, ffc0, FPU);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr
  2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 1/7] target/m68k: add fscc Laurent Vivier
@ 2017-06-26 22:03 ` Laurent Vivier
  2017-06-27 15:45   ` Philippe Mathieu-Daudé
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 3/7] target/m68k: add explicit single and double precision operations Laurent Vivier
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

fmovecr moves a floating point constant from the
FPU ROM to a floating point register.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target/m68k/fpu_helper.c | 30 ++++++++++++++++++++++++++++++
 target/m68k/helper.h     |  1 +
 target/m68k/translate.c  | 13 ++++++++++++-
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index a9e17f5..912c0b7 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -23,6 +23,31 @@
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
 
+static const floatx80 fpu_rom[128] = {
+    [0x00] = floatx80_pi,                                   /* Pi */
+    [0x0b] = make_floatx80(0x3ffd, 0x9a209a84fbcff798ULL),  /* Log10(2) */
+    [0x0c] = make_floatx80(0x4000, 0xadf85458a2bb4a9aULL),  /* e        */
+    [0x0d] = make_floatx80(0x3fff, 0xb8aa3b295c17f0bcULL),  /* Log2(e)  */
+    [0x0e] = make_floatx80(0x3ffd, 0xde5bd8a937287195ULL),  /* Log10(e) */
+    [0x0f] = floatx80_zero,                                 /* Zero     */
+    [0x30] = floatx80_ln2,                                  /* ln(2)    */
+    [0x31] = make_floatx80(0x4000, 0x935d8dddaaa8ac17ULL),  /* ln(10)   */
+    [0x32] = floatx80_one,                                  /* 10^0     */
+    [0x33] = make_floatx80(0x4002, 0xa000000000000000ULL),  /* 10^1     */
+    [0x34] = make_floatx80(0x4005, 0xc800000000000000ULL),  /* 10^2     */
+    [0x35] = make_floatx80(0x400c, 0x9c40000000000000ULL),  /* 10^4     */
+    [0x36] = make_floatx80(0x4019, 0xbebc200000000000ULL),  /* 10^8     */
+    [0x37] = make_floatx80(0x4034, 0x8e1bc9bf04000000ULL),  /* 10^16    */
+    [0x38] = make_floatx80(0x4069, 0x9dc5ada82b70b59eULL),  /* 10^32    */
+    [0x39] = make_floatx80(0x40d3, 0xc2781f49ffcfa6d5ULL),  /* 10^64    */
+    [0x3a] = make_floatx80(0x41a8, 0x93ba47c980e98ce0ULL),  /* 10^128   */
+    [0x3b] = make_floatx80(0x4351, 0xaa7eebfb9df9de8eULL),  /* 10^256   */
+    [0x3c] = make_floatx80(0x46a3, 0xe319a0aea60e91c7ULL),  /* 10^512   */
+    [0x3d] = make_floatx80(0x4d48, 0xc976758681750c17ULL),  /* 10^1024  */
+    [0x3e] = make_floatx80(0x5a92, 0x9e8b3b5dc53d5de5ULL),  /* 10^2048  */
+    [0x3f] = make_floatx80(0x7525, 0xc46052028a20979bULL),  /* 10^4096  */
+};
+
 int32_t HELPER(reds32)(CPUM68KState *env, FPReg *val)
 {
     return floatx80_to_int32(val->d, &env->fp_status);
@@ -204,3 +229,8 @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
     }
     env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | cc;
 }
+
+void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset)
+{
+    val->d = fpu_rom[offset];
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 98cbf18..d6e80e4 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -35,6 +35,7 @@ DEF_HELPER_4(fdiv, void, env, fp, fp, fp)
 DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp)
 DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp)
+DEF_HELPER_3(fconst, void, env, fp, i32)
 
 DEF_HELPER_3(mac_move, void, env, i32, i32)
 DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 8824f81..ab2fe50 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -4510,6 +4510,7 @@ static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s,
 DISAS_INSN(fpu)
 {
     uint16_t ext;
+    uint8_t rom_offset;
     int opmode;
     TCGv tmp32;
     int opsize;
@@ -4518,10 +4519,20 @@ DISAS_INSN(fpu)
     ext = read_im16(env, s);
     opmode = ext & 0x7f;
     switch ((ext >> 13) & 7) {
-    case 0: case 2:
+    case 0:
         break;
     case 1:
         goto undef;
+    case 2:
+        if (insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
+            /* fmovecr */
+            rom_offset = ext & 0x7f;
+            cpu_dest = gen_fp_ptr(REG(ext, 7));
+            gen_helper_fconst(cpu_env, cpu_dest, tcg_const_i32(rom_offset));
+            tcg_temp_free_ptr(cpu_dest);
+            return;
+        }
+        break;
     case 3: /* fmove out */
         cpu_src = gen_fp_ptr(REG(ext, 7));
         opsize = ext_opsize(ext, 10);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 3/7] target/m68k: add explicit single and double precision operations
  2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 1/7] target/m68k: add fscc Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr Laurent Vivier
@ 2017-06-26 22:03 ` Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 4/7] softfloat: define floatx80_round() Laurent Vivier
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

Add fssqrt, fdsqrt, fsadd, fdadd, fssub, fdsub, fsmul, fdmul,
fsdiv, fddiv.

The precision is managed using set_floatx80_rounding_precision().

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target/m68k/fpu_helper.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
 target/m68k/helper.h     | 10 ++++++
 target/m68k/translate.c  | 40 +++++++++++++++++++++---
 3 files changed, 125 insertions(+), 5 deletions(-)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 912c0b7..f6b6788 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -153,11 +153,35 @@ void HELPER(set_fpcr)(CPUM68KState *env, uint32_t val)
     cpu_m68k_set_fpcr(env, val);
 }
 
+#define PREC_BEGIN(prec)                                        \
+    do {                                                        \
+        int old;                                                \
+        old = get_floatx80_rounding_precision(&env->fp_status); \
+        set_floatx80_rounding_precision(prec, &env->fp_status)  \
+
+#define PREC_END()                                              \
+        set_floatx80_rounding_precision(old, &env->fp_status);  \
+    } while (0)
+
 void HELPER(fsqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_sqrt(val->d, &env->fp_status);
 }
 
+void HELPER(fssqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    PREC_BEGIN(32);
+    res->d = floatx80_sqrt(val->d, &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fdsqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_sqrt(val->d, &env->fp_status);
+    PREC_END();
+}
+
 void HELPER(fabs)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_abs(val->d);
@@ -173,21 +197,77 @@ void HELPER(fadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
     res->d = floatx80_add(val0->d, val1->d, &env->fp_status);
 }
 
+void HELPER(fsadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(32);
+    res->d = floatx80_add(val0->d, val1->d, &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fdadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_add(val0->d, val1->d, &env->fp_status);
+    PREC_END();
+}
+
 void HELPER(fsub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 {
     res->d = floatx80_sub(val1->d, val0->d, &env->fp_status);
 }
 
+void HELPER(fssub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(32);
+    res->d = floatx80_sub(val1->d, val0->d, &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fdsub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_sub(val1->d, val0->d, &env->fp_status);
+    PREC_END();
+}
+
 void HELPER(fmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 {
     res->d = floatx80_mul(val0->d, val1->d, &env->fp_status);
 }
 
+void HELPER(fsmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(32);
+    res->d = floatx80_mul(val0->d, val1->d, &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fdmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_mul(val0->d, val1->d, &env->fp_status);
+    PREC_END();
+}
+
 void HELPER(fdiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 {
     res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
 }
 
+void HELPER(fsdiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(32);
+    res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fddiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
+    PREC_END();
+}
+
 static int float_comp_to_cc(int float_compare)
 {
     switch (float_compare) {
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index d6e80e4..0c7f06f 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -26,12 +26,22 @@ DEF_HELPER_2(reds32, s32, env, fp)
 DEF_HELPER_3(firound, void, env, fp, fp)
 DEF_HELPER_3(fitrunc, void, env, fp, fp)
 DEF_HELPER_3(fsqrt, void, env, fp, fp)
+DEF_HELPER_3(fssqrt, void, env, fp, fp)
+DEF_HELPER_3(fdsqrt, void, env, fp, fp)
 DEF_HELPER_3(fabs, void, env, fp, fp)
 DEF_HELPER_3(fchs, void, env, fp, fp)
 DEF_HELPER_4(fadd, void, env, fp, fp, fp)
+DEF_HELPER_4(fsadd, void, env, fp, fp, fp)
+DEF_HELPER_4(fdadd, void, env, fp, fp, fp)
 DEF_HELPER_4(fsub, void, env, fp, fp, fp)
+DEF_HELPER_4(fssub, void, env, fp, fp, fp)
+DEF_HELPER_4(fdsub, void, env, fp, fp, fp)
 DEF_HELPER_4(fmul, void, env, fp, fp, fp)
+DEF_HELPER_4(fsmul, void, env, fp, fp, fp)
+DEF_HELPER_4(fdmul, void, env, fp, fp, fp)
 DEF_HELPER_4(fdiv, void, env, fp, fp, fp)
+DEF_HELPER_4(fsdiv, void, env, fp, fp, fp)
+DEF_HELPER_4(fddiv, void, env, fp, fp, fp)
 DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp)
 DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ab2fe50..df79653 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -4604,27 +4604,57 @@ DISAS_INSN(fpu)
     case 3: /* fintrz */
         gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src);
         break;
-    case 4: case 0x41: case 0x45: /* fsqrt */
+    case 4: /* fsqrt */
         gen_helper_fsqrt(cpu_env, cpu_dest, cpu_src);
         break;
+    case 0x41: /* fssqrt */
+        gen_helper_fssqrt(cpu_env, cpu_dest, cpu_src);
+        break;
+    case 0x45: /* fdsqrt */
+        gen_helper_fdsqrt(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x18: case 0x58: case 0x5c: /* fabs */
         gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
         break;
     case 0x1a: case 0x5a: case 0x5e: /* fneg */
         gen_helper_fchs(cpu_env, cpu_dest, cpu_src);
         break;
-    case 0x20: case 0x60: case 0x64: /* fdiv */
+    case 0x20: /* fdiv */
         gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
         break;
-    case 0x22: case 0x62: case 0x66: /* fadd */
+    case 0x60: /* fsdiv */
+        gen_helper_fsdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x64: /* fddiv */
+        gen_helper_fddiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x22: /* fadd */
         gen_helper_fadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
         break;
-    case 0x23: case 0x63: case 0x67: /* fmul */
+    case 0x62: /* fsadd */
+        gen_helper_fsadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x66: /* fdadd */
+        gen_helper_fdadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x23: /* fmul */
         gen_helper_fmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
         break;
-    case 0x28: case 0x68: case 0x6c: /* fsub */
+    case 0x63: /* fsmul */
+        gen_helper_fsmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x67: /* fdmul */
+        gen_helper_fdmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x28: /* fsub */
         gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
         break;
+    case 0x68: /* fssub */
+        gen_helper_fssub(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x6c: /* fdsub */
+        gen_helper_fdsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
     case 0x38: /* fcmp */
         gen_helper_fcmp(cpu_env, cpu_src, cpu_dest);
         return;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 4/7] softfloat: define floatx80_round()
  2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
                   ` (2 preceding siblings ...)
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 3/7] target/m68k: add explicit single and double precision operations Laurent Vivier
@ 2017-06-26 22:03 ` Laurent Vivier
  2017-06-27 15:13   ` Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 5/7] target/m68k: add fsglmul and fsgldiv Laurent Vivier
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

Add a function to round a floatx80 to the defined precision
(floatx80_rounding_precision)

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 fpu/softfloat.c         | 15 +++++++++++++++
 include/fpu/softfloat.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 7af14e2..e9bf359 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -5086,6 +5086,21 @@ float128 floatx80_to_float128(floatx80 a, float_status *status)
 }
 
 /*----------------------------------------------------------------------------
+| Rounds the extended double-precision floating-point value `a'
+| and returns the result as an extended double-precision floating-point
+| value.  The operation is performed according to the IEC/IEEE Standard for
+| Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+floatx80 floatx80_round(floatx80 a, float_status *status)
+{
+    return roundAndPackFloatx80(status->floatx80_rounding_precision,
+                                extractFloatx80Sign(a),
+                                extractFloatx80Exp(a),
+                                extractFloatx80Frac(a), 0, status);
+}
+
+/*----------------------------------------------------------------------------
 | Rounds the extended double-precision floating-point value `a' to an integer,
 | and returns the result as an extended quadruple-precision floating-point
 | value.  The operation is performed according to the IEC/IEEE Standard for
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index f1288ef..d9689ec 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -621,6 +621,7 @@ float128 floatx80_to_float128(floatx80, float_status *status);
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision operations.
 *----------------------------------------------------------------------------*/
+floatx80 floatx80_round(floatx80 a, float_status *status);
 floatx80 floatx80_round_to_int(floatx80, float_status *status);
 floatx80 floatx80_add(floatx80, floatx80, float_status *status);
 floatx80 floatx80_sub(floatx80, floatx80, float_status *status);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 5/7] target/m68k: add fsglmul and fsgldiv
  2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
                   ` (3 preceding siblings ...)
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 4/7] softfloat: define floatx80_round() Laurent Vivier
@ 2017-06-26 22:03 ` Laurent Vivier
  2017-06-26 22:57   ` Richard Henderson
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 6/7] target/m68k: add explicit single and double precision operations (part 2) Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 7/7] target/m68k: add fmovem Laurent Vivier
  6 siblings, 1 reply; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

fsglmul and fsgldiv truncate data to single precision before computing
results.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target/m68k/fpu_helper.c | 22 ++++++++++++++++++++++
 target/m68k/helper.h     |  2 ++
 target/m68k/translate.c  |  6 ++++++
 3 files changed, 30 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index f6b6788..888abf6 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -249,6 +249,17 @@ void HELPER(fdmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
     PREC_END();
 }
 
+void HELPER(fsglmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    floatx80 a, b;
+
+    PREC_BEGIN(32);
+    a = floatx80_round(val0->d, &env->fp_status);
+    b = floatx80_round(val1->d, &env->fp_status);
+    res->d = floatx80_mul(a, b, &env->fp_status);
+    PREC_END();
+}
+
 void HELPER(fdiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 {
     res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
@@ -268,6 +279,17 @@ void HELPER(fddiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
     PREC_END();
 }
 
+void HELPER(fsgldiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+    floatx80 a, b;
+
+    PREC_BEGIN(32);
+    a = floatx80_round(val1->d, &env->fp_status);
+    b = floatx80_round(val0->d, &env->fp_status);
+    res->d = floatx80_div(a, b, &env->fp_status);
+    PREC_END();
+}
+
 static int float_comp_to_cc(int float_compare)
 {
     switch (float_compare) {
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 0c7f06f..f05191b 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -39,9 +39,11 @@ DEF_HELPER_4(fdsub, void, env, fp, fp, fp)
 DEF_HELPER_4(fmul, void, env, fp, fp, fp)
 DEF_HELPER_4(fsmul, void, env, fp, fp, fp)
 DEF_HELPER_4(fdmul, void, env, fp, fp, fp)
+DEF_HELPER_4(fsglmul, void, env, fp, fp, fp)
 DEF_HELPER_4(fdiv, void, env, fp, fp, fp)
 DEF_HELPER_4(fsdiv, void, env, fp, fp, fp)
 DEF_HELPER_4(fddiv, void, env, fp, fp, fp)
+DEF_HELPER_4(fsgldiv, void, env, fp, fp, fp)
 DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp)
 DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index df79653..253b8cc 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -4646,6 +4646,12 @@ DISAS_INSN(fpu)
     case 0x67: /* fdmul */
         gen_helper_fdmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
         break;
+    case 0x24: /* fsgldiv */
+        gen_helper_fsgldiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
+    case 0x27: /* fsglmul */
+        gen_helper_fsglmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
+        break;
     case 0x28: /* fsub */
         gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
         break;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 6/7] target/m68k: add explicit single and double precision operations (part 2)
  2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
                   ` (4 preceding siblings ...)
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 5/7] target/m68k: add fsglmul and fsgldiv Laurent Vivier
@ 2017-06-26 22:03 ` Laurent Vivier
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 7/7] target/m68k: add fmovem Laurent Vivier
  6 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

Add fsabs, fdabs, fsneg, fdneg, fsmove and fdmove.

The value is converted using the new floatx80_round() function.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target/m68k/fpu_helper.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
 target/m68k/helper.h     |  8 +++++++-
 target/m68k/translate.c  | 26 ++++++++++++++++++++++----
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 888abf6..c07ab05 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -163,6 +163,20 @@ void HELPER(set_fpcr)(CPUM68KState *env, uint32_t val)
         set_floatx80_rounding_precision(old, &env->fp_status);  \
     } while (0)
 
+void HELPER(fsround)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    PREC_BEGIN(32);
+    res->d = floatx80_round(val->d, &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fdround)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_round(val->d, &env->fp_status);
+    PREC_END();
+}
+
 void HELPER(fsqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_sqrt(val->d, &env->fp_status);
@@ -184,12 +198,40 @@ void HELPER(fdsqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
 
 void HELPER(fabs)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
-    res->d = floatx80_abs(val->d);
+    res->d = floatx80_round(floatx80_abs(val->d), &env->fp_status);
+}
+
+void HELPER(fsabs)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    PREC_BEGIN(32);
+    res->d = floatx80_round(floatx80_abs(val->d), &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fdabs)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_round(floatx80_abs(val->d), &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fneg)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_round(floatx80_chs(val->d), &env->fp_status);
 }
 
-void HELPER(fchs)(CPUM68KState *env, FPReg *res, FPReg *val)
+void HELPER(fsneg)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
-    res->d = floatx80_chs(val->d);
+    PREC_BEGIN(32);
+    res->d = floatx80_round(floatx80_chs(val->d), &env->fp_status);
+    PREC_END();
+}
+
+void HELPER(fdneg)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    PREC_BEGIN(64);
+    res->d = floatx80_round(floatx80_chs(val->d), &env->fp_status);
+    PREC_END();
 }
 
 void HELPER(fadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index f05191b..b396899 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -23,13 +23,19 @@ DEF_HELPER_2(redf32, f32, env, fp)
 DEF_HELPER_2(redf64, f64, env, fp)
 DEF_HELPER_2(reds32, s32, env, fp)
 
+DEF_HELPER_3(fsround, void, env, fp, fp)
+DEF_HELPER_3(fdround, void, env, fp, fp)
 DEF_HELPER_3(firound, void, env, fp, fp)
 DEF_HELPER_3(fitrunc, void, env, fp, fp)
 DEF_HELPER_3(fsqrt, void, env, fp, fp)
 DEF_HELPER_3(fssqrt, void, env, fp, fp)
 DEF_HELPER_3(fdsqrt, void, env, fp, fp)
 DEF_HELPER_3(fabs, void, env, fp, fp)
-DEF_HELPER_3(fchs, void, env, fp, fp)
+DEF_HELPER_3(fsabs, void, env, fp, fp)
+DEF_HELPER_3(fdabs, void, env, fp, fp)
+DEF_HELPER_3(fneg, void, env, fp, fp)
+DEF_HELPER_3(fsneg, void, env, fp, fp)
+DEF_HELPER_3(fdneg, void, env, fp, fp)
 DEF_HELPER_4(fadd, void, env, fp, fp, fp)
 DEF_HELPER_4(fsadd, void, env, fp, fp, fp)
 DEF_HELPER_4(fdadd, void, env, fp, fp, fp)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 253b8cc..e120935 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -4595,9 +4595,15 @@ DISAS_INSN(fpu)
     }
     cpu_dest = gen_fp_ptr(REG(ext, 7));
     switch (opmode) {
-    case 0: case 0x40: case 0x44: /* fmove */
+    case 0: /* fmove */
         gen_fp_move(cpu_dest, cpu_src);
         break;
+    case 0x40: /* fsmove */
+        gen_helper_fsround(cpu_env, cpu_dest, cpu_src);
+        break;
+    case 0x44: /* fdmove */
+        gen_helper_fdround(cpu_env, cpu_dest, cpu_src);
+        break;
     case 1: /* fint */
         gen_helper_firound(cpu_env, cpu_dest, cpu_src);
         break;
@@ -4613,11 +4619,23 @@ DISAS_INSN(fpu)
     case 0x45: /* fdsqrt */
         gen_helper_fdsqrt(cpu_env, cpu_dest, cpu_src);
         break;
-    case 0x18: case 0x58: case 0x5c: /* fabs */
+    case 0x18: /* fabs */
         gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
         break;
-    case 0x1a: case 0x5a: case 0x5e: /* fneg */
-        gen_helper_fchs(cpu_env, cpu_dest, cpu_src);
+    case 0x58: /* fsabs */
+        gen_helper_fsabs(cpu_env, cpu_dest, cpu_src);
+        break;
+    case 0x5c: /* fdabs */
+        gen_helper_fdabs(cpu_env, cpu_dest, cpu_src);
+        break;
+    case 0x1a: /* fneg */
+        gen_helper_fneg(cpu_env, cpu_dest, cpu_src);
+        break;
+    case 0x5a: /* fsneg */
+        gen_helper_fsneg(cpu_env, cpu_dest, cpu_src);
+        break;
+    case 0x5e: /* fdneg */
+        gen_helper_fdneg(cpu_env, cpu_dest, cpu_src);
         break;
     case 0x20: /* fdiv */
         gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 7/7] target/m68k: add fmovem
  2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
                   ` (5 preceding siblings ...)
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 6/7] target/m68k: add explicit single and double precision operations (part 2) Laurent Vivier
@ 2017-06-26 22:03 ` Laurent Vivier
  2017-06-26 23:32   ` Richard Henderson
  6 siblings, 1 reply; 15+ messages in thread
From: Laurent Vivier @ 2017-06-26 22:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target/m68k/fpu_helper.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++
 target/m68k/helper.h     |   6 +++
 target/m68k/translate.c  |  93 ++++++++++++++++++++++++------------
 3 files changed, 189 insertions(+), 30 deletions(-)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index c07ab05..3e38151 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -22,6 +22,7 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
 
 static const floatx80 fpu_rom[128] = {
     [0x00] = floatx80_pi,                                   /* Pi */
@@ -378,3 +379,122 @@ void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset)
 {
     val->d = fpu_rom[offset];
 }
+
+typedef int (*float_access)(CPUM68KState *env, uint32_t addr, FPReg *fp,
+                            uintptr_t ra);
+
+static uint32_t fmovem_predec(CPUM68KState *env, uint32_t addr, uint32_t mask,
+                               float_access access)
+{
+    uintptr_t ra = GETPC();
+    int i, size;
+
+    for (i = 7; i >= 0; i--, mask <<= 1) {
+        if (mask & 0x80) {
+            size = access(env, addr, &env->fregs[i], ra);
+            if ((mask & 0xff) != 0x80) {
+                addr -= size;
+            }
+        }
+    }
+
+    return addr;
+}
+
+static uint32_t fmovem_postinc(CPUM68KState *env, uint32_t addr, uint32_t mask,
+                               float_access access)
+{
+    uintptr_t ra = GETPC();
+    int i, size;
+
+    for (i = 0; i < 8; i++, mask <<= 1) {
+        if (mask & 0x80) {
+            size = access(env, addr, &env->fregs[i], ra);
+            addr += size;
+        }
+    }
+
+    return addr;
+}
+
+static int cpu_ld_floatx80_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
+                              uintptr_t ra)
+{
+    uint32_t high;
+    uint64_t low;
+
+    high = cpu_ldl_data_ra(env, addr, ra);
+    low = cpu_ldq_data_ra(env, addr + 4, ra);
+
+    fp->l.upper = high >> 16;
+    fp->l.lower = low;
+
+    return 12;
+}
+
+static int cpu_st_floatx80_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
+                               uintptr_t ra)
+{
+    cpu_stl_data_ra(env, addr, fp->l.upper << 16, ra);
+    cpu_stq_data_ra(env, addr + 4, fp->l.lower, ra);
+
+    return 12;
+}
+
+static int cpu_ld_float64_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
+                             uintptr_t ra)
+{
+    uint64_t val;
+
+    val = cpu_ldq_data_ra(env, addr, ra);
+    fp->d = float64_to_floatx80(*(float64 *)&val, &env->fp_status);
+
+    return 8;
+}
+
+static int  cpu_st_float64_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
+                             uintptr_t ra)
+{
+    float64 val;
+
+    val = floatx80_to_float64(fp->d, &env->fp_status);
+    cpu_stq_data_ra(env, addr, *(uint64_t *)&val, ra);
+
+    return 8;
+}
+
+uint32_t HELPER(fmovemx_st_predec)(CPUM68KState *env, uint32_t addr,
+                                   uint32_t mask)
+{
+    return fmovem_predec(env, addr, mask, cpu_st_floatx80_ra);
+}
+
+uint32_t HELPER(fmovemx_st_postinc)(CPUM68KState *env, uint32_t addr,
+                                    uint32_t mask)
+{
+    return fmovem_postinc(env, addr, mask, cpu_st_floatx80_ra);
+}
+
+uint32_t HELPER(fmovemx_ld_postinc)(CPUM68KState *env, uint32_t addr,
+                                    uint32_t mask)
+{
+    return fmovem_postinc(env, addr, mask, cpu_ld_floatx80_ra);
+}
+
+uint32_t HELPER(fmovemd_st_predec)(CPUM68KState *env, uint32_t addr,
+                                   uint32_t mask)
+{
+    return fmovem_predec(env, addr, mask, cpu_st_float64_ra);
+}
+
+uint32_t HELPER(fmovemd_st_postinc)(CPUM68KState *env, uint32_t addr,
+                                    uint32_t mask)
+{
+    return fmovem_postinc(env, addr, mask, cpu_st_float64_ra);
+}
+
+uint32_t HELPER(fmovemd_ld_postinc)(CPUM68KState *env, uint32_t addr,
+                                    uint32_t mask)
+{
+    return fmovem_postinc(env, addr, mask, cpu_ld_float64_ra);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index b396899..475a1f2 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -54,6 +54,12 @@ DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp)
 DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp)
 DEF_HELPER_3(fconst, void, env, fp, i32)
+DEF_HELPER_3(fmovemx_st_predec, i32, env, i32, i32)
+DEF_HELPER_3(fmovemx_st_postinc, i32, env, i32, i32)
+DEF_HELPER_3(fmovemx_ld_postinc, i32, env, i32, i32)
+DEF_HELPER_3(fmovemd_st_predec, i32, env, i32, i32)
+DEF_HELPER_3(fmovemd_st_postinc, i32, env, i32, i32)
+DEF_HELPER_3(fmovemd_ld_postinc, i32, env, i32, i32)
 
 DEF_HELPER_3(mac_move, void, env, i32, i32)
 DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index e120935..71cfc70 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -4505,6 +4505,66 @@ static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s,
     tcg_temp_free_i32(addr);
 }
 
+static void gen_op_fmovem(CPUM68KState *env, DisasContext *s,
+                          uint32_t insn, uint32_t ext)
+{
+    int opsize;
+    TCGv addr, tmp;
+    int mode = (ext >> 11) & 0x3;
+    int is_load = ((ext & 0x2000) == 0);
+
+    if (m68k_feature(s->env, M68K_FEATURE_FPU)) {
+        opsize = OS_EXTENDED;
+    } else {
+        opsize = OS_DOUBLE;  /* FIXME */
+    }
+
+    addr = gen_lea(env, s, insn, opsize);
+    if (IS_NULL_QREG(addr)) {
+        gen_addr_fault(s);
+        return;
+    }
+
+    tmp = tcg_temp_new();
+    if (mode & 0x1) {
+        /* Dynamic register list */
+        tcg_gen_ext8u_i32(tmp, DREG(ext, 4));
+    } else {
+        /* Static register list */
+        tcg_gen_movi_i32(tmp, ext & 0xff);
+    }
+
+    if (!is_load && (mode & 2) == 0) {
+        /* predecrement addressing mode
+         * only available to store register to memory
+         */
+        if (opsize == OS_EXTENDED) {
+            gen_helper_fmovemx_st_predec(tmp, cpu_env, addr, tmp);
+        } else {
+            gen_helper_fmovemd_st_predec(tmp, cpu_env, addr, tmp);
+        }
+    } else {
+        /* postincrement addressing mode */
+        if (opsize == OS_EXTENDED) {
+            if (is_load) {
+                gen_helper_fmovemx_ld_postinc(tmp, cpu_env, addr, tmp);
+            } else {
+                gen_helper_fmovemx_st_postinc(tmp, cpu_env, addr, tmp);
+            }
+        } else {
+            if (is_load) {
+                gen_helper_fmovemd_ld_postinc(tmp, cpu_env, addr, tmp);
+            } else {
+                gen_helper_fmovemd_st_postinc(tmp, cpu_env, addr, tmp);
+            }
+        }
+    }
+    if ((insn & 070) == 030 || (insn & 070) == 040) {
+        tcg_gen_mov_i32(AREG(insn, 0), tmp);
+    }
+    tcg_temp_free(tmp);
+}
+
 /* ??? FP exceptions are not implemented.  Most exceptions are deferred until
    immediately before the next FP instruction is executed.  */
 DISAS_INSN(fpu)
@@ -4512,7 +4572,6 @@ DISAS_INSN(fpu)
     uint16_t ext;
     uint8_t rom_offset;
     int opmode;
-    TCGv tmp32;
     int opsize;
     TCGv_ptr cpu_src, cpu_dest;
 
@@ -4548,36 +4607,10 @@ DISAS_INSN(fpu)
         return;
     case 6: /* fmovem */
     case 7:
-        {
-            TCGv addr;
-            TCGv_ptr fp;
-            uint16_t mask;
-            int i;
-            if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
-                goto undef;
-            tmp32 = gen_lea(env, s, insn, OS_LONG);
-            if (IS_NULL_QREG(tmp32)) {
-                gen_addr_fault(s);
-                return;
-            }
-            addr = tcg_temp_new_i32();
-            tcg_gen_mov_i32(addr, tmp32);
-            mask = 0x80;
-            fp = tcg_temp_new_ptr();
-            for (i = 0; i < 8; i++) {
-                if (ext & mask) {
-                    tcg_gen_addi_ptr(fp, cpu_env,
-                                     offsetof(CPUM68KState, fregs[i]));
-                    gen_ldst_fp(s, OS_DOUBLE, addr, fp,
-                                (ext & (1 << 13)) ?  EA_STORE : EA_LOADS);
-                    if (ext & (mask - 1))
-                        tcg_gen_addi_i32(addr, addr, 8);
-                }
-                mask >>= 1;
-            }
-            tcg_temp_free_i32(addr);
-            tcg_temp_free_ptr(fp);
+        if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU)) {
+            goto undef;
         }
+        gen_op_fmovem(env, s, insn, ext);
         return;
     }
     if (ext & (1 << 14)) {
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/7] target/m68k: add fscc.
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 1/7] target/m68k: add fscc Laurent Vivier
@ 2017-06-26 22:55   ` Richard Henderson
  0 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2017-06-26 22:55 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: Aurelien Jarno, Philippe Mathieu-Daudé

On 06/26/2017 03:03 PM, Laurent Vivier wrote:
>       case 12: /* Unordered or Less Than A || (N && !Z) */
>       case 28: /* Not Greater than or Equal A || (N && !Z) */
> -        assert(FPSR_CC_Z == (FPSR_CC_N >> 1));
> -        tmp = tcg_temp_new();
> -        tcg_gen_xori_i32(tmp, fpsr, FPSR_CC_Z);
> -        tcg_gen_shli_i32(tmp, tmp, 1);
> -        tcg_gen_ori_i32(tmp, tmp, FPSR_CC_A);
> -        tcg_gen_and_i32(tmp, tmp, fpsr);
> -        tcg_gen_andi_i32(tmp, tmp, FPSR_CC_A | FPSR_CC_N);
> -        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
> +        g_assert(FPSR_CC_Z == (FPSR_CC_N >> 1));
> +        c->v1 = tcg_temp_new();
> +        c->g1 = 0;
> +        tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_Z);
> +        tcg_gen_shli_i32(c->v1, c->v1, 1);
> +        tcg_gen_ori_i32(c->v1, c->v1, FPSR_CC_A);
> +        tcg_gen_and_i32(c->v1, c->v1, fpsr);
> +        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_A | FPSR_CC_N);
> +        c->tcond = TCG_COND_NE;

I think you're making a mistake wrt all of these shifts, in that you haven't 
masked out the other bits in FPSR.  Eventually you'll add support for the FPSR 
quotient and the byte below CC won't be zero.

Of course, one possibility is to deconstruct FPSR into pieces so that you can 
avoid extra masking.  Whether that's worthwhile, I don't know.

Another possibility for this one is

	tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_Z);
	tcg_gen_shli_i32(tmp, tmp, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z));
	tcg_gen_andc_i32(tmp, fpsr, tmp);
	tcg_gen_andi_i32(tmp, tmp, FPSR_CC_A | FPSR_CC_N);


r~

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/7] target/m68k: add fsglmul and fsgldiv
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 5/7] target/m68k: add fsglmul and fsgldiv Laurent Vivier
@ 2017-06-26 22:57   ` Richard Henderson
  0 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2017-06-26 22:57 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: Aurelien Jarno, Philippe Mathieu-Daudé

On 06/26/2017 03:03 PM, Laurent Vivier wrote:
> +void HELPER(fsglmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
> +{
> +    floatx80 a, b;
> +
> +    PREC_BEGIN(32);
> +    a = floatx80_round(val0->d, &env->fp_status);
> +    b = floatx80_round(val1->d, &env->fp_status);
> +    res->d = floatx80_mul(a, b, &env->fp_status);
> +    PREC_END();
> +}
> +

You need to set the rounding mode to truncate for the first two operations.


r~

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 7/7] target/m68k: add fmovem
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 7/7] target/m68k: add fmovem Laurent Vivier
@ 2017-06-26 23:32   ` Richard Henderson
  0 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2017-06-26 23:32 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: Aurelien Jarno, Philippe Mathieu-Daudé

On 06/26/2017 03:03 PM, Laurent Vivier wrote:
> +static int  cpu_st_float64_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,

Extra space.  Otherwise,

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/7] softfloat: define floatx80_round()
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 4/7] softfloat: define floatx80_round() Laurent Vivier
@ 2017-06-27 15:13   ` Laurent Vivier
  0 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2017-06-27 15:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: Aurelien Jarno, Philippe Mathieu-Daudé,
	Richard Henderson, Peter Maydell

Aurélien or Peter, could you ACK this one?

Thanks,
Laurent

Le 27/06/2017 à 00:03, Laurent Vivier a écrit :
> Add a function to round a floatx80 to the defined precision
> (floatx80_rounding_precision)
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> ---
>  fpu/softfloat.c         | 15 +++++++++++++++
>  include/fpu/softfloat.h |  1 +
>  2 files changed, 16 insertions(+)
> 
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index 7af14e2..e9bf359 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -5086,6 +5086,21 @@ float128 floatx80_to_float128(floatx80 a, float_status *status)
>  }
>  
>  /*----------------------------------------------------------------------------
> +| Rounds the extended double-precision floating-point value `a'
> +| and returns the result as an extended double-precision floating-point
> +| value.  The operation is performed according to the IEC/IEEE Standard for
> +| Binary Floating-Point Arithmetic.
> +*----------------------------------------------------------------------------*/
> +
> +floatx80 floatx80_round(floatx80 a, float_status *status)
> +{
> +    return roundAndPackFloatx80(status->floatx80_rounding_precision,
> +                                extractFloatx80Sign(a),
> +                                extractFloatx80Exp(a),
> +                                extractFloatx80Frac(a), 0, status);
> +}
> +
> +/*----------------------------------------------------------------------------
>  | Rounds the extended double-precision floating-point value `a' to an integer,
>  | and returns the result as an extended quadruple-precision floating-point
>  | value.  The operation is performed according to the IEC/IEEE Standard for
> diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
> index f1288ef..d9689ec 100644
> --- a/include/fpu/softfloat.h
> +++ b/include/fpu/softfloat.h
> @@ -621,6 +621,7 @@ float128 floatx80_to_float128(floatx80, float_status *status);
>  /*----------------------------------------------------------------------------
>  | Software IEC/IEEE extended double-precision operations.
>  *----------------------------------------------------------------------------*/
> +floatx80 floatx80_round(floatx80 a, float_status *status);
>  floatx80 floatx80_round_to_int(floatx80, float_status *status);
>  floatx80 floatx80_add(floatx80, floatx80, float_status *status);
>  floatx80 floatx80_sub(floatx80, floatx80, float_status *status);
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr
  2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr Laurent Vivier
@ 2017-06-27 15:45   ` Philippe Mathieu-Daudé
  2017-06-27 17:58     ` Laurent Vivier
  0 siblings, 1 reply; 15+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-06-27 15:45 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel, Aurelien Jarno, Richard Henderson

I find this patch aesthetically very nice :)

On Tue, 27 Jun 2017 00:03:25 +0200
Laurent Vivier <laurent@vivier.eu> wrote:
> fmovecr moves a floating point constant from the
> FPU ROM to a floating point register.
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/m68k/fpu_helper.c | 30 ++++++++++++++++++++++++++++++
>  target/m68k/helper.h     |  1 +
>  target/m68k/translate.c  | 13 ++++++++++++-
>  3 files changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
> index a9e17f5..912c0b7 100644
> --- a/target/m68k/fpu_helper.c
> +++ b/target/m68k/fpu_helper.c
> @@ -23,6 +23,31 @@
>  #include "exec/helper-proto.h"
>  #include "exec/exec-all.h"
>  
> +static const floatx80 fpu_rom[128] = {
> +    [0x00] = floatx80_pi,                                   /* Pi */
> +    [0x0b] = make_floatx80(0x3ffd, 0x9a209a84fbcff798ULL),  /*
> Log10(2) */
> +    [0x0c] = make_floatx80(0x4000, 0xadf85458a2bb4a9aULL),  /*
> e        */
> +    [0x0d] = make_floatx80(0x3fff, 0xb8aa3b295c17f0bcULL),  /*
> Log2(e)  */
> +    [0x0e] = make_floatx80(0x3ffd, 0xde5bd8a937287195ULL),  /*
> Log10(e) */
> +    [0x0f] = floatx80_zero,                                 /*
> Zero     */
> +    [0x30] = floatx80_ln2,                                  /*
> ln(2)    */
> +    [0x31] = make_floatx80(0x4000, 0x935d8dddaaa8ac17ULL),  /*
> ln(10)   */
> +    [0x32] = floatx80_one,                                  /*
> 10^0     */
> +    [0x33] = make_floatx80(0x4002, 0xa000000000000000ULL),  /*
> 10^1     */
> +    [0x34] = make_floatx80(0x4005, 0xc800000000000000ULL),  /*
> 10^2     */
> +    [0x35] = make_floatx80(0x400c, 0x9c40000000000000ULL),  /*
> 10^4     */
> +    [0x36] = make_floatx80(0x4019, 0xbebc200000000000ULL),  /*
> 10^8     */
> +    [0x37] = make_floatx80(0x4034, 0x8e1bc9bf04000000ULL),  /*
> 10^16    */
> +    [0x38] = make_floatx80(0x4069, 0x9dc5ada82b70b59eULL),  /*
> 10^32    */
> +    [0x39] = make_floatx80(0x40d3, 0xc2781f49ffcfa6d5ULL),  /*
> 10^64    */
> +    [0x3a] = make_floatx80(0x41a8, 0x93ba47c980e98ce0ULL),  /*
> 10^128   */
> +    [0x3b] = make_floatx80(0x4351, 0xaa7eebfb9df9de8eULL),  /*
> 10^256   */
> +    [0x3c] = make_floatx80(0x46a3, 0xe319a0aea60e91c7ULL),  /*
> 10^512   */
> +    [0x3d] = make_floatx80(0x4d48, 0xc976758681750c17ULL),  /*
> 10^1024  */
> +    [0x3e] = make_floatx80(0x5a92, 0x9e8b3b5dc53d5de5ULL),  /*
> 10^2048  */
> +    [0x3f] = make_floatx80(0x7525, 0xc46052028a20979bULL),  /*
> 10^4096  */ +};
> +
>  int32_t HELPER(reds32)(CPUM68KState *env, FPReg *val)
>  {
>      return floatx80_to_int32(val->d, &env->fp_status);
> @@ -204,3 +229,8 @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
>      }
>      env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | cc;
>  }
> +
> +void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset)
> +{
> +    val->d = fpu_rom[offset];

For offset not declared in fpu_rom (0x1..0xa, 0x10..0x2f, 0x40..0x7f),
this will return floatx80_zero, is this correct?

> +}
> diff --git a/target/m68k/helper.h b/target/m68k/helper.h
> index 98cbf18..d6e80e4 100644
> --- a/target/m68k/helper.h
> +++ b/target/m68k/helper.h
> @@ -35,6 +35,7 @@ DEF_HELPER_4(fdiv, void, env, fp, fp, fp)
>  DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp)
>  DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32)
>  DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp)
> +DEF_HELPER_3(fconst, void, env, fp, i32)
>  
>  DEF_HELPER_3(mac_move, void, env, i32, i32)
>  DEF_HELPER_3(macmulf, i64, env, i32, i32)
> diff --git a/target/m68k/translate.c b/target/m68k/translate.c
> index 8824f81..ab2fe50 100644
> --- a/target/m68k/translate.c
> +++ b/target/m68k/translate.c
> @@ -4510,6 +4510,7 @@ static void gen_op_fmove_fcr(CPUM68KState *env,
> DisasContext *s, DISAS_INSN(fpu)
>  {
>      uint16_t ext;
> +    uint8_t rom_offset;
>      int opmode;
>      TCGv tmp32;
>      int opsize;
> @@ -4518,10 +4519,20 @@ DISAS_INSN(fpu)
>      ext = read_im16(env, s);
>      opmode = ext & 0x7f;
>      switch ((ext >> 13) & 7) {
> -    case 0: case 2:
> +    case 0:
>          break;
>      case 1:
>          goto undef;
> +    case 2:
> +        if (insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
> +            /* fmovecr */
> +            rom_offset = ext & 0x7f;

you can use opmode directly.

> +            cpu_dest = gen_fp_ptr(REG(ext, 7));
> +            gen_helper_fconst(cpu_env, cpu_dest,
> tcg_const_i32(rom_offset));
> +            tcg_temp_free_ptr(cpu_dest);
> +            return;
> +        }
> +        break;
>      case 3: /* fmove out */
>          cpu_src = gen_fp_ptr(REG(ext, 7));
>          opsize = ext_opsize(ext, 10);

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr
  2017-06-27 15:45   ` Philippe Mathieu-Daudé
@ 2017-06-27 17:58     ` Laurent Vivier
  2017-06-27 20:52       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 15+ messages in thread
From: Laurent Vivier @ 2017-06-27 17:58 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: qemu-devel, Aurelien Jarno, Richard Henderson

Le 27/06/2017 à 17:45, Philippe Mathieu-Daudé a écrit :
> I find this patch aesthetically very nice :)
> 
> On Tue, 27 Jun 2017 00:03:25 +0200
> Laurent Vivier <laurent@vivier.eu> wrote:
>> fmovecr moves a floating point constant from the
>> FPU ROM to a floating point register.
>>
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>> Reviewed-by: Richard Henderson <rth@twiddle.net>
>> ---
>>  target/m68k/fpu_helper.c | 30 ++++++++++++++++++++++++++++++
>>  target/m68k/helper.h     |  1 +
>>  target/m68k/translate.c  | 13 ++++++++++++-
>>  3 files changed, 43 insertions(+), 1 deletion(-)
>>
>> diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
>> index a9e17f5..912c0b7 100644
>> --- a/target/m68k/fpu_helper.c
>> +++ b/target/m68k/fpu_helper.c
>> @@ -23,6 +23,31 @@
>>  #include "exec/helper-proto.h"
>>  #include "exec/exec-all.h"
>>  
>> +static const floatx80 fpu_rom[128] = {
>> +    [0x00] = floatx80_pi,                                   /* Pi */
>> +    [0x0b] = make_floatx80(0x3ffd, 0x9a209a84fbcff798ULL),  /*
>> Log10(2) */
>> +    [0x0c] = make_floatx80(0x4000, 0xadf85458a2bb4a9aULL),  /*
>> e        */
>> +    [0x0d] = make_floatx80(0x3fff, 0xb8aa3b295c17f0bcULL),  /*
>> Log2(e)  */
>> +    [0x0e] = make_floatx80(0x3ffd, 0xde5bd8a937287195ULL),  /*
>> Log10(e) */
>> +    [0x0f] = floatx80_zero,                                 /*
>> Zero     */
>> +    [0x30] = floatx80_ln2,                                  /*
>> ln(2)    */
>> +    [0x31] = make_floatx80(0x4000, 0x935d8dddaaa8ac17ULL),  /*
>> ln(10)   */
>> +    [0x32] = floatx80_one,                                  /*
>> 10^0     */
>> +    [0x33] = make_floatx80(0x4002, 0xa000000000000000ULL),  /*
>> 10^1     */
>> +    [0x34] = make_floatx80(0x4005, 0xc800000000000000ULL),  /*
>> 10^2     */
>> +    [0x35] = make_floatx80(0x400c, 0x9c40000000000000ULL),  /*
>> 10^4     */
>> +    [0x36] = make_floatx80(0x4019, 0xbebc200000000000ULL),  /*
>> 10^8     */
>> +    [0x37] = make_floatx80(0x4034, 0x8e1bc9bf04000000ULL),  /*
>> 10^16    */
>> +    [0x38] = make_floatx80(0x4069, 0x9dc5ada82b70b59eULL),  /*
>> 10^32    */
>> +    [0x39] = make_floatx80(0x40d3, 0xc2781f49ffcfa6d5ULL),  /*
>> 10^64    */
>> +    [0x3a] = make_floatx80(0x41a8, 0x93ba47c980e98ce0ULL),  /*
>> 10^128   */
>> +    [0x3b] = make_floatx80(0x4351, 0xaa7eebfb9df9de8eULL),  /*
>> 10^256   */
>> +    [0x3c] = make_floatx80(0x46a3, 0xe319a0aea60e91c7ULL),  /*
>> 10^512   */
>> +    [0x3d] = make_floatx80(0x4d48, 0xc976758681750c17ULL),  /*
>> 10^1024  */
>> +    [0x3e] = make_floatx80(0x5a92, 0x9e8b3b5dc53d5de5ULL),  /*
>> 10^2048  */
>> +    [0x3f] = make_floatx80(0x7525, 0xc46052028a20979bULL),  /*
>> 10^4096  */ +};
>> +
>>  int32_t HELPER(reds32)(CPUM68KState *env, FPReg *val)
>>  {
>>      return floatx80_to_int32(val->d, &env->fp_status);
>> @@ -204,3 +229,8 @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
>>      }
>>      env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | cc;
>>  }
>> +
>> +void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset)
>> +{
>> +    val->d = fpu_rom[offset];
> 
> For offset not declared in fpu_rom (0x1..0xa, 0x10..0x2f, 0x40..0x7f),
> this will return floatx80_zero, is this correct?

yes, according to the doc:

The values contained at offsets other than those defined above are
reserved for the use of Motorola and may be different on various mask
sets of the floating-point coprocessor. These undefined values yield the
value 0.0 in the M68040FPSP

> 
>> +}
>> diff --git a/target/m68k/helper.h b/target/m68k/helper.h
>> index 98cbf18..d6e80e4 100644
>> --- a/target/m68k/helper.h
>> +++ b/target/m68k/helper.h
>> @@ -35,6 +35,7 @@ DEF_HELPER_4(fdiv, void, env, fp, fp, fp)
>>  DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp)
>>  DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32)
>>  DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp)
>> +DEF_HELPER_3(fconst, void, env, fp, i32)
>>  
>>  DEF_HELPER_3(mac_move, void, env, i32, i32)
>>  DEF_HELPER_3(macmulf, i64, env, i32, i32)
>> diff --git a/target/m68k/translate.c b/target/m68k/translate.c
>> index 8824f81..ab2fe50 100644
>> --- a/target/m68k/translate.c
>> +++ b/target/m68k/translate.c
>> @@ -4510,6 +4510,7 @@ static void gen_op_fmove_fcr(CPUM68KState *env,
>> DisasContext *s, DISAS_INSN(fpu)
>>  {
>>      uint16_t ext;
>> +    uint8_t rom_offset;
>>      int opmode;
>>      TCGv tmp32;
>>      int opsize;
>> @@ -4518,10 +4519,20 @@ DISAS_INSN(fpu)
>>      ext = read_im16(env, s);
>>      opmode = ext & 0x7f;
>>      switch ((ext >> 13) & 7) {
>> -    case 0: case 2:
>> +    case 0:
>>          break;
>>      case 1:
>>          goto undef;
>> +    case 2:
>> +        if (insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
>> +            /* fmovecr */
>> +            rom_offset = ext & 0x7f;
> 
> you can use opmode directly.

yes, I will update.

Thanks,
Laurent

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr
  2017-06-27 17:58     ` Laurent Vivier
@ 2017-06-27 20:52       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 15+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-06-27 20:52 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel, Aurelien Jarno, Richard Henderson

On 06/27/2017 02:58 PM, Laurent Vivier wrote:
> Le 27/06/2017 à 17:45, Philippe Mathieu-Daudé a écrit :
>>> +static const floatx80 fpu_rom[128] = {
>>> +    [0x00] = floatx80_pi,                                   /* Pi */
>>> +    [0x0b] = make_floatx80(0x3ffd, 0x9a209a84fbcff798ULL),  /*
>>> Log10(2) */
>>> +    [0x0c] = make_floatx80(0x4000, 0xadf85458a2bb4a9aULL),  /*
>>> e        */
>>> +    [0x0d] = make_floatx80(0x3fff, 0xb8aa3b295c17f0bcULL),  /*
>>> Log2(e)  */
>>> +    [0x0e] = make_floatx80(0x3ffd, 0xde5bd8a937287195ULL),  /*
>>> Log10(e) */
>>> +    [0x0f] = floatx80_zero,                                 /*
>>> Zero     */
>>> +    [0x30] = floatx80_ln2,                                  /*
>>> ln(2)    */
>>> +    [0x31] = make_floatx80(0x4000, 0x935d8dddaaa8ac17ULL),  /*
>>> ln(10)   */
>>> +    [0x32] = floatx80_one,                                  /*
>>> 10^0     */
>>> +    [0x33] = make_floatx80(0x4002, 0xa000000000000000ULL),  /*
>>> 10^1     */
>>> +    [0x34] = make_floatx80(0x4005, 0xc800000000000000ULL),  /*
>>> 10^2     */
>>> +    [0x35] = make_floatx80(0x400c, 0x9c40000000000000ULL),  /*
>>> 10^4     */
>>> +    [0x36] = make_floatx80(0x4019, 0xbebc200000000000ULL),  /*
>>> 10^8     */
>>> +    [0x37] = make_floatx80(0x4034, 0x8e1bc9bf04000000ULL),  /*
>>> 10^16    */
>>> +    [0x38] = make_floatx80(0x4069, 0x9dc5ada82b70b59eULL),  /*
>>> 10^32    */
>>> +    [0x39] = make_floatx80(0x40d3, 0xc2781f49ffcfa6d5ULL),  /*
>>> 10^64    */
>>> +    [0x3a] = make_floatx80(0x41a8, 0x93ba47c980e98ce0ULL),  /*
>>> 10^128   */
>>> +    [0x3b] = make_floatx80(0x4351, 0xaa7eebfb9df9de8eULL),  /*
>>> 10^256   */
>>> +    [0x3c] = make_floatx80(0x46a3, 0xe319a0aea60e91c7ULL),  /*
>>> 10^512   */
>>> +    [0x3d] = make_floatx80(0x4d48, 0xc976758681750c17ULL),  /*
>>> 10^1024  */
>>> +    [0x3e] = make_floatx80(0x5a92, 0x9e8b3b5dc53d5de5ULL),  /*
>>> 10^2048  */
>>> +    [0x3f] = make_floatx80(0x7525, 0xc46052028a20979bULL),  /*
>>> 10^4096  */ +};
>>> +
>>>   int32_t HELPER(reds32)(CPUM68KState *env, FPReg *val)
>>>   {
>>>       return floatx80_to_int32(val->d, &env->fp_status);
>>> @@ -204,3 +229,8 @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
>>>       }
>>>       env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | cc;
>>>   }
>>> +
>>> +void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset)
>>> +{
>>> +    val->d = fpu_rom[offset];
>>
>> For offset not declared in fpu_rom (0x1..0xa, 0x10..0x2f, 0x40..0x7f),
>> this will return floatx80_zero, is this correct?
> 
> yes, according to the doc:
> 
> The values contained at offsets other than those defined above are
> reserved for the use of Motorola and may be different on various mask
> sets of the floating-point coprocessor. These undefined values yield the
> value 0.0 in the M68040FPSP

can you add this comment before/in the fpu_rom array please?

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2017-06-27 20:52 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-26 22:03 [Qemu-devel] [PATCH v2 0/7] target/m68k: implement 680x0 FPU (part 2) Laurent Vivier
2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 1/7] target/m68k: add fscc Laurent Vivier
2017-06-26 22:55   ` Richard Henderson
2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 2/7] target/m68k: add fmovecr Laurent Vivier
2017-06-27 15:45   ` Philippe Mathieu-Daudé
2017-06-27 17:58     ` Laurent Vivier
2017-06-27 20:52       ` Philippe Mathieu-Daudé
2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 3/7] target/m68k: add explicit single and double precision operations Laurent Vivier
2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 4/7] softfloat: define floatx80_round() Laurent Vivier
2017-06-27 15:13   ` Laurent Vivier
2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 5/7] target/m68k: add fsglmul and fsgldiv Laurent Vivier
2017-06-26 22:57   ` Richard Henderson
2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 6/7] target/m68k: add explicit single and double precision operations (part 2) Laurent Vivier
2017-06-26 22:03 ` [Qemu-devel] [PATCH v2 7/7] target/m68k: add fmovem Laurent Vivier
2017-06-26 23:32   ` Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.