Patchwork [033/111] m68k: Add fmovecr

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

Comments

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

This patch allows to read constant from the FPU ROM.
It implements instructions like "fmovecrx #0,%fp0" (which loads
Pi to %fp0).

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |   33 +++++++++++++++++++++++++++++++++
 target-m68k/helpers.h   |    1 +
 target-m68k/translate.c |   12 +++++++++++-
 3 files changed, 45 insertions(+), 1 deletions(-)

Patch

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index d0fc155..914147a 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -815,6 +815,39 @@  HELPER_ROXL(uint16_t, 16)
 HELPER_ROXL(uint32_t, 32)
 
 /* FPU helpers.  */
+
+static const floatx80 fpu_rom[128] = {
+    [0x00] = { .high = 0x4000, .low = 0xc90fdaa22168c235 },	/* Pi */
+
+    [0x0b] = { .high = 0x3ffd, .low = 0x9a209a84fbcff798 },	/* Log10(2) */
+    [0x0c] = { .high = 0x4000, .low = 0xadf85458a2bb4a9a },	/* e        */
+    [0x0d] = { .high = 0x3fff, .low = 0xb8aa3b295c17f0bc },	/* Log2(e)  */
+    [0x0e] = { .high = 0x3ffd, .low = 0xde5bd8a937287195 },	/* Log10(e) */
+    [0x0f] = { .high = 0x0000, .low = 0x0000000000000000 },	/* Zero     */
+
+    [0x30] = { .high = 0x3ffe, .low = 0xb17217f7d1cf79ac },	/* ln(2)    */
+    [0x31] = { .high = 0x4000, .low = 0x935d8dddaaa8ac17 },	/* ln(10)   */
+    [0x32] = { .high = 0x3fff, .low = 0x8000000000000000 },	/* 10^0     */
+    [0x33] = { .high = 0x4002, .low = 0xa000000000000000 },	/* 10^1     */
+    [0x34] = { .high = 0x4005, .low = 0xc800000000000000 },	/* 10^2     */
+    [0x35] = { .high = 0x400c, .low = 0x9c40000000000000 },	/* 10^4     */
+    [0x36] = { .high = 0x4019, .low = 0xbebc200000000000 },	/* 10^8     */
+    [0x37] = { .high = 0x4034, .low = 0x8e1bc9bf04000000 },	/* 10^16    */
+    [0x38] = { .high = 0x4069, .low = 0x9dc5ada82b70b59e },	/* 10^32    */
+    [0x39] = { .high = 0x40d3, .low = 0xc2781f49ffcfa6d5 },	/* 10^64    */
+    [0x3a] = { .high = 0x41a8, .low = 0x93ba47c980e98ce0 },	/* 10^128   */
+    [0x3b] = { .high = 0x4351, .low = 0xaa7eebfb9df9de8e },	/* 10^256   */
+    [0x3c] = { .high = 0x46a3, .low = 0xe319a0aea60e91c7 },	/* 10^512   */
+    [0x3d] = { .high = 0x4d48, .low = 0xc976758681750c17 },	/* 10^1024  */
+    [0x3e] = { .high = 0x5a92, .low = 0x9e8b3b5dc53d5de5 },	/* 10^2048  */
+    [0x3f] = { .high = 0x7525, .low = 0xc46052028a20979b },	/* 10^4096  */
+};
+
+float64 HELPER(const_f64)(CPUState *env, uint32_t offset)
+{
+    return floatx80_to_float64(fpu_rom[offset], &env->fp_status);
+}
+
 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
 {
     return float64_to_int32(val, &env->fp_status);
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index d71ed26..50f5486 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -41,6 +41,7 @@  DEF_HELPER_2(xflag_lt, i32, i32, i32)
 DEF_HELPER_2(set_sr, void, env, i32)
 DEF_HELPER_3(movec, void, env, i32, i32)
 
+DEF_HELPER_2(const_f64, f64, env, i32);
 DEF_HELPER_2(f64_to_i32, f32, env, f64)
 DEF_HELPER_2(f64_to_f32, f32, env, f64)
 DEF_HELPER_2(i32_to_f64, f64, env, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 896e187..3ce5f53 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2949,6 +2949,7 @@  DISAS_INSN(trap)
 DISAS_INSN(fpu)
 {
     uint16_t ext;
+    uint8_t rom_offset;
     int opmode;
     TCGv_i64 src;
     TCGv_i64 dest;
@@ -2962,10 +2963,19 @@  DISAS_INSN(fpu)
     ext = read_im16(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;
+            dest = FREG(ext, 7);
+            gen_helper_const_f64(dest, cpu_env, tcg_const_i32(rom_offset));
+            return;
+        }
+        break;
     case 3: /* fmove out */
         src = FREG(ext, 7);
         tmp32 = tcg_temp_new_i32();