Hi All,
At the moment I'm spending pretty much all of my working time tracking
down VM crashes. It sounds like there may be others working on the same
issue (Guille?, Pablo?), if so it would be good to be able to exchange
notes and hopefully reach a resolution a little earlier.
So my status...
I'm currently focusing on two corruptions that I've seen:
1. Frame Pointers aren't being updated when the receiver or rcvr/clsr
they point to is moved during scavenging / compaction.
2. The current frame pointer (framePointer) contains an address that is
in a free stack page.
I'm doing all the investigation using a Pharo minimal image, so there's
no FreeType, and from what I've seen FFI isn't being used.
The script I'm using to reproduce the crash is at:
https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/444#issuecomment-5…
(the good part about this is that even the memory addresses are
consistent across runs, so it is highly reproducible).
For the Frame Pointers not being updated, what I'm seeing is that after
a scavenge has finished copying all the referenced objects, but before
the survivor spaces are exchanged, the call stack looks like:
(gdb) call printCallStack()
0x7ffffffe3f70 I SessionManager>launchSnapshot:andQuit: 0x1508860:
a(n) SessionManager
0x7ffffffe3fe0 I [] in SessionManager>snapshot:andQuit: 0x1508860:
a(n) SessionManager
0x7ffffffe4020 I [] in INVALID RECEIVER>newProcess 0x118a728
0x118a728 is a forwarded object to 0x488fca0 of slot size 7
hdr8 .....
Once the survivor spaces have been exchanged:
(gdb) call printCallStack()
0x7ffffffe3f70 I SessionManager>launchSnapshot:andQuit: 0x1508860:
a(n) SessionManager
0x7ffffffe3fe0 I [] in SessionManager>snapshot:andQuit: 0x1508860:
a(n) SessionManager
0x7ffffffe4020 I [] in INVALID RECEIVER>newProcess 0x118a728 is in new space
For the framePointer containing an address in a free stack page: adding
a check during the scavenge shows that the framePointer is in a free
page.
I'm assuming it is never valid for the framePointer to be in a free
stack page, and that the receiver and rcvr/clsr should never be in new
space. If my assumptions are wrong please let me know.
If you'd like any more information, please let me know.
Thanks,
Alistair
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: d1cdad3d1ca0d7409d6c02e7531b4b43f3d98d38
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/d1cdad3d1ca0d7409d…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2019-11-24 (Sun, 24 Nov 2019)
Changed paths:
M src/plugins/BochsIA32Plugin/BochsIA32Plugin.c
M src/plugins/BochsX64Plugin/BochsX64Plugin.c
M src/plugins/GdbARMPlugin/GdbARMPlugin.c
M src/plugins/GdbARMv8Plugin/GdbARMv8Plugin.c
Log Message:
-----------
Generate the processor plugins with a clean version stamp.
[ci skip]
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 4386f0f9783c8a445cf08d85b2480fb62be715c9
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/4386f0f9783c8a445c…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2019-11-24 (Sun, 24 Nov 2019)
Changed paths:
M platforms/Cross/plugins/GdbARMPlugin/GdbARMPlugin.h
M platforms/Cross/plugins/GdbARMPlugin/sqGdbARMPlugin.c
M processors/ARM/exploration64/printcpuctrl.c
M processors/ARM/gdb-8.3.1/sim/arm/armulmem.c
Log Message:
-----------
Fix a necessary change in processors/ARM/gdb-8.3.1/sim/arm/armulmem.c now that
there is only one kind of MemoryBOundsError (no Read & Write variants).
Add access for the instr field to ARM/exploration64/printcpuctrl.c.
Change runOnCPU in GdbARMPlugin so that the cast is not necessary and we can
directly dereference fields in cpu. Fix minor slips in GdbARMPlugin.h.
[ci skip]
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2592.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2592
Author: eem
Time: 24 November 2019, 7:31:01.460535 pm
UUID: 760ff6d7-453c-4ba2-a154-ca5e68ecc0ec
Ancestors: VMMaker.oscog-tpr.2591
Fix a bogus assert fail in cloning an OS or FFI error object on failing a primitive. On Spur we shouldn't check for a known class index, as a PrimitiveError does not have a known class.
=============== Diff against VMMaker.oscog-tpr.2591 ===============
Item was added:
+ ----- Method: SpurMemoryManager>>eeInstantiateAnySmallClassIndex:format:numSlots: (in category 'instantiation') -----
+ eeInstantiateAnySmallClassIndex: classIndex format: objFormat numSlots: numSlots
+ "Instantiate a small instance of a class. ee stands for execution engine and
+ implies that this allocation will *NOT* cause a GC. small implies the object will have
+ less than 255 slots. N.B. the instantiated object IS NOT FILLED and must be completed
+ before returning it to Smalltalk. Since this call is used in routines that do just that we
+ are safe. Break this rule and die in GC. Result is guaranteed to be young."
+ <inline: true>
+ self assert: (numSlots >= 0 and: [classIndex ~= 0 and: [(self classAtIndex: classIndex) ~= nilObj]]).
+ self assert: (objFormat < self firstByteFormat
+ ifTrue: [objFormat]
+ ifFalse: [objFormat bitAnd: self byteFormatMask])
+ = (self instSpecOfClass: (self classAtIndex: classIndex)).
+ ^self allocateSmallNewSpaceSlots: numSlots format: objFormat classIndex: classIndex!
Item was changed:
----- Method: StackInterpreter>>cloneOSErrorObj:numSlots: (in category 'message sending') -----
cloneOSErrorObj: errObj numSlots: numSlots
"If errObj is a pointer object with at least two slots, then answer a clone
of the error object with the second slot set to the value of osErrorCode,
and if an PrimErrFFIException, then the third slow with the exceptionPC."
| clone |
<inline: true>
clone := objectMemory hasSpurMemoryManagerAPI
ifTrue: [objectMemory
+ eeInstantiateAnySmallClassIndex: (objectMemory classIndexOf: errObj)
- eeInstantiateSmallClassIndex: (objectMemory classIndexOf: errObj)
format: objectMemory nonIndexablePointerFormat
numSlots: numSlots]
ifFalse: [objectMemory
eeInstantiateSmallClass: (objectMemory fetchClassOfNonImm: errObj)
numSlots: numSlots].
0 to: numSlots - 1 do:
[:i| objectMemory
storePointerUnchecked: i
ofObject: clone
withValue: (objectMemory fetchPointer: i ofObject: errObj)].
(numSlots > 2
and: [primFailCode = PrimErrFFIException])
ifTrue:
[objectMemory
storePointerUnchecked: 1
ofObject: clone
withValue: (self positive64BitIntegerFor: (self cCoerceSimple: osErrorCode to: #usqLong));
storePointerUnchecked: 2
ofObject: clone
withValue: (self positiveMachineIntegerFor: exceptionPC)]
ifFalse:
[objectMemory
storePointerUnchecked: 1
ofObject: clone
withValue: (self signed64BitIntegerFor: osErrorCode)].
^clone!
tim Rowledge uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-tpr.2591.mcz
==================== Summary ====================
Name: VMMaker.oscog-tpr.2591
Author: tpr
Time: 24 November 2019, 11:43:59.349144 am
UUID: ff381407-add6-4400-9056-25ecc797f78e
Ancestors: VMMaker.oscog-eem.2590
Fill in some simple bits, extend comments to refer to ARM doc etc.
Add condition codes to class vars; maybe better in the opcodes pool?
=============== Diff against VMMaker.oscog-eem.2590 ===============
Item was changed:
CogAbstractInstruction subclass: #CogARMv8Compiler
instanceVariableNames: ''
+ classVariableNames: 'AL CC CS D0 D1 D10 D11 D12 D13 D14 D15 D16 D17 D18 D19 D2 D20 D21 D22 D23 D24 D25 D26 D27 D28 D29 D3 D30 D31 D4 D5 D6 D7 D8 D9 EQ GE GT HI LE LS LT MI NE PL R0 R1 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R2 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 R3 R30 R31 R4 R5 R6 R7 R8 R9 VC VS'
- classVariableNames: 'D0 D1 D10 D11 D12 D13 D14 D15 D16 D17 D18 D19 D2 D20 D21 D22 D23 D24 D25 D26 D27 D28 D29 D3 D30 D31 D4 D5 D6 D7 D8 D9 R0 R1 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R2 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 R3 R30 R31 R4 R5 R6 R7 R8 R9'
poolDictionaries: 'ARMv8A64Opcodes'
category: 'VMMaker-JIT'!
Item was added:
+ ----- Method: CogARMv8Compiler class>>ISA (in category 'translation') -----
+ ISA
+ "Answer the name of the ISA the receiver implements."
+ ^#ARMv8!
Item was added:
+ ----- Method: CogARMv8Compiler class>>identifyingPredefinedMacros (in category 'translation') -----
+ identifyingPredefinedMacros
+ "currently guesswork but we have to have something here"
+ ^#('__ARM_ARCH_8__' '__arm__' '__arm64__' 'ARM64' )!
Item was changed:
----- Method: CogARMv8Compiler class>>initialize (in category 'class initialization') -----
initialize
+ "Initialize various ARM64 instruction-related constants."
"self initialize"
+ "main registers; a minor complication in reading the doc.
+ ARM refer to the 64bit registers as X0...30 and use R0...30 to refer to the 32bit lower halves.They also use a whole suite of names for the floating point/SIMD registers. See ARMARM DDI0487 B1.2.1 etc for the gory details.
+ Note that R30 (yes, yes, X30) is used as the link register and as such is not really a general purpose register.
+ Also note that R31 (named XZR in ARM doc) is a pseudo-register that always reads as 0 and writes to /dev/null.
+ And note that unlike the ARM32, there is no general purpose register for either the PC or SP; a big difference. See ARMARM DDI0487 C1.2.5. wrt to both issues.
+
+ We will stick with R0...30 to refer to the 64 bit general regs and D0...31 (note the extra reg here!!) for the FP/SIMD regs"
#( (D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 D14 D15 D16 D17 D18 D19 D20 D21 D22 D23 D24 D25 D26 D27 D28 D29 D30 D31)
(R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 R30 R31)) do:
[:classVarNames|
classVarNames doWithIndex:
[:k :v|
+ CogARMv8Compiler classPool at: k put: v - 1]].
+
+ "Condition Codes. Note that cc=16rF is mapped back to AL in AARCH64. Generally it shouldn't be used"
+ "Perhaps have these in the ARMv8A64Opcodes pool?"
+ EQ := 0.
+ NE := 1.
+ CS := 2.
+ CC := 3.
+ MI := 4.
+ PL := 5.
+ VS := 6.
+ VC := 7.
+ HI := 8.
+ LS := 9.
+ GE := 10.
+ LT := 11.
+ GT := 12.
+ LE := 13.
+ AL := 14.!
- CogARMv8Compiler classPool at: k put: v - 1]]!
Item was added:
+ ----- Method: CogARMv8Compiler class>>machineCodeDeclaration (in category 'translation') -----
+ machineCodeDeclaration
+ "Answer the declaration for the machineCode array.
+ AARCH64 instructions are 32-bits in length."
+ ^{#'unsigned int'. '[', self basicNew machineCodeWords printString, ']'}!
Item was added:
+ ----- Method: CogARMv8Compiler class>>wordSize (in category 'translation') -----
+ wordSize
+ "This is a 64-bit ISA"
+ ^8!
Item was added:
+ ----- Method: CogARMv8Compiler>>hasLinkRegister (in category 'testing') -----
+ hasLinkRegister
+ ^true "lr"!
Item was added:
+ ----- Method: CogARMv8Compiler>>hasThreeAddressArithmetic (in category 'testing') -----
+ hasThreeAddressArithmetic
+ "Answer if the receiver supports three-address arithmetic instructions (currently only AndCqRR)"
+ ^true!
Item was added:
+ ----- Method: CogARMv8Compiler>>isBigEndian (in category 'testing') -----
+ isBigEndian
+ ^false!
Item was added:
+ ----- Method: CogARMv8Compiler>>machineCodeAt: (in category 'accessing') -----
+ machineCodeAt: anOffset
+ "read aWord from machineCode, with little endian"
+ <inline: true>
+ ^machineCode at: anOffset // 4!
Item was added:
+ ----- Method: CogARMv8Compiler>>machineCodeAt:put: (in category 'accessing') -----
+ machineCodeAt: anOffset put: aWord
+ "add aWord to machineCode, with little endian"
+ <inline: true>
+ machineCode at: anOffset // 4 put: aWord!
Item was added:
+ ----- Method: CogARMv8Compiler>>machineCodeBytes (in category 'generate machine code') -----
+ machineCodeBytes
+ "Answer the maximum number of bytes of machine code generated for any abstract instruction.
+ e.g. CmpCwR =>
+ mov R3, #<addressByte1>, 12
+ orr R3, R3, #<addressByte2>, 8
+ orr R3, R3, #<addressByte3>, 4
+ orr R3, R3, #<addressByte4>, 0
+ cmp R?, R3
+ Likely to be quite different for AARCH64"
+ ^20!
Item was added:
+ ----- Method: CogARMv8Compiler>>machineCodeWords (in category 'generate machine code') -----
+ machineCodeWords
+ "Answer the maximum number of words of machine code generated for any abstract instruction.
+ e.g. CmpCwR =>
+ mov R3, #<addressByte1>, 12
+ orr R3, R3, #<addressByte2>, 8
+ orr R3, R3, #<addressByte3>, 4
+ orr R3, R3, #<addressByte4>, 0
+ cmp R?, R3
+ Likely to be quite different for AARCH64"
+ ^self machineCodeBytes// 4!
Item was changed:
----- Method: CogAbstractInstruction>>hasPCRegister (in category 'testing') -----
hasPCRegister
+ "Answer if the processor has a generally addressable pc register, such as the ARM32.
- "Answer if the processor has a generally addressable pc register, such as the ARM.
On such processors we can execute jumping to pop top of stack by popping into
+ the pc register.
+ Note that this is not a generic RISC feature. The PowerPC does not
+ allow one to pop into the pc for example, and now the AARCH64 ARM works the same way.
+ So by default, answer false."
- the pc register. Note that this is not a generic RISC feature. The PowerPC does not
- allow one to pop into the pc for example. So by default, answer false."
^false!
tim Rowledge uploaded a new version of CogPools-ISAs to project VM Maker:
http://source.squeak.org/VMMaker/CogPools-ISAs-tpr.2.mcz
==================== Summary ====================
Name: CogPools-ISAs-tpr.2
Author: tpr
Time: 24 November 2019, 11:42:20.745973 am
UUID: 0c4c8a3e-cc66-4760-8012-fdf3fea328b6
Ancestors: CogPools-ISAs-eem.1
fix trivial spilling mistook because CDO. Which is OCD but with the the letters in the CORRECT DAMN ORDER
=============== Diff against CogPools-ISAs-eem.1 ===============
Item was changed:
SharedPool subclass: #ARMv8A64Opcodes
instanceVariableNames: ''
classVariableNames: 'NOP RET'
poolDictionaries: ''
category: 'CogPools-ISAs'!
+ !ARMv8A64Opcodes commentStamp: 'tpr 11/24/2019 11:35' prior: 0!
+ ARMv8A64Opcodes is a pool of named constants for the A64 instruction set in the ARMv8 64-bit instruction set architecture. It does not define A32 & T32 instruction sets.!
- !ARMv8A64Opcodes commentStamp: 'eem 11/24/2019 07:26' prior: 0!
- ARMv8A64Opcodes is a pool of named constants for the A64 instructiin set in the ARMv8 64-bit instruction set architecture. It does not define A32 & T32 instruction sets.!
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2590.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2590
Author: eem
Time: 24 November 2019, 7:49:27.903788 am
UUID: f58fa0fe-e844-47b7-9889-0db0484adc5d
Ancestors: VMMaker.oscog-eem.2589
Add the compiler for the ARMv8 A64 backend.
Correct a typo. Add Integer>>binary as a convenience.
=============== Diff against VMMaker.oscog-eem.2589 ===============
Item was added:
+ CogAbstractInstruction subclass: #CogARMv8Compiler
+ instanceVariableNames: ''
+ classVariableNames: 'D0 D1 D10 D11 D12 D13 D14 D15 D16 D17 D18 D19 D2 D20 D21 D22 D23 D24 D25 D26 D27 D28 D29 D3 D30 D31 D4 D5 D6 D7 D8 D9 R0 R1 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R2 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 R3 R30 R31 R4 R5 R6 R7 R8 R9'
+ poolDictionaries: 'ARMv8A64Opcodes'
+ category: 'VMMaker-JIT'!
Item was added:
+ ----- Method: CogARMv8Compiler class>>initialize (in category 'class initialization') -----
+ initialize
+ "self initialize"
+
+ #( (D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 D14 D15 D16 D17 D18 D19 D20 D21 D22 D23 D24 D25 D26 D27 D28 D29 D30 D31)
+ (R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 R30 R31)) do:
+ [:classVarNames|
+ classVarNames doWithIndex:
+ [:k :v|
+ CogARMv8Compiler classPool at: k put: v - 1]]!
Item was added:
+ ----- Method: CogARMv8Compiler class>>literalsManagerClass (in category 'accessing class hierarchy') -----
+ literalsManagerClass
+ ^OutOfLineLiteralsManager!
Item was added:
+ ----- Method: CogARMv8Compiler>>sizePCDependentInstructionAt: (in category 'generate machine code') -----
+ sizePCDependentInstructionAt: eventualAbsoluteAddress
+ "Size a jump and set its address. The target may be another instruction
+ or an absolute address. On entry the address inst var holds our virtual
+ address. On exit address is set to eventualAbsoluteAddress, which is
+ where this instruction will be output. The span of a jump to a following
+ instruction is therefore between that instruction's address and this
+ instruction's address ((which are both still their virtual addresses), but the
+ span of a jump to a preceding instruction or to an absolute address is
+ between that instruction's address (which by now is its eventual absolute
+ address) or absolute address and eventualAbsoluteAddress.
+
+ ARMv8 is simple; the 26-bit call/jump range (for a signed 28 bit extent, +/- 128Mb) and
+ 19 bit conditional branch range (for a signed 21 bit extent, +/- 1Mb) means no short
+ jumps. This routine only has to determine the targets of jumps, not determine sizes.
+
+ This version also deals with out-of-line literals. If this is the real literal,
+ update the stand-in in literalsManager with the address (because instructions
+ referring to the literal are referring to the stand-in). If this is annotated with
+ IsObjectReference transfer the annotation to the stand-in, whence it will be
+ transferred to the real literal, simplifying update of literals."
+
+ opcode = AlignmentNops ifTrue:
+ [| alignment |
+ address := eventualAbsoluteAddress.
+ alignment := operands at: 0.
+ ^machineCodeSize := (eventualAbsoluteAddress + (alignment - 1) bitAnd: alignment negated)
+ - eventualAbsoluteAddress].
+ self assert: (self isJump or: [opcode = Call or: [opcode = CallFull
+ or: [dependent notNil and: [dependent opcode = Literal]]]]).
+ self isJump ifTrue: [self resolveJumpTarget].
+ address := eventualAbsoluteAddress.
+ (dependent notNil and: [dependent opcode = Literal]) ifTrue:
+ [opcode = Literal ifTrue:
+ [dependent address: address].
+ annotation = cogit getIsObjectReference ifTrue:
+ [dependent annotation: annotation.
+ annotation := nil]].
+ ^machineCodeSize := maxSize!
Item was changed:
----- Method: CogRTLOpcodes class>>initialize (in category 'class initialization') -----
initialize
"Abstract opcodes are a compound of a one word operation specifier and zero or more operand type specifiers.
The assembler is in Cogit protocol abstract instructions and uses `at&t' syntax, assigning to the register on the
right. e.g. MoveRR is the Move opcode with two register operand specifiers and defines a move register to
register instruction from operand 0 to operand 1. The word and register size is assumed to be either 32-bits
on a 32-bit architecture or 64-bits on a 64-bit architecture. The abstract machine is mostly a 2 address machine
with the odd three address instruction added to better exploit RISCs.
(self initialize)
The operand specifiers are
R - general purpose register
Rs - single-precision floating-point register
Rd - double-precision floating-point register
Cq - a `quick' constant that can be encoded in the minimum space possible.
Cw - a constant with word size where word is the default operand size for the Smalltalk VM, 32-bits
for a 32-bit VM, 64-bits for a 64-bit VM. The generated constant must occupy the default number
of bits. This allows e.g. a garbage collector to update the value without invalidating the code.
C32 - a constant with 32 bit size. The generated constant must occupy 32 bits.
C64 - a constant with 64 bit size. The generated constant must occupy 64 bits.
Aw - memory word (32-bits for a 32-bit VM, 64-bits for a 64-bit VM) at an absolute address
See note about MoveAwR and MoveRAw in the opcodeNames literal array below!!!!
Ab - memory byte at an absolute address
A32 - memory 32-bit halfword at an absolute address
Mwr - memory word whose address is at a constant offset from an address in a register
Mbr - memory byte whose address is at a constant offset from an address in a register (zero-extended on read)
M16r - memory 16-bit halfword whose address is at a constant offset from an address in a register
M32r - memory 32-bit halfword whose address is at a constant offset from an address in a register
M64r - memory 64-bit doubleword whose address is at a constant offset from an address in a register
Xbr - memory byte whose address is r * byte size away from an address in a register
X16r - memory 16-bit halfword whose address is r * (2 bytes size) away from an address in a register
X32r - memory 32-bit halfword whose address is r * (4 bytes size) away from an address in a register (64-bit ISAs only)
Xwr - memory word whose address is r * word size away from an address in a register
Xowr - memory word whose address is o + (r * word size) away from an address in a register (scaled indexed)
An alternative would be to decouple opcodes from operands, e.g.
Move := 1. Add := 2. Sub := 3...
RegisterOperand := 1. ConstantQuickOperand := 2. ConstantWordOperand := 3...
But not all combinations make sense and even fewer are used so we stick with the simple compound approach.
The assumption is that comparison and arithmetic instructions set condition codes and that move instructions
leave the condition codes unaffected. In particular LoadEffectiveAddressMwrR does not set condition codes
although it can be used to do arithmetic. On processors such as MIPS this distinction is invalid; there are no
condition codes. So the backend is allowed to collapse operation, branch pairs to internal instruction definitions
(see senders and implementors of noteFollowingConditionalBranch:).
Not all of the definitions in opcodeDefinitions below are implemented. In particular we do not implement the
XowrR scaled index addressing mode since it requires 4 operands.
+ Not all instructions make sense on all architectures. MoveRRd and MoveRdR are meaningful only on 64-bit machines.
- Not all instructions make sense on all architectures. MoveRRd and MoveRdR aqre meaningful only on 64-bit machines.
Note that there are no generic division instructions defined, but a processor may define some.
Branch/Call ranges. Jump[Cond] can be generated as short as possible. Call/Jump[Cond]Long must be generated
in the same number of bytes irrespective of displacement since their targets may be updated, but they need only
span 16Mb, the maximum size of the code zone. This allows e.g. ARM to use single-word call and jump instructions
for most calls and jumps. CallFull/JumpFull must also be generated in the same number of bytes irrespective of
displacement for the same reason, but they must be able to span the full (32-bit or 64-bit) address space because
they are used to call code in the C runtime, which may be distant from the code zone. CallFull/JumpFull are allowed
to use the cResultRegister as a scratch if required (e.g. on x64 where there is no direct 64-bit call or jump).
Byte reads. If the concrete compiler class answers true to byteReadsZeroExtend then byte reads must zero-extend
the byte read into the destination register. If not, the other bits of the register should be left undisturbed and the
Cogit will add an instruction to zero the register as required. Under no circumstances should byte reads sign-extend.
16-bit (and on 64-bits, 32-bit) reads. These /are/ expected to always zero-extend."
| opcodeNames refs |
opcodeNames := #("Noops & Pseudo Ops"
Label
Literal "a word-sized literal"
AlignmentNops
Fill32 "output four byte's worth of bytes with operand 0"
Nop
"Control"
Call "call within the code zone"
CallFull "call anywhere within the full address space"
CallR
RetN
JumpR "Not a regular jump, i.e. not pc dependent."
Stop "Halt the processor"
"N.B. Jumps are contiguous. Long and Full jumps are contiguous within them. See FirstJump et al below"
JumpFull "Jump anywhere within the address space"
JumpLong "Jump anywhere within the 16mb code zone."
JumpLongZero "a.k.a. JumpLongEqual"
JumpLongNonZero "a.k.a. JumpLongNotEqual"
Jump "short jumps; can be encoded in as few bytes as possible; will not be disturbed by GC or relocation."
JumpZero "a.k.a. JumpEqual"
JumpNonZero "a.k.a. JumpNotEqual"
JumpNegative
JumpNonNegative
JumpOverflow
JumpNoOverflow
JumpCarry
JumpNoCarry
JumpLess "signed"
JumpGreaterOrEqual
JumpGreater
JumpLessOrEqual
JumpBelow "unsigned"
JumpAboveOrEqual
JumpAbove
JumpBelowOrEqual
JumpFPEqual
JumpFPNotEqual
JumpFPLess
JumpFPLessOrEqual
JumpFPGreater
JumpFPGreaterOrEqual
JumpFPOrdered
JumpFPUnordered
"Data Movement; destination is always last operand"
MoveRR
"N.B. On certain targets (including X64) MoveAwR & MoveRAw may
smash TempReg if the register argument is either FPReg or SPReg!!!!"
MoveAwR MoveA32R
MoveRAw MoveRA32
MoveAbR
MoveRAb
MoveMwrR MoveRMwr MoveXwrRR MoveRXwrR "MoveXowrR MoveRXowr""Unused"
MoveM8rR MoveMs8rR MoveRM8r
MoveM16rR MoveRM16r MoveX16rRR MoveRX16rR
MoveM32rR MoveRM32r MoveX32rRR MoveRX32rR
MoveMbrR MoveRMbr MoveXbrRR MoveRXbrR
MoveCqR MoveCwR MoveC32R "MoveC64R""Not used"
MoveRRd MoveRdR MoveRdRd MoveM64rRd MoveRdM64r
MoveRsRs MoveM32rRs MoveRsM32r
PopR PushR PushCq PushCw
PrefetchAw
"Arithmetic; destination is always last operand except Cmp; CmpXR is SubRX with no update of result"
LoadEffectiveAddressMwrR "LoadEffectiveAddressXowrR" "Variants of add/multiply"
NegateR "2's complement negation"
NotR
ArithmeticShiftRightCqR ArithmeticShiftRightRR
LogicalShiftRightCqR LogicalShiftRightRR
LogicalShiftLeftCqR LogicalShiftLeftRR
RotateLeftCqR RotateRightCqR
CmpRR AddRR SubRR AndRR OrRR XorRR
CmpCqR AddCqR SubCqR AndCqR OrCqR TstCqR XorCqR
CmpCwR CmpC32R AddCwR SubCwR AndCwR OrCwR XorCwR
AddcRR AddcCqR SubbRR SubbCqR
AndCqRR "Three address ops for RISCs; feel free to add and extend"
CmpRdRd AddRdRd SubRdRd MulRdRd DivRdRd SqrtRd XorRdRd
CmpRsRs AddRsRs SubRsRs MulRsRs DivRsRs SqrtRs XorRsRs
"Conversion"
ConvertRRd ConvertRdR
ConvertRsRd ConvertRdRs ConvertRsR ConvertRRs
SignExtend8RR SignExtend16RR SignExtend32RR
ZeroExtend8RR ZeroExtend16RR ZeroExtend32RR
"Advanced bit manipulation (aritmetic)"
ClzRR
LastRTLCode).
"Magic auto declaration. Add to the classPool any new variables and nuke any obsolete ones, and assign values"
"Find the variables directly referenced by this method"
refs := (thisContext method literals select: [:l| l isVariableBinding and: [classPool includesKey: l key]]) collect:
[:ea| ea key].
"Move to Undeclared any opcodes in classPool not in opcodes or this method."
(classPool keys reject: [:k| (opcodeNames includes: k) or: [refs includes: k]]) do:
[:k|
Undeclared declare: k from: classPool].
"Declare as class variables and number elements of opcodeArray above"
opcodeNames withIndexDo:
[:classVarName :value|
self classPool
declare: classVarName from: Undeclared;
at: classVarName put: value].
"For CogAbstractInstruction>>isJump etc..."
FirstJump := JumpFull.
LastJump := JumpFPUnordered.
FirstShortJump := Jump.
"And now initialize the backends; they add their own opcodes and hence these must be reinitialized."
(Smalltalk classNamed: #CogAbstractInstruction) ifNotNil:
[:cogAbstractInstruction| cogAbstractInstruction allSubclasses do: [:sc| sc initialize]]!
Item was added:
+ ----- Method: Integer>>binary (in category '*VMMaker-printing') -----
+ binary
+ ^self printStringRadix: 2!
Eliot Miranda uploaded a new version of Cog to project VM Maker:
http://source.squeak.org/VMMaker/Cog-eem.371.mcz
==================== Summary ====================
Name: Cog-eem.371
Author: eem
Time: 24 November 2019, 7:47:28.106077 am
UUID: f8a8b383-cc2d-430c-a433-d2f4afcfdf73
Ancestors: Cog-eem.370
Start using the ARMv8A64Opcodes pools in GdbARMv8Alien.
=============== Diff against Cog-eem.370 ===============
Item was changed:
CogProcessorAlien variableByteSubclass: #GdbARMv8Alien
instanceVariableNames: ''
classVariableNames: 'Level0FailureTable Level0OpcodeTable'
+ poolDictionaries: 'ARMv8A64Opcodes'
- poolDictionaries: ''
category: 'Cog-Processors'!
!GdbARMv8Alien commentStamp: 'eem 11/19/2019 15:39' prior: 0!
I am a wrapper around the struct sim aarch64 CPU instance and emulator routines and I give access to disassembling using libopcodes.!
Item was changed:
----- Method: GdbARMv8Alien>>handleFailingBranch:at:in: (in category 'error handling') -----
handleFailingBranch: instruction at: pc in: memoryArray "<Bitmap|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"
| decode |
decode := ((instruction bitShift: -29) bitShift: 1) + ((instruction bitShift: -25) bitAnd: 1).
decode = 2r1101 ifTrue: "Unconditional branch (register) on page C4-262"
+ [instruction = RET ifTrue:
- [instruction = 2r11010110010111110000001111000000 ifTrue:
[^(ProcessorSimulationTrap
pc: pc
nextpc: pc + 4
address: self lr
type: #return)
signal]].
self reportPrimitiveFailure!
Item was changed:
----- Method: GdbARMv8Alien>>nopOpcode (in category 'opcodes') -----
nopOpcode
+ ^NOP!
- ^16rd503201f!
Eliot Miranda uploaded a new version of CogPools-ISAs to project VM Maker:
http://source.squeak.org/VMMaker/CogPools-ISAs-eem.1.mcz
==================== Summary ====================
Name: CogPools-ISAs-eem.1
Author: eem
Time: 24 November 2019, 7:43:36.902208 am
UUID: b28e21e3-95ff-4a96-b49b-1cb729197ff1
Ancestors:
Add a package to contain pools defining instruction set architecture related constants. Add ARMv8A64Opcodes to define specific ARMv8 A64 opcodes.
==================== Snapshot ====================
SystemOrganization addCategory: #'CogPools-ISAs'!
SharedPool subclass: #ARMv8A64Opcodes
instanceVariableNames: ''
classVariableNames: 'NOP RET'
poolDictionaries: ''
category: 'CogPools-ISAs'!
!ARMv8A64Opcodes commentStamp: 'eem 11/24/2019 07:26' prior: 0!
ARMv8A64Opcodes is a pool of named constants for the A64 instructiin set in the ARMv8 64-bit instruction set architecture. It does not define A32 & T32 instruction sets.!
----- Method: ARMv8A64Opcodes class>>initialize (in category 'class initialization') -----
initialize
"self initialize"
| linkreg |
linkreg := 30.
"C6.2.202" NOP := 2r11010101000000110010000000011111.
"C6.2.218" RET := 2r11010110010111110000000000000000 + (linkreg << 5).!