diff -r 4e1ea429556c -r 8b445d3198e0 src/arch/x86/isa/decoder/x87.isa --- a/src/arch/x86/isa/decoder/x87.isa Tue Jun 11 10:09:33 2013 +0200 +++ b/src/arch/x86/isa/decoder/x87.isa Tue Jun 11 10:11:35 2013 +0200 @@ -67,11 +67,11 @@ 0x0: fnop(); default: Inst::UD2(); } - default: fst(); + default: Inst::FST(Ed); } 0x3: decode MODRM_MOD { 0x3: Inst::UD2(); - default: fstp(); + default: Inst::FSTP(Ed); } 0x4: decode MODRM_MOD { 0x3: decode MODRM_RM { @@ -189,7 +189,7 @@ 0x5: decode MODRM_MOD { 0x3: fucomi(); // 80-bit load - default: fld(); + default: Inst::FLD80(); } 0x6: decode MODRM_MOD { 0x3: fcomi(); @@ -197,7 +197,7 @@ } 0x7: decode MODRM_MOD { 0x3: Inst::UD2(); - default: fstp(); + default: Inst::FST80P(); } } //0x4: esc4(); diff -r 4e1ea429556c -r 8b445d3198e0 src/arch/x86/isa/insts/x87/data_transfer_and_conversion/load_or_store_floating_point.py --- a/src/arch/x86/isa/insts/x87/data_transfer_and_conversion/load_or_store_floating_point.py Tue Jun 11 10:09:33 2013 +0200 +++ b/src/arch/x86/isa/insts/x87/data_transfer_and_conversion/load_or_store_floating_point.py Tue Jun 11 10:11:35 2013 +0200 @@ -37,13 +37,13 @@ microcode = ''' def macroop FLD_M { - ldfp ufp1, seg, sib, disp + ldfp87 ufp1, seg, sib, disp movfp st(-1), ufp1, spm=-1 }; def macroop FLD_P { rdip t7 - ldfp ufp1, seg, riprel, disp + ldfp87 ufp1, seg, riprel, disp movfp st(-1), ufp1, spm=-1 }; @@ -51,17 +51,23 @@ movfp st(-1), sti, spm=-1 }; +def macroop FLD80 { + ld t1, seg, sib, "DISPLACEMENT", dataSize=8 + ld t2, seg, sib, "DISPLACEMENT + 8", dataSize=2 + cvtint_fp80 st(-1), t1, t2, spm=-1 +}; + def macroop FST_R { movfp sti, st(0) }; def macroop FST_M { - stfp st(0), seg, sib, disp + stfp87 st(0), seg, sib, disp }; def macroop FST_P { rdip t7 - stfp st(0), seg, riprel, disp + stfp87 st(0), seg, riprel, disp }; def macroop FSTP_R { @@ -70,12 +76,20 @@ def macroop FSTP_M { movfp ufp1, st(0), spm=1 - stfp ufp1, seg, sib, disp + stfp87 ufp1, seg, sib, disp }; def macroop FSTP_P { movfp ufp1, st(0), spm=1 rdip t7 - stfp ufp1, seg, riprel, disp + stfp87 ufp1, seg, riprel, disp }; + +def macroop FST80P { + cvtfp80h_int t1, st(0) + cvtfp80l_int t2, st(0), spm=1 + st t1, seg, sib, "DISPLACEMENT + 0", dataSize=8 + st t2, seg, sib, "DISPLACEMENT + 8", dataSize=2 +}; + ''' diff -r 4e1ea429556c -r 8b445d3198e0 src/arch/x86/isa/microops/fpop.isa --- a/src/arch/x86/isa/microops/fpop.isa Tue Jun 11 10:09:33 2013 +0200 +++ b/src/arch/x86/isa/microops/fpop.isa Tue Jun 11 10:11:35 2013 +0200 @@ -277,9 +277,10 @@ class ConvOp(FpBinaryOp): abstract = True op_class = 'FloatCvtOp' - def __init__(self, dest, src1): + def __init__(self, dest, src1, **kwargs): super(ConvOp, self).__init__(dest, src1, \ - "InstRegIndex(FLOATREG_MICROFP0)") + "InstRegIndex(FLOATREG_MICROFP0)", \ + **kwargs) # These probably shouldn't look at the ExtMachInst directly to figure # out what size to use and should instead delegate that to the macroop's @@ -306,6 +307,32 @@ SDestReg = merge(SDestReg, intSrcReg1, 4); ''' + # Convert two integers registers representing an 80-bit floating + # point number to an x87 register. + class cvtint_fp80(FpBinaryOp): + code = ''' + uint8_t bits[10]; + *(uint64_t *)(bits + 0) = SSrcReg1; + *(uint16_t *)(bits + 8) = (uint16_t)SSrcReg2; + FpDestReg = *(__float80 *)bits; + ''' + + # Convert an x87 register (double) into extended precision and + # extract the highest 64 bits. + class cvtfp80h_int(ConvOp): + code = ''' + __float80 fp80(FpSrcReg1); + SDestReg = *(uint64_t *)((char *)&fp80 + 0); + ''' + + # Convert an x87 register (double) into extended precision and + # extract the lowest 16 bits. + class cvtfp80l_int(ConvOp): + code = ''' + __float80 fp80(FpSrcReg1); + SDestReg = *(uint16_t *)((char *)&fp80 + 8); + ''' + # These need to consider size at some point. They'll always use doubles # for the moment. class addfp(FpBinaryOp): diff -r 4e1ea429556c -r 8b445d3198e0 src/arch/x86/isa/microops/ldstop.isa --- a/src/arch/x86/isa/microops/ldstop.isa Tue Jun 11 10:09:33 2013 +0200 +++ b/src/arch/x86/isa/microops/ldstop.isa Tue Jun 11 10:11:35 2013 +0200 @@ -410,7 +410,22 @@ defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);', 'Data = Mem & mask(dataSize * 8);', '(StoreCheck << FlagShift) | Request::LOCKED') - defineMicroLoadOp('Ldfp', 'FpData_uqw = Mem;', big = False) + + defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False) + + defineMicroLoadOp('Ldfp87', code=''' + switch (dataSize) + { + case 4: + FpData_df = *(float *)&Mem; + break; + case 8: + FpData_df = *(double *)&Mem; + break; + default: + panic("Unhandled data size in LdFp87.\\n"); + } + ''', big = False) def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"): global header_output @@ -447,7 +462,24 @@ defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);') defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);', mem_flags="Request::LOCKED") - defineMicroStoreOp('Stfp', 'Mem = FpData_uqw;') + + defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;') + + defineMicroStoreOp('Stfp87', code=''' + switch (dataSize) + { + case 4: { + float single(FpData_df); + Mem = *(uint32_t *)&single; + } break; + case 8: + Mem = *(uint64_t *)&FpData_df; + break; + default: + panic("Unhandled data size in StFp87.\\n"); + } + ''') + defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS") iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',