diff --git a/host-utils.c b/host-utils.c
index dc96123..3073ef8 100644
--- a/host-utils.c
+++ b/host-utils.c
@@ -102,4 +102,18 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t
a, int64_t b)
            a, b, *phigh, *plow);
 #endif
 }
+
 #endif /* !defined(__x86_64__) */
+void addc(uint64_t res [], uint64_t a, int i)
+{
+    uint64_t c = res[i];
+    for (;i < 4;i++) {
+        res[i] = c + a;
+        if (res[i] < a) {
+            c = 1;
+            a = res[i+1];
+        }
+        else
+            break;
+    }
+}
diff --git a/host-utils.h b/host-utils.h
index 0ddc176..172c4fd 100644
--- a/host-utils.h
+++ b/host-utils.h
@@ -46,6 +46,7 @@ static inline void muls64(uint64_t *plow, uint64_t *phigh,
 void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
 void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
 #endif
+void addc(uint64_t res [], uint64_t a, int i);

 /* Binary search for leading zeros.  */

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2832a33..9399e44 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1662,6 +1662,11 @@ int load_elf_binary(struct linux_binprm * bprm,
struct target_pt_regs * regs,
        when we load the interpreter.  */
     elf_ex = *(struct elfhdr *)bprm->buf;

+#if defined(TARGET_MIPS64)
+    if ((elf_ex.e_flags & EF_MIPS_MARCH) == E_MIPS_MACH_OCTEON) {
+        info->elf_arch = 1;
+    }
+#endif
     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
     bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
     bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
diff --git a/linux-user/main.c b/linux-user/main.c
index a7f4955..acf9cac 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3348,6 +3348,11 @@ int main(int argc, char **argv, char **envp)
         if (regs->cp0_epc & 1) {
             env->hflags |= MIPS_HFLAG_M16;
         }
+#if defined(TARGET_MIPS64)
+        if (info->elf_arch) {
+            env->TARGET_OCTEON = 1;
+        }
+#endif
     }
 #elif defined(TARGET_SH4)
     {
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 250814d..adef428 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -51,6 +51,7 @@ struct image_info {
         abi_ulong       arg_start;
         abi_ulong       arg_end;
  int personality;
+ int elf_arch;
 #ifdef CONFIG_USE_FDPIC
         abi_ulong       loadmap_addr;
         uint16_t        nsegs;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bb0999d..d5da0ee 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7320,6 +7320,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
     case TARGET_NR_set_thread_area:
 #if defined(TARGET_MIPS)
       ((CPUMIPSState *) cpu_env)->tls_value = arg1;
+      if (((CPUMIPSState *) cpu_env)->TARGET_OCTEON) {
+          /* tls entry is moved to k0 so that this can be used later
+           * currently this thing is tested only for Octeon */
+          ((CPUMIPSState *) cpu_env)->active_tc.gpr[26] = arg1;
+      }
       ret = 0;
       break;
 #elif defined(TARGET_CRIS)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 0b98d10..8ef8afb 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -5,6 +5,11 @@

 #define ELF_MACHINE EM_MIPS

+/* These flags are used to check whether given
+ * user mode binary is octeon specific or not */
+#define EF_MIPS_MARCH 0xFF0000
+#define E_MIPS_MACH_OCTEON 0x8B0000
+
 #define CPUState struct CPUMIPSState

 #include "config.h"
@@ -171,6 +176,15 @@ struct TCState {
     target_ulong CP0_TCSchedule;
     target_ulong CP0_TCScheFBack;
     int32_t CP0_Debug_tcstatus;
+    /* Multiplier registers for Octeon */
+    target_ulong MPL0;
+    target_ulong MPL1;
+    target_ulong MPL2;
+    target_ulong P0;
+    target_ulong P1;
+    target_ulong P2;
+    /* Octeon specific Coprocessor 0 register */
+    target_ulong cvmctl;
 };

 typedef struct CPUMIPSState CPUMIPSState;
@@ -178,6 +192,7 @@ struct CPUMIPSState {
     TCState active_tc;
     CPUMIPSFPUContext active_fpu;

+    int TARGET_OCTEON;
     uint32_t current_tc;
     uint32_t current_fpu;

diff --git a/target-mips/helper.h b/target-mips/helper.h
index 297ab64..409c08d 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -8,7 +8,12 @@ DEF_HELPER_3(ldl, tl, tl, tl, int)
 DEF_HELPER_3(ldr, tl, tl, tl, int)
 DEF_HELPER_3(sdl, void, tl, tl, int)
 DEF_HELPER_3(sdr, void, tl, tl, int)
+DEF_HELPER_3(v3mulu, void, tl, tl, int)
+DEF_HELPER_3(vmulu, void, tl, tl, int)
+DEF_HELPER_2(dpop, void, tl, i32)
 #endif
+DEF_HELPER_2(pop, void, tl, i32)
+
 DEF_HELPER_3(lwl, tl, tl, tl, int)
 DEF_HELPER_3(lwr, tl, tl, tl, int)
 DEF_HELPER_3(swl, void, tl, tl, int)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index bd16ce3..de793ba 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -266,7 +266,77 @@ void helper_dmultu (target_ulong arg1, target_ulong
arg2)
 {
     mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
 }
+void helper_v3mulu (target_ulong arg1, target_ulong arg2, int rd)
+{
+    uint64_t hi, lo, res[4];
+    int i;
+    for (i = 0;i < 4; i++) {
+        res[i] = 0;
+    }
+    mulu64(&res[0], &res[1], env->active_tc.MPL0, arg1);
+    mulu64(&lo, &hi, env->active_tc.MPL1, arg1);
+    res[1] = res[1] + lo;
+    if (res[1] < lo)
+        res[2]++;
+    res[2] = res[2] + hi;
+    if (res[2] < hi)
+        res[3]++;
+    mulu64(&lo, &hi, env->active_tc.MPL2, arg1);
+    res[2] = res[2] + lo;
+    if (res[2] < lo)
+        res[3]++;
+    res[3] = res[3] + hi;
+    addc(res, arg2, 0);
+    addc(res, env->active_tc.P0, 0);
+    addc(res, env->active_tc.P1, 1);
+    addc(res, env->active_tc.P2, 2);
+    env->active_tc.gpr[rd] = res[0];
+    env->active_tc.P0 = res[1];
+    env->active_tc.P1 = res[2];
+    env->active_tc.P2 = res[3];
+}
+void helper_vmulu (target_ulong arg1, target_ulong arg2, int rd)
+{
+ uint64_t hi, lo;
+ mulu64(&lo, &hi, env->active_tc.MPL0, arg1);
+ lo = lo + arg2;
+ if (lo < arg2)
+ hi++;
+ lo = lo + env->active_tc.P0;
+ if (lo < env->active_tc.P0)
+ hi++;
+ env->active_tc.gpr[rd] = lo;
+ env->active_tc.P0 = hi;
+}
+void helper_dpop (target_ulong arg, uint32_t rd)
+{
+    uint32_t rem, ones = 0;
+    while (arg >= 1) {
+        arg = arg/2;
+        rem = arg % 2;
+        if(rem == 1)
+            ones++;
+        if(arg == 1)
+            ones++;
+    }
+    env->active_tc.gpr[rd] = ones;
+}
 #endif
+void helper_pop (target_ulong arg, uint32_t rd)
+{
+    uint32_t rem, i, ones = 0;
+    i = 0;
+    while(i <= 31) {
+        arg = arg/2;
+        rem = arg % 2;
+        if(rem == 1)
+            ones++;
+        if(arg == 1)
+            ones++;
+        i++;
+    }
+    env->active_tc.gpr[rd] = ones;
+}

 #ifndef CONFIG_USER_ONLY

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 63c2563..1394e18 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -36,6 +36,14 @@
 #define GEN_HELPER 1
 #include "helper.h"

+#if defined(TARGET_MIPS64)
+/* Macros for setting values of cvmctl registers */
+#define FUSE_START_BIT(cvmctl)  (cvmctl | 0x80000000)
+#define KASUMI(cvmctl)  (cvmctl | 0x20000000)
+#define IPPCI(cvmctl)  (cvmctl | 0x380)
+#define IPTI(cvmctl)  (cvmctl | 0x70)
+#endif
+
 //#define MIPS_DEBUG_DISAS
 //#define MIPS_DEBUG_SIGN_EXTENSIONS

@@ -70,6 +78,11 @@ enum {
     OPC_JAL      = (0x03 << 26),
     OPC_JALS     = OPC_JAL | 0x5,
     OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
+    /* Cavium Specific */
+    OPC_BBIT1    = (0x3a << 26),  /* jump on bit set, cavium specific */
+    OPC_BBIT132  = (0x3e << 26),  /* jump on bit set(for upper 32 bits) */
+    OPC_BBIT0    = (0x32 << 26),  /* jump on bit clear, cavium specific */
+    OPC_BBIT032  = (0x36 << 26),  /* jump on bit clear(for upper 32 bits)
*/
     OPC_BEQL     = (0x14 << 26),
     OPC_BNE      = (0x05 << 26),
