summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/mips/isa/decoder.isa201
-rw-r--r--arch/mips/isa/formats/fp.isa18
-rw-r--r--arch/mips/isa_traits.cc13
-rw-r--r--arch/mips/isa_traits.hh7
4 files changed, 214 insertions, 25 deletions
diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa
index 143d0bae2..5e1f02869 100644
--- a/arch/mips/isa/decoder.isa
+++ b/arch/mips/isa/decoder.isa
@@ -1021,39 +1021,193 @@ decode OPCODE_HI default Unknown::unknown() {
Fd.uw = fpConvert(Fs1.uw, PL_TO_SINGLE);
}});
- 0x4: pll({{ Fd.ud = Fs.ud<31:0> << 32 | Ft.ud<31:0>; }});
- 0x5: plu({{ Fd.ud = Fs.ud<31:0> << 32 | Ft.ud<63:32>;}});
- 0x6: pul({{ Fd.ud = Fs.ud<63:32> << 32 | Ft.ud<31:0>; }});
- 0x7: puu({{ Fd.ud = Fs.ud<63:32> << 32 | Ft.ud<63:32>;}});
+ 0x4: pll({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft1.uw; }});
+ 0x5: plu({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft2.uw; }});
+ 0x6: pul({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft1.uw; }});
+ 0x7: puu({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft2.uw; }});
}
}
0x6: decode FUNCTION_LO {
- format FloatOp {
- 0x0: c_f_ps({{ ; }});
- 0x1: c_un_ps({{ ; }});
- 0x2: c_eq_ps({{ ; }});
- 0x3: c_ueq_ps({{ ; }});
- 0x4: c_olt_ps({{ ; }});
- 0x5: c_ult_ps({{ ; }});
- 0x6: c_ole_ps({{ ; }});
- 0x7: c_ule_ps({{ ; }});
+ format FloatPSCompareOp {
+ 0x0: c_f_ps({{ cond1 = 0; cond2 = 0; }});
+
+ 0x1: c_un_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = 0;
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = 0;
+
+ }});
+
+ 0x2: c_eq_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x3: c_ueq_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x4: c_olt_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf < Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x5: c_ult_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs.sf < Ft.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x6: c_ole_ps({{
+ if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs.sf <= Ft.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
+
+ 0x7: c_ule_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf <= Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
}
}
0x7: decode FUNCTION_LO {
- format FloatOp {
- 0x0: c_sf_ps({{ ; }});
- 0x1: c_ngle_ps({{ ; }});
- 0x2: c_seq_ps({{ ; }});
- 0x3: c_ngl_ps({{ ; }});
- 0x4: c_lt_ps({{ ; }});
- 0x5: c_nge_ps({{ ; }});
- 0x6: c_le_ps({{ ; }});
- 0x7: c_ngt_ps({{ ; }});
+ format FloatPSCompareWithXcptOp {
+ 0x0: c_sf_ps({{ cond1 = 0; cond2 = 0; }});
+
+ 0x1: c_ngle_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = 0;
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = 0;
+ }});
+
+ 0x2: c_seq_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x3: c_ngl_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x4: c_lt_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf < Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x5: c_nge_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf < Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x6: c_le_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf <= Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
+
+ 0x7: c_ngt_ps({{
+ if (unorderedFP(Fs1.sf) || unorderedFP(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf <= Ft1.sf);
+
+ if (unorderedFP(Fs2.sf) || unorderedFP(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
}
}
-
}
}
}
@@ -1148,7 +1302,6 @@ decode OPCODE_HI default Unknown::unknown() {
0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }});
0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.df) - Fr.df; }});
0x6: nmsub_ps({{
- 0x6: msub_ps({{
Fd1.sf = -1 * ((Fs1.df * Ft1.df) - Fr1.df);
Fd2.sf = -1 * ((Fs2.df * Ft2.df) - Fr2.df);
}});
diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa
index 2ea4d6bf8..0414e30c3 100644
--- a/arch/mips/isa/formats/fp.isa
+++ b/arch/mips/isa/formats/fp.isa
@@ -81,3 +81,21 @@ def format Float64ConvertOp(code, *flags) {{
decode_block = BasicDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
}};
+
+def format FloatPSCompareOp(code, *flags) {{
+ code = 'bool cond1;\nbool cond2;\n' + code
+ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format FloatPSCompareWithXcptOp(code, *flags) {{
+ code = 'bool cond1;\nbool cond2;\n' + code
+ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
diff --git a/arch/mips/isa_traits.cc b/arch/mips/isa_traits.cc
index 05499f4dc..19ef46291 100644
--- a/arch/mips/isa_traits.cc
+++ b/arch/mips/isa_traits.cc
@@ -102,6 +102,12 @@ MipsISA::roundFP(float val)
return 1.5;
}
+float
+MipsISA::roundFP(uint64_t val)
+{
+ return 1.5;
+}
+
double
MipsISA::roundFP(double val)
{
@@ -121,6 +127,13 @@ MipsISA::truncFP(float val)
}
double
+MipsISA::truncFP(uint64_t val)
+{
+ int trunc_val = (int) val;
+ return (double) trunc_val;
+}
+
+double
MipsISA::truncFP(double val)
{
int trunc_val = (int) val;
diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh
index 097736dda..6788806c1 100644
--- a/arch/mips/isa_traits.hh
+++ b/arch/mips/isa_traits.hh
@@ -138,10 +138,15 @@ namespace MipsISA
void copyRegs(ExecContext *src, ExecContext *dest);
uint64_t fpConvert(double fp_val, ConvertType cvt_type);
+
float roundFP(float val);
double roundFP(double val);
+ float roundFP(uint64_t val);
+
float truncFP(float val);
- float truncFP(float val);
+ double truncFP(uint64_t val);
+ double truncFP(double val);
+
bool unorderedFP(float val);
bool unorderedFP(double val);
bool getFPConditionCode(int cc);