* Copyright (C) IBM Corporation, 2009
  */
 
+#include <asm/byteorder.h>
 /* insn_attr_t is defined in inat.h */
 #include <asm/inat.h>
 
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
+
 struct insn_field {
        union {
                insn_value_t value;
        unsigned char nbytes;
 };
 
+static inline void insn_field_set(struct insn_field *p, insn_value_t v,
+                                 unsigned char n)
+{
+       p->value = v;
+       p->nbytes = n;
+}
+
+#else
+
+struct insn_field {
+       insn_value_t value;
+       union {
+               insn_value_t little;
+               insn_byte_t bytes[4];
+       };
+       /* !0 if we've run insn_get_xxx() for this field */
+       unsigned char got;
+       unsigned char nbytes;
+};
+
+static inline void insn_field_set(struct insn_field *p, insn_value_t v,
+                                 unsigned char n)
+{
+       p->value = v;
+       p->little = __cpu_to_le32(v);
+       p->nbytes = n;
+}
+
+#endif
+
 struct insn {
        struct insn_field prefixes;     /*
                                         * Prefixes
 
  * Copyright (C) IBM Corporation, 2002, 2004, 2009
  */
 
+#include <linux/kernel.h>
 #ifdef __KERNEL__
 #include <linux/string.h>
 #else
 
 #include <asm/emulate_prefix.h>
 
+#define leXX_to_cpu(t, r)                                              \
+({                                                                     \
+       __typeof__(t) v;                                                \
+       switch (sizeof(t)) {                                            \
+       case 4: v = le32_to_cpu(r); break;                              \
+       case 2: v = le16_to_cpu(r); break;                              \
+       case 1: v = r; break;                                           \
+       default:                                                        \
+               BUILD_BUG(); break;                                     \
+       }                                                               \
+       v;                                                              \
+})
+
 /* Verify next sizeof(t) bytes can be on the same instruction */
 #define validate_next(t, insn, n)      \
        ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
 
 #define __get_next(t, insn)    \
-       ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+       ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); leXX_to_cpu(t, r); })
 
 #define __peek_nbyte_next(t, insn, n)  \
-       ({ t r = *(t*)((insn)->next_byte + n); r; })
+       ({ t r = *(t*)((insn)->next_byte + n); leXX_to_cpu(t, r); })
 
 #define get_next(t, insn)      \
        ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
                b = peek_next(insn_byte_t, insn);
                attr = inat_get_opcode_attribute(b);
                if (inat_is_rex_prefix(attr)) {
-                       insn->rex_prefix.value = b;
-                       insn->rex_prefix.nbytes = 1;
+                       insn_field_set(&insn->rex_prefix, b, 1);
                        insn->next_byte++;
                        if (X86_REX_W(b))
                                /* REX.W overrides opnd_size */
 
        if (inat_has_modrm(insn->attr)) {
                mod = get_next(insn_byte_t, insn);
-               modrm->value = mod;
-               modrm->nbytes = 1;
+               insn_field_set(modrm, mod, 1);
                if (inat_is_group(insn->attr)) {
                        pfx_id = insn_last_prefix_id(insn);
                        insn->attr = inat_get_group_attribute(mod, pfx_id,
         * For rip-relative instructions, the mod field (top 2 bits)
         * is zero and the r/m field (bottom 3 bits) is 0x5.
         */
-       return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
+       return (modrm->nbytes && (modrm->bytes[0] & 0xc7) == 0x5);
 }
 
 /**
        if (!insn->modrm.got)
                insn_get_modrm(insn);
        if (insn->modrm.nbytes) {
-               modrm = (insn_byte_t)insn->modrm.value;
+               modrm = insn->modrm.bytes[0];
                if (insn->addr_bytes != 2 &&
                    X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
-                       insn->sib.value = get_next(insn_byte_t, insn);
-                       insn->sib.nbytes = 1;
+                       insn_field_set(&insn->sib,
+                                      get_next(insn_byte_t, insn), 1);
                }
        }
        insn->sib.got = 1;
                if (mod == 3)
                        goto out;
                if (mod == 1) {
-                       insn->displacement.value = get_next(signed char, insn);
-                       insn->displacement.nbytes = 1;
+                       insn_field_set(&insn->displacement,
+                                      get_next(signed char, insn), 1);
                } else if (insn->addr_bytes == 2) {
                        if ((mod == 0 && rm == 6) || mod == 2) {
-                               insn->displacement.value =
-                                        get_next(short, insn);
-                               insn->displacement.nbytes = 2;
+                               insn_field_set(&insn->displacement,
+                                              get_next(short, insn), 2);
                        }
                } else {
                        if ((mod == 0 && rm == 5) || mod == 2 ||
                            (mod == 0 && base == 5)) {
-                               insn->displacement.value = get_next(int, insn);
-                               insn->displacement.nbytes = 4;
+                               insn_field_set(&insn->displacement,
+                                              get_next(int, insn), 4);
                        }
                }
        }
 {
        switch (insn->addr_bytes) {
        case 2:
-               insn->moffset1.value = get_next(short, insn);
-               insn->moffset1.nbytes = 2;
+               insn_field_set(&insn->moffset1, get_next(short, insn), 2);
                break;
        case 4:
-               insn->moffset1.value = get_next(int, insn);
-               insn->moffset1.nbytes = 4;
+               insn_field_set(&insn->moffset1, get_next(int, insn), 4);
                break;
        case 8:
-               insn->moffset1.value = get_next(int, insn);
-               insn->moffset1.nbytes = 4;
-               insn->moffset2.value = get_next(int, insn);
-               insn->moffset2.nbytes = 4;
+               insn_field_set(&insn->moffset1, get_next(int, insn), 4);
+               insn_field_set(&insn->moffset2, get_next(int, insn), 4);
                break;
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
 {
        switch (insn->opnd_bytes) {
        case 2:
-               insn->immediate.value = get_next(short, insn);
-               insn->immediate.nbytes = 2;
+               insn_field_set(&insn->immediate, get_next(short, insn), 2);
                break;
        case 4:
        case 8:
-               insn->immediate.value = get_next(int, insn);
-               insn->immediate.nbytes = 4;
+               insn_field_set(&insn->immediate, get_next(int, insn), 4);
                break;
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
 {
        switch (insn->opnd_bytes) {
        case 2:
-               insn->immediate1.value = get_next(short, insn);
-               insn->immediate1.nbytes = 2;
+               insn_field_set(&insn->immediate1, get_next(short, insn), 2);
                break;
        case 4:
-               insn->immediate1.value = get_next(int, insn);
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
                insn->immediate1.nbytes = 4;
                break;
        case 8:
-               insn->immediate1.value = get_next(int, insn);
-               insn->immediate1.nbytes = 4;
-               insn->immediate2.value = get_next(int, insn);
-               insn->immediate2.nbytes = 4;
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
+               insn_field_set(&insn->immediate2, get_next(int, insn), 4);
                break;
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
 {
        switch (insn->opnd_bytes) {
        case 2:
-               insn->immediate1.value = get_next(short, insn);
-               insn->immediate1.nbytes = 2;
+               insn_field_set(&insn->immediate1, get_next(short, insn), 2);
                break;
        case 4:
-               insn->immediate1.value = get_next(int, insn);
-               insn->immediate1.nbytes = 4;
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
                break;
        case 8:
                /* ptr16:64 is not exist (no segment) */
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
        }
-       insn->immediate2.value = get_next(unsigned short, insn);
-       insn->immediate2.nbytes = 2;
+       insn_field_set(&insn->immediate2, get_next(unsigned short, insn), 2);
        insn->immediate1.got = insn->immediate2.got = 1;
 
        return 1;
 
        switch (inat_immediate_size(insn->attr)) {
        case INAT_IMM_BYTE:
-               insn->immediate.value = get_next(signed char, insn);
-               insn->immediate.nbytes = 1;
+               insn_field_set(&insn->immediate, get_next(signed char, insn), 1);
                break;
        case INAT_IMM_WORD:
-               insn->immediate.value = get_next(short, insn);
-               insn->immediate.nbytes = 2;
+               insn_field_set(&insn->immediate, get_next(short, insn), 2);
                break;
        case INAT_IMM_DWORD:
-               insn->immediate.value = get_next(int, insn);
-               insn->immediate.nbytes = 4;
+               insn_field_set(&insn->immediate, get_next(int, insn), 4);
                break;
        case INAT_IMM_QWORD:
-               insn->immediate1.value = get_next(int, insn);
-               insn->immediate1.nbytes = 4;
-               insn->immediate2.value = get_next(int, insn);
-               insn->immediate2.nbytes = 4;
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
+               insn_field_set(&insn->immediate2, get_next(int, insn), 4);
                break;
        case INAT_IMM_PTR:
                if (!__get_immptr(insn))
                goto err_out;
        }
        if (inat_has_second_immediate(insn->attr)) {
-               insn->immediate2.value = get_next(signed char, insn);
-               insn->immediate2.nbytes = 1;
+               insn_field_set(&insn->immediate2, get_next(signed char, insn), 1);
        }
 done:
        insn->immediate.got = 1;
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-
-#define unlikely(cond) (cond)
-#define ARRAY_SIZE(a)  (sizeof(a)/sizeof(a[0]))
-
 #include <asm/insn.h>
 #include <inat.c>
 #include <insn.c>
 
  * Copyright (C) IBM Corporation, 2009
  */
 
+#include <asm/byteorder.h>
 /* insn_attr_t is defined in inat.h */
 #include "inat.h"
 
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
+
 struct insn_field {
        union {
                insn_value_t value;
        unsigned char nbytes;
 };
 
+static inline void insn_field_set(struct insn_field *p, insn_value_t v,
+                                 unsigned char n)
+{
+       p->value = v;
+       p->nbytes = n;
+}
+
+#else
+
+struct insn_field {
+       insn_value_t value;
+       union {
+               insn_value_t little;
+               insn_byte_t bytes[4];
+       };
+       /* !0 if we've run insn_get_xxx() for this field */
+       unsigned char got;
+       unsigned char nbytes;
+};
+
+static inline void insn_field_set(struct insn_field *p, insn_value_t v,
+                                 unsigned char n)
+{
+       p->value = v;
+       p->little = __cpu_to_le32(v);
+       p->nbytes = n;
+}
+
+#endif
+
 struct insn {
        struct insn_field prefixes;     /*
                                         * Prefixes
 
  * Copyright (C) IBM Corporation, 2002, 2004, 2009
  */
 
+#include <linux/kernel.h>
 #ifdef __KERNEL__
 #include <linux/string.h>
 #else
 
 #include "../include/asm/emulate_prefix.h"
 
+#define leXX_to_cpu(t, r)                                              \
+({                                                                     \
+       __typeof__(t) v;                                                \
+       switch (sizeof(t)) {                                            \
+       case 4: v = le32_to_cpu(r); break;                              \
+       case 2: v = le16_to_cpu(r); break;                              \
+       case 1: v = r; break;                                           \
+       default:                                                        \
+               BUILD_BUG(); break;                                     \
+       }                                                               \
+       v;                                                              \
+})
+
 /* Verify next sizeof(t) bytes can be on the same instruction */
 #define validate_next(t, insn, n)      \
        ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
 
 #define __get_next(t, insn)    \
-       ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+       ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); leXX_to_cpu(t, r); })
 
 #define __peek_nbyte_next(t, insn, n)  \
-       ({ t r = *(t*)((insn)->next_byte + n); r; })
+       ({ t r = *(t*)((insn)->next_byte + n); leXX_to_cpu(t, r); })
 
 #define get_next(t, insn)      \
        ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
                b = peek_next(insn_byte_t, insn);
                attr = inat_get_opcode_attribute(b);
                if (inat_is_rex_prefix(attr)) {
-                       insn->rex_prefix.value = b;
-                       insn->rex_prefix.nbytes = 1;
+                       insn_field_set(&insn->rex_prefix, b, 1);
                        insn->next_byte++;
                        if (X86_REX_W(b))
                                /* REX.W overrides opnd_size */
 
        if (inat_has_modrm(insn->attr)) {
                mod = get_next(insn_byte_t, insn);
-               modrm->value = mod;
-               modrm->nbytes = 1;
+               insn_field_set(modrm, mod, 1);
                if (inat_is_group(insn->attr)) {
                        pfx_id = insn_last_prefix_id(insn);
                        insn->attr = inat_get_group_attribute(mod, pfx_id,
         * For rip-relative instructions, the mod field (top 2 bits)
         * is zero and the r/m field (bottom 3 bits) is 0x5.
         */
-       return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
+       return (modrm->nbytes && (modrm->bytes[0] & 0xc7) == 0x5);
 }
 
 /**
        if (!insn->modrm.got)
                insn_get_modrm(insn);
        if (insn->modrm.nbytes) {
-               modrm = (insn_byte_t)insn->modrm.value;
+               modrm = insn->modrm.bytes[0];
                if (insn->addr_bytes != 2 &&
                    X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
-                       insn->sib.value = get_next(insn_byte_t, insn);
-                       insn->sib.nbytes = 1;
+                       insn_field_set(&insn->sib,
+                                      get_next(insn_byte_t, insn), 1);
                }
        }
        insn->sib.got = 1;
                if (mod == 3)
                        goto out;
                if (mod == 1) {
-                       insn->displacement.value = get_next(signed char, insn);
-                       insn->displacement.nbytes = 1;
+                       insn_field_set(&insn->displacement,
+                                      get_next(signed char, insn), 1);
                } else if (insn->addr_bytes == 2) {
                        if ((mod == 0 && rm == 6) || mod == 2) {
-                               insn->displacement.value =
-                                        get_next(short, insn);
-                               insn->displacement.nbytes = 2;
+                               insn_field_set(&insn->displacement,
+                                              get_next(short, insn), 2);
                        }
                } else {
                        if ((mod == 0 && rm == 5) || mod == 2 ||
                            (mod == 0 && base == 5)) {
-                               insn->displacement.value = get_next(int, insn);
-                               insn->displacement.nbytes = 4;
+                               insn_field_set(&insn->displacement,
+                                              get_next(int, insn), 4);
                        }
                }
        }
 {
        switch (insn->addr_bytes) {
        case 2:
-               insn->moffset1.value = get_next(short, insn);
-               insn->moffset1.nbytes = 2;
+               insn_field_set(&insn->moffset1, get_next(short, insn), 2);
                break;
        case 4:
-               insn->moffset1.value = get_next(int, insn);
-               insn->moffset1.nbytes = 4;
+               insn_field_set(&insn->moffset1, get_next(int, insn), 4);
                break;
        case 8:
-               insn->moffset1.value = get_next(int, insn);
-               insn->moffset1.nbytes = 4;
-               insn->moffset2.value = get_next(int, insn);
-               insn->moffset2.nbytes = 4;
+               insn_field_set(&insn->moffset1, get_next(int, insn), 4);
+               insn_field_set(&insn->moffset2, get_next(int, insn), 4);
                break;
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
 {
        switch (insn->opnd_bytes) {
        case 2:
-               insn->immediate.value = get_next(short, insn);
-               insn->immediate.nbytes = 2;
+               insn_field_set(&insn->immediate, get_next(short, insn), 2);
                break;
        case 4:
        case 8:
-               insn->immediate.value = get_next(int, insn);
-               insn->immediate.nbytes = 4;
+               insn_field_set(&insn->immediate, get_next(int, insn), 4);
                break;
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
 {
        switch (insn->opnd_bytes) {
        case 2:
-               insn->immediate1.value = get_next(short, insn);
-               insn->immediate1.nbytes = 2;
+               insn_field_set(&insn->immediate1, get_next(short, insn), 2);
                break;
        case 4:
-               insn->immediate1.value = get_next(int, insn);
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
                insn->immediate1.nbytes = 4;
                break;
        case 8:
-               insn->immediate1.value = get_next(int, insn);
-               insn->immediate1.nbytes = 4;
-               insn->immediate2.value = get_next(int, insn);
-               insn->immediate2.nbytes = 4;
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
+               insn_field_set(&insn->immediate2, get_next(int, insn), 4);
                break;
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
 {
        switch (insn->opnd_bytes) {
        case 2:
-               insn->immediate1.value = get_next(short, insn);
-               insn->immediate1.nbytes = 2;
+               insn_field_set(&insn->immediate1, get_next(short, insn), 2);
                break;
        case 4:
-               insn->immediate1.value = get_next(int, insn);
-               insn->immediate1.nbytes = 4;
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
                break;
        case 8:
                /* ptr16:64 is not exist (no segment) */
        default:        /* opnd_bytes must be modified manually */
                goto err_out;
        }
-       insn->immediate2.value = get_next(unsigned short, insn);
-       insn->immediate2.nbytes = 2;
+       insn_field_set(&insn->immediate2, get_next(unsigned short, insn), 2);
        insn->immediate1.got = insn->immediate2.got = 1;
 
        return 1;
 
        switch (inat_immediate_size(insn->attr)) {
        case INAT_IMM_BYTE:
-               insn->immediate.value = get_next(signed char, insn);
-               insn->immediate.nbytes = 1;
+               insn_field_set(&insn->immediate, get_next(signed char, insn), 1);
                break;
        case INAT_IMM_WORD:
-               insn->immediate.value = get_next(short, insn);
-               insn->immediate.nbytes = 2;
+               insn_field_set(&insn->immediate, get_next(short, insn), 2);
                break;
        case INAT_IMM_DWORD:
-               insn->immediate.value = get_next(int, insn);
-               insn->immediate.nbytes = 4;
+               insn_field_set(&insn->immediate, get_next(int, insn), 4);
                break;
        case INAT_IMM_QWORD:
-               insn->immediate1.value = get_next(int, insn);
-               insn->immediate1.nbytes = 4;
-               insn->immediate2.value = get_next(int, insn);
-               insn->immediate2.nbytes = 4;
+               insn_field_set(&insn->immediate1, get_next(int, insn), 4);
+               insn_field_set(&insn->immediate2, get_next(int, insn), 4);
                break;
        case INAT_IMM_PTR:
                if (!__get_immptr(insn))
                goto err_out;
        }
        if (inat_has_second_immediate(insn->attr)) {
-               insn->immediate2.value = get_next(signed char, insn);
-               insn->immediate2.nbytes = 1;
+               insn_field_set(&insn->immediate2, get_next(signed char, insn), 1);
        }
 done:
        insn->immediate.got = 1;