+ int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
+ address_word vaddr;
+ address_word paddr;
+ int uncached;
+ unsigned64 memval;
+ unsigned64 v;
+
+ vaddr = loadstore_ea (SD_, base, offset);
+ if ((vaddr & AccessLength_DOUBLEWORD) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, STATE_CPU (SD, 0), cia, read_map,
+ AccessLength_DOUBLEWORD + 1, vaddr, read_transfer,
+ sim_core_unaligned_signal);
+ }
+ AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET,
+ isREAL);
+ LoadMemory (&memval, NULL, uncached, AccessLength_WORD, paddr, vaddr,
+ isDATA, isREAL);
+ v = (unsigned64)memval;
+ LoadMemory (&memval, NULL, uncached, AccessLength_WORD, paddr + 4, vaddr + 4,
+ isDATA, isREAL);
+ return (bigendian ? ((v << 32) | memval) : (v | (memval << 32)));
+}
+
+
+// Helper:
+//
+// Store a double word FP value using 2 32-bit memory cycles a la MIPS II
+// or MIPS32. do_load cannot be used instead because it returns an
+// unsigned_word, which is limited to the size of the machine's registers.
+//
+
+:function:::void:do_store_double:address_word base, address_word offset, unsigned64 v
+*mipsII:
+*mips32:
+{
+ int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
+ address_word vaddr;
+ address_word paddr;
+ int uncached;
+ unsigned64 memval;
+
+ vaddr = loadstore_ea (SD_, base, offset);
+ if ((vaddr & AccessLength_DOUBLEWORD) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, STATE_CPU(SD, 0), cia, read_map,
+ AccessLength_DOUBLEWORD + 1, vaddr, write_transfer,
+ sim_core_unaligned_signal);
+ }
+ AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET,
+ isREAL);
+ memval = (bigendian ? (v >> 32) : (v & 0xFFFFFFFF));
+ StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
+ isREAL);
+ memval = (bigendian ? (v & 0xFFFFFFFF) : (v >> 32));
+ StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr + 4, vaddr + 4,
+ isREAL);
+}
+
+
+010001,10,3.FMT,00000,5.FS,5.FD,000101:COP1:32,f::ABS.fmt
+"abs.%s<FMT> f<FD>, f<FS>"
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips64:
+*vr4100:
+*vr5000:
+*r3900:
+{
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (FD, fmt, AbsoluteValue (ValueFPR (FS, fmt), fmt));
+}
+
+
+
+010001,10,3.FMT,5.FT,5.FS,5.FD,000000:COP1:32,f::ADD.fmt
+"add.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips64:
+*vr4100:
+*vr5000:
+*r3900:
+{
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (FD, fmt, Add (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt));
+}
+
+
+010011,5.RS,5.FT,5.FS,5.FD,011,110:COP1X:64,f::ALNV.PS
+"alnv.ps f<FD>, f<FS>, f<FT>, r<RS>"
+*mipsV:
+*mips64:
+{
+ unsigned64 fs;
+ unsigned64 ft;
+ unsigned64 fd;
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ fs = ValueFPR (FS, fmt_ps);
+ if ((GPR[RS] & 0x3) != 0)
+ Unpredictable ();
+ if ((GPR[RS] & 0x4) == 0)
+ fd = fs;
+ else
+ {
+ ft = ValueFPR (FT, fmt_ps);
+ if (BigEndianCPU)
+ fd = PackPS (PSLower (fs), PSUpper (ft));
+ else
+ fd = PackPS (PSLower (ft), PSUpper (fs));
+ }
+ StoreFPR (FD, fmt_ps, fd);
+}
+
+
+// BC1F
+// BC1FL
+// BC1T
+// BC1TL
+
+010001,01000,3.0,1.ND,1.TF,16.OFFSET:COP1S:32,f::BC1a
+"bc1%s<TF>%s<ND> <OFFSET>"
+*mipsI:
+*mipsII:
+*mipsIII:
+{
+ check_fpu (SD_);
+ TRACE_BRANCH_INPUT (PREVCOC1());
+ if (PREVCOC1() == TF)