opflags: Rework opflags bits with OP_ macros
authorCyrill Gorcunov <gorcunov@gmail.com>
Sat, 15 Sep 2012 16:01:32 +0000 (20:01 +0400)
committerCyrill Gorcunov <gorcunov@gmail.com>
Sun, 16 Sep 2012 19:23:56 +0000 (23:23 +0400)
In this path the opflags bits are completely reworked
in a sake of simplier extension. Inparticular for Knights
Corener instructions we will need new registers and new
sizes.

What's done

 - all bits are grouped in sequences, and start using OP_
   macros, thus if one need to extend some field -- just
   tune up @shift and @bits where needed

 - the #define we use in code are OR'ed in symbols, this
   should be a way more convenient to deal with instead of
   pure hex numbers.

The tests are passed but more eyes needed to review this
rather big and intrusive patch. The reason why it's done
in one single path -- for revertability in one command.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
opflags.h

index 904a53a..883d13b 100644 (file)
--- a/opflags.h
+++ b/opflags.h
  *    (class & ~operand) == 0
  *
  * if and only if "operand" belongs to class type "class".
+ */
+
+typedef uint64_t opflags_t;
+
+#define OP_GENMASK(bits, shift)         (((UINT64_C(1) << (bits)) - 1) << (shift))
+#define OP_GENBIT(bit, shift)           (UINT64_C(1) << ((shift) + (bit)))
+
+/*
+ * Type of operand: memory reference, register, etc.
  *
- * The bits are assigned as follows:
- *
- * Bits 0-7, 23, 29: sizes
- *  0:  8 bits (BYTE)
- *  1: 16 bits (WORD)
- *  2: 32 bits (DWORD)
- *  3: 64 bits (QWORD)
- *  4: 80 bits (TWORD)
- *  5: FAR
- *  6: NEAR
- *  7: SHORT
- * 23: 256 bits (YWORD)
- * 29: 128 bits (OWORD)
- *
- * Bits 8-10 modifiers
- *  8: TO
- *  9: COLON
- * 10: STRICT
- *
- * Bits 12-15: type of operand
- * 12: REGISTER
- * 13: IMMEDIATE
- * 14: MEMORY (always has REGMEM attribute as well)
- * 15: REGMEM (valid EA operand)
- *
- * Bits 11, 16-19, 28: subclasses
- * With REG_CDT:
- * 16: REG_CREG (CRx)
- * 17: REG_DREG (DRx)
- * 18: REG_TREG (TRx)
-
- * With REG_GPR:
- * 16: REG_ACCUM  (AL, AX, EAX, RAX)
- * 17: REG_COUNT  (CL, CX, ECX, RCX)
- * 18: REG_DATA   (DL, DX, EDX, RDX)
- * 19: REG_HIGH   (AH, CH, DH, BH)
- * 28: REG_NOTACC (not REG_ACCUM)
- *
- * With REG_SREG:
- * 16: REG_CS
- * 17: REG_DESS (DS, ES, SS)
- * 18: REG_FSGS
- * 19: REG_SEG67
- *
- * With FPUREG:
- * 16: FPU0
- *
- * With XMMREG:
- * 16: XMM0
- *
- * With YMMREG:
- * 16: YMM0
- *
- * With MEMORY:
- * 16: MEM_OFFS (this is a simple offset)
- * 17: IP_REL (IP-relative offset)
+ * Bits: 0 - 3
+ */
+#define OPTYPE_SHIFT            (0)
+#define OPTYPE_BITS             (4)
+#define OPTYPE_MASK             OP_GENMASK(OPTYPE_BITS, OPTYPE_SHIFT)
+#define GEN_OPTYPE(bit)         OP_GENBIT(bit, OPTYPE_SHIFT)
+
+/*
+ * Modifiers.
  *
- * With IMMEDIATE:
- * 16: UNITY (1)
- * 17: BYTENESS16 (-128..127)
- * 18: BYTENESS32 (-128..127)
- * 19: BYTENESS64 (-128..127)
- * 28: SDWORD64 (-2^31..2^31-1)
- * 11: UDWORD64 (0..2^32-1)
+ * Bits: 4 - 6
+ */
+#define MODIFIER_SHIFT          (4)
+#define MODIFIER_BITS           (3)
+#define MODIFIER_MASK           OP_GENMASK(MODIFIER_BITS, MODIFIER_SHIFT)
+#define GEN_MODIFIER(bit)       OP_GENBIT(bit, MODIFIER_SHIFT)
+
+/*
+ * Register classes.
  *
- * Bits 20-22, 24-27: register classes
- * 20: REG_CDT (CRx, DRx, TRx)
- * 21: RM_GPR (REG_GPR) (integer register)
- * 22: REG_SREG
- * 24: FPUREG
- * 25: RM_MMX (MMXREG)
- * 26: RM_XMM (XMMREG)
- * 27: RM_YMM (YMMREG)
+ * Bits: 7 - 16
+ */
+#define REG_CLASS_SHIFT         (7)
+#define REG_CLASS_BITS          (10)
+#define REG_CLASS_MASK          OP_GENMASK(REG_CLASS_BITS, REG_CLASS_SHIFT)
+#define GEN_REG_CLASS(bit)      OP_GENBIT(bit, REG_CLASS_SHIFT)
+
+/*
+ * Subclasses. Depends on type of operand.
  *
- * 30: SAME_AS
- * Special flag only used in instruction patterns; means this operand
- * has to be identical to another operand.  Currently only supported
- * for registers.
+ * Bits: 17 - 24
  */
+#define SUBCLASS_SHIFT          (17)
+#define SUBCLASS_BITS           (8)
+#define SUBCLASS_MASK           OP_GENMASK(SUBCLASS_BITS, SUBCLASS_SHIFT)
+#define GEN_SUBCLASS(bit)       OP_GENBIT(bit, SUBCLASS_SHIFT)
 
-typedef uint64_t opflags_t;
+/*
+ * Special flags. Context dependant.
+ *
+ * Bits: 25 - 31
+ */
+#define SPECIAL_SHIFT           (25)
+#define SPECIAL_BITS            (7)
+#define SPECIAL_MASK            OP_GENMASK(SPECIAL_BITS, SPECIAL_SHIFT)
+#define GEN_SPECIAL(bit)        OP_GENBIT(bit, SPECIAL_SHIFT)
 
-#define OP_GENMASK(bits, shift)         (((UINT64_C(1) << (bits)) - 1) << (shift))
-#define OP_GENBIT(bit, shift)           (UINT64_C(1) << ((shift) + (bit)))
+/*
+ * Sizes of the operands and attributes.
+ *
+ * Bits: 32 - 42
+ */
+#define SIZE_SHIFT              (32)
+#define SIZE_BITS               (11)
+#define SIZE_MASK               OP_GENMASK(SIZE_BITS, SIZE_SHIFT)
+#define GEN_SIZE(bit)           OP_GENBIT(bit, SIZE_SHIFT)
 
+/*
+ * Bits distribution (counted from 0)
+ *
+ *    6         5         4         3         2         1
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ *                                 |
+ *                                 | dword bound
+ *
+ * ............................................................1111 optypes
+ * .........................................................111.... modifiers
+ * ...............................................1111111111....... register classes
+ * .......................................11111111................. subclasses
+ * ................................1111111......................... specials
+ * .....................11111111111................................ sizes
+ */
 
-/* Size, and other attributes, of the operand */
-#define BITS8           UINT64_C(0x00000001)
-#define BITS16          UINT64_C(0x00000002)
-#define BITS32          UINT64_C(0x00000004)
-#define BITS64          UINT64_C(0x00000008)    /* x64 and FPU only */
-#define BITS80          UINT64_C(0x00000010)    /* FPU only */
-#define BITS128         UINT64_C(0x20000000)
-#define BITS256         UINT64_C(0x00800000)
-#define FAR             UINT64_C(0x00000020)    /* grotty: this means 16:16 or */
-                                                /* 16:32, like in CALL/JMP */
-#define NEAR            UINT64_C(0x00000040)
-#define SHORT           UINT64_C(0x00000080)    /* and this means what it says :) */
-
-#define SIZE_MASK       UINT64_C(0x208000FF)    /* all the size attributes */
-
-/* Modifiers */
-#define MODIFIER_MASK   UINT64_C(0x00000700)
-#define TO              UINT64_C(0x00000100)    /* reverse effect in FADD, FSUB &c */
-#define COLON           UINT64_C(0x00000200)    /* operand is followed by a colon */
-#define STRICT          UINT64_C(0x00000400)    /* do not optimize this operand */
-
-/* Type of operand: memory reference, register, etc. */
-#define OPTYPE_MASK     UINT64_C(0x0000f000)
-#define REGISTER        UINT64_C(0x00001000)    /* register number in 'basereg' */
-#define IMMEDIATE       UINT64_C(0x00002000)
-#define MEMORY          UINT64_C(0x0000c000)
-#define REGMEM          UINT64_C(0x00008000)    /* for r/m, ie EA, operands */
+#define REGISTER                GEN_OPTYPE(0)                   /* register number in 'basereg' */
+#define IMMEDIATE               GEN_OPTYPE(1)
+#define REGMEM                  GEN_OPTYPE(2)                   /* for r/m, ie EA, operands */
+#define MEMORY                  (GEN_OPTYPE(3) | REGMEM)
+
+#define BITS8                   GEN_SIZE(0)                     /*   8 bits (BYTE) */
+#define BITS16                  GEN_SIZE(1)                     /*  16 bits (WORD) */
+#define BITS32                  GEN_SIZE(2)                     /*  32 bits (DWORD) */
+#define BITS64                  GEN_SIZE(3)                     /*  64 bits (QWORD), x64 and FPU only */
+#define BITS80                  GEN_SIZE(4)                     /*  80 bits (TWORD), FPU only */
+#define BITS128                 GEN_SIZE(5)                     /* 128 bits (OWORD) */
+#define BITS256                 GEN_SIZE(6)                     /* 256 bits (YWORD) */
+#define BITS512                 GEN_SIZE(7)                     /* 512 bits (ZWORD) */
+#define FAR                     GEN_SIZE(8)                     /* grotty: this means 16:16 or 16:32, like in CALL/JMP */
+#define NEAR                    GEN_SIZE(9)
+#define SHORT                   GEN_SIZE(10)                    /* and this means what it says :) */
+
+#define TO                      GEN_MODIFIER(0)                 /* reverse effect in FADD, FSUB &c */
+#define COLON                   GEN_MODIFIER(1)                 /* operand is followed by a colon */
+#define STRICT                  GEN_MODIFIER(2)                 /* do not optimize this operand */
+
+#define REG_CLASS_CDT           GEN_REG_CLASS(0)
+#define REG_CLASS_GPR           GEN_REG_CLASS(1)
+#define REG_CLASS_SREG          GEN_REG_CLASS(2)
+#define REG_CLASS_FPUREG        GEN_REG_CLASS(3)
+#define REG_CLASS_RM_MMX        GEN_REG_CLASS(4)
+#define REG_CLASS_RM_XMM        GEN_REG_CLASS(5)
+#define REG_CLASS_RM_YMM        GEN_REG_CLASS(6)
 
 #define is_class(class, op)     (!((opflags_t)(class) & ~(opflags_t)(op)))
 
@@ -172,73 +169,76 @@ typedef uint64_t opflags_t;
 #define IS_FSGS(op)             is_class(REG_FSGS, nasm_reg_flags[(op)])
 
 /* Register classes */
-#define REG_EA          UINT64_C(0x00009000)    /* 'normal' reg, qualifies as EA */
-#define RM_GPR          UINT64_C(0x00208000)    /* integer operand */
-#define REG_GPR         UINT64_C(0x00209000)    /* integer register */
-#define REG8            UINT64_C(0x00209001)    /*  8-bit GPR  */
-#define REG16           UINT64_C(0x00209002)    /* 16-bit GPR */
-#define REG32           UINT64_C(0x00209004)    /* 32-bit GPR */
-#define REG64           UINT64_C(0x00209008)    /* 64-bit GPR */
-#define FPUREG          UINT64_C(0x01001000)    /* floating point stack registers */
-#define FPU0            UINT64_C(0x01011000)    /* FPU stack register zero */
-#define RM_MMX          UINT64_C(0x02008000)    /* MMX operand */
-#define MMXREG          UINT64_C(0x02009000)    /* MMX register */
-#define RM_XMM          UINT64_C(0x04008000)    /* XMM (SSE) operand */
-#define XMMREG          UINT64_C(0x04009000)    /* XMM (SSE) register */
-#define XMM0            UINT64_C(0x04019000)    /* XMM register zero */
-#define RM_YMM          UINT64_C(0x08008000)    /* YMM (AVX) operand */
-#define YMMREG          UINT64_C(0x08009000)    /* YMM (AVX) register */
-#define YMM0            UINT64_C(0x08019000)    /* YMM register zero */
-#define REG_CDT         UINT64_C(0x00101004)    /* CRn, DRn and TRn */
-#define REG_CREG        UINT64_C(0x00111004)    /* CRn */
-#define REG_DREG        UINT64_C(0x00121004)    /* DRn */
-#define REG_TREG        UINT64_C(0x00141004)    /* TRn */
-#define REG_SREG        UINT64_C(0x00401002)    /* any segment register */
-#define REG_CS          UINT64_C(0x00411002)    /* CS */
-#define REG_DESS        UINT64_C(0x00421002)    /* DS, ES, SS */
-#define REG_FSGS        UINT64_C(0x00441002)    /* FS, GS */
-#define REG_SEG67       UINT64_C(0x00481002)    /* Unimplemented segment registers */
+#define REG_EA                  (                                               REGMEM | REGISTER)      /* 'normal' reg, qualifies as EA */
+#define RM_GPR                  (                  REG_CLASS_GPR              | REGMEM)                 /* integer operand */
+#define REG_GPR                 (                  REG_CLASS_GPR              | REGMEM | REGISTER)      /* integer register */
+#define REG8                    (                  REG_CLASS_GPR    | BITS8   | REGMEM | REGISTER)      /*  8-bit GPR  */
+#define REG16                   (                  REG_CLASS_GPR    | BITS16  | REGMEM | REGISTER)      /* 16-bit GPR */
+#define REG32                   (                  REG_CLASS_GPR    | BITS32  | REGMEM | REGISTER)      /* 32-bit GPR */
+#define REG64                   (                  REG_CLASS_GPR    | BITS64  | REGMEM | REGISTER)      /* 64-bit GPR */
+#define FPUREG                  (                  REG_CLASS_FPUREG                    | REGISTER)      /* floating point stack registers */
+#define FPU0                    (GEN_SUBCLASS(1) | REG_CLASS_FPUREG                    | REGISTER)      /* FPU stack register zero */
+#define RM_MMX                  (                  REG_CLASS_RM_MMX           | REGMEM)                 /* MMX operand */
+#define MMXREG                  (                  REG_CLASS_RM_MMX           | REGMEM | REGISTER)      /* MMX register */
+#define RM_XMM                  (                  REG_CLASS_RM_XMM           | REGMEM)                 /* XMM (SSE) operand */
+#define XMMREG                  (                  REG_CLASS_RM_XMM           | REGMEM | REGISTER)      /* XMM (SSE) register */
+#define XMM0                    (GEN_SUBCLASS(1) | REG_CLASS_RM_XMM           | REGMEM | REGISTER)      /* XMM register zero */
+#define RM_YMM                  (                  REG_CLASS_RM_YMM           | REGMEM)                 /* YMM (AVX) operand */
+#define YMMREG                  (                  REG_CLASS_RM_YMM           | REGMEM | REGISTER)      /* YMM (AVX) register */
+#define YMM0                    (GEN_SUBCLASS(1) | REG_CLASS_RM_YMM           | REGMEM | REGISTER)      /* YMM register zero */
+#define REG_CDT                 (                  REG_CLASS_CDT    | BITS32           | REGISTER)      /* CRn, DRn and TRn */
+#define REG_CREG                (GEN_SUBCLASS(1) | REG_CLASS_CDT    | BITS32           | REGISTER)      /* CRn */
+#define REG_DREG                (GEN_SUBCLASS(2) | REG_CLASS_CDT    | BITS32           | REGISTER)      /* DRn */
+#define REG_TREG                (GEN_SUBCLASS(3) | REG_CLASS_CDT    | BITS32           | REGISTER)      /* TRn */
+#define REG_SREG                (                  REG_CLASS_SREG   | BITS16           | REGISTER)      /* any segment register */
+#define REG_CS                  (GEN_SUBCLASS(1) | REG_CLASS_SREG   | BITS16           | REGISTER)      /* CS */
+#define REG_DESS                (GEN_SUBCLASS(2) | REG_CLASS_SREG   | BITS16           | REGISTER)      /* DS, ES, SS */
+#define REG_FSGS                (GEN_SUBCLASS(3) | REG_CLASS_SREG   | BITS16           | REGISTER)      /* FS, GS */
+#define REG_SEG67               (GEN_SUBCLASS(4) | REG_CLASS_SREG   | BITS16           | REGISTER)      /* Unimplemented segment registers */
 
 /* Special GPRs */
-#define REG_SMASK       UINT64_C(0x100f0800)    /* a mask for the following */
-#define REG_ACCUM       UINT64_C(0x00219000)    /* accumulator: AL, AX, EAX, RAX */
-#define REG_AL          UINT64_C(0x00219001)
-#define REG_AX          UINT64_C(0x00219002)
-#define REG_EAX         UINT64_C(0x00219004)
-#define REG_RAX         UINT64_C(0x00219008)
-#define REG_COUNT       UINT64_C(0x10229000)    /* counter: CL, CX, ECX, RCX */
-#define REG_CL          UINT64_C(0x10229001)
-#define REG_CX          UINT64_C(0x10229002)
-#define REG_ECX         UINT64_C(0x10229004)
-#define REG_RCX         UINT64_C(0x10229008)
-#define REG_DL          UINT64_C(0x10249001)    /* data: DL, DX, EDX, RDX */
-#define REG_DX          UINT64_C(0x10249002)
-#define REG_EDX         UINT64_C(0x10249004)
-#define REG_RDX         UINT64_C(0x10249008)
-#define REG_HIGH        UINT64_C(0x10289001)    /* high regs: AH, CH, DH, BH */
-#define REG_NOTACC      UINT64_C(0x10000000)    /* non-accumulator register */
-#define REG8NA          UINT64_C(0x10209001)    /*  8-bit non-acc GPR  */
-#define REG16NA         UINT64_C(0x10209002)    /* 16-bit non-acc GPR */
-#define REG32NA         UINT64_C(0x10209004)    /* 32-bit non-acc GPR */
-#define REG64NA         UINT64_C(0x10209008)    /* 64-bit non-acc GPR */
+#define REG_SMASK               SUBCLASS_MASK                                                                           /* a mask for the following */
+#define REG_ACCUM               (GEN_SUBCLASS(1)                   | REG_CLASS_GPR           | REGMEM | REGISTER)       /* accumulator: AL, AX, EAX, RAX */
+#define REG_AL                  (GEN_SUBCLASS(1)                   | REG_CLASS_GPR | BITS8   | REGMEM | REGISTER)
+#define REG_AX                  (GEN_SUBCLASS(1)                   | REG_CLASS_GPR | BITS16  | REGMEM | REGISTER)
+#define REG_EAX                 (GEN_SUBCLASS(1)                   | REG_CLASS_GPR | BITS32  | REGMEM | REGISTER)
+#define REG_RAX                 (GEN_SUBCLASS(1)                   | REG_CLASS_GPR | BITS64  | REGMEM | REGISTER)
+#define REG_COUNT               (GEN_SUBCLASS(5) | GEN_SUBCLASS(2) | REG_CLASS_GPR           | REGMEM | REGISTER)       /* counter: CL, CX, ECX, RCX */
+#define REG_CL                  (GEN_SUBCLASS(5) | GEN_SUBCLASS(2) | REG_CLASS_GPR | BITS8   | REGMEM | REGISTER)
+#define REG_CX                  (GEN_SUBCLASS(5) | GEN_SUBCLASS(2) | REG_CLASS_GPR | BITS16  | REGMEM | REGISTER)
+#define REG_ECX                 (GEN_SUBCLASS(5) | GEN_SUBCLASS(2) | REG_CLASS_GPR | BITS32  | REGMEM | REGISTER)
+#define REG_RCX                 (GEN_SUBCLASS(5) | GEN_SUBCLASS(2) | REG_CLASS_GPR | BITS64  | REGMEM | REGISTER)
+#define REG_DL                  (GEN_SUBCLASS(5) | GEN_SUBCLASS(3) | REG_CLASS_GPR | BITS8   | REGMEM | REGISTER)       /* data: DL, DX, EDX, RDX */
+#define REG_DX                  (GEN_SUBCLASS(5) | GEN_SUBCLASS(3) | REG_CLASS_GPR | BITS16  | REGMEM | REGISTER)
+#define REG_EDX                 (GEN_SUBCLASS(5) | GEN_SUBCLASS(3) | REG_CLASS_GPR | BITS32  | REGMEM | REGISTER)
+#define REG_RDX                 (GEN_SUBCLASS(5) | GEN_SUBCLASS(3) | REG_CLASS_GPR | BITS64  | REGMEM | REGISTER)
+#define REG_HIGH                (GEN_SUBCLASS(5) | GEN_SUBCLASS(4) | REG_CLASS_GPR | BITS8   | REGMEM | REGISTER)       /* high regs: AH, CH, DH, BH */
+#define REG_NOTACC              GEN_SUBCLASS(5)                                                                         /* non-accumulator register */
+#define REG8NA                  (GEN_SUBCLASS(5)                   | REG_CLASS_GPR | BITS8   | REGMEM | REGISTER)       /*  8-bit non-acc GPR  */
+#define REG16NA                 (GEN_SUBCLASS(5)                   | REG_CLASS_GPR | BITS16  | REGMEM | REGISTER)       /* 16-bit non-acc GPR */
+#define REG32NA                 (GEN_SUBCLASS(5)                   | REG_CLASS_GPR | BITS32  | REGMEM | REGISTER)       /* 32-bit non-acc GPR */
+#define REG64NA                 (GEN_SUBCLASS(5)                   | REG_CLASS_GPR | BITS64  | REGMEM | REGISTER)       /* 64-bit non-acc GPR */
 
 /* special types of EAs */
-#define MEM_OFFS        UINT64_C(0x0001c000)    /* simple [address] offset - absolute! */
-#define IP_REL          UINT64_C(0x0002c000)    /* IP-relative offset */
+#define MEM_OFFS                (GEN_SUBCLASS(1) | MEMORY)      /* simple [address] offset - absolute! */
+#define IP_REL                  (GEN_SUBCLASS(2) | MEMORY)      /* IP-relative offset */
 
 /* memory which matches any type of r/m operand */
-#define MEMORY_ANY      (MEMORY|RM_GPR|RM_MMX|RM_XMM|RM_YMM)
+#define MEMORY_ANY              (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM)
 
 /* special type of immediate operand */
-#define UNITY           UINT64_C(0x00012000)    /* for shift/rotate instructions */
-#define SBYTE16         UINT64_C(0x00022000)    /* for op r16,immediate instrs. */
-#define SBYTE32         UINT64_C(0x00042000)    /* for op r32,immediate instrs. */
-#define SBYTE64         UINT64_C(0x00082000)    /* for op r64,immediate instrs. */
-#define BYTENESS        UINT64_C(0x000e0000)    /* for testing for byteness */
-#define SDWORD64       UINT64_C(0x10002000)    /* for op r64,simm32 instrs. */
-#define UDWORD64       UINT64_C(0x00002800)    /* for op r64,uimm32 instrs. */
+#define UNITY                   (GEN_SUBCLASS(1) | IMMEDIATE)   /* for shift/rotate instructions */
+#define SBYTE16                 (GEN_SUBCLASS(2) | IMMEDIATE)   /* for op r16,immediate instrs. */
+#define SBYTE32                 (GEN_SUBCLASS(3) | IMMEDIATE)   /* for op r32,immediate instrs. */
+#define SBYTE64                 (GEN_SUBCLASS(4) | IMMEDIATE)   /* for op r64,immediate instrs. */
+#define SDWORD64               (GEN_SUBCLASS(5) | IMMEDIATE)   /* for op r64,simm32 instrs. */
+#define UDWORD64               (GEN_SUBCLASS(0) | IMMEDIATE)   /* for op r64,uimm32 instrs. */
+
+#define BYTENESS                (GEN_SUBCLASS(2) | \
+                                 GEN_SUBCLASS(3) | \
+                                 GEN_SUBCLASS(4))               /* for testing for byteness */
 
 /* special flags */
-#define SAME_AS         UINT64_C(0x40000000)
+#define SAME_AS                 GEN_SPECIAL(0)
 
 #endif /* NASM_OPFLAGS_H */