Eliot Miranda uploaded a new version of Cog to project VM Maker: http://source.squeak.org/VMMaker/Cog-eem.448.mcz
==================== Summary ====================
Name: Cog-eem.448 Author: eem Time: 20 November 2021, 10:16:30.198832 pm UUID: e6bb1c15-697d-434f-b09a-53afc0219839 Ancestors: Cog-eem.447
CogProcessorAlien: Factor in memoryOffset, allowing the SpurMemoryManager simulators to implement a nuill pointer trap by leaving out the first word in memory.
=============== Diff against Cog-eem.447 ===============
Item was changed: ----- Method: BochsIA32Alien>>handleCallFailureAt:in: (in category 'error handling') ----- handleCallFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a call into a ProcessorSimulationTrap signal." | relativeJump | + relativeJump := memoryArray longAt: pc + 2 - self primitiveMemoryOffset. - relativeJump := memoryArray longAt: pc + 2 bigEndian: false. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 address: (pc + 5 + relativeJump) signedIntToLong type: #call) signal!
Item was changed: ----- Method: BochsIA32Alien>>handleExecutionPrimitiveFailureIn:minimumAddress: (in category 'error handling') ----- handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "Handle an execution primitive failure. Convert out-of-range call and absolute memory read into register instructions into ProcessorSimulationTrap signals." "self printIntegerRegistersOn: Transcript" "self printRegistersOn: Transcript" | pc opcode | ((pc := self eip) between: minimumAddress and: memoryArray byteSize - 1) ifTrue: + [opcode := memoryArray byteAt: pc + 1 - self primitiveMemoryOffset. - [opcode := memoryArray byteAt: pc + 1. opcode ~= 16r0f ifTrue: [^self perform: (OpcodeExceptionMap at: opcode + 1) with: pc with: memoryArray]. + opcode := memoryArray byteAt: pc + 2 - self primitiveMemoryOffset. - opcode := memoryArray byteAt: pc + 2. ^self perform: (ExtendedOpcodeExceptionMap at: opcode + 1) with: pc with: memoryArray]. ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsIA32Alien>>handleJmpFailureAt:in: (in category 'error handling') ----- handleJmpFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a jmp into a ProcessorSimulationTrap signal." | relativeJump | + relativeJump := memoryArray longAt: pc + 2 - self primitiveMemoryOffset. - relativeJump := memoryArray longAt: pc + 2 bigEndian: false. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 address: (pc + 5 + relativeJump) signedIntToLong type: #jump) signal!
Item was changed: ----- Method: BochsIA32Alien>>handleMovALObFailureAt:in: (in category 'error handling') ----- handleMovALObFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a read into al into a ProcessorSimulationTrap signal." ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 + address: (memoryArray unsignedLongAt: pc + 2 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 2 bigEndian: false) type: #read accessor: #al:) signal!
Item was changed: ----- Method: BochsIA32Alien>>handleMovAXOvFailureAt:in: (in category 'error handling') ----- handleMovAXOvFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a read into eax into a ProcessorSimulationTrap signal." ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 + address: (memoryArray unsignedLongAt: pc + 2 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 2 bigEndian: false) type: #read accessor: #eax:) signal!
Item was changed: ----- Method: BochsIA32Alien>>handleMovEbGbFailureAt:in: (in category 'error handling') ----- handleMovEbGbFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a byte register write into a ProcessorSimulationTrap signal." | modrmByte address | modrmByte := memoryArray byteAt: pc + 2. (modrmByte bitAnd: 7) ~= 4 ifTrue: "MoveRMbr with r = ESP requires an SIB byte" [address := (modrmByte bitAnd: 16rC0) caseOf: { [0 "ModRegInd"] + -> [memoryArray unsignedLongAt: pc + 3 - self primitiveMemoryOffset]. - -> [memoryArray unsignedLongAt: pc + 3 bigEndian: false]. [16r80 "ModRegRegDisp32"] -> [(self perform: (#(eax ecx edx ebx esp ebp esi edi) at: (modrmByte bitAnd: 7) + 1)) + + (memoryArray unsignedLongAt: pc + 3 - self primitiveMemoryOffset) - + (memoryArray unsignedLongAt: pc + 3 bigEndian: false) bitAnd: 16rFFFFFFFF] } otherwise: [^self reportPrimitiveFailure]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 6 address: address type: #write accessor: (#(al cl dl bl ah ch dh bh) at: ((modrmByte >> 3 bitAnd: 7) + 1))) signal]. ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsIA32Alien>>handleMovEvGvFailureAt:in: (in category 'error handling') ----- handleMovEvGvFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a register write into a ProcessorSimulationTrap signal." | modrmByte | + ^((modrmByte := memoryArray byteAt: pc + 2 - self primitiveMemoryOffset) bitAnd: 16rC7) = 16r5 "ModRegInd & disp32" - ^((modrmByte := memoryArray byteAt: pc + 2) bitAnd: 16rC7) = 16r5 "ModRegInd & disp32" ifTrue: [(ProcessorSimulationTrap pc: pc nextpc: pc + 6 + address: (memoryArray unsignedLongAt: pc + 3 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 3 bigEndian: false) type: #write accessor: (#(eax ecx edx ebx esp ebp esi edi) at: ((modrmByte >> 3 bitAnd: 7) + 1))) signal] ifFalse: [self reportPrimitiveFailure]!
Item was changed: ----- Method: BochsIA32Alien>>handleMovGbEbFailureAt:in: (in category 'error handling') ----- handleMovGbEbFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a byte register load into a ProcessorSimulationTrap signal." | modrmByte address | modrmByte := memoryArray byteAt: pc + 2. address := (modrmByte bitAnd: 16rC0) caseOf: { [0 "ModRegInd"] + -> [memoryArray unsignedLongAt: pc + 3 - self primitiveMemoryOffset]. - -> [memoryArray unsignedLongAt: pc + 3 bigEndian: false]. [16r80 "ModRegRegDisp32"] -> [(self perform: (#(eax ecx edx ebx esp ebp esi edi) at: (modrmByte bitAnd: 7) + 1)) + + (memoryArray unsignedLongAt: pc + 3 - self primitiveMemoryOffset) - + (memoryArray unsignedLongAt: pc + 3 bigEndian: false) bitAnd: 16rFFFFFFFF] } otherwise: [^self reportPrimitiveFailure]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 6 address: address type: #read accessor: (#(al: cl: dl: bl: ah: ch: dh: bh:) at: ((modrmByte >> 3 bitAnd: 7) + 1))) signal!
Item was changed: ----- Method: BochsIA32Alien>>handleMovGvEbFailureAt:in: (in category 'error handling') ----- handleMovGvEbFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a register load into a ProcessorSimulationTrap signal." | modrmByte mode srcIsSP srcVal dst offset | modrmByte := memoryArray byteAt: pc + 3. mode := modrmByte >> 6 bitAnd: 3. dst := #(eax: ecx: edx: ebx: esp: ebp: esi: edi:) at: ((modrmByte >> 3 bitAnd: 7) + 1). mode = 0 ifTrue: "ModRegInd" + [offset := memoryArray unsignedLongAt: pc + 4 - self primitiveMemoryOffset. "1-relative" - [offset := memoryArray unsignedLongAt: pc + 4. "1-relative" ^(ProcessorSimulationTrap pc: pc nextpc: pc + 7 address: offset type: #read accessor: dst) signal]. srcIsSP := (modrmByte bitAnd: 7) = 4. srcVal := self perform: (#(eax ecx edx ebx esp ebp esi edi) at: (modrmByte bitAnd: 7) + 1). mode = 1 ifTrue: "ModRegRegDisp8" + [offset := memoryArray byteAt: pc + ((srcIsSP ifTrue: [5] ifFalse: [4] "1-relative") - self primitiveMemoryOffset). - [offset := memoryArray byteAt: pc + (srcIsSP ifTrue: [5] ifFalse: [4]). "1-relative" offset > 127 ifTrue: [offset := offset - 256]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + (srcIsSP ifTrue: [5] ifFalse: [4]) address: (srcVal + offset bitAnd: 16rFFFFFFFF) type: #read accessor: dst) signal]. mode = 2 ifTrue: "ModRegRegDisp32" + [offset := memoryArray unsignedLongAt: pc + ((srcIsSP ifTrue: [5] ifFalse: [4] "1-relative") - self primitiveMemoryOffset). - [offset := memoryArray unsignedLongAt: pc + (srcIsSP ifTrue: [5] ifFalse: [4]). "1-relative" ^(ProcessorSimulationTrap pc: pc nextpc: pc + (srcIsSP ifTrue: [8] ifFalse: [7]) address: (srcVal + offset bitAnd: 16rFFFFFFFF) type: #read accessor: dst) signal]. ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsIA32Alien>>handleMovGvEvFailureAt:in: (in category 'error handling') ----- handleMovGvEvFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a register load into a ProcessorSimulationTrap signal." | modrmByte | + ^(((modrmByte := memoryArray byteAt: pc + 2 - self primitiveMemoryOffset) bitAnd: 16rC7) = 16r5) "ModRegInd & disp32" - ^(((modrmByte := memoryArray byteAt: pc + 2) bitAnd: 16rC7) = 16r5) "ModRegInd & disp32" ifTrue: [(ProcessorSimulationTrap pc: pc nextpc: pc + 6 + address: (memoryArray unsignedLongAt: pc + 3 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 3 bigEndian: false) type: #read accessor: (#(eax: ecx: edx: ebx: esp: ebp: esi: edi:) at: ((modrmByte >> 3 bitAnd: 7) + 1))) signal] ifFalse: [self reportPrimitiveFailure]!
Item was changed: ----- Method: BochsIA32Alien>>handleMovObALFailureAt:in: (in category 'error handling') ----- handleMovObALFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a byte write of al into a ProcessorSimulationTrap signal." ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 + address: (memoryArray unsignedLongAt: pc + 2 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 2 bigEndian: false) type: #write accessor: #al) signal!
Item was changed: ----- Method: BochsIA32Alien>>handleMovOvAXFailureAt:in: (in category 'error handling') ----- handleMovOvAXFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a write of eax into a ProcessorSimulationTrap signal." ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 + address: (memoryArray unsignedLongAt: pc + 2 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 2 bigEndian: false) type: #write accessor: #eax) signal!
Item was changed: ----- Method: BochsIA32Alien>>handleRetFailureAt:in: (in category 'error handling') ----- handleRetFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" "Convert an execution primitive failure for a ret into a ProcessorSimulationTrap signal." ^(ProcessorSimulationTrap pc: pc nextpc: pc + 1 + address: (memoryArray unsignedLongAt: self esp + 1 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: self esp + 1) type: #return accessor: #eip:) signal!
Item was changed: ----- Method: BochsIA32Alien>>leafRetpcIn: (in category 'accessing-abstract') ----- leafRetpcIn: aMemory + ^aMemory unsignedLongAt: self esp + 1 - self primitiveMemoryOffset! - ^aMemory unsignedLongAt: self esp + 1 bigEndian: false!
Item was changed: ----- Method: BochsIA32Alien>>popWordIn: (in category 'execution') ----- popWordIn: aMemory | sp word | + word := aMemory unsignedLongAt: (sp := self esp) + 1 - self primitiveMemoryOffset. - word := aMemory unsignedLongAt: (sp := self esp) + 1 bigEndian: false. self esp: sp + 4. ^word!
Item was added: + ----- Method: BochsIA32Alien>>primitiveMemoryOffset (in category 'primitives') ----- + primitiveMemoryOffset + "Answer the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap." + <primitive: 'primitiveMemoryOffset' module: 'BochsIA32Plugin' error: ec> + ^self reportPrimitiveFailure!
Item was added: + ----- Method: BochsIA32Alien>>primitiveSetMemoryOffset: (in category 'primitives') ----- + primitiveSetMemoryOffset: memoryOffset + "Set the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap. + Answer the previous value." + <primitive: 'primitiveMemoryOffset' module: 'BochsIA32Plugin' error: ec> + ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsIA32Alien>>pushWord:in: (in category 'execution') ----- pushWord: aValue in: aMemory | sp | sp := (self esp: self esp - 4). + aMemory longAt: sp + 1 - self primitiveMemoryOffset put: aValue bigEndian: false! - aMemory longAt: sp + 1 put: aValue bigEndian: false!
Item was changed: ----- Method: BochsIA32Alien>>retpcIn: (in category 'accessing-abstract') ----- retpcIn: aMemory + ^aMemory unsignedLongAt: self ebp + 5 - self primitiveMemoryOffset! - ^aMemory unsignedLongAt: self ebp + 5 bigEndian: false!
Item was changed: ----- Method: BochsX64Alien>>handleCallFailureAt:in:rex: (in category 'error handling') ----- handleCallFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a call into a ProcessorSimulationTrap signal." | relativeJump | self assert: rexByteOrNil isNil. + relativeJump := memoryArray longAt: pc + 2 - self primitiveMemoryOffset. - relativeJump := memoryArray longAt: pc + 2 bigEndian: false. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 address: (pc + 5 + relativeJump) signedIntToLong64 type: #call) signal!
Item was changed: ----- Method: BochsX64Alien>>handleExecutionPrimitiveFailureIn:minimumAddress: (in category 'error handling') ----- handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "Handle an execution primitive failure. Convert out-of-range call and absolute memory read into register instructions into ProcessorSimulationTrap signals." "self printIntegerRegistersOn: Transcript" "self printRegistersOn: Transcript" + | pc opcode rexByteOrNil | - | pc opcode rexByteOrNil offset | ((pc := self rip) between: minimumAddress and: memoryArray byteSize - 1) ifTrue: + [opcode := memoryArray byteAt: pc + 1 - self primitiveMemoryOffset. - [opcode := memoryArray byteAt: pc + (offset := 1). (opcode bitAnd: 16rF8) = self rexPrefix ifTrue: "skip rex prefix if present" [rexByteOrNil := opcode. + opcode := memoryArray byteAt: pc + 2 - self primitiveMemoryOffset]. - opcode := memoryArray byteAt: pc + (offset := 2)]. ^self perform: (OpcodeExceptionMap at: opcode + 1) with: pc with: memoryArray with: rexByteOrNil]. ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsX64Alien>>handleGroup5FailureAt:in:rex: (in category 'error handling') ----- handleGroup5FailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a group 5 instruction into the relevant ProcessorSimulationTrap signal." | modrmByte getter | self assert: rexByteOrNil isNil. + modrmByte := memoryArray byteAt: pc + 2 - self primitiveMemoryOffset. - modrmByte := memoryArray byteAt: pc + 2. (modrmByte >> 3 bitAnd: 7) caseOf: { [2 "Call Ev"] -> [getter := self registerStateGetters at: (modrmByte bitAnd: 7) + 1. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 2 address: (self perform: getter) type: #call) signal]. [4 "Jump Ev"] -> [getter := self registerStateGetters at: (modrmByte bitAnd: 7) + 1. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 2 address: (self perform: getter) type: #jump) + signal] } + otherwise: [self reportPrimitiveFailure]! - signal] }!
Item was changed: ----- Method: BochsX64Alien>>handleGroup6through10FailureAt:in:rex: (in category 'error handling') ----- handleGroup6through10FailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" + "Convert an execution primitive failure for a group 6 instruction into the relevant ProcessorSimulationTrap signal." - "Convert an execution primitive failure for a group 5 instruction into the relevant ProcessorSimulationTrap signal." | rexByte modrmByte baseReg srcReg | + (((rexByte := memoryArray byteAt: pc + 2 - self primitiveMemoryOffset) bitAnd: 16rF8) = self rexPrefix + and: [(memoryArray byteAt: pc + 3 - self primitiveMemoryOffset) = 16r0F + and: [(memoryArray byteAt: pc + 4 - self primitiveMemoryOffset) = 16rB1]]) ifTrue: + [modrmByte := memoryArray byteAt: pc + 5 - self primitiveMemoryOffset. - (((rexByte := memoryArray byteAt: pc + 2) bitAnd: 16rF8) = self rexPrefix - and: [(memoryArray byteAt: pc + 3) = 16r0F - and: [(memoryArray byteAt: pc + 4) = 16rB1]]) ifTrue: - [modrmByte := memoryArray byteAt: pc + 5. modrmByte >> 6 = 0 ifTrue: "ModRegInd" [srcReg := (modrmByte >> 3 bitAnd: 7) + ((rexByte bitAnd: 4) bitShift: 1). baseReg := (modrmByte bitAnd: 7) + ((rexByte bitAnd: 1) bitShift: 3). ^(CompareAndSwapSimulationTrap pc: pc nextpc: pc + 5 address: (self perform: (self registerStateGetters at: baseReg + 1)) type: #write accessor: (self registerStateSetters at: srcReg + 1)) failedComparisonRegisterAccessor: #rax:; expectedValue: self rax; storedValue: (self perform: (self registerStateGetters at: srcReg + 1)); + signal]]. + self reportPrimitiveFailure! - signal]]!
Item was changed: ----- Method: BochsX64Alien>>handleJmpFailureAt:in:rex: (in category 'error handling') ----- handleJmpFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a jmp into a ProcessorSimulationTrap signal." | relativeJump | self assert: rexByteOrNil isNil. + relativeJump := memoryArray longAt: pc + 2 - self primitiveMemoryOffset. - relativeJump := memoryArray longAt: pc + 2 bigEndian: false. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 address: (pc + 5 + relativeJump) signedIntToLong64 type: #jump) signal!
Item was changed: ----- Method: BochsX64Alien>>handleMovALObFailureAt:in:rex: (in category 'error handling') ----- handleMovALObFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a read into al into a ProcessorSimulationTrap signal." rexByteOrNil ifNotNil: [self assert: rexByteOrNil = 16r48. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 10 + address: (memoryArray unsignedLong64At: pc + 3 - self primitiveMemoryOffset) - address: (memoryArray unsignedLong64At: pc + 3) type: #read accessor: #al:) signal]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 + address: (memoryArray unsignedLongAt: pc + 2 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 2) type: #read accessor: #al:) signal!
Item was changed: ----- Method: BochsX64Alien>>handleMovAXOvFailureAt:in:rex: (in category 'error handling') ----- handleMovAXOvFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a read into rax/eax into a ProcessorSimulationTrap signal." rexByteOrNil ifNotNil: [self assert: rexByteOrNil = 16r48. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 10 + address: (memoryArray unsignedLong64At: pc + 3 - self primitiveMemoryOffset) - address: (memoryArray unsignedLong64At: pc + 3) type: #read accessor: #rax:) signal]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 5 + address: (memoryArray unsignedLongAt: pc + 2 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 2) type: #read accessor: #eax:) signal!
Item was changed: ----- Method: BochsX64Alien>>handleMovEbGbFailureAt:in:rex: (in category 'error handling') ----- handleMovEbGbFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a byte register write into a ProcessorSimulationTrap signal." | modrmByte offset size baseReg srcReg | modrmByte := memoryArray byteAt: pc + 3. (modrmByte bitAnd: 16rC0) caseOf: { + [16r80 "ModRegRegDisp32"] -> [offset := memoryArray unsignedLongAt: pc + 4 - self primitiveMemoryOffset. - [16r80 "ModRegRegDisp32"] -> [offset := memoryArray unsignedLongAt: pc + 4 bigEndian: false. size := 7]. + [16r40 "ModRegRegDisp8"] -> [offset := memoryArray byteAt: pc + 4 - self primitiveMemoryOffset. - [16r40 "ModRegRegDisp8"] -> [offset := memoryArray byteAt: pc + 4. offset > 127 ifTrue: [offset := offset - 256]. size := 4]. [16r0 "ModRegInd"] -> [offset := 0. size := 3]} otherwise: [self reportPrimitiveFailure]. srcReg := (modrmByte >> 3 bitAnd: 7) + ((rexByteOrNil bitAnd: 4) bitShift: 1). baseReg := (modrmByte bitAnd: 7) + ((rexByteOrNil bitAnd: 1) bitShift: 3). ^(ProcessorSimulationTrap pc: pc nextpc: pc + size address: (((self perform: (self registerStateGetters at: baseReg + 1)) + offset) bitAnd: 16rFFFFFFFFFFFFFFFF) type: #write accessor: (#(al cl dl bl spl bpl sil dil r8l r9l r10l r11l r12l r13l r14l r15l) at: srcReg + 1)) signal!
Item was changed: ----- Method: BochsX64Alien>>handleMovEvGvFailureAt:in:rex: (in category 'error handling') ----- handleMovEvGvFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a register write into a ProcessorSimulationTrap signal." | modrmByte getter base offset | self assert: rexByteOrNil notNil. + modrmByte := memoryArray byteAt: pc + 3 - self primitiveMemoryOffset. - modrmByte := memoryArray byteAt: pc + 3. getter := self registerStateGetters at: (modrmByte >> 3 bitAnd: 7) + ((rexByteOrNil bitAnd: 4) << 1) + 1. (modrmByte bitAnd: 16rC7) = 16r5 ifTrue: "ModRegInd & disp32" [^(ProcessorSimulationTrap pc: pc nextpc: pc + 7 + address: (memoryArray unsignedLongAt: pc + 4 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 4 bigEndian: false) type: #write accessor: getter) signal]. (modrmByte bitAnd: 16rC0) = 0 ifTrue: "ModRegInd" [base := self registerStateGetters at: (modrmByte bitAnd: 7) + ((rexByteOrNil bitAnd: 1) << 3) + 1. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 3 address: (self perform: base) type: #write accessor: getter) signal]. (modrmByte bitAnd: 16rC0) = 16r80 ifTrue: "ModRegRegDisp32" + [offset := memoryArray longAt: pc + 4 - self primitiveMemoryOffset. - [offset := memoryArray longAt: pc + 4 bigEndian: false. base := self registerStateGetters at: (modrmByte bitAnd: 7) + ((rexByteOrNil bitAnd: 1) << 3) + 1. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 7 address: (self perform: base) + offset type: #write accessor: getter) signal]. (modrmByte bitAnd: 16rC0) = 16r40 ifTrue: "ModRegRegDisp8" + [offset := memoryArray unsignedByteAt: pc + 4 - self primitiveMemoryOffset. - [offset := memoryArray unsignedByteAt: pc + 4. offset > 127 ifTrue: [offset := offset - 256]. base := self registerStateGetters at: (modrmByte bitAnd: 7) + ((rexByteOrNil bitAnd: 1) << 3) + 1. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 4 address: (self perform: base) + offset type: #write accessor: getter) signal]. ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsX64Alien>>handleMovGbEbFailureAt:in:rex: (in category 'error handling') ----- handleMovGbEbFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a byte register load into a ProcessorSimulationTrap signal." | modrmByte offset size | + modrmByte := memoryArray byteAt: pc + 3 - self primitiveMemoryOffset. - modrmByte := memoryArray byteAt: pc + 3. (modrmByte bitAnd: 16rC0) caseOf: { + [16r80 "ModRegRegDisp32"] -> [offset := memoryArray unsignedLongAt: pc + 4 - self primitiveMemoryOffset. - [16r80 "ModRegRegDisp32"] -> [offset := memoryArray unsignedLongAt: pc + 4 bigEndian: false. size := 7]. [16r40 "ModRegRegDisp8"] -> [offset := memoryArray byteAt: pc + 4. offset > 127 ifTrue: [offset := offset - 256]. size := 4] } otherwise: [self reportPrimitiveFailure]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + size address: (((self perform: (self registerStateGetters at: (modrmByte bitAnd: 7) + ((rexByteOrNil bitAnd: 1) bitShift: 3) + 1)) + offset) bitAnd: 16rFFFFFFFFFFFFFFFF) type: #read accessor: (#(al: cl: dl: bl: spl: bpl: sil: dil: r8l: r9l: r10l: r11l: r12l: r13l: r14l: r15l:) at: ((modrmByte >> 3 bitAnd: 7) + ((rexByteOrNil bitAnd: 4) bitShift: 1) + 1))) signal!
Item was changed: ----- Method: BochsX64Alien>>handleMovGvEbFailureAt:in:rex: (in category 'error handling') ----- handleMovGvEbFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a register load into a ProcessorSimulationTrap signal." | modrmByte mode srcIsSP srcVal dst offset | self shouldBeImplemented. modrmByte := memoryArray byteAt: pc + 3. mode := modrmByte >> 6 bitAnd: 3. srcIsSP := (modrmByte bitAnd: 7) = 4. srcVal := self perform: (#(eax ecx edx ebx esp ebp esi edi) at: (modrmByte bitAnd: 7) + 1). dst := #(eax: ecx: edx: ebx: esp: ebp: esi: edi:) at: ((modrmByte >> 3 bitAnd: 7) + 1). mode = 1 ifTrue: "ModRegRegDisp8" + [offset := memoryArray byteAt: pc + ((srcIsSP ifTrue: [5] ifFalse: [4] "1-relative") - self primitiveMemoryOffset). - [offset := memoryArray byteAt: pc + (srcIsSP ifTrue: [5] ifFalse: [4]). "1-relative" offset > 127 ifTrue: [offset := offset - 256]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + (srcIsSP ifTrue: [5] ifFalse: [4]) address: ((srcVal + offset) bitAnd: 16rFFFFFFFF) type: #read accessor: dst) signal]. mode = 2 ifTrue: "ModRegRegDisp32" + [offset := memoryArray unsignedLongAt: pc + ((srcIsSP ifTrue: [5] ifFalse: [4] "1-relative") - self primitiveMemoryOffset). - [offset := memoryArray unsignedLongAt: pc + (srcIsSP ifTrue: [5] ifFalse: [4]). "1-relative" ^(ProcessorSimulationTrap pc: pc nextpc: pc + (srcIsSP ifTrue: [8] ifFalse: [7]) address: ((srcVal + offset) bitAnd: 16rFFFFFFFF) type: #read accessor: dst) signal]. ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsX64Alien>>handleMovGvEvFailureAt:in:rex: (in category 'error handling') ----- handleMovGvEvFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a register load into a ProcessorSimulationTrap signal." | modrmByte getter setter offset | self assert: rexByteOrNil notNil. + modrmByte := memoryArray byteAt: pc + 3 - self primitiveMemoryOffset. - modrmByte := memoryArray byteAt: pc + 3. setter := self registerStateSetters at: ((modrmByte >> 3 bitAnd: 7) + ((rexByteOrNil bitAnd: 4) << 1) + 1). (modrmByte bitAnd: 16rC7) = 16r5 ifTrue: "ModRegInd & disp32" [^(ProcessorSimulationTrap pc: pc nextpc: pc + 7 + address: (memoryArray unsignedLongAt: pc + 4 - self primitiveMemoryOffset) - address: (memoryArray unsignedLongAt: pc + 4 bigEndian: false) type: #read accessor: setter) signal]. getter := self registerStateGetters at: ((modrmByte bitAnd: 7) + ((rexByteOrNil bitAnd: 1) << 3) + 1). (modrmByte bitAnd: 16rC0) = 16r80 ifTrue: "ModRegRegDisp32" + [offset := memoryArray longAt: pc + 4 - self primitiveMemoryOffset. - [offset := memoryArray longAt: pc + 4 bigEndian: false. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 7 address: (self perform: getter) + offset type: #read accessor: setter) signal]. (modrmByte bitAnd: 16rC0) = 16r40 ifTrue: "ModRegRegDisp8" + [offset := memoryArray byteAt: pc + 4 - self primitiveMemoryOffset. - [offset := memoryArray byteAt: pc + 4. offset > 16r7F ifTrue: [offset := offset - 16r100]. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 4 address: (self perform: getter) + offset type: #read accessor: setter) signal]. (modrmByte bitAnd: 16rC0) = 16r00 ifTrue: "ModRegInd" [^(ProcessorSimulationTrap pc: pc nextpc: pc + 3 address: (self perform: getter) type: #read accessor: setter) signal]. ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsX64Alien>>handleMovObALFailureAt:in:rex: (in category 'error handling') ----- handleMovObALFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a write of al into a ProcessorSimulationTrap signal." self assert: rexByteOrNil = 16r48. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 10 + address: (memoryArray unsignedLong64At: pc + 3 - self primitiveMemoryOffset) - address: (memoryArray unsignedLong64At: pc + 3) type: #write accessor: #al) signal!
Item was changed: ----- Method: BochsX64Alien>>handleMovOvAXFailureAt:in:rex: (in category 'error handling') ----- handleMovOvAXFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a write of rax into a ProcessorSimulationTrap signal." self assert: rexByteOrNil = 16r48. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 10 + address: (memoryArray unsignedLong64At: pc + 3 - self primitiveMemoryOffset) - address: (memoryArray unsignedLong64At: pc + 3) type: #write accessor: #rax) signal!
Item was changed: ----- Method: BochsX64Alien>>handleRetFailureAt:in:rex: (in category 'error handling') ----- handleRetFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "<Integer|nil>" "Convert an execution primitive failure for a ret into a ProcessorSimulationTrap signal." self shouldBeImplemented. ^(ProcessorSimulationTrap pc: pc nextpc: pc + 1 + address: (memoryArray unsignedLong64At: self rsp + 1 - self primitiveMemoryOffset) - address: (memoryArray unsignedLong64At: self rsp + 1) type: #return accessor: #rip:) signal!
Item was changed: ----- Method: BochsX64Alien>>handleTwoByteEscapeFailureAt:in:rex: (in category 'error handling') ----- handleTwoByteEscapeFailureAt: pc in: memoryArray "<Bitmap|ByteArray>" rex: rexByteOrNil "Handle an execution primitive failure for the 0f prefix. Convert failures into ProcessorSimulationTrap signals." "self printIntegerRegistersOn: Transcript" "self printRegistersOn: Transcript" + | opcode | - | opcode offset | "assume 0fh opcode or 0fh rex opcode" + opcode := memoryArray byteAt: pc + (rexByteOrNil ifNil: [2] ifNotNil: [3] "1 relative") - self primitiveMemoryOffset. - offset := rexByteOrNil ifNil: [1] ifNotNil: [2]. - opcode := memoryArray byteAt: pc + offset + 1. ^self perform: (ExtendedOpcodeExceptionMap at: opcode + 1) with: pc with: memoryArray with: rexByteOrNil!
Item was changed: ----- Method: BochsX64Alien>>popWordIn: (in category 'execution') ----- popWordIn: aMemory | sp word | + word := aMemory long64At: (sp := self rsp) + 1 - self primitiveMemoryOffset. - word := aMemory long64At: (sp := self rsp) + 1. self rsp: sp + 8. ^word!
Item was added: + ----- Method: BochsX64Alien>>primitiveMemoryOffset (in category 'primitives') ----- + primitiveMemoryOffset + "Answer the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap." + <primitive: 'primitiveMemoryOffset' module: 'BochsX64Plugin' error: ec> + ^self reportPrimitiveFailure!
Item was added: + ----- Method: BochsX64Alien>>primitiveSetMemoryOffset: (in category 'primitives') ----- + primitiveSetMemoryOffset: memoryOffset + "Set the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap. + Answer the previous value." + <primitive: 'primitiveMemoryOffset' module: 'BochsX64Plugin' error: ec> + ^self reportPrimitiveFailure!
Item was changed: ----- Method: BochsX64Alien>>pushWord:in: (in category 'execution') ----- pushWord: aValue in: aMemory | sp | + sp := self rsp: self rsp - 8. + aMemory long64At: sp + 1 - self primitiveMemoryOffset put: aValue! - sp := (self rsp: self rsp - 8). - aMemory long64At: sp + 1 put: aValue!
Item was changed: ----- Method: BochsX64Alien>>retpcIn: (in category 'accessing-abstract') ----- retpcIn: aMemory + ^aMemory long64At: self rbp + 9 - self primitiveMemoryOffset! - ^aMemory long64At: self rbp + 9!
Item was added: + ----- Method: CogProcessorAlien>>memoryOffset (in category 'Cog API') ----- + memoryOffset + "Answer the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap." + ^self primitiveMemoryOffset!
Item was added: + ----- Method: CogProcessorAlien>>memoryOffset: (in category 'Cog API') ----- + memoryOffset: anInteger + "Set the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap. + Answer the previous value." + ^self primitiveSetMemoryOffset: anInteger!
Item was changed: ----- Method: GdbARMAlien>>handleExecutionPrimitiveFailureIn:minimumAddress: (in category 'error handling') ----- handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" "Handle an execution primitive failure. Convert out-of-range call and absolute memory read into register instructions into ProcessorSimulationTrap signals." "self printRegistersOn: Transcript" | pcOnEntry pc instr | pc := pcOnEntry := self pc. self endCondition = InstructionPrefetchError ifTrue: [pc := self pc: self priorPc].
(pc between: minimumAddress and: memoryArray byteSize - 1) ifTrue: + [instr := memoryArray unsignedLongAt: pc + 1 - self primitiveMemoryOffset. - [instr := memoryArray unsignedLongAt: pc + 1 bigEndian: false.
(self endCondition = InstructionPrefetchError) ifTrue: [^self handleFailingBranch: instr to: pcOnEntry at: pc].
(self instructionIsAnyLoadStore: instr) ifTrue: [^self handleFailingLoadStore: instr at: pc].
(self instructionIsAnyFPArithmetic: instr) ifTrue: [^self handleFailingFPArithmetic: instr at: pc].
^self handleExecutionPrimitiveFailureAt: pc in: memoryArray].
^self reportPrimitiveFailure!
Item was changed: ----- Method: GdbARMAlien>>handleExecutionPrimitiveFailureIn:minimumAddress:code: (in category 'error handling') ----- handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>"code: errorCode "<Integer>" "Handle an execution primitive failure. Convert out-of-range call and absolute memory read into register instructions into ProcessorSimulationTrap signals." "self printRegistersOn: Transcript" | pcOnEntry pc instr | pc := pcOnEntry := self pc. errorCode = InstructionPrefetchError ifTrue: [pc := self pc: self priorPc].
(pc between: minimumAddress and: memoryArray byteSize - 1) ifTrue: + [instr := memoryArray unsignedLongAt: pc + 1 - self primitiveMemoryOffset. - [instr := memoryArray unsignedLongAt: pc + 1 bigEndian: false.
errorCode = InstructionPrefetchError ifTrue: [^self handleFailingBranch: instr to: pcOnEntry at: pc].
(self instructionIsAnyLoadStore: instr) ifTrue: [^self handleFailingLoadStore: instr at: pc].
(self instructionIsAnyFPArithmetic: instr) ifTrue: + [^self handleFailingFPArithmetic: instr at: pc]]. - [^self handleFailingFPArithmetic: instr at: pc].
- ^self handleExecutionPrimitiveFailureAt: pc in: memoryArray]. - ^self reportPrimitiveFailure!
Item was changed: ----- Method: GdbARMAlien>>popWordIn: (in category 'execution') ----- popWordIn: aMemory | sp word | + word := aMemory unsignedLongAt: (sp := self sp) + 1 - self primitiveMemoryOffset. - word := aMemory unsignedLongAt: (sp := self sp) + 1 bigEndian: false. self sp: sp + 4. ^word!
Item was added: + ----- Method: GdbARMAlien>>primitiveMemoryOffset (in category 'primitives') ----- + primitiveMemoryOffset + "Answer the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap." + <primitive: 'primitiveMemoryOffset' module: 'GdbARMPlugin' error: ec> + ^self reportPrimitiveFailure!
Item was added: + ----- Method: GdbARMAlien>>primitiveSetMemoryOffset: (in category 'primitives') ----- + primitiveSetMemoryOffset: memoryOffset + "Set the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap. + Answer the previous value." + <primitive: 'primitiveMemoryOffset' module: 'GdbARMPlugin' error: ec> + ^self reportPrimitiveFailure!
Item was changed: ----- Method: GdbARMAlien>>pushWord:in: (in category 'execution') ----- pushWord: aValue in: aMemory + aMemory longAt: (self sp: self sp - 4) + 1 - self primitiveMemoryOffset put: aValue bigEndian: false! - aMemory longAt: (self sp: self sp - 4) + 1 put: aValue bigEndian: false!
Item was changed: ----- Method: GdbARMAlien>>retpcIn: (in category 'accessing-abstract') ----- retpcIn: aMemory "The return address is on the stack, having been pushed by either simulateCallOf:nextpc:memory: or simulateJumpCallOf:memory:" + ^aMemory unsignedLongAt: self fp + 5 - self primitiveMemoryOffset! - ^aMemory unsignedLongAt: self fp + 5 bigEndian: false!
Item was changed: ----- Method: GdbARMv8Alien class>>initialize (in category 'class initialization') ----- initialize "Initialize the execution failure dispatch table. This is organized around op0 in C4.1 of the Arm ARM. Each tuple is a type and a failure routine, or nil of not needed to be handled as an execution failure." "self initialize" Level0FailureTable := #( "0" nil nil nil nil + "4" (LDST handleFailingLoadStore:at:) - "4" (LDST handleFailingLoadStore:at:in:) "5" nil + "6" (LDST handleFailingLoadStore:at:) - "6" (LDST handleFailingLoadStore:at:in:) "7" nil nil nil + "a" (BR handleFailingBranch:at:) + "b" (BR handleFailingBranch:at:) + "c" (LDST handleFailingLoadStore:at:) - "a" (BR handleFailingBranch:at:in:) - "b" (BR handleFailingBranch:at:in:) - "c" (LDST handleFailingLoadStore:at:in:) "d" nil + "e" (LDST handleFailingLoadStore:at:) - "e" (LDST handleFailingLoadStore:at:in:) nil).
"At least Raspberry Pi 4 running Manjaro allows access to EL1 level system registers... These values are derived from the program in https://android.googlesource.com/kernel/common/+/refs/tags/ASB-2019-03-05_4.... run on a raspberry Pi 4 Model B" ID_AA64ISAR0_EL1 := 16r00010000. ID_AA64ISAR1_EL1 := 16r00000000. ID_AA64MMFR0_EL1 := 16rFF000000. ID_AA64MMFR1_EL1 := 16r00000000. ID_AA64PFR0_EL1 := 16r00000011. ID_AA64PFR1_EL1 := 16r00000000. ID_AA64DFR0_EL1 := 16r00000006. ID_AA64DFR1_EL1 := 16r00000000 !
Item was changed: ----- Method: GdbARMv8Alien>>handleExecutionPrimitiveFailureIn:minimumAddress:code: (in category 'error handling') ----- handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" code: errorCode "<Integer>" "Handle an execution primitive failure. Convert out-of-range call and absolute memory read into register instructions into ProcessorSimulationTrap signals." "self disassembleInstructionAt: self pc In: memoryArray" | instr pc op | pc := self pc. instr := self instr. + "(pc between: minimumAddress and: memoryArray byteSize - 1) ifTrue: + [self assert: instr = (memoryArray unsignedLongAt: pc + 1 - self primitiveGetMemoryOffset)]." - (pc between: minimumAddress and: memoryArray byteSize - 1) ifTrue: - [self assert: instr = (memoryArray unsignedLongAt: pc + 1 bigEndian: false)]. op := instr >> 25 bitAnd: 16rF. (Level0FailureTable at: op + 1) ifNotNil: [:tuple| + ^self perform: (tuple at: 2) with: instr with: pc]. - ^self perform: (tuple at: 2) with: instr with: pc with: memoryArray]. ^self reportPrimitiveFailure!
Item was added: + ----- Method: GdbARMv8Alien>>handleFailingBranch:at: (in category 'error handling') ----- + handleFailingBranch: instruction at: pc + "see C4.1.3 Branches, Exception Generating and System instructions in Arm ARM. + Table C4-4 op1 plus the two top bit of op1" + | opcOp2Op3Op4 op1CRnCRmOp2 | + "self disassembleInstructionAt: self pc In: memoryArray" + (instruction bitShift: -25) = 2r1101011 ifTrue: "Unconditional branch (register) on page C4-262" + [opcOp2Op3Op4 := instruction bitAnd: 2r1111111111111110000011111. + opcOp2Op3Op4 = 2r10111110000000000000000 ifTrue: "RET" + [^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: self lr + type: #return) + signal]. + opcOp2Op3Op4 = 2r1111110000000000000000 ifTrue: "BLR" + [^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: (self perform: (self registerStateGetters at: ((instruction >> 5) bitAnd: 31) + 1)) + type: #call) + signal]. + opcOp2Op3Op4 = 2r0111110000000000000000 ifTrue: "BR" + [^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: (self perform: (self registerStateGetters at: ((instruction >> 5) bitAnd: 31) + 1)) + type: #jump) + signal]]. + instruction = self clrexOpcode ifTrue: + [self pc: pc + 4. + ^self]. + (instruction bitShift: -19) = 2r1101010100111 ifTrue: "MRS Op0=3" + [op1CRnCRmOp2 := instruction bitAnd: 2r1111111111111100000. + "At least Raspberry Pi 4 running Manjaro allows access to ID_AA64ISAR0_EL1" + op1CRnCRmOp2 = 2r11000000000 ifTrue: + [self perform: (self registerStateSetters at: (instruction bitAnd: 31) + 1) with: ID_AA64ISAR0_EL1. + self pc: pc + 4. + ^self]]. + self reportPrimitiveFailure!
Item was removed: - ----- Method: GdbARMv8Alien>>handleFailingBranch:at:in: (in category 'error handling') ----- - handleFailingBranch: instruction at: pc in: memoryArray "<DoubleWordArray|ByteArray>" - "see C4.1.3 Branches, Exception Generating and System instructions in Arm ARM. - Table C4-4 op1 plus the two top bit of op1" - | opcOp2Op3Op4 op1CRnCRmOp2 | - "self disassembleInstructionAt: self pc In: memoryArray" - (instruction bitShift: -25) = 2r1101011 ifTrue: "Unconditional branch (register) on page C4-262" - [opcOp2Op3Op4 := instruction bitAnd: 2r1111111111111110000011111. - opcOp2Op3Op4 = 2r10111110000000000000000 ifTrue: "RET" - [^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: self lr - type: #return) - signal]. - opcOp2Op3Op4 = 2r1111110000000000000000 ifTrue: "BLR" - [^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: (self perform: (self registerStateGetters at: ((instruction >> 5) bitAnd: 31) + 1)) - type: #call) - signal]. - opcOp2Op3Op4 = 2r0111110000000000000000 ifTrue: "BR" - [^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: (self perform: (self registerStateGetters at: ((instruction >> 5) bitAnd: 31) + 1)) - type: #jump) - signal]]. - instruction = self clrexOpcode ifTrue: - [self pc: pc + 4. - ^self]. - (instruction bitShift: -19) = 2r1101010100111 ifTrue: "MRS Op0=3" - [op1CRnCRmOp2 := instruction bitAnd: 2r1111111111111100000. - "At least Raspberry Pi 4 running Manjaro allows access to ID_AA64ISAR0_EL1" - op1CRnCRmOp2 = 2r11000000000 ifTrue: - [self perform: (self registerStateSetters at: (instruction bitAnd: 31) + 1) with: ID_AA64ISAR0_EL1. - self pc: pc + 4. - ^self]]. - self reportPrimitiveFailure!
Item was added: + ----- Method: GdbARMv8Alien>>handleFailingLoadStore:at: (in category 'error handling') ----- + handleFailingLoadStore: instruction at: pc + "C4.1.4 Loads and Stores C4-266 + This section describes the encoding of the Loads and Stores group. The encodings in this section are decoded from A64 instruction set encoding on page C4-252. + + Table C4-5 Encoding table for the Loads and Stores group + + op0 31:28 1 op1 26 0 op2 24:23 x op3 21:16 x op4 11:10 + + op0 op2 op3 op4 + xx11 0x 0xxxxx 00 Load/store register (unscaled immediate) on page C4-283 + xx11 0x 0xxxxx 01 Load/store register (immediate post-indexed) on page C4-284 + xx11 0x 0xxxxx 10 Load/store register (unprivileged) on page C4-286 + xx11 0x 0xxxxx 11 Load/store register (immediate pre-indexed) on page C4-286 + xx11 0x 1xxxxx 00 Atomic memory operations on page C4-288 + xx11 0x 1xxxxx 10 Load/store register (register offset) on page C4-295 + xx11 0x 1xxxxx x1 Load/store register (pac) on page C4-297 + xx11 1x 1xxxxx - Load/store register (unsigned immediate) on page C4-297 + + Load/store exclusive table starts on page C4-277 (. implies a bit) + |size..|0 0 1 0 0 0|o2.|L.|o1.|Rs.....|o0.|Rt2.....|Rn.....|Rt.....| + o2 = bit 23, L=bit 22, o1 = bit 21, o0 = bit 15" + + | op0op2 size op4 rm rn rt opc v offsetFromImm addr shift | + "self disassembleInstructionAt: self pc In: memoryArray" + size := instruction bitShift: -30. + opc := (instruction bitShift: -22) bitAnd: 3. + op4 := (instruction bitShift: -10) bitAnd: 3. + rn := (instruction bitShift: -5) bitAnd: 31. + rt := instruction bitAnd: 31. + (rn = 31 and: [self sp anyMask: 15]) ifTrue: + [self reportStackAlignmentVolation]. + "op0 = xx11 op2 = 0x" + (op0op2 := (instruction bitShift: -23) bitAnd: 2r1100010) = 2r1100000 ifFalse: + [offsetFromImm := ARMv8A64Opcodes extractOffsetFromLoadStore: instruction. + (v := instruction >> 26 bitAnd: 1) = 0 ifFalse: [self halt]. + addr := (self perform: (self registerStateGetters at: rn + 1)) + offsetFromImm. + op0op2 = 2r1100010 ifTrue: "Load/store register (unsigned immediate) on page C4-297" + [^(opc = 0 + ifTrue: + [ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #write + accessor: ((self registerStateGettersForSizes: size) at: rt + 1)] + ifFalse: + [ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #read + accessor: ((self registerStateSettersForSizes: size) at: rt + 1)]) + signal]. + op0op2 = 2r1000010 ifTrue: "Load/store register pair (signed immediate) on page C4-282" + [| rt2 | + rt2 := (instruction bitShift: -10) bitAnd: 31. + ^opc = 0 + ifTrue: + [(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #write + accessor: ((self registerStateGettersForSizes: size + 1) at: rt + 1)) + signal. + (ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + 8 + type: #write + accessor: ((self registerStateGettersForSizes: size + 1) at: rt2 + 1)) + signal] + ifFalse: + [(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #read + accessor: ((self registerStateSettersForSizes: size + 1) at: rt + 1)) + signal. + (ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + 8 + type: #read + accessor: ((self registerStateSettersForSizes: size + 1) at: rt2 + 1)) + signal]]. + + op0op2 = 0 ifTrue: "LDAXR/STLXR register on page C4-279" + [| result rs | + self assert: size = 3. + opc = 1 ifTrue: + [^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #read + accessor: (self registerStateSetters at: rt + 1)) signal]. + opc = 0 ifTrue: + [result := (ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #write + accessor: (self registerStateGetters at: rt + 1)) signal. + rs := instruction >> 16 bitAnd: 31. + "For now assume the write succeeded..." + self perform: ((self registerStateSettersForSizes: 2) at: rs + 1) + with: 0. + ^result]]]. + + ((instruction bitShift: -21) noMask: 1) ifTrue: "op3 = 0xxxxx" + [offsetFromImm := ((instruction bitShift: -12) bitAnd: 16r1FF) bitShift: size. + opc = 0 ifTrue:"C4-286 opc = 0 => store" + [self assert: size = 3. + ^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: (self perform: (self registerStateGetters at: rn + 1)) + offsetFromImm + type: #write + accessor: (self registerStateGetters at: rt + 1)) + signal]. + opc = 1 ifTrue: + [^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: (self perform: (self registerStateGetters at: rn + 1)) + offsetFromImm + type: #read + accessor: ((self registerStateSettersForSizes: size) at: rt + 1)) + signal]. + self halt: 'op3 = 0xxxxx opc > 1']. + + "op0 op2 op3 op4 + xx11 0x 1xxxxx 10 Load/store register (register offset) on page C4-295 (296/297)" + + v := instruction >> 26 bitAnd: 1. + rm := instruction >> 16 bitAnd: 31. + shift := instruction anyMask: 1 << 12. + (size = 3 and: [v = 0]) ifTrue: + [addr := (self perform: (self registerStateGetters at: rn + 1)) + + (shift + ifTrue: [(self perform: (self registerStateGetters at: rm + 1)) << size] + ifFalse: [self perform: (self registerStateGetters at: rm + 1)]). + opc = 0 ifTrue: "STR (register) - 64-bit variant on page C6-1242" + [^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #write + accessor: (self registerStateGetters at: rt + 1)) + signal]. + opc = 1 ifTrue: "LDR (register) - 64-bit variant on page C6-981" + [^(ProcessorSimulationTrap + pc: pc + nextpc: pc + 4 + address: addr + type: #read + accessor: (self registerStateSetters at: rt + 1)) + signal]. + (opc = 3 and: [instruction >> 10 allMask: 63]) ifTrue: "CASAL C4-278/C6-829" + [^(CompareAndSwapSimulationTrap + pc: pc + nextpc: pc + 4 + address: (self perform: (self registerStateGetters at: rn + 1)) + type: #write + accessor: (self registerStateSetters at: rm + 1)) + expectedValue: (self perform: (self registerStateGetters at: rm + 1)); + storedValue: (self perform: (self registerStateGetters at: rt + 1)); + signal]. + self halt: 'op3 = 1xxxxx opc > 1']. + self halt: 'op3 = 1xxxxx size ~= 3'!
Item was removed: - ----- Method: GdbARMv8Alien>>handleFailingLoadStore:at:in: (in category 'error handling') ----- - handleFailingLoadStore: instruction at: pc in: memoryArray "<DoubleWordArray|ByteArray>" - "C4.1.4 Loads and Stores C4-266 - This section describes the encoding of the Loads and Stores group. The encodings in this section are decoded from A64 instruction set encoding on page C4-252. - - Table C4-5 Encoding table for the Loads and Stores group - - op0 31:28 1 op1 26 0 op2 24:23 x op3 21:16 x op4 11:10 - - op0 op2 op3 op4 - xx11 0x 0xxxxx 00 Load/store register (unscaled immediate) on page C4-283 - xx11 0x 0xxxxx 01 Load/store register (immediate post-indexed) on page C4-284 - xx11 0x 0xxxxx 10 Load/store register (unprivileged) on page C4-286 - xx11 0x 0xxxxx 11 Load/store register (immediate pre-indexed) on page C4-286 - xx11 0x 1xxxxx 00 Atomic memory operations on page C4-288 - xx11 0x 1xxxxx 10 Load/store register (register offset) on page C4-295 - xx11 0x 1xxxxx x1 Load/store register (pac) on page C4-297 - xx11 1x 1xxxxx - Load/store register (unsigned immediate) on page C4-297 - - Load/store exclusive table starts on page C4-277 (. implies a bit) - |size..|0 0 1 0 0 0|o2.|L.|o1.|Rs.....|o0.|Rt2.....|Rn.....|Rt.....| - o2 = bit 23, L=bit 22, o1 = bit 21, o0 = bit 15" - - | op0op2 size op4 rm rn rt opc v offsetFromImm addr shift | - "self disassembleInstructionAt: self pc In: memoryArray" - size := instruction bitShift: -30. - opc := (instruction bitShift: -22) bitAnd: 3. - op4 := (instruction bitShift: -10) bitAnd: 3. - rn := (instruction bitShift: -5) bitAnd: 31. - rt := instruction bitAnd: 31. - (rn = 31 and: [self sp anyMask: 15]) ifTrue: - [self reportStackAlignmentVolation]. - "op0 = xx11 op2 = 0x" - (op0op2 := (instruction bitShift: -23) bitAnd: 2r1100010) = 2r1100000 ifFalse: - [offsetFromImm := ARMv8A64Opcodes extractOffsetFromLoadStore: instruction. - (v := instruction >> 26 bitAnd: 1) = 0 ifFalse: [self halt]. - addr := (self perform: (self registerStateGetters at: rn + 1)) + offsetFromImm. - op0op2 = 2r1100010 ifTrue: "Load/store register (unsigned immediate) on page C4-297" - [^(opc = 0 - ifTrue: - [ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #write - accessor: ((self registerStateGettersForSizes: size) at: rt + 1)] - ifFalse: - [ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #read - accessor: ((self registerStateSettersForSizes: size) at: rt + 1)]) - signal]. - op0op2 = 2r1000010 ifTrue: "Load/store register pair (signed immediate) on page C4-282" - [| rt2 | - rt2 := (instruction bitShift: -10) bitAnd: 31. - ^opc = 0 - ifTrue: - [(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #write - accessor: ((self registerStateGettersForSizes: size + 1) at: rt + 1)) - signal. - (ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr + 8 - type: #write - accessor: ((self registerStateGettersForSizes: size + 1) at: rt2 + 1)) - signal] - ifFalse: - [(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #read - accessor: ((self registerStateSettersForSizes: size + 1) at: rt + 1)) - signal. - (ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr + 8 - type: #read - accessor: ((self registerStateSettersForSizes: size + 1) at: rt2 + 1)) - signal]]. - - op0op2 = 0 ifTrue: "LDAXR/STLXR register on page C4-279" - [| result rs | - self assert: size = 3. - opc = 1 ifTrue: - [^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #read - accessor: (self registerStateSetters at: rt + 1)) signal]. - opc = 0 ifTrue: - [result := (ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #write - accessor: (self registerStateGetters at: rt + 1)) signal. - rs := instruction >> 16 bitAnd: 31. - "For now assume the write succeeded..." - self perform: ((self registerStateSettersForSizes: 2) at: rs + 1) - with: 0. - ^result]]]. - - ((instruction bitShift: -21) noMask: 1) ifTrue: "op3 = 0xxxxx" - [offsetFromImm := ((instruction bitShift: -12) bitAnd: 16r1FF) bitShift: size. - opc = 0 ifTrue:"C4-286 opc = 0 => store" - [self assert: size = 3. - ^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: (self perform: (self registerStateGetters at: rn + 1)) + offsetFromImm - type: #write - accessor: (self registerStateGetters at: rt + 1)) - signal]. - opc = 1 ifTrue: - [^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: (self perform: (self registerStateGetters at: rn + 1)) + offsetFromImm - type: #read - accessor: ((self registerStateSettersForSizes: size) at: rt + 1)) - signal]. - self halt: 'op3 = 0xxxxx opc > 1']. - - "op0 op2 op3 op4 - xx11 0x 1xxxxx 10 Load/store register (register offset) on page C4-295 (296/297)" - - v := instruction >> 26 bitAnd: 1. - rm := instruction >> 16 bitAnd: 31. - shift := instruction anyMask: 1 << 12. - (size = 3 and: [v = 0]) ifTrue: - [addr := (self perform: (self registerStateGetters at: rn + 1)) - + (shift - ifTrue: [(self perform: (self registerStateGetters at: rm + 1)) << size] - ifFalse: [self perform: (self registerStateGetters at: rm + 1)]). - opc = 0 ifTrue: "STR (register) - 64-bit variant on page C6-1242" - [^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #write - accessor: (self registerStateGetters at: rt + 1)) - signal]. - opc = 1 ifTrue: "LDR (register) - 64-bit variant on page C6-981" - [^(ProcessorSimulationTrap - pc: pc - nextpc: pc + 4 - address: addr - type: #read - accessor: (self registerStateSetters at: rt + 1)) - signal]. - (opc = 3 and: [instruction >> 10 allMask: 63]) ifTrue: "CASAL C4-278/C6-829" - [^(CompareAndSwapSimulationTrap - pc: pc - nextpc: pc + 4 - address: (self perform: (self registerStateGetters at: rn + 1)) - type: #write - accessor: (self registerStateSetters at: rm + 1)) - expectedValue: (self perform: (self registerStateGetters at: rm + 1)); - storedValue: (self perform: (self registerStateGetters at: rt + 1)); - signal]. - self halt: 'op3 = 1xxxxx opc > 1']. - self halt: 'op3 = 1xxxxx size ~= 3'!
Item was changed: ----- Method: GdbARMv8Alien>>popWordIn: (in category 'execution') ----- popWordIn: aMemory | sp word | + word := aMemory long64At: (sp := self sp) + 1 - self primitiveMemoryOffset. - word := aMemory long64At: (sp := self sp) + 1. self sp: sp + 8. ^word!
Item was added: + ----- Method: GdbARMv8Alien>>primitiveMemoryOffset (in category 'primitives') ----- + primitiveMemoryOffset + "Answer the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap." + <primitive: 'primitiveMemoryOffset' module: 'GdbARMv8Plugin' error: ec> + ^self reportPrimitiveFailure!
Item was added: + ----- Method: GdbARMv8Alien>>primitiveSetMemoryOffset: (in category 'primitives') ----- + primitiveSetMemoryOffset: memoryOffset + "Set the memory offset. This may be non-zero to adapt to the SpurMemoryManager + simulators discarding the first work of memory to implement a null pointer trap. + Answer the previous value." + <primitive: 'primitiveMemoryOffset' module: 'GdbARMv8Plugin' error: ec> + ^self reportPrimitiveFailure!
Item was changed: ----- Method: GdbARMv8Alien>>pushPair:and:in: (in category 'execution') ----- pushPair: aValue and: bValue in: aMemory | sp | sp := self sp. self assert: (sp noMask: 15). aMemory + unsignedLong64At: sp - 8 + 1 - self primitiveMemoryOffset put: aValue; + unsignedLong64At: sp - 16 + 1 - self primitiveMemoryOffset put: bValue. - unsignedLong64At: sp - 8 + 1 put: aValue; - unsignedLong64At: sp - 16 + 1 put: bValue. ^self sp: sp - 16!
Item was changed: ----- Method: GdbARMv8Alien>>pushWord:in: (in category 'execution') ----- pushWord: aValue in: aMemory self assert: (self sp noMask: 15). + aMemory unsignedLong64At: (self sp: self sp - 8) + 1 - self primitiveMemoryOffset put: aValue! - aMemory unsignedLong64At: (self sp: self sp - 8) + 1 put: aValue!
Item was changed: ----- Method: GdbARMv8Alien>>retpcIn: (in category 'accessing-abstract') ----- retpcIn: aMemory "The return address is on the stack, having been pushed by either simulateCallOf:nextpc:memory: or simulateJumpCallOf:memory:" + ^aMemory long64At: self fp + 9 - self primitiveMemoryOffset! - ^aMemory long64At: self fp + 9!
Item was added: + ----- Method: GdbARMv8Alien64>>handleExecutionPrimitiveFailureIn:minimumAddress:code: (in category 'error handling') ----- + handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" code: errorCode "<Integer>" + "Handle an execution primitive failure. Convert out-of-range call and absolute + memory read into register instructions into ProcessorSimulationTrap signals." + "self disassembleInstructionAt: self pc In: memoryArray" + | instr pc op | + pc := self pc. + instr := self instr. + "(pc between: minimumAddress and: memoryArray byteSize - 1) ifTrue: + [self assert: instr = (memoryArray unsignedLongAt: pc + 1 - self primitiveGetMemoryOffset)]." + op := instr >> 25 bitAnd: 16rF. + (Level0FailureTable at: op + 1) ifNotNil: + [:tuple| + ^self perform: (tuple at: 2) with: instr with: pc]. + ^self reportPrimitiveFailure!
Item was changed: ----- Method: MIPSSimulator>>popWordIn: (in category 'processor api') ----- popWordIn: aMemory | sp word | + word := aMemory unsignedLongAt: (sp := self sp) + 1 - self memoryOffset. - word := aMemory unsignedLongAt: (sp := self sp) + 1 bigEndian: false. self sp: sp + 4. ^word!
Item was changed: ----- Method: MIPSSimulator>>pushWord:in: (in category 'processor api') ----- pushWord: aValue in: aMemory + aMemory longAt: (self sp: self sp - 4) + 1 - self memoryOffset put: aValue bigEndian: false! - aMemory longAt: (self sp: self sp - 4) + 1 put: aValue bigEndian: false!
vm-dev@lists.squeakfoundation.org