diff mbox

[1/4] target-tilegx: Add fpu header file

Message ID COL130-W5173AC7B4DBB9A33083E7DB9160@phx.gbl
State New
Headers show

Commit Message

Chen Gang Nov. 8, 2015, 5:43 a.m. UTC
From 91a3d7d591cac6c4a39d4dbc5c3ffe8c17b10b6a Mon Sep 17 00:00:00 2001
From: Chen Gang <gang.chen.5i5j@gmail.com>
Date: Sun, 8 Nov 2015 09:05:29 +0800
Subject: [PATCH 1/4] target-tilegx: Add fpu header file

It defines the main data structures for tilegx fpu. Also it provides the
summary description for each floating point instructions impmementation.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
---
 target-tilegx/fpu.h | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 228 insertions(+)
 create mode 100644 target-tilegx/fpu.h

-- 
1.9.3

Comments

Richard Henderson Nov. 12, 2015, 2:34 p.m. UTC | #1
On 11/08/2015 06:43 AM, Chen Gang wrote:

> +#if !defined(HOST_WORDS_BIGENDIAN)
> +    /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
> +    uint64_t exp : 8;             /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
> +    uint64_t uiknown0 : 2;        /* unknown */

I would really rather you didn't use bitfields, because of exactly this sort of 
endianness problem.  Because, really, you can't trust this layout.  But I won't 
press this point, because it is complicated enough already.

> +#endif
> +} TileGXFPSFmt;
> +/*

Watch your spacing.

> + * Double exp analyzing: (0x21b00 << 1) - 0x36(54) = 0x400
> + *
> + *   17  16  15  14  13  12  11  10   9   8   7    6   5   4   3   2   1   0
> + *
> + *    1   0   0   0   0   1   1   0   1   1   0    0   0   0   0   0   0   0
> + *
> + *    0   0   0   0   0   1   1   0   1   1   1    => 0x37(55)
> + *
> + *    0   1   1   1   1   1   1   1   1   1   1    => 0x3ff

What is this table supposed to mean?

> +#if 0
> +        uint64_t exp : 11;        /* exp, 0x21b << 1: 55 + TILEGX_F_EXP_DZERO */
> +        uint64_t ov : 1;          /* overflow for mul, low priority */
> +        uint64_t uv : 1;          /* underflow for mul, high priority */
> +#endif


No if 0.

> +#pragma pack(pop)

Huh?  What are you attempting to do here?


r~
Chen Gang Nov. 12, 2015, 4:04 p.m. UTC | #2
On 11/12/15 22:34, Richard Henderson wrote:
> On 11/08/2015 06:43 AM, Chen Gang wrote:
> 
>> +#if !defined(HOST_WORDS_BIGENDIAN)
>> +    /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
>> +    uint64_t exp : 8;             /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
>> +    uint64_t uiknown0 : 2;        /* unknown */
> 
> I would really rather you didn't use bitfields, because of exactly this sort of endianness problem.  Because, really, you can't trust this layout.  But I won't press this point, because it is complicated enough already.
> 

Because of endianess issues, for me, I don't like bit fields either. But
I can not find any other simpler ways than current.

>> +#endif
>> +} TileGXFPSFmt;
>> +/*
> 
> Watch your spacing.
> 

OK, thanks. And I also shall let the related comments above the structure.


>> + * Double exp analyzing: (0x21b00 << 1) - 0x36(54) = 0x400

Oh, it should be (0x21b00 << 1) - 0x37(55) = 0x3ff

>> + *
>> + *   17  16  15  14  13  12  11  10   9   8   7    6   5   4   3   2   1   0
>> + *
>> + *    1   0   0   0   0   1   1   0   1   1   0    0   0   0   0   0   0   0
>> + *
>> + *    0   0   0   0   0   1   1   0   1   1   1    => 0x37(55)
>> + *
>> + *    0   1   1   1   1   1   1   1   1   1   1    => 0x3ff
> 
> What is this table supposed to mean?
> 

I want to use this table to explain my guess: at first, we don't know
the internal exp position, neither know the internal mantasa bits. We
have to guess both of them:

 - the real exp should not be less than 11 bits (IEEE double exp is 11
   bits).

 - Since IEEE double exp 0 is 0x3ff, probobly, for tilegx internally,
   0x3ff shoul be '0', too (don't move mantissa).

 - After analyzing the data from floatunssidf2 in gcc tilegx.md (the
   table above is part for it), I found that "(0x21b00 << 1) - 0x37 =
   0x3ff" is the best to match "all things".

So, I guess: the double exp is from bit 7 to bit 17, then the mantissa
is 60 bits (55 + 1 + 4), it from bit 0 to bit 59.

We can use 7 - 19 bits for normal exp calculation, then can get the real
exp (7 - 17 bits) with the overflow and underflow (so, I guess 18 bit is
for overflow, and 19 bit is for underflow).

>> +#if 0
>> +        uint64_t exp : 11;        /* exp, 0x21b << 1: 55 + TILEGX_F_EXP_DZERO */
>> +        uint64_t ov : 1;          /* overflow for mul, low priority */
>> +        uint64_t uv : 1;          /* underflow for mul, high priority */
>> +#endif
> 
> 
> No if 0.
> 

OK, I shall remove them.

>> +#pragma pack(pop)
> 
> Huh?  What are you attempting to do here?
> 

It is for matching "#pragma pack(push, 1)" which is above all related
struct/unions in this header file.

For the bit fields, we use uint64_t, but gcc still treate it as two
uint32_t, so for safety reason, I use pragma pack for our structures.

Thanks.
Peter Maydell Nov. 12, 2015, 4:10 p.m. UTC | #3
On 12 November 2015 at 16:04, Chen Gang <xili_gchen_5257@hotmail.com> wrote:
> On 11/12/15 22:34, Richard Henderson wrote:
>> On 11/08/2015 06:43 AM, Chen Gang wrote:
>>
>>> +#if !defined(HOST_WORDS_BIGENDIAN)
>>> +    /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
>>> +    uint64_t exp : 8;             /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
>>> +    uint64_t uiknown0 : 2;        /* unknown */
>>
>> I would really rather you didn't use bitfields, because of exactly this sort of endianness problem.  Because, really, you can't trust this layout.  But I won't press this point, because it is complicated enough already.
>>
>
> Because of endianess issues, for me, I don't like bit fields either. But
> I can not find any other simpler ways than current.

> OK, I shall remove them.
>
>>> +#pragma pack(pop)
>>
>> Huh?  What are you attempting to do here?
>>
>
> It is for matching "#pragma pack(push, 1)" which is above all related
> struct/unions in this header file.

Please don't use 'pragma pack' or bitfields. If you need to pack
and unpack things from a target-CPU defined field use bit operations
and/or extract32/deposit32/extract64/deposit64.

thanks
-- PMM
Chen Gang Nov. 12, 2015, 4:28 p.m. UTC | #4
On 11/13/15 00:10, Peter Maydell wrote:
> On 12 November 2015 at 16:04, Chen Gang <xili_gchen_5257@hotmail.com> wrote:
>> On 11/12/15 22:34, Richard Henderson wrote:
>>> On 11/08/2015 06:43 AM, Chen Gang wrote:
>>>
>>>> +#if !defined(HOST_WORDS_BIGENDIAN)
>>>> +    /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
>>>> +    uint64_t exp : 8;             /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
>>>> +    uint64_t uiknown0 : 2;        /* unknown */
>>>
>>> I would really rather you didn't use bitfields, because of exactly this sort of endianness problem.  Because, really, you can't trust this layout.  But I won't press this point, because it is complicated enough already.
>>>
>>
>> Because of endianess issues, for me, I don't like bit fields either. But
>> I can not find any other simpler ways than current.
> 
>> OK, I shall remove them.
>>
>>>> +#pragma pack(pop)
>>>
>>> Huh?  What are you attempting to do here?
>>>
>>
>> It is for matching "#pragma pack(push, 1)" which is above all related
>> struct/unions in this header file.
> 
> Please don't use 'pragma pack' or bitfields. If you need to pack
> and unpack things from a target-CPU defined field use bit operations
> and/or extract32/deposit32/extract64/deposit64.
> 

OK, thanks, although it means I have to rewrite most of code, and test
them again. I shall try to send patch v2 within the next week.

Thanks.
diff mbox

Patch

diff --git a/target-tilegx/fpu.h b/target-tilegx/fpu.h
new file mode 100644
index 0000000..adfa1f5
--- /dev/null
+++ b/target-tilegx/fpu.h
@@ -0,0 +1,228 @@ 
+/*
+ *  TILE-Gx virtual FPU header
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * 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 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
+ * 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/>.
+ */
+#ifndef FPU_TILEGX_H
+#define FPU_TILEGX_H
+
+/*
+ * From IEEE standard, exp of float is 8-bits, exp of double is 11-bits.
+ */
+#define TILEGX_F_EXP_FZERO  0x7f  /* Zero exp for single 8-bits */
+#define TILEGX_F_EXP_FMAX   0xfe  /* max exp for single 8-bits */
+#define TILEGX_F_EXP_DZERO  0x3ff /* Zero exp for double 11-bits */
+#define TILEGX_F_EXP_DMAX   0x7fe /* max exp for double 11-bits */
+#define TILEGX_F_EXP_DUF    0x1000/* underflow exp bit for double */
+
+/*
+ * For fdouble absolute cacluation flag
+ */
+#define TILEGX_F_CALC_CVT   0     /* Perform int to fsingle/fdouble */
+#define TILEGX_F_CALC_ADD   1     /* Perform absolute add operation */
+#define TILEGX_F_CALC_SUB   2     /* Perform absolute sub operation */
+#define TILEGX_F_CALC_MUL   3     /* Perform absolute mul operation */
+
+#pragma pack(push, 1)
+
+/*
+ * Single format, it is 64-bit.
+ *
+ * Single exp analyzing: 0x9e - 0x1e(30) = 0x80
+ *
+ *   7   6   5   4   3   2   1   0
+ *
+ *   1   0   0   1   1   1   1   0
+ *
+ *   0   0   0   1   1   1   1   1    => 0x1f(31)
+ *
+ *   0   1   1   1   1   1   1   1    => 0x7f
+ */
+typedef struct TileGXFPSFmt {
+
+#if !defined(HOST_WORDS_BIGENDIAN)
+    /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
+    uint64_t exp : 8;             /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
+    uint64_t uiknown0 : 2;        /* unknown */
+    uint64_t sign : 1;            /* Sign bit for the total value */
+    uint64_t calc: 2;             /* calculation flag */
+    uint64_t unknown1 : 12;       /* unknown */
+
+    /* Come from TILE-Gx ISA document, Table 7-2 for floating point */
+    uint64_t unordered : 1;       /* The two are unordered */
+    uint64_t lt : 1;              /* 1st is less than 2nd */
+    uint64_t le : 1;              /* 1st is less than or equal to 2nd */
+    uint64_t gt : 1;              /* 1st is greater than 2nd */
+    uint64_t ge : 1;              /* 1st is greater than or equal to 2nd */
+    uint64_t eq : 1;              /* The two operands are equal */
+    uint64_t neq : 1;             /* The two operands are not equal */
+
+    /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
+    uint64_t mantissa : 32;       /* mantissa */
+#else
+    uint64_t mantissa : 32;       /* mantissa */
+    uint64_t neq : 1;             /* The two operands are not equal */
+    uint64_t eq : 1;              /* The two operands are equal */
+    uint64_t ge : 1;              /* 1st is greater than or equal to 2nd */
+    uint64_t gt : 1;              /* 1st is greater than 2nd */
+    uint64_t le : 1;              /* 1st is less than or equal to 2nd */
+    uint64_t lt : 1;              /* 1st is less than 2nd */
+    uint64_t unordered : 1;       /* The two are unordered */
+    uint64_t unknown1 : 12;       /* unknown */
+    uint64_t calc: 2;             /* calculation flag */
+    uint64_t sign : 1;            /* Sign bit for the total value */
+    uint64_t unknown0 : 2;        /* unknown */
+    uint64_t exp : 8;             /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
+#endif
+} TileGXFPSFmt;
+/*
+ * FSingle instructions implemenation:
+ *
+ * fsingle_add1         ; calc srca and srcb,
+ *                      ; convert float_32 to TileGXFPSFmt result.
+ *                      ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_sub1         ; calc srca and srcb.
+ *                      ; convert float_32 to TileGXFPSFmt result.
+ *                      ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_addsub2      ; nop.
+ *
+ * fsingle_mul1         ; calc srca and srcb.
+ *                      ; convert float_32 value to TileGXFPSFmt result.
+ *                      ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_mul2         ; move srca to dest.
+ *
+ * fsingle_pack1        ; nop
+ *
+ * fsingle_pack2        ; treate srca as TileGXFPSFmt result.
+ *                      ; convert TileGXFPSFmt result to float_32 value.
+ *                      ; move float_32 value to dest.
+ */
+
+/*
+ * Dobule format. flag: 64 bits, value: 64 bits.
+ *
+ * Double exp analyzing: (0x21b00 << 1) - 0x36(54) = 0x400
+ *
+ *   17  16  15  14  13  12  11  10   9   8   7    6   5   4   3   2   1   0
+ *
+ *    1   0   0   0   0   1   1   0   1   1   0    0   0   0   0   0   0   0
+ *
+ *    0   0   0   0   0   1   1   0   1   1   1    => 0x37(55)
+ *
+ *    0   1   1   1   1   1   1   1   1   1   1    => 0x3ff
+ *
+ */
+typedef union TileGXFPDFmtF {
+
+    struct {
+#if !defined(HOST_WORDS_BIGENDIAN)
+        uint64_t unknown0 : 7;    /* unknown */
+        uint64_t vexp : 13;      /* vexp = exp | ov | uv */
+#if 0
+        uint64_t exp : 11;        /* exp, 0x21b << 1: 55 + TILEGX_F_EXP_DZERO */
+        uint64_t ov : 1;          /* overflow for mul, low priority */
+        uint64_t uv : 1;          /* underflow for mul, high priority */
+#endif
+        uint64_t sign : 1;        /* Sign bit for the total value */
+
+        uint64_t calc: 2;         /* absolute add, sub, or mul */
+        uint64_t inf: 1;          /* infinit */
+        uint64_t nan: 1;          /* nan */
+
+        /* Come from TILE-Gx ISA document, Table 7-2 for floating point */
+        uint64_t unordered : 1;   /* The two are unordered */
+        uint64_t lt : 1;          /* 1st is less than 2nd */
+        uint64_t le : 1;          /* 1st is less than or equal to 2nd */
+        uint64_t gt : 1;          /* 1st is greater than 2nd */
+        uint64_t ge : 1;          /* 1st is greater than or equal to 2nd */
+        uint64_t eq : 1;          /* The two operands are equal */
+        uint64_t neq : 1;         /* The two operands are not equal */
+
+        uint64_t unknown1 : 32;   /* unknown */
+#else
+        uint64_t unknown1 : 32;   /* unknown */
+        uint64_t neq : 1;         /* The two operands are not equal */
+        uint64_t eq : 1;          /* The two operands are equal */
+        uint64_t ge : 1;          /* 1st is greater than or equal to 2nd */
+        uint64_t gt : 1;          /* 1st is greater than 2nd */
+        uint64_t le : 1;          /* 1st is less than or equal to 2nd */
+        uint64_t lt : 1;          /* 1st is less than 2nd */
+        uint64_t unordered : 1;   /* The two are unordered */
+        uint64_t nan: 1;          /* nan */
+        uint64_t inf: 1;          /* infinit */
+        uint64_t calc: 2;         /* absolute add, sub, or mul */
+        uint64_t sign : 1;        /* Sign bit for the total value */
+        uint64_t vexp : 13;      /* vexp = exp | ov | uv */
+        uint64_t unknown0 : 7;    /* unknown */
+#endif
+    } fmt;
+    uint64_t ll;                  /* only for easy using */
+} TileGXFPDFmtF;
+
+typedef union TileGXFPDFmtV {
+    struct {
+#if !defined(HOST_WORDS_BIGENDIAN)
+        uint64_t mantissa : 60;   /* mantissa */
+        uint64_t overflow : 1;    /* carry/overflow bit for absolute add/mul */
+        uint64_t unknown1 : 3;    /* unknown */
+#else
+        uint64_t unknown1 : 3;    /* unknown */
+        uint64_t overflow : 1;    /* carry/overflow bit for absolute add/mul */
+        uint64_t mantissa : 60;   /* mantissa */
+#endif
+    } fmt;
+    uint64_t ll;                  /* only for easy using */
+} TileGXFPDFmtV;
+/*
+ * FDouble instructions implemenation:
+ *
+ * fdouble_unpack_min   ; srca and srcb are float_64 value.
+ *                      ; get the min absolute value's mantissa.
+ *                      ; move "mantissa>> (exp_max - exp_min)" to dest.
+ *
+ * fdouble_unpack_max   ; srca and srcb are float_64 value.
+ *                      ; get the max absolute value's mantissa.
+ *                      ; move mantissa to dest.
+ *
+ * fdouble_add_flags    ; srca and srcb are float_64 value.
+ *                      ; calc exp (exp_max), sign, and comp bits for flags.
+ *                      ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_sub_flags    ; srca and srcb are float_64 value.
+ *                      ; calc exp (exp_max), sign, and comp bits for flags.
+ *                      ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_addsub:      ; dest, srca (max, min mantissa), and srcb (flags).
+ *                      ; "dest +/- srca" depend on the add/sub bit of flags.
+ *                      ; move result mantissa to dest.
+ *
+ * fdouble_mul_flags:   ; srca and srcb are float_64 value.
+ *                      ; calc sign (xor), exp (exp_min + exp_max), and comp bits.
+ *                      ; mix sign, exp, and comp bits as flags to dest.
+ *
+ * fdouble_pack1        ; move srcb (flags) to dest.
+ *
+ * fdouble_pack2        ; srca, srcb (high, low mantissa), and dest (flags)
+ *                      ; normalize and pack result from srca, srcb, and dest.
+ *                      ; move result to dest.
+ */
+
+#pragma pack(pop)
+
+#endif /* FPU_TILEGX_H */