Patchwork [029/111] m68k: allow fpu to manage double data type with fmove to <ea>

login
register
mail settings
Submitter Bryce Lanham
Date Aug. 17, 2011, 8:46 p.m.
Message ID <1313614076-28878-30-git-send-email-blanham@gmail.com>
Download mbox | patch
Permalink /patch/110350/
State New
Headers show

Comments

Bryce Lanham - Aug. 17, 2011, 8:46 p.m.
From: Laurent Vivier <laurent@vivier.eu>

This patch allows to manage instructions like "fmoved %fp0,%fp@(-512)".

Original function manages double data only through an address register.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |   73 +++++++++++++++++-----------------------------
 1 files changed, 27 insertions(+), 46 deletions(-)

Patch

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index a91f557..01dea9c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2933,7 +2933,6 @@  DISAS_INSN(trap)
 DISAS_INSN(fpu)
 {
     uint16_t ext;
-    int32_t offset;
     int opmode;
     TCGv_i64 src;
     TCGv_i64 dest;
@@ -2944,8 +2943,7 @@  DISAS_INSN(fpu)
     int set_dest;
     int opsize;
 
-    ext = lduw_code(s->pc);
-    s->pc += 2;
+    ext = read_im16(s);
     opmode = ext & 0x7f;
     switch ((ext >> 13) & 7) {
     case 0: case 2:
@@ -2958,55 +2956,38 @@  DISAS_INSN(fpu)
         /* fmove */
         /* ??? TODO: Proper behavior on overflow.  */
         switch ((ext >> 10) & 7) {
-        case 0:
-            opsize = OS_LONG;
-            gen_helper_f64_to_i32(tmp32, cpu_env, src);
-            break;
-        case 1:
-            opsize = OS_SINGLE;
-            gen_helper_f64_to_f32(tmp32, cpu_env, src);
-            break;
-        case 4:
-            opsize = OS_WORD;
-            gen_helper_f64_to_i32(tmp32, cpu_env, src);
-            break;
-        case 5: /* OS_DOUBLE */
-            tcg_gen_mov_i32(tmp32, AREG(insn, 0));
-            switch ((insn >> 3) & 7) {
-            case 2:
-            case 3:
-                break;
-            case 4:
-                tcg_gen_addi_i32(tmp32, tmp32, -8);
-                break;
-            case 5:
-                offset = ldsw_code(s->pc);
-                s->pc += 2;
-                tcg_gen_addi_i32(tmp32, tmp32, offset);
-                break;
-            default:
-                goto undef;
+        case 0: opsize = OS_LONG; break;
+        case 1: opsize = OS_SINGLE; break;
+        case 4: opsize = OS_WORD; break;
+        case 5: opsize = OS_DOUBLE; break;
+        case 6: opsize = OS_BYTE; break;
+        default:
+            goto undef;
+        }
+        if (opsize == OS_DOUBLE) {
+            tmp32 = gen_lea(s, insn, opsize);
+            if (IS_NULL_QREG(tmp32)) {
+                gen_addr_fault(s);
+                return;
             }
             gen_store64(s, tmp32, src);
-            switch ((insn >> 3) & 7) {
-            case 3:
-                tcg_gen_addi_i32(tmp32, tmp32, 8);
-                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
+            if ( ((insn >> 3) & 7) == 3) { /* post-increment */
+                reg = AREG(insn, 0);
+                tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+            }
+        } else {
+            switch (opsize) {
+            case OS_LONG:
+            case OS_WORD:
+            case OS_BYTE:
+                gen_helper_f64_to_i32(tmp32, cpu_env, src);
                 break;
-            case 4:
-                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
+            case OS_SINGLE:
+                gen_helper_f64_to_f32(tmp32, cpu_env, src);
                 break;
             }
-            tcg_temp_free_i32(tmp32);
-            return;
-        case 6:
-            opsize = OS_BYTE;
-            gen_helper_f64_to_i32(tmp32, cpu_env, src);
-            break;
-        default:
-            goto undef;
+            DEST_EA(insn, opsize, tmp32, NULL);
         }
-        DEST_EA(insn, opsize, tmp32, NULL);
         tcg_temp_free_i32(tmp32);
         return;
     case 4: /* fmove to control register.  */