diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py index eaaa18208..18ba93e19 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py @@ -45,7 +45,7 @@ def macroop CALL_NEAR_I limm t1, imm rdip t7 # Check target of call - st t7, ss, [0, t0, rsp], "-env.dataSize" + st_stack t7, ss, [0, t0, rsp], "-env.dataSize" subi rsp, rsp, ssz wrip t7, t1 }; @@ -58,7 +58,7 @@ def macroop CALL_NEAR_R rdip t1 # Check target of call - st t1, ss, [0, t0, rsp], "-env.dataSize" + st_stack t1, ss, [0, t0, rsp], "-env.dataSize" subi rsp, rsp, ssz wripi reg, 0 }; diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py index be9387ecf..2117a943c 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py @@ -40,7 +40,7 @@ def macroop POP_R { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp], dataSize=ssz + ld_stack t1, ss, [1, t0, rsp], dataSize=ssz addi rsp, rsp, ssz, dataSize=asz mov reg, reg, t1 }; @@ -49,7 +49,7 @@ def macroop POP_M { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp], dataSize=ssz + ld_stack t1, ss, [1, t0, rsp], dataSize=ssz cda seg, sib, disp, dataSize=ssz addi rsp, rsp, ssz, dataSize=asz st t1, seg, sib, disp, dataSize=ssz @@ -70,7 +70,7 @@ def macroop PUSH_R { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - st reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + st_stack reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz subi rsp, rsp, ssz }; @@ -79,7 +79,7 @@ def macroop PUSH_I { .adjust_env oszIn64Override limm t1, imm - st t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + st_stack t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz subi rsp, rsp, ssz }; @@ -138,7 +138,7 @@ def macroop LEAVE { .adjust_env oszIn64Override mov t1, t1, rbp, dataSize=ssz - ld rbp, ss, [1, t0, t1], dataSize=ssz + ld_stack rbp, ss, [1, t0, t1], dataSize=ssz mov rsp, rsp, t1, dataSize=ssz addi rsp, rsp, ssz, dataSize=ssz }; @@ -156,7 +156,7 @@ def macroop ENTER_I_I { # t1 is now the masked nesting level, and t2 is the amount of storage. # Push rbp. - st rbp, ss, [1, t0, rsp], "-env.dataSize" + st_stack rbp, ss, [1, t0, rsp], "-env.dataSize" subi rsp, rsp, ssz # Save the stack pointer for later @@ -172,8 +172,8 @@ def macroop ENTER_I_I { limm t4, "ULL(-1)", dataSize=8 topOfLoop: - ld t5, ss, [dsz, t4, rbp] - st t5, ss, [1, t0, rsp], "-env.dataSize" + ld_stack t5, ss, [dsz, t4, rbp] + st_stack t5, ss, [1, t0, rsp], "-env.dataSize" subi rsp, rsp, ssz # If we're not done yet, loop @@ -183,7 +183,7 @@ topOfLoop: bottomOfLoop: # Push the old rbp onto the stack - st t6, ss, [1, t0, rsp], "-env.dataSize" + st_stack t6, ss, [1, t0, rsp], "-env.dataSize" subi rsp, rsp, ssz skipLoop: diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index a22bc5fe2..7ba78c8f9 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -315,7 +315,8 @@ def template MicroLdStSplitOpConstructor {{ let {{ class LdStOp(X86Microop): def __init__(self, data, segment, addr, disp, - dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): + dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, + implicitStack): self.data = data [self.scale, self.index, self.base] = addr self.disp = disp @@ -331,8 +332,11 @@ let {{ self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" if nonSpec: self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" - self.memFlags += " | (machInst.legacy.addr ? " + \ - "(AddrSizeFlagBit << FlagShift) : 0)" + # For implicit stack operations, we should use *not* use the + # alternative addressing mode for loads/stores if the prefix is set + if not implicitStack: + self.memFlags += " | (machInst.legacy.addr ? " + \ + "(AddrSizeFlagBit << FlagShift) : 0)" def getAllocator(self, microFlags): allocator = '''new %(class_name)s(machInst, macrocodeBlock, @@ -351,7 +355,8 @@ let {{ class BigLdStOp(X86Microop): def __init__(self, data, segment, addr, disp, - dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): + dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, + implicitStack): self.data = data [self.scale, self.index, self.base] = addr self.disp = disp @@ -367,8 +372,11 @@ let {{ self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" if nonSpec: self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" - self.memFlags += " | (machInst.legacy.addr ? " + \ - "(AddrSizeFlagBit << FlagShift) : 0)" + # For implicit stack operations, we should use *not* use the + # alternative addressing mode for loads/stores if the prefix is set + if not implicitStack: + self.memFlags += " | (machInst.legacy.addr ? " + \ + "(AddrSizeFlagBit << FlagShift) : 0)" def getAllocator(self, microFlags): allocString = ''' @@ -395,9 +403,11 @@ let {{ class LdStSplitOp(LdStOp): def __init__(self, data, segment, addr, disp, - dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): + dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, + implicitStack): super(LdStSplitOp, self).__init__(0, segment, addr, disp, - dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec) + dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec, + implicitStack) (self.dataLow, self.dataHi) = data def getAllocator(self, microFlags): @@ -435,7 +445,8 @@ let {{ calculateEA = 'EA = SegBase + ' + segmentEAExpr def defineMicroLoadOp(mnemonic, code, bigCode='', - mem_flags="0", big=True, nonSpec=False): + mem_flags="0", big=True, nonSpec=False, + implicitStack=False): global header_output global decoder_output global exec_output @@ -460,17 +471,26 @@ let {{ exec_output += MicroLoadInitiateAcc.subst(iop) exec_output += MicroLoadCompleteAcc.subst(iop) + if implicitStack: + # For instructions that implicitly access the stack, the address + # size is the same as the stack segment pointer size, not the + # address size if specified by the instruction prefix + addressSize = "env.stackSize" + else: + addressSize = "env.addressSize" + base = LdStOp if big: base = BigLdStOp class LoadOp(base): def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", - addressSize="env.addressSize", - atCPL0=False, prefetch=False, nonSpec=nonSpec): + addressSize=addressSize, + atCPL0=False, prefetch=False, nonSpec=nonSpec, + implicitStack=implicitStack): super(LoadOp, self).__init__(data, segment, addr, disp, dataSize, addressSize, mem_flags, - atCPL0, prefetch, nonSpec) + atCPL0, prefetch, nonSpec, implicitStack) self.className = Name self.mnemonic = name @@ -478,6 +498,10 @@ let {{ defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);', 'Data = Mem & mask(dataSize * 8);') + # Load micro-op used in macro-ops that implicitly access the stack + defineMicroLoadOp('Ld_stack', 'Data = merge(Data, Mem, dataSize);', + 'Data = Mem & mask(dataSize * 8);', + implicitStack=True) defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'Data = Mem & mask(dataSize * 8);', '(StoreCheck << FlagShift)') @@ -544,10 +568,11 @@ let {{ def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize", - atCPL0=False, prefetch=False, nonSpec=nonSpec): + atCPL0=False, prefetch=False, nonSpec=nonSpec, + implicitStack=False): super(LoadOp, self).__init__(data, segment, addr, disp, dataSize, addressSize, mem_flags, - atCPL0, prefetch, nonSpec) + atCPL0, prefetch, nonSpec, implicitStack) self.className = Name self.mnemonic = name @@ -574,7 +599,8 @@ let {{ '(StoreCheck << FlagShift) | Request::LOCKED_RMW', nonSpec=True) - def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"): + def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0", + implicitStack=False): global header_output global decoder_output global exec_output @@ -594,20 +620,31 @@ let {{ exec_output += MicroStoreInitiateAcc.subst(iop) exec_output += MicroStoreCompleteAcc.subst(iop) + if implicitStack: + # For instructions that implicitly access the stack, the address + # size is the same as the stack segment pointer size, not the + # address size if specified by the instruction prefix + addressSize = "env.stackSize" + else: + addressSize = "env.addressSize" + class StoreOp(LdStOp): def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", - addressSize="env.addressSize", - atCPL0=False, nonSpec=False): + addressSize=addressSize, + atCPL0=False, nonSpec=False, implicitStack=implicitStack): super(StoreOp, self).__init__(data, segment, addr, disp, dataSize, addressSize, mem_flags, atCPL0, False, - nonSpec) + nonSpec, implicitStack) self.className = Name self.mnemonic = name microopClasses[name] = StoreOp defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);') + # Store micro-op used in macro-ops that implicitly access the stack + defineMicroStoreOp('St_stack', 'Mem = pick(Data, 2, dataSize);', + implicitStack=True) defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);', mem_flags="Request::LOCKED_RMW") @@ -655,10 +692,10 @@ let {{ def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize", - atCPL0=False, nonSpec=False): + atCPL0=False, nonSpec=False, implicitStack=False): super(StoreOp, self).__init__(data, segment, addr, disp, dataSize, addressSize, mem_flags, atCPL0, False, - nonSpec) + nonSpec, implicitStack) self.className = Name self.mnemonic = name @@ -694,7 +731,7 @@ let {{ def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize"): super(LeaOp, self).__init__(data, segment, addr, disp, - dataSize, addressSize, "0", False, False, False) + dataSize, addressSize, "0", False, False, False, False) self.className = "Lea" self.mnemonic = "lea" @@ -715,7 +752,7 @@ let {{ addressSize="env.addressSize"): super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, addr, disp, dataSize, addressSize, "0", False, False, - False) + False, False) self.className = "Tia" self.mnemonic = "tia" @@ -727,10 +764,9 @@ let {{ addressSize="env.addressSize", atCPL0=False): super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, addr, disp, dataSize, addressSize, "Request::NO_ACCESS", - atCPL0, False, False) + atCPL0, False, False, False) self.className = "Cda" self.mnemonic = "cda" microopClasses["cda"] = CdaOp }}; -