diff mbox

[v3,5/6] target-mips: Adding support for Cavium specific instructions

Message ID 1319278273-32437-6-git-send-email-khansa@kics.edu.pk
State New
Headers show

Commit Message

Khansa Butt Oct. 22, 2011, 10:11 a.m. UTC
From: Khansa Butt <khansa@kics.edu.pk>


Signed-off-by: Khansa Butt <khansa@kics.edu.pk>
Signed-off-by: Ehsan Ul Haq <ehsan.ulhaq@kics.edu.pk>
Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk>
Signed-off-by: Abdul Waheed <awaheed@kics.edu.pk>
---
 target-mips/cpu.h       |    7 +
 target-mips/helper.h    |    5 +
 target-mips/machine.c   |   12 ++
 target-mips/op_helper.c |   73 ++++++++
 target-mips/translate.c |  428 ++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 520 insertions(+), 5 deletions(-)

Comments

Andreas Färber Oct. 22, 2011, 11:36 a.m. UTC | #1
Am 22.10.2011 12:11, schrieb khansa@kics.edu.pk:
> From: Khansa Butt <khansa@kics.edu.pk>

Commit message should mention here at least that new registers are
introduced and that load/save format is being changed.

> Signed-off-by: Khansa Butt <khansa@kics.edu.pk>
> Signed-off-by: Ehsan Ul Haq <ehsan.ulhaq@kics.edu.pk>
> Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk>
> Signed-off-by: Abdul Waheed <awaheed@kics.edu.pk>
> ---

> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 79e2558..9180ee9 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -173,6 +173,13 @@ 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;
>  };
>  
>  typedef struct CPUMIPSState CPUMIPSState;

> diff --git a/target-mips/machine.c b/target-mips/machine.c
> index be72b36..a274ce2 100644
> --- a/target-mips/machine.c
> +++ b/target-mips/machine.c
> @@ -25,6 +25,12 @@ static void save_tc(QEMUFile *f, TCState *tc)
>      qemu_put_betls(f, &tc->CP0_TCSchedule);
>      qemu_put_betls(f, &tc->CP0_TCScheFBack);
>      qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
> +    qemu_put_betls(f, &tc->MPL0);
> +    qemu_put_betls(f, &tc->MPL1);

MPL2 is not being saved but loaded below.

> +    qemu_put_betls(f, &tc->P0);
> +    qemu_put_betls(f, &tc->P1);
> +    qemu_put_betls(f, &tc->P2);
> +
>  }
>  
>  static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
> @@ -173,6 +179,12 @@ static void load_tc(QEMUFile *f, TCState *tc)
>      qemu_get_betls(f, &tc->CP0_TCSchedule);
>      qemu_get_betls(f, &tc->CP0_TCScheFBack);
>      qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
> +    qemu_get_betls(f, &tc->MPL0);
> +    qemu_get_betls(f, &tc->MPL1);
> +    qemu_get_betls(f, &tc->MPL2);
> +    qemu_get_betls(f, &tc->P0);
> +    qemu_get_betls(f, &tc->P1);
> +    qemu_get_betls(f, &tc->P2);
>  }
>  
>  static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)

You're saving new fields, so you'll need to bump the version somewhere.
For loading, since you're adding at the end, you might be able to make
your additions conditional on the to-be-bumped version.

I'm wondering whether those register and serialization additions could
and should be limited to TARGET_MIPS64.

Andreas
Khansa Butt Oct. 28, 2011, 4:42 a.m. UTC | #2
On Sat, Oct 22, 2011 at 4:36 PM, Andreas Färber <andreas.faerber@web.de>wrote:

> Am 22.10.2011 12:11, schrieb khansa@kics.edu.pk:
> > From: Khansa Butt <khansa@kics.edu.pk>
>
> Commit message should mention here at least that new registers are
> introduced and that load/save format is being changed.
>
> > Signed-off-by: Khansa Butt <khansa@kics.edu.pk>
> > Signed-off-by: Ehsan Ul Haq <ehsan.ulhaq@kics.edu.pk>
> > Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk>
> > Signed-off-by: Abdul Waheed <awaheed@kics.edu.pk>
> > ---
>
> > diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> > index 79e2558..9180ee9 100644
> > --- a/target-mips/cpu.h
> > +++ b/target-mips/cpu.h
> > @@ -173,6 +173,13 @@ 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;
> >  };
> >
> >  typedef struct CPUMIPSState CPUMIPSState;
>
> > diff --git a/target-mips/machine.c b/target-mips/machine.c
> > index be72b36..a274ce2 100644
> > --- a/target-mips/machine.c
> > +++ b/target-mips/machine.c
> > @@ -25,6 +25,12 @@ static void save_tc(QEMUFile *f, TCState *tc)
> >      qemu_put_betls(f, &tc->CP0_TCSchedule);
> >      qemu_put_betls(f, &tc->CP0_TCScheFBack);
> >      qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
> > +    qemu_put_betls(f, &tc->MPL0);
> > +    qemu_put_betls(f, &tc->MPL1);
>
> MPL2 is not being saved but loaded below.
>
> > +    qemu_put_betls(f, &tc->P0);
> > +    qemu_put_betls(f, &tc->P1);
> > +    qemu_put_betls(f, &tc->P2);
> > +
> >  }
> >
> >  static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
> > @@ -173,6 +179,12 @@ static void load_tc(QEMUFile *f, TCState *tc)
> >      qemu_get_betls(f, &tc->CP0_TCSchedule);
> >      qemu_get_betls(f, &tc->CP0_TCScheFBack);
> >      qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
> > +    qemu_get_betls(f, &tc->MPL0);
> > +    qemu_get_betls(f, &tc->MPL1);
> > +    qemu_get_betls(f, &tc->MPL2);
> > +    qemu_get_betls(f, &tc->P0);
> > +    qemu_get_betls(f, &tc->P1);
> > +    qemu_get_betls(f, &tc->P2);
> >  }
> >
> >  static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
>
> You're saving new fields, so you'll need to bump the version somewhere.
> For loading, since you're adding at the end, you might be able to make
> your additions conditional on the to-be-bumped version.
>

I 'm not able to understand " bump the version somewhere"  kindly
explain this.


>
> I'm wondering whether those register and serialization additions could
> and should be limited to TARGET_MIPS64.
>
> you want me to limit these registers to TARGET_OCTEON
Andreas Färber Oct. 31, 2011, 8:24 p.m. UTC | #3
Am 28.10.2011 06:42, schrieb Khansa Butt:
> 
> 
> On Sat, Oct 22, 2011 at 4:36 PM, Andreas Färber <andreas.faerber@web.de
> <mailto:andreas.faerber@web.de>> wrote:
> 
>     Am 22.10.2011 12:11, schrieb khansa@kics.edu.pk
>     <mailto:khansa@kics.edu.pk>:

HTML again :(

>     > From: Khansa Butt <khansa@kics.edu.pk <mailto:khansa@kics.edu.pk>>
> 
>     Commit message should mention here at least that new registers are
>     introduced and that load/save format is being changed.
> 
>     > Signed-off-by: Khansa Butt <khansa@kics.edu.pk
>     <mailto:khansa@kics.edu.pk>>
>     > Signed-off-by: Ehsan Ul Haq <ehsan.ulhaq@kics.edu.pk
>     <mailto:ehsan.ulhaq@kics.edu.pk>>
>     > Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk
>     <mailto:qadeer@kics.edu.pk>>
>     > Signed-off-by: Abdul Waheed <awaheed@kics.edu.pk
>     <mailto:awaheed@kics.edu.pk>>
>     > ---
> 
>     > diff --git a/target-mips/cpu.h b/target-mips/cpu.h
>     > index 79e2558..9180ee9 100644
>     > --- a/target-mips/cpu.h
>     > +++ b/target-mips/cpu.h
>     > @@ -173,6 +173,13 @@ 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;
>     >  };
>     >
>     >  typedef struct CPUMIPSState CPUMIPSState;
> 
>     > diff --git a/target-mips/machine.c b/target-mips/machine.c
>     > index be72b36..a274ce2 100644
>     > --- a/target-mips/machine.c
>     > +++ b/target-mips/machine.c
>     > @@ -25,6 +25,12 @@ static void save_tc(QEMUFile *f, TCState *tc)
>     >      qemu_put_betls(f, &tc->CP0_TCSchedule);
>     >      qemu_put_betls(f, &tc->CP0_TCScheFBack);
>     >      qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
>     > +    qemu_put_betls(f, &tc->MPL0);
>     > +    qemu_put_betls(f, &tc->MPL1);
> 
>     MPL2 is not being saved but loaded below.
> 
>     > +    qemu_put_betls(f, &tc->P0);
>     > +    qemu_put_betls(f, &tc->P1);
>     > +    qemu_put_betls(f, &tc->P2);
>     > +
>     >  }
>     >
>     >  static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
>     > @@ -173,6 +179,12 @@ static void load_tc(QEMUFile *f, TCState *tc)
>     >      qemu_get_betls(f, &tc->CP0_TCSchedule);
>     >      qemu_get_betls(f, &tc->CP0_TCScheFBack);
>     >      qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
>     > +    qemu_get_betls(f, &tc->MPL0);
>     > +    qemu_get_betls(f, &tc->MPL1);
>     > +    qemu_get_betls(f, &tc->MPL2);
>     > +    qemu_get_betls(f, &tc->P0);
>     > +    qemu_get_betls(f, &tc->P1);
>     > +    qemu_get_betls(f, &tc->P2);
>     >  }
>     >
>     >  static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
> 
>     You're saving new fields, so you'll need to bump the version somewhere.
>     For loading, since you're adding at the end, you might be able to make
>     your additions conditional on the to-be-bumped version.
> 
> 
> I 'm not able to understand " bump the version somewhere"  kindly
> explain this.

"Somewhere" indicates I don't know the exact line for mips. Compare the
recent patch to arm_gic.
The general idea is that QEMU needs to be able to load files saved with
an older version, the file format is therefore versioned. If you
unconditionally try to load your new registers, you break loading older
files that don't include them.

>     I'm wondering whether those register and serialization additions could
>     and should be limited to TARGET_MIPS64.
> 
> you want me to limit these registers to TARGET_OCTEON

No, there shouldn't be a TARGET_OCTEON, there's no Octeon-specific
executable.

My point is, IIUC, qemu-system-mips will never have Octeon registers
because they're in qemu-system-mips64 only. So without #ifdef it would
save and load unused registers.

Andreas
Khansa Butt Nov. 22, 2011, 8:31 a.m. UTC | #4
On Tue, Nov 1, 2011 at 1:24 AM, Andreas Färber <andreas.faerber@web.de> wrote:
>
> Am 28.10.2011 06:42, schrieb Khansa Butt:
> >
> >
> > On Sat, Oct 22, 2011 at 4:36 PM, Andreas Färber <andreas.faerber@web.de
> > <mailto:andreas.faerber@web.de>> wrote:
> >
> >     Am 22.10.2011 12:11, schrieb khansa@kics.edu.pk
> >     <mailto:khansa@kics.edu.pk>:
>
> HTML again :(
>
> >     > From: Khansa Butt <khansa@kics.edu.pk <mailto:khansa@kics.edu.pk>>
> >
> >     Commit message should mention here at least that new registers are
> >     introduced and that load/save format is being changed.
> >
> >     > Signed-off-by: Khansa Butt <khansa@kics.edu.pk
> >     <mailto:khansa@kics.edu.pk>>
> >     > Signed-off-by: Ehsan Ul Haq <ehsan.ulhaq@kics.edu.pk
> >     <mailto:ehsan.ulhaq@kics.edu.pk>>
> >     > Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk
> >     <mailto:qadeer@kics.edu.pk>>
> >     > Signed-off-by: Abdul Waheed <awaheed@kics.edu.pk
> >     <mailto:awaheed@kics.edu.pk>>
> >     > ---
> >
> >     > diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> >     > index 79e2558..9180ee9 100644
> >     > --- a/target-mips/cpu.h
> >     > +++ b/target-mips/cpu.h
> >     > @@ -173,6 +173,13 @@ 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;
> >     >  };
> >     >
> >     >  typedef struct CPUMIPSState CPUMIPSState;
> >
> >     > diff --git a/target-mips/machine.c b/target-mips/machine.c
> >     > index be72b36..a274ce2 100644
> >     > --- a/target-mips/machine.c
> >     > +++ b/target-mips/machine.c
> >     > @@ -25,6 +25,12 @@ static void save_tc(QEMUFile *f, TCState *tc)
> >     >      qemu_put_betls(f, &tc->CP0_TCSchedule);
> >     >      qemu_put_betls(f, &tc->CP0_TCScheFBack);
> >     >      qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
> >     > +    qemu_put_betls(f, &tc->MPL0);
> >     > +    qemu_put_betls(f, &tc->MPL1);
> >
> >     MPL2 is not being saved but loaded below.
> >
> >     > +    qemu_put_betls(f, &tc->P0);
> >     > +    qemu_put_betls(f, &tc->P1);
> >     > +    qemu_put_betls(f, &tc->P2);
> >     > +
> >     >  }
> >     >
> >     >  static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
> >     > @@ -173,6 +179,12 @@ static void load_tc(QEMUFile *f, TCState *tc)
> >     >      qemu_get_betls(f, &tc->CP0_TCSchedule);
> >     >      qemu_get_betls(f, &tc->CP0_TCScheFBack);
> >     >      qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
> >     > +    qemu_get_betls(f, &tc->MPL0);
> >     > +    qemu_get_betls(f, &tc->MPL1);
> >     > +    qemu_get_betls(f, &tc->MPL2);
> >     > +    qemu_get_betls(f, &tc->P0);
> >     > +    qemu_get_betls(f, &tc->P1);
> >     > +    qemu_get_betls(f, &tc->P2);
> >     >  }
> >     >
> >     >  static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
> >
> >     You're saving new fields, so you'll need to bump the version somewhere.
> >     For loading, since you're adding at the end, you might be able to make
> >     your additions conditional on the to-be-bumped version.
> >
> >
> > I 'm not able to understand " bump the version somewhere"  kindly
> > explain this.
>
> "Somewhere" indicates I don't know the exact line for mips. Compare the
> recent patch to arm_gic.
> The general idea is that QEMU needs to be able to load files saved with
> an older version, the file format is therefore versioned. If you
> unconditionally try to load your new registers, you break loading older
> files that don't include them.

Thanks for your response.
As I can't see any example of bumping the version of registers  in
mips ( 32 or 64) so i'm in a bit difficult situation
From arm_gic what i understand is that version_id is related to
devices which are specific to some board
as gic is related to RealView board. considering that i'm in user
mode, can i do the same thing with Cavium's  registers as these are
related to multiplier unit? Also please tell me about mips maintainer,
Aurelien Jarno. I think he is not active in developer list for a
while.

>
> >     I'm wondering whether those register and serialization additions could
> >     and should be limited to TARGET_MIPS64.
> >
> > you want me to limit these registers to TARGET_OCTEON
>
> No, there shouldn't be a TARGET_OCTEON, there's no Octeon-specific
> executable.
>
> My point is, IIUC, qemu-system-mips will never have Octeon registers
> because they're in qemu-system-mips64 only. So without #ifdef it would
> save and load unused registers.
>
> Andreas
Andreas Färber Nov. 30, 2011, 11:54 a.m. UTC | #5
Am 22.11.2011 09:31, schrieb Khansa Butt:
> On Tue, Nov 1, 2011 at 1:24 AM, Andreas Färber <andreas.faerber@web.de> wrote:
>>
>> Am 28.10.2011 06:42, schrieb Khansa Butt:
>>>
>>>
>>> On Sat, Oct 22, 2011 at 4:36 PM, Andreas Färber <andreas.faerber@web.de
>>> <mailto:andreas.faerber@web.de>> wrote:
>>>
>>>     Am 22.10.2011 12:11, schrieb khansa@kics.edu.pk
>>>     <mailto:khansa@kics.edu.pk>:
>>>
>>>     > diff --git a/target-mips/machine.c b/target-mips/machine.c
>>>     > index be72b36..a274ce2 100644
>>>     > --- a/target-mips/machine.c
>>>     > +++ b/target-mips/machine.c
>>>     > @@ -173,6 +179,12 @@ static void load_tc(QEMUFile *f, TCState *tc)
>>>     >      qemu_get_betls(f, &tc->CP0_TCSchedule);
>>>     >      qemu_get_betls(f, &tc->CP0_TCScheFBack);
>>>     >      qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
>>>     > +    qemu_get_betls(f, &tc->MPL0);
>>>     > +    qemu_get_betls(f, &tc->MPL1);
>>>     > +    qemu_get_betls(f, &tc->MPL2);
>>>     > +    qemu_get_betls(f, &tc->P0);
>>>     > +    qemu_get_betls(f, &tc->P1);
>>>     > +    qemu_get_betls(f, &tc->P2);
>>>     >  }
>>>     >
>>>     >  static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
>>>
>>>     You're saving new fields, so you'll need to bump the version somewhere.
>>>     For loading, since you're adding at the end, you might be able to make
>>>     your additions conditional on the to-be-bumped version.
>>>
>>>
>>> I 'm not able to understand " bump the version somewhere"  kindly
>>> explain this.
>>
>> "Somewhere" indicates I don't know the exact line for mips. Compare the
>> recent patch to arm_gic.
>> The general idea is that QEMU needs to be able to load files saved with
>> an older version, the file format is therefore versioned. If you
>> unconditionally try to load your new registers, you break loading older
>> files that don't include them.
> 
> Thanks for your response.
> As I can't see any example of bumping the version of registers  in
> mips ( 32 or 64) so i'm in a bit difficult situation
> From arm_gic what i understand is that version_id is related to
> devices which are specific to some board
> as gic is related to RealView board. considering that i'm in user
> mode, can i do the same thing with Cavium's  registers as these are
> related to multiplier unit?

No, this is not board- or device-specific, it's CPU-specific. Cf.
target-mips/cpu.h:CPU_SAVE_VERSION
target-mips/savevm.c:cpu_load()

My suggestion was to bump CPU_SAVE_VERSION to 4, change the error check
to "if (version_id < 3)" and to enclose your cpuo_load() additions in
"if (version_id >= 4) { ... }".

Depending how long you need to resend, note that Juan is working on a
VMState refactoring of machine.c, which will make it more like devices.

Andreas
Khansa Butt Dec. 1, 2011, 5:35 a.m. UTC | #6
On Wed, Nov 30, 2011 at 4:54 PM, Andreas Färber <andreas.faerber@web.de> wrote:
> Am 22.11.2011 09:31, schrieb Khansa Butt:
>> On Tue, Nov 1, 2011 at 1:24 AM, Andreas Färber <andreas.faerber@web.de> wrote:
>>>
>>> Am 28.10.2011 06:42, schrieb Khansa Butt:
>>>>
>>>>
>>>> On Sat, Oct 22, 2011 at 4:36 PM, Andreas Färber <andreas.faerber@web.de
>>>> <mailto:andreas.faerber@web.de>> wrote:
>>>>
>>>>     Am 22.10.2011 12:11, schrieb khansa@kics.edu.pk
>>>>     <mailto:khansa@kics.edu.pk>:
>>>>
>>>>     > diff --git a/target-mips/machine.c b/target-mips/machine.c
>>>>     > index be72b36..a274ce2 100644
>>>>     > --- a/target-mips/machine.c
>>>>     > +++ b/target-mips/machine.c
>>>>     > @@ -173,6 +179,12 @@ static void load_tc(QEMUFile *f, TCState *tc)
>>>>     >      qemu_get_betls(f, &tc->CP0_TCSchedule);
>>>>     >      qemu_get_betls(f, &tc->CP0_TCScheFBack);
>>>>     >      qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
>>>>     > +    qemu_get_betls(f, &tc->MPL0);
>>>>     > +    qemu_get_betls(f, &tc->MPL1);
>>>>     > +    qemu_get_betls(f, &tc->MPL2);
>>>>     > +    qemu_get_betls(f, &tc->P0);
>>>>     > +    qemu_get_betls(f, &tc->P1);
>>>>     > +    qemu_get_betls(f, &tc->P2);
>>>>     >  }
>>>>     >
>>>>     >  static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
>>>>
>>>>     You're saving new fields, so you'll need to bump the version somewhere.
>>>>     For loading, since you're adding at the end, you might be able to make
>>>>     your additions conditional on the to-be-bumped version.
>>>>
>>>>
>>>> I 'm not able to understand " bump the version somewhere"  kindly
>>>> explain this.
>>>
>>> "Somewhere" indicates I don't know the exact line for mips. Compare the
>>> recent patch to arm_gic.
>>> The general idea is that QEMU needs to be able to load files saved with
>>> an older version, the file format is therefore versioned. If you
>>> unconditionally try to load your new registers, you break loading older
>>> files that don't include them.
>>
>> Thanks for your response.
>> As I can't see any example of bumping the version of registers  in
>> mips ( 32 or 64) so i'm in a bit difficult situation
>> From arm_gic what i understand is that version_id is related to
>> devices which are specific to some board
>> as gic is related to RealView board. considering that i'm in user
>> mode, can i do the same thing with Cavium's  registers as these are
>> related to multiplier unit?
>
> No, this is not board- or device-specific, it's CPU-specific. Cf.
> target-mips/cpu.h:CPU_SAVE_VERSION
> target-mips/savevm.c:cpu_load()
>
> My suggestion was to bump CPU_SAVE_VERSION to 4, change the error check
> to "if (version_id < 3)" and to enclose your cpuo_load() additions in
> "if (version_id >= 4) { ... }".
>
Thanks for your response!
Here is a confusion. I found that cpu_save() and cpu_load() are not called in
user mode emulation, here is the code from exec.c
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                    cpu_save, cpu_load, env);
#endif
As these patches are related to UME so we decided to postpone Octeon
specific changes ( registers and instructions) and will include them in our
SME work( we are currently working on system mode emulation of Octeon board)
that's why yesterday I sent only MIPS64 user mode emulation patches
here is the link
http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg03527.html
Please review them
I'm sorry, the words "with	Cavium specific instruction support" are
mistakenly added
 into subject line.

Please guide me towards the right track. should we stick to are old patches or
submit MIPS64 UME patches only(which are  without Cavium's Instruction support)


> Depending how long you need to resend, note that Juan is working on a
> VMState refactoring of machine.c, which will make it more like devices.
>
> Andreas
>
diff mbox

Patch

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 79e2558..9180ee9 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -173,6 +173,13 @@  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;
 };
 
 typedef struct CPUMIPSState CPUMIPSState;
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 442f684..7ba5d9f 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_2(v3mulu, tl, tl, tl)
+DEF_HELPER_2(vmulu, tl, tl, tl)
+DEF_HELPER_1(dpop, tl, tl)
 #endif
+DEF_HELPER_1(pop, tl, tl)
+
 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/machine.c b/target-mips/machine.c
index be72b36..a274ce2 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -25,6 +25,12 @@  static void save_tc(QEMUFile *f, TCState *tc)
     qemu_put_betls(f, &tc->CP0_TCSchedule);
     qemu_put_betls(f, &tc->CP0_TCScheFBack);
     qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
+    qemu_put_betls(f, &tc->MPL0);
+    qemu_put_betls(f, &tc->MPL1);
+    qemu_put_betls(f, &tc->P0);
+    qemu_put_betls(f, &tc->P1);
+    qemu_put_betls(f, &tc->P2);
+
 }
 
 static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
@@ -173,6 +179,12 @@  static void load_tc(QEMUFile *f, TCState *tc)
     qemu_get_betls(f, &tc->CP0_TCSchedule);
     qemu_get_betls(f, &tc->CP0_TCScheFBack);
     qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
+    qemu_get_betls(f, &tc->MPL0);
+    qemu_get_betls(f, &tc->MPL1);
+    qemu_get_betls(f, &tc->MPL2);
+    qemu_get_betls(f, &tc->P0);
+    qemu_get_betls(f, &tc->P1);
+    qemu_get_betls(f, &tc->P2);
 }
 
 static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 96e40c6..4565d17 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -320,8 +320,81 @@  void helper_dmultu (target_ulong arg1, target_ulong arg2)
 {
     mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
 }
+
+static 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;
+        }
+    }
+}
+
+target_ulong helper_v3mulu(target_ulong arg1, target_ulong arg2)
+{
+    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.P0 = res[1];
+    env->active_tc.P1 = res[2];
+    env->active_tc.P2 = res[3];
+    return res[0];
+}
+
+target_ulong helper_vmulu(target_ulong arg1, target_ulong arg2)
+{
+    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.P0 = hi;
+    return lo;
+}
+
+target_ulong helper_dpop(target_ulong arg)
+{
+    return ctpop64(arg);
+}
 #endif
 
+target_ulong helper_pop(target_ulong arg)
+{
+    return ctpop32((uint32_t)arg);
+}
+
 #ifndef CONFIG_USER_ONLY
 
 static inline target_phys_addr_t do_translate_address(target_ulong address, int rw)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0550333..e57f3fe 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -78,6 +78,11 @@  enum {
     OPC_BGTZL    = (0x17 << 26),
     OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
     OPC_JALXS    = OPC_JALX | 0x5,
+    /* Cavium Specific branches */
+    OPC_BBIT1    = (0x3a << 26),  /* jump on bit set */
+    OPC_BBIT132  = (0x3e << 26),  /* jump on bit set (for upper 32 bits) */
+    OPC_BBIT0    = (0x32 << 26),  /* jump on bit clear */
+    OPC_BBIT032  = (0x36 << 26),  /* jump on bit clear (for upper 32 bits) */
     /* Load and stores */
     OPC_LDL      = (0x1A << 26),
     OPC_LDR      = (0x1B << 26),
@@ -286,6 +291,30 @@  enum {
     OPC_DCLO     = 0x25 | OPC_SPECIAL2,
     /* Special */
     OPC_SDBBP    = 0x3F | OPC_SPECIAL2,
+    /* Cavium Specific Instructions */
+    OPC_BADDU    = 0x28 | OPC_SPECIAL2,
+    OPC_DMUL     = 0x03 | OPC_SPECIAL2,
+    OPC_EXTS     = 0x3a | OPC_SPECIAL2,
+    OPC_EXTS32   = 0x3b | OPC_SPECIAL2,
+    OPC_CINS     = 0x32 | OPC_SPECIAL2,
+    OPC_CINS32   = 0x33 | OPC_SPECIAL2,
+    OPC_SEQI     = 0x2e | OPC_SPECIAL2,
+    OPC_SNEI     = 0x2f | OPC_SPECIAL2,
+    OPC_MTM0     = 0x08 | OPC_SPECIAL2,
+    OPC_MTM1     = 0x0c | OPC_SPECIAL2,
+    OPC_MTM2     = 0x0d | OPC_SPECIAL2,
+    OPC_MTP0     = 0x09 | OPC_SPECIAL2,
+    OPC_MTP1     = 0x0a | OPC_SPECIAL2,
+    OPC_MTP2     = 0x0b | OPC_SPECIAL2,
+    OPC_V3MULU   = 0x11 | OPC_SPECIAL2,
+    OPC_VMM0     = 0x10 | OPC_SPECIAL2,
+    OPC_VMULU    = 0x0f | OPC_SPECIAL2,
+    OPC_POP      = 0X2C | OPC_SPECIAL2,
+    OPC_DPOP     = 0X2D | OPC_SPECIAL2,
+    OPC_SEQ      = 0x2a | OPC_SPECIAL2,
+    OPC_SNE      = 0x2b | OPC_SPECIAL2,
+    OPC_SAA      = 0x18 | OPC_SPECIAL2,
+    OPC_SAAD     = 0x19 | OPC_SPECIAL2,
 };
 
 /* Special3 opcodes */
@@ -1419,6 +1448,224 @@  static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
 }
 
+#if defined(TARGET_MIPS64)
+/* set on equal/not equal immediate */
+static void gen_set_imm(CPUState *env, uint32_t opc,
+                        int rt, int rs, int16_t imm)
+{
+    target_ulong uimm = (target_long)imm;
+    TCGv t0;
+    const char *opn = "imm set";
+    if (rt == 0) {
+        /* If no destination, treat it as a NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+    t0 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+    switch (opc) {
+    case OPC_SEQI:
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[rt], t0, uimm);
+        opn = "seqi";
+        break;
+    case OPC_SNEI:
+        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[rt], t0, uimm);
+        opn = "snei";
+        break;
+    }
+    tcg_temp_free(t0);
+}
+
+/* Cavium specific Large Multiply Instructions */
+static void gen_LMI(DisasContext *ctx, uint32_t opc, int rs, int rt, int rd)
+{
+    const char *opn = "LMI";
+    TCGv t0, t1;
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+    gen_load_gpr(t1, rt);
+    switch (opc) {
+    case OPC_MTM0:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.MPL0));
+        tcg_gen_movi_tl(t0, 0);
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        opn = "mtm0";
+        break;
+    case OPC_MTM1:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.MPL1));
+        tcg_gen_movi_tl(t0, 0);
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        opn = "mtm1";
+        break;
+    case OPC_MTM2:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.MPL2));
+        tcg_gen_movi_tl(t0, 0);
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        break;
+    case OPC_MTP0:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        opn = "mtp0";
+        break;
+    case OPC_MTP1:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        opn = "mtp1";
+        break;
+    case OPC_MTP2:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        opn = "mtp2";
+        break;
+    case OPC_VMM0:
+        {
+            TCGv t2, t3;
+            t2 = tcg_temp_new();
+            t3 = tcg_temp_new();
+            tcg_gen_ld_tl(t2, cpu_env, offsetof(CPUState, active_tc.MPL0));
+            tcg_gen_ld_tl(t3, cpu_env, offsetof(CPUState, active_tc.P0));
+            tcg_gen_mul_i64(t0, t0, t2);
+            tcg_gen_add_tl(t1, t1, t0);
+            tcg_gen_add_tl(t1, t1, t3);
+            gen_store_gpr(t1, rd);
+            tcg_gen_movi_tl(t0, 0);
+            tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, active_tc.MPL0));
+            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+            tcg_temp_free(t2);
+            tcg_temp_free(t3);
+            opn = "vmm0";
+            break;
+        }
+    case OPC_VMULU:
+        gen_helper_vmulu(t0, t0, t1);
+        gen_store_gpr(t0, rd);
+        opn = "vmulu";
+        break;
+    case OPC_V3MULU:
+        gen_helper_v3mulu(t0, t0, t1);
+        gen_store_gpr(t0, rd);
+        opn = "v3mulu";
+        break;
+    }
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+/* set if equal/not equal */
+static void gen_set(DisasContext *ctx, uint32_t opc,
+                        int rd, int rs, int rt)
+{
+    const char *opn = "seq/sne";
+    TCGv t0, t1;
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+    gen_load_gpr(t1, rt);
+    switch (opc) {
+    case OPC_SEQ:
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1);
+        opn = "seq";
+        break;
+    case OPC_SNE:
+        tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1);
+        opn = "sne";
+        break;
+    default:
+        MIPS_INVAL(opn);
+        generate_exception(ctx, EXCP_RI);
+    }
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+
+}
+
+/* Store atomic add */
+static void gen_saa(CPUState *env, DisasContext *ctx, uint32_t opc,
+                     int rt, int base)
+{
+    const char *opn = "saa";
+    TCGv t0, t1, temp;
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+    temp = tcg_temp_new();
+    gen_load_gpr(t1, rt);
+    gen_base_offset_addr(ctx, t0, base, 0);
+    switch (opc) {
+    case OPC_SAA:
+        save_cpu_state(ctx, 1);
+        op_ld_ll(temp, t0, ctx);
+        tcg_gen_add_tl(temp, temp, t1);
+        op_st_sc(temp, t0, rt, ctx);
+        opn = "saa";
+        break;
+    case OPC_SAAD:
+        save_cpu_state(ctx, 0);
+        op_ld_lld(temp, t0, ctx);
+        tcg_gen_add_tl(temp, temp, t1);
+        op_st_scd(temp, t0, rt, ctx);
+        opn = "saad";
+        break;
+    }
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+static void gen_pop_count(DisasContext *ctx, uint32_t opc, int rd, int rs)
+{
+    const char *opn = "pop";
+        TCGv t0;
+        t0 = tcg_temp_new();
+        gen_load_gpr(t0, rs);
+        switch (opc) {
+        case OPC_DPOP:
+            gen_helper_dpop(t0, t0);
+            gen_store_gpr(t0, rd);
+            opn = "dpop";
+            break;
+        case OPC_POP:
+            gen_helper_pop(t0, t0);
+            gen_store_gpr(t0, rd);
+            opn = "pop";
+            break;
+        }
+        tcg_temp_free(t0);
+}
+
+/* Cavium specific extract instructions */
+static void gen_exts(CPUState *env, DisasContext *ctx, uint32_t opc, int rt,
+                      int rs, int lsb, int msb)
+{
+    TCGv t0 = tcg_temp_new();
+    uint32_t lshft, rshft;
+    gen_load_gpr(t0, rs);
+    switch (opc) {
+    case OPC_EXTS:
+        lshft = 64 - msb - 1 - lsb;
+        rshft = lshft + lsb;
+        tcg_gen_shli_tl(t0, t0, lshft);
+        tcg_gen_sari_tl(t0, t0, rshft);
+        gen_store_gpr(t0, rt);
+        break;
+    case OPC_EXTS32:
+        lshft = 32 - msb - 1 - lsb;
+        rshft = 64 - msb - 1;
+        tcg_gen_shli_tl(t0, t0, lshft);
+        tcg_gen_sari_tl(t0, t0, rshft);
+        gen_store_gpr(t0, rt);
+        break;
+
+    }
+    tcg_temp_free(t0);
+}
+#endif
+
 /* Logic with immediate operand */
 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
 {
@@ -1636,6 +1883,32 @@  static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
         }
         opn = "addu";
         break;
+    case OPC_BADDU:
+        {
+            TCGv t0 = tcg_temp_new();
+            TCGv t1 = tcg_temp_new();
+            gen_load_gpr(t0, rs);
+            gen_load_gpr(t1, rt);
+            tcg_gen_add_tl(t0, t1, t0);
+            tcg_gen_ext8u_tl(t0, t0);
+            gen_store_gpr(t0, rd);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+            opn = "baddu";
+            break;
+        }
+    case OPC_DMUL:
+        {
+            TCGv t0 = tcg_temp_new();
+            TCGv t1 = tcg_temp_new();
+            gen_load_gpr(t0, rs);
+            gen_load_gpr(t1, rt);
+            tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+            opn = "dmul";
+            break;
+        }
     case OPC_SUB:
         {
             TCGv t0 = tcg_temp_local_new();
@@ -2729,6 +3002,28 @@  static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
         }
         btgt = ctx->pc + insn_bytes + offset;
         break;
+    case OPC_BBIT0:
+    case OPC_BBIT1:
+        {
+            target_ulong maskb;
+            gen_load_gpr(t0, rs);
+            maskb = 1ULL << rt;
+            tcg_gen_andi_tl(t0, t0, maskb);
+            bcond_compute = 1;
+            btgt = ctx->pc + insn_bytes + offset;
+            break;
+        }
+    case OPC_BBIT032:
+    case OPC_BBIT132:
+        {
+            target_ulong maskb;
+            gen_load_gpr(t0, rs);
+            maskb = 1ULL << (rt + 32);
+            tcg_gen_andi_tl(t0, t0, maskb);
+            bcond_compute = 1;
+            btgt = ctx->pc + insn_bytes + offset;
+            break;
+        }
     case OPC_BGEZ:
     case OPC_BGEZAL:
     case OPC_BGEZALS:
@@ -2887,6 +3182,14 @@  static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
                        regnames[rs], regnames[rt], btgt);
             goto not_likely;
+        case OPC_BBIT1:
+        case OPC_BBIT132:
+            tcg_gen_setcondi_tl(TCG_COND_NE, bcond, t0, 0);
+            goto not_likely;
+        case OPC_BBIT0:
+        case OPC_BBIT032:
+            tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, t0, 0);
+            goto not_likely;
         case OPC_BNEL:
             tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
             MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
@@ -3062,6 +3365,22 @@  static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
         tcg_gen_andi_tl(t1, t1, mask);
         tcg_gen_or_tl(t0, t0, t1);
         break;
+    case OPC_CINS:
+        mask =  (1ULL << (msb+1))-1;
+        gen_load_gpr(t0, rt);
+        tcg_gen_andi_tl(t0, t0, 0);
+        tcg_gen_andi_tl(t1, t1, mask);
+        tcg_gen_shli_tl(t1, t1, lsb);
+        tcg_gen_or_tl(t0, t0, t1);
+        break;
+    case OPC_CINS32:
+        mask =  (1ULL << (msb+1))-1;
+        gen_load_gpr(t0, rt);
+        tcg_gen_andi_tl(t0, t0, 0);
+        tcg_gen_andi_tl(t1, t1, mask);
+        tcg_gen_shli_tl(t1, t1, (lsb+32));
+        tcg_gen_or_tl(t0, t0, t1);
+        break;
 #endif
     default:
 fail:
@@ -11948,6 +12267,57 @@  static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
         case OPC_MUL:
             gen_arith(env, ctx, op1, rd, rs, rt);
             break;
+#if defined(TARGET_MIPS64)
+        case OPC_DMUL:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_arith(env, ctx, op1, rd, rs, rt);
+            break;
+        case OPC_CINS:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_bitops(ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_CINS32:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_bitops(ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_MTM0:
+        case OPC_MTM1:
+        case OPC_MTM2:
+        case OPC_MTP0:
+        case OPC_MTP1:
+        case OPC_MTP2:
+        case OPC_VMULU:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_LMI(ctx, op1, rs, rt, rd);
+            break;
+        case OPC_BADDU:
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_arith(env, ctx, op1, rd, rs, rt);
+            break;
+        case OPC_EXTS:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_exts(env, ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_EXTS32:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_exts(env, ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_SAA:
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_saa(env, ctx, op1, rt, rs);
+            break;
+        case OPC_SAAD:
+            check_insn(env, ctx, INSN_OCTEON);
+            check_mips_64(ctx);
+            gen_saa(env, ctx, op1, rt, rs);
+            break;
+#endif
         case OPC_CLO:
         case OPC_CLZ:
             check_insn(env, ctx, ISA_MIPS32);
@@ -11965,9 +12335,18 @@  static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             }
             /* Treat as NOP. */
             break;
+        case OPC_MULT_G_2F:
+#if defined(TARGET_MIPS64)
+             /* Is Cavium Specific vmm0? */
+             if ((env->insn_flags & CPU_OCTEON)) {
+                check_mips_64(ctx);
+                gen_LMI(ctx, op1, rs, rt, rd);
+                break;
+             }
+#endif
+        /* Otherwise fall through */
         case OPC_DIV_G_2F:
         case OPC_DIVU_G_2F:
-        case OPC_MULT_G_2F:
         case OPC_MULTU_G_2F:
         case OPC_MOD_G_2F:
         case OPC_MODU_G_2F:
@@ -11982,6 +12361,12 @@  static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             gen_cl(ctx, op1, rd, rs);
             break;
         case OPC_DMULT_G_2F:
+            /* Is Cavium Specific instruction v3mulu? */
+            if ((env->insn_flags & CPU_OCTEON)) {
+                check_mips_64(ctx);
+                gen_LMI(ctx, op1, rs, rt, rd);
+                break;
+            }
         case OPC_DMULTU_G_2F:
         case OPC_DDIV_G_2F:
         case OPC_DDIVU_G_2F:
@@ -11990,6 +12375,31 @@  static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             check_insn(env, ctx, INSN_LOONGSON2F);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
+        case OPC_SEQ:
+        case OPC_SNE:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_set(ctx, op1, rd, rs, rt);
+            break;
+        case OPC_SEQI:
+        case OPC_SNEI:
+            {
+                int16_t imm10;
+                imm10 = (ctx->opcode >> 6) & 0x3ff;
+                check_mips_64(ctx);
+                check_insn(env, ctx, INSN_OCTEON);
+                gen_set_imm(env, op1, rt, rs, imm10);
+                break;
+            }
+        case OPC_POP:
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_pop_count(ctx, op1, rd, rs);
+            break;
+        case OPC_DPOP:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_pop_count(ctx, op1, rd, rs);
+            break;
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special2");
@@ -12281,10 +12691,18 @@  static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
         break;
 
     /* COP2.  */
-    case OPC_LWC2:
-    case OPC_LDC2:
-    case OPC_SWC2:
-    case OPC_SDC2:
+    /* Conflicting opcodes with Cavium specific branch instructions
+       if cpu_model is set to Octeon these opcodes will
+       belong to INSN_OCTEON */
+    case OPC_LWC2: /* BBIT0 */
+    case OPC_LDC2: /* BBIT032 */
+    case OPC_SWC2: /* BBIT1 */
+    case OPC_SDC2: /* BBIT132 */
+        if (env->insn_flags & INSN_OCTEON) {
+            gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
+            *is_branch = 1;
+            break;
+        }
     case OPC_CP2:
         /* COP2: Not implemented. */
         generate_exception_err(ctx, EXCP_CpU, 2);