[Vm-dev] VM Maker: VMMaker.oscog-eem.1465.mcz

Ryan Macnak rmacnak at gmail.com
Fri Sep 25 02:34:48 UTC 2015


Why does ARM get so many fewer scratch registers than X64? I would expect
them only to differ by two (LR and PC).

On Wed, Sep 23, 2015 at 11:08 AM, <commits at source.squeak.org> wrote:

>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1465.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.1465
> Author: eem
> Time: 23 September 2015, 11:07:41.674 am
> UUID: abda63f2-d72f-486d-8163-d23e6a7ebaeb
> Ancestors: VMMaker.oscog-eem.1464
>
> Cogit:
> Extend the abstract register scheme to include 8 scratch registers.  Allow
> ARMv6 use one, and x64 use 6.  Hence nuke the ill-thought-out GPRegMax
> GPRegMin, and coincidentally, the unused MulCqR MulCwR MulRR.
>
> Add in-image compilation support for x64.
>
> =============== Diff against VMMaker.oscog-eem.1464 ===============
>
> Item was changed:
>   ----- Method: CogARMCompiler>>abstractRegisterForConcreteRegister: (in
> category 'private') -----
>   abstractRegisterForConcreteRegister: reg
>         (self concreteRegister: TempReg) = reg ifTrue: [^TempReg].
>         (self concreteRegister: ReceiverResultReg) = reg ifTrue:
> [^ReceiverResultReg].
>         (self concreteRegister: ClassReg) = reg ifTrue: [^ClassReg].
>         (self concreteRegister: SendNumArgsReg) = reg ifTrue:
> [^SendNumArgsReg].
>         (self concreteRegister: Arg0Reg) = reg ifTrue: [^Arg0Reg].
>         (self concreteRegister: Arg1Reg) = reg ifTrue: [^Arg1Reg].
>         (self concreteRegister: FPReg) = reg ifTrue: [^FPReg].
>         (self concreteRegister: SPReg) = reg ifTrue: [^SPReg].
>         (self concreteRegister: LinkReg) = reg ifTrue: [^LinkReg].
>         (self concreteRegister: RISCTempReg) = reg ifTrue: [^RISCTempReg].
>         (self concreteRegister: PCReg) = reg ifTrue: [^PCReg].
>         (self concreteRegister: VarBaseReg) = reg ifTrue: [^VarBaseReg].
> +       (self concreteRegister: Scratch0Reg) = reg ifTrue: [^Scratch0Reg].
>         self error: 'could not find abstract register'.
>         ^0
>
>         "({     TempReg. ReceiverResultReg. ClassReg. SendNumArgsReg.
> Arg0Reg. Arg1Reg.
>                 FPReg. SPReg.
> +               LinkReg. RISCTempReg. PCReg. VarBaseReg.
> +               Scratch0Reg } collect: [:i| self basicNew
> concreteRegister: i]) sort"
> -               LinkReg. RISCTempReg. PCReg. VarBaseReg} collect: [:i|
> self basicNew concreteRegister: i]) sort"
>
>         "While the below works fine in Smalltalk it of course doesn't work
> in C ;)"
>
>         "^reg caseOf: {
>                 [self concreteRegister: TempReg] -> [TempReg].
>                 [self concreteRegister: ReceiverResultReg] ->
> [ReceiverResultReg].
>                 [self concreteRegister: ClassReg] -> [ClassReg].
>                 [self concreteRegister: SendNumArgsReg] ->
> [SendNumArgsReg].
>                 [self concreteRegister: Arg0Reg] -> [Arg0Reg].
>                 [self concreteRegister: Arg1Reg] -> [Arg1Reg].
>                 [self concreteRegister: FPReg] -> [FPReg].
>                 [self concreteRegister: SPReg] -> [SPReg] }"!
>
> Item was changed:
>   ----- Method: CogARMCompiler>>concreteRegister: (in category 'encoding')
> -----
>   concreteRegister: registerIndex
>          "Map a possibly abstract register into a concrete one.  Abstract
> registers
>           (defined in CogAbstractOpcodes) are all negative.  If
> registerIndex is
>           negative assume it is an abstract register."
>
>         "N.B. According to BSABI, R0-R3 are caller-save, R4-R12 are callee
> save.
>          Note that R9 might be a special register for the implementation.
> In some slides
>          it is refered to as sb. R10 can contain the stack limit (sl), R11
> the fp. R12 is an
>          intra-procedure scratch instruction pointer for link purposes. It
> can also be used.
>          R10 is used as temporary inside a single abstract opcode
> implementation"
>         "R0-R3 are used when calling back to the interpreter. Using them
> would require
>          saving and restoring their values, so they are omitted so far.
> R12 is the only
> +        scratch register at the moment.."
> -        unused register at the moment.."
>         ^registerIndex
>                 caseOf: {
>                         [TempReg]                               -> [R0].
>                         [ClassReg]                              -> [R8].
>                         [ReceiverResultReg]     -> [R7].
>                         [SendNumArgsReg]                -> [R6].
>                         [SPReg]                                 -> [SP].
> "R13"
>                         [FPReg]                                 -> [R11].
>                         [Arg0Reg]                               -> [R4].
>                         [Arg1Reg]                               -> [R5].
>                         [VarBaseReg]                    ->
> [ConcreteVarBaseReg]. "Must be callee saved"
>                         [RISCTempReg]                   ->
> [ConcreteIPReg]. "a.k.a. IP"
> +                       [Scratch0Reg]                   -> [R12].
>                         [LinkReg]                               -> [LR].
> "R14"
>                         [PCReg]                                 -> [PC]
> "R15" }
>                 otherwise:
>                         [self assert: (registerIndex between: R0 and: PC).
>                          registerIndex]!
>
> Item was added:
> + ----- Method: CogARMCompiler>>minAbstractGeneralPurposeReg (in category
> 'accessing') -----
> + minAbstractGeneralPurposeReg
> +       "Answer the smallest index of an abstract general-purpose register
> used by this compiler.
> +        N.B.  Abstract registers are negative numbers."
> +       <inline: true>
> +       ^Scratch0Reg!
>
> Item was added:
> + ----- Method: CogAbstractInstruction>>maxAbstractGeneralPurposeReg (in
> category 'accessing') -----
> + maxAbstractGeneralPurposeReg
> +       "Answer the largest index of an abstract general-purpose register
> used by this compiler.
> +        N.B.  Abstract registers are negative numbers."
> +       <inline: true>
> +       ^ReceiverResultReg!
>
> Item was added:
> + ----- Method: CogAbstractInstruction>>minAbstractGeneralPurposeReg (in
> category 'accessing') -----
> + minAbstractGeneralPurposeReg
> +       "Answer the smallest index of an abstract general-purpose register
> used by this compiler.
> +        N.B.  Abstract registers are negative numbers."
> +       <inline: true>
> +       ^self subclassResponsibility!
>
> Item was changed:
>   ----- Method: CogIA32Compiler>>concreteRegister: (in category
> 'encoding') -----
>   concreteRegister: registerIndex
>          "Map a possibly abstract register into a concrete one.  Abstract
> registers
>           (defined in CogAbstractOpcodes) are all negative.  If
> registerIndex is
>          negative assume it is an abstract register.
>
>         [1] IA-32 Intel® Architecture Software Developer's Manual Volume
> 2A: Instruction Set Reference, A-M
>
>
> +       N.B. EAX ECX & EDX are caller-save (scratch) registers.  Hence we
> use ECX for class and EDX for
> -       N.B. EAX ECX & EDX are caller-save (scratch) registers.  Hence we
> use ECX for class and EDC for
>                 receiver/result since these are written in all normal
> sends.  EBX ESI & EDI are callee-save."
>
>         ^registerIndex
>                 caseOf: {
>                         [TempReg]                               -> [EAX].
>                         [ClassReg]                              -> [ECX].
>                         [ReceiverResultReg]     -> [EDX].
>                         [SendNumArgsReg]                -> [EBX].
>                         [SPReg]                                 -> [ESP].
>                         [FPReg]                                 -> [EBP].
>                         [Arg0Reg]                               -> [ESI].
>                         [Arg1Reg]                               -> [EDI] }
>                 otherwise:
>                         [self assert: (registerIndex between: EAX and:
> EDI).
>                          registerIndex]!
>
> Item was added:
> + ----- Method: CogIA32Compiler>>minAbstractGeneralPurposeReg (in category
> 'accessing') -----
> + minAbstractGeneralPurposeReg
> +       "Answer the smallest index of an abstract general-purpose register
> used by this compiler.
> +        N.B.  Abstract registers are negative numbers."
> +       <inline: true>
> +       ^Arg1Reg!
>
> Item was added:
> + ----- Method:
> CogInLineLiteralsX64Compiler>>abstractRegisterForConcreteRegister: (in
> category 'private') -----
> + abstractRegisterForConcreteRegister: reg
> +       (self concreteRegister: TempReg) = reg ifTrue: [^TempReg].
> +       (self concreteRegister: ReceiverResultReg) = reg ifTrue:
> [^ReceiverResultReg].
> +       (self concreteRegister: ClassReg) = reg ifTrue: [^ClassReg].
> +       (self concreteRegister: SendNumArgsReg) = reg ifTrue:
> [^SendNumArgsReg].
> +       (self concreteRegister: Arg0Reg) = reg ifTrue: [^Arg0Reg].
> +       (self concreteRegister: Arg1Reg) = reg ifTrue: [^Arg1Reg].
> +       (self concreteRegister: FPReg) = reg ifTrue: [^FPReg].
> +       (self concreteRegister: SPReg) = reg ifTrue: [^SPReg].
> +       (self concreteRegister: RISCTempReg) = reg ifTrue: [^RISCTempReg].
> +       (self concreteRegister: VarBaseReg) = reg ifTrue: [^VarBaseReg].
> +       (self concreteRegister: Scratch0Reg) = reg ifTrue: [^Scratch0Reg].
> +       (self concreteRegister: Scratch1Reg) = reg ifTrue: [^Scratch1Reg].
> +       (self concreteRegister: Scratch2Reg) = reg ifTrue: [^Scratch2Reg].
> +       (self concreteRegister: Scratch3Reg) = reg ifTrue: [^Scratch3Reg].
> +       (self concreteRegister: Scratch4Reg) = reg ifTrue: [^Scratch4Reg].
> +       (self concreteRegister: Scratch5Reg) = reg ifTrue: [^Scratch5Reg].
> +       self error: 'could not find abstract register'.
> +       ^0
> +
> +       "({     TempReg. ReceiverResultReg. ClassReg. SendNumArgsReg.
> Arg0Reg. Arg1Reg.
> +               FPReg. SPReg.
> +               RISCTempReg. VarBaseReg.
> +               Scratch0Reg. Scratch1Reg. Scratch2Reg. Scratch3Reg.
> Scratch4Reg. Scratch5Reg. } collect: [:i| self basicNew concreteRegister:
> i]) sort"
> +
> +       "While the below works fine in Smalltalk it of course doesn't work
> in C ;)"
> +
> +       "^reg caseOf: {
> +               [self concreteRegister: TempReg] -> [TempReg].
> +               [self concreteRegister: ReceiverResultReg] ->
> [ReceiverResultReg].
> +               [self concreteRegister: ClassReg] -> [ClassReg].
> +               [self concreteRegister: SendNumArgsReg] ->
> [SendNumArgsReg].
> +               [self concreteRegister: Arg0Reg] -> [Arg0Reg].
> +               [self concreteRegister: Arg1Reg] -> [Arg1Reg].
> +               [self concreteRegister: FPReg] -> [FPReg].
> +               [self concreteRegister: SPReg] -> [SPReg] }"!
>
> Item was added:
> + ----- Method: CogInLineLiteralsX64Compiler>>concreteRegister: (in
> category 'encoding') -----
> + concreteRegister: registerIndex
> +        "Map a possibly abstract register into a concrete one.  Abstract
> registers
> +         (defined in CogAbstractOpcodes) are all negative.  If
> registerIndex is
> +        negative assume it is an abstract register.
> +
> +       [1] Figure 3.4 Register Usage in
> +               System V Application Binary Interface
> +               AMD64 Architecture Processor Supplement
> +
> +
> +       N.B. RAX RCX & RDX are caller-save (scratch) registers.  Hence we
> use RCX for class and RDX for
> +               receiver/result since these are written in all normal
> sends."
> +
> +       ^registerIndex
> +               caseOf: {
> +                       [TempReg]                               -> [RAX].
> +                       [ClassReg]                              -> [RCX].
> +                       [ReceiverResultReg]     -> [RDX].
> +                       [SendNumArgsReg]                -> [R9].
> +                       [SPReg]                                 -> [RSP].
> +                       [FPReg]                                 -> [RBP].
> +                       [Arg0Reg]                               -> [RSI].
> +                       [Arg1Reg]                               -> [RDI].
> +                       [VarBaseReg]                    -> [RBX]. "Must be
> callee saved"
> +                       [RISCTempReg]                   -> [R8].
> +                       [Scratch0Reg]                   -> [R10].
> +                       [Scratch1Reg]                   -> [R11].
> +                       [Scratch2Reg]                   -> [R12].
> +                       [Scratch3Reg]                   -> [R13].
> +                       [Scratch4Reg]                   -> [R14].
> +                       [Scratch5Reg]                   -> [R15] }
> +               otherwise:
> +                       [self assert: (registerIndex between: RAX and:
> R15).
> +                        registerIndex]!
>
> Item was changed:
>   SharedPool subclass: #CogRTLOpcodes
>         instanceVariableNames: ''
> +       classVariableNames: 'AddCqR AddCwR AddRR AddRdRd AlignmentNops
> AndCqR AndCqRR AndCwR AndRR Arg0Reg Arg1Reg ArithmeticShiftRightCqR
> ArithmeticShiftRightRR Call CallFull ClassReg CmpCqR CmpCwR CmpRR CmpRdRd
> ConvertRRd DPFPReg0 DPFPReg1 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6
> DPFPReg7 DivRdRd FPReg Fill16 Fill32 Fill8 FillBytesFrom FillFromWord
> FirstJump FirstShortJump Jump JumpAbove JumpAboveOrEqual JumpBelow
> JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater JumpFPGreaterOrEqual
> JumpFPLess JumpFPLessOrEqual JumpFPNotEqual JumpFPOrdered JumpFPUnordered
> JumpFull JumpGreater JumpGreaterOrEqual JumpLess JumpLessOrEqual JumpLong
> JumpLongNonZero JumpLongZero JumpNegative JumpNoCarry JumpNoOverflow
> JumpNonNegative JumpNonZero JumpOverflow JumpR JumpZero Label LastJump
> LastRTLCode LinkReg Literal LoadEffectiveAddressMwrR
> LoadEffectiveAddressXowrR LogicalShiftLeftCqR LogicalShiftLeftRR
> LogicalShiftRightCqR LogicalShiftRightRR MoveAbR MoveAwR MoveC32R MoveC64R
> MoveCqR MoveCwR MoveM16rR MoveM32rR MoveM64rRd MoveMbrR MoveMwrR MoveRAb
> MoveRAw MoveRM16r MoveRM32r MoveRMbr MoveRMwr MoveRR MoveRX16rR MoveRX32rR
> MoveRXbrR MoveRXowr MoveRXwrR MoveRdM64r MoveRdRd MoveX16rRR MoveX32rRR
> MoveXbrRR MoveXowrR MoveXwrRR MulRdRd NegateR Nop OrCqR OrCwR OrRR PCReg
> PopR PrefetchAw PushCq PushCw PushR RISCTempReg ReceiverResultReg RetN
> SPReg Scratch0Reg Scratch1Reg Scratch2Reg Scratch3Reg Scratch4Reg
> Scratch5Reg Scratch6Reg Scratch7Reg SendNumArgsReg SqrtRd Stop SubCqR
> SubCwR SubRR SubRdRd TempReg TstCqR VarBaseReg XorCqR XorCwR XorRR'
> -       classVariableNames: 'AddCqR AddCwR AddRR AddRdRd AlignmentNops
> AndCqR AndCqRR AndCwR AndRR Arg0Reg Arg1Reg ArithmeticShiftRightCqR
> ArithmeticShiftRightRR Call CallFull ClassReg CmpCqR CmpCwR CmpRR CmpRdRd
> ConvertRRd DPFPReg0 DPFPReg1 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6
> DPFPReg7 DivRdRd FPReg Fill16 Fill32 Fill8 FillBytesFrom FillFromWord
> FirstJump FirstShortJump GPRegMax GPRegMin Jump JumpAbove JumpAboveOrEqual
> JumpBelow JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater
> JumpFPGreaterOrEqual JumpFPLess JumpFPLessOrEqual JumpFPNotEqual
> JumpFPOrdered JumpFPUnordered JumpFull JumpGreater JumpGreaterOrEqual
> JumpLess JumpLessOrEqual JumpLong JumpLongNonZero JumpLongZero JumpNegative
> JumpNoCarry JumpNoOverflow JumpNonNegative JumpNonZero JumpOverflow JumpR
> JumpZero Label LastJump LastRTLCode LinkReg Literal
> LoadEffectiveAddressMwrR LoadEffectiveAddressXowrR LogicalShiftLeftCqR
> LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightRR MoveAbR MoveAwR
> MoveC32R MoveC64R MoveCqR MoveCwR MoveM16rR MoveM32rR MoveM64rRd MoveMbrR
> MoveMwrR MoveRAb MoveRAw MoveRM16r MoveRM32r MoveRMbr MoveRMwr MoveRR
> MoveRX16rR MoveRX32rR MoveRXbrR MoveRXowr MoveRXwrR MoveRdM64r MoveRdRd
> MoveX16rRR MoveX32rRR MoveXbrRR MoveXowrR MoveXwrRR MulCqR MulCwR MulRR
> MulRdRd NegateR Nop OrCqR OrCwR OrRR PCReg PopR PrefetchAw PushCq PushCw
> PushR RISCTempReg ReceiverResultReg RetN SPReg SendNumArgsReg SqrtRd Stop
> SubCqR SubCwR SubRR SubRdRd TempReg TstCqR VarBaseReg XorCqR XorCwR XorRR'
>         poolDictionaries: ''
>         category: 'VMMaker-JIT'!
>
>   !CogRTLOpcodes commentStamp: '<historical>' prior: 0!
>   I am a pool for the Register-Transfer-Language to which Cog compiles.  I
> define unique integer values for all RTL opcodes and abstract registers.
> See CogAbstractInstruction for instances of instructions with the opcodes
> that I define.!
>
> 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.
>          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
>                 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 at an absolute address
>                 Ab              - memory byte 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
>                 XbrR    - memory word whose address is r * byte size away
> from an address in a register
>                 X16rR   - memory word whose address is r * (2 bytes size)
> away from an address in a register
>                 XwrR    - memory word whose address is r * word size away
> from an address in a register
>                 XowrR   - memory word whose address is (r * word size) + o
> 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.
>
>         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.
>
>         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)."
>
>         | opcodeNames refs |
> -       self flag: 'GPRegMin and GPRegMax are poorly thought-out and
> should instead defer to the backEnd for allocateable registers.'.
>         "A small fixed set of abstract registers are defined and used in
> code generation
>          for Smalltalk code, and executes on stack pages in the stack zone.
>          These are mapped to processor-specific registers by
> concreteRegister:"
>         FPReg := -1.    "A frame pointer is used for Smalltalk frames."
>         SPReg := -2.
> +       ReceiverResultReg := -3.                "The receiver at point of
> send, and return value of a send"
> -       ReceiverResultReg := GPRegMax := -3. "The receiver at point of
> send, and return value from a send"
>         TempReg := -4.
> +       ClassReg := -5.                                 "The inline send
> cache class tag is in this register, loaded at the send site"
> +       SendNumArgsReg := -6.           "Sends > 2 args set the arg count
> in this reg"
> +       Arg0Reg := -7.                                  "In the
> StackToRegisterMappingCogit 1 & 2 arg sends marshall into these registers."
> +       Arg1Reg := -8.
> -       ClassReg := -5.
>  "The inline send cache class tag is in this register, loaded at the send
> site"
> -       SendNumArgsReg := -6.                           "Sends > 2 args
> set the arg count in this reg"
> -       Arg0Reg := -7.
> "In the StackToregisterMappingCogit 1 & 2 arg sends marshall into these
> registers."
> -       Arg1Reg := GPRegMin := -8.
>
> +       "A small fixed set of abstract scratch registers for register-rich
> machines (ARM can use 1, x64 can use 6)."
> +       Scratch0Reg := -9.
> +       Scratch1Reg := -10.
> +       Scratch2Reg := -11.
> +       Scratch3Reg := -12.
> +       Scratch4Reg := -13.
> +       Scratch5Reg := -14.
> +       Scratch6Reg := -15.
> +       Scratch7Reg := -16.
> -       "Floating-point registers"
> -       DPFPReg0 := -9.
> -       DPFPReg1 := -10.
> -       DPFPReg2 := -11.
> -       DPFPReg3 := -12.
> -       DPFPReg4 := -13.
> -       DPFPReg5 := -14.
> -       DPFPReg6 := -15.
> -       DPFPReg7 := -16.
>
> +       "RISC-specific registers"
> -       "RISC-specific"
>         LinkReg := -17.
> +       RISCTempReg := -18.     "Used to synthesize CISC instructions from
> multiple RISC instructions."
> -       RISCTempReg := -18.
>         PCReg := -19.
> +       VarBaseReg := -20.              "If useful, points to base of
> interpreter variables."
> -       VarBaseReg := -20. "If useful, points to base of interpreter
> variables."
>
> +       "Floating-point registers"
> +       DPFPReg0 := -21.
> +       DPFPReg1 := -22.
> +       DPFPReg2 := -23.
> +       DPFPReg3 := -24.
> +       DPFPReg4 := -25.
> +       DPFPReg5 := -26.
> +       DPFPReg6 := -27.
> +       DPFPReg7 := -28.
> +
>         opcodeNames := #("Noops & Pseudo Ops"
>                                                 Label
>                                                 Literal                 "a
> word-sized literal"
>                                                 AlignmentNops
>                                                 FillBytesFrom   "output
> operand 0's worth of bytes from the address in operand 1"
>                                                 Fill8
>      "output a byte's worth of bytes with operand 0"
>                                                 Fill16
> "output two byte's worth of bytes with operand 0"
>                                                 Fill32
> "output four byte's worth of bytes with operand 0"
>                                                 FillFromWord    "output
> BytesPerWord's worth of bytes with operand 0 + operand 1"
>                                                 Nop
>
>                                                 "Control"
>                                                 Call
>               "call within the code zone"
>                                                 CallFull
>               "call anywhere within the full address space"
>                                                 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 contigiuous 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
>                                                 MoveAwR
>                                                 MoveRAw
>                                                 MoveAbR
>                                                 MoveRAb
>                                                 MoveMwrR MoveRMwr
> MoveXwrRR MoveRXwrR MoveXowrR MoveRXowr
>                                                 MoveM16rR MoveRM16r
> MoveX16rRR MoveRX16rR
>                                                 MoveM32rR MoveRM32r
> MoveX32rRR MoveRX32rR
>                                                 MoveMbrR MoveRMbr
> MoveXbrRR MoveRXbrR
>                                                 MoveCqR MoveCwR MoveC32R
> MoveC64R
>                                                 MoveRdRd MoveM64rRd
> MoveRdM64r
>                                                 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"
>                                                 ArithmeticShiftRightCqR
> ArithmeticShiftRightRR
>                                                 LogicalShiftRightCqR
> LogicalShiftRightRR
>                                                 LogicalShiftLeftCqR
> LogicalShiftLeftRR
>
> +                                               CmpRR AddRR SubRR AndRR
> OrRR XorRR
> +                                               CmpCqR AddCqR SubCqR
> AndCqR OrCqR TstCqR XorCqR
> +                                               CmpCwR AddCwR SubCwR
> AndCwR OrCwR XorCwR
> -                                               CmpRR AddRR SubRR AndRR
> OrRR XorRR MulRR
> -                                               CmpCqR AddCqR SubCqR
> AndCqR OrCqR TstCqR XorCqR MulCqR
> -                                               CmpCwR AddCwR SubCwR
> AndCwR OrCwR XorCwR MulCwR
>
>                                                 AndCqRR
>
>                                                 CmpRdRd AddRdRd SubRdRd
> MulRdRd DivRdRd SqrtRd
>
>                                                 "Conversion"
>                                                 ConvertRRd
>
>                                                 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: CogX64Compiler>>callerSavedRegisterMask (in category
> 'accessing') -----
> + callerSavedRegisterMask
> +       "See e.g. Figure 3.4 Register Usage in
> +               System V Application Binary Interface
> +               AMD64 Architecture Processor Supplement
> +        N.B.  We are playing fast and loose here being processor-specific.
> +        Soon enough this needs to be OS-specific."
> +       ^cogit
> +               registerMaskFor: (self
> abstractRegisterForConcreteRegister: RAX)
> +               and: (self abstractRegisterForConcreteRegister: RCX)
> +               and: (self abstractRegisterForConcreteRegister: RDX)
> +               and: (self abstractRegisterForConcreteRegister: RSI)
> +               and: (self abstractRegisterForConcreteRegister: RDI)
> +               and: (self abstractRegisterForConcreteRegister: R8)
> +               and: (self abstractRegisterForConcreteRegister: R9)
> +               and: (self abstractRegisterForConcreteRegister: R10)
> +               and: (self abstractRegisterForConcreteRegister: R11)!
>
> Item was changed:
>   ----- Method: Cogit class>>initializeMiscConstants (in category 'class
> initialization') -----
>   initializeMiscConstants
>         super initializeMiscConstants.
>         Debug := initializationOptions at: #Debug ifAbsent: [false].
>         (initializationOptions includesKey: #EagerInstructionDecoration)
>                 ifTrue:
>                         [EagerInstructionDecoration :=
> initializationOptions at: #EagerInstructionDecoration]
>                 ifFalse:
>                         [EagerInstructionDecoration ifNil:
>                                 [EagerInstructionDecoration := false]].
> "speeds up single stepping but could lose fidelity"
>
>         ProcessorClass := (initializationOptions at: #ISA ifAbsentPut:
> [#IA32]) caseOf: {
> +                                                       [#X64]
> ->      [BochsX64Alien].
>                                                         [#IA32]
>  ->      [BochsIA32Alien].
>                                                         [#ARMv5]
> ->      [GdbARMAlien]. }.
>         CogCompilerClass := self activeCompilerClass.
>         "Our criterion for which methods to JIT is literal count.  The
> default value is 60 literals or less."
>         MaxLiteralCountForCompile := initializationOptions at:
> #MaxLiteralCountForCompile ifAbsent: [60].
>         "we special-case 0, 1 & 2 argument sends, N is numArgs >= 3"
>         NumSendTrampolines := 4.
>         "Currently not even the ceImplicitReceiverTrampoline contains
> object references."
>         NumObjRefsInRuntime := 0.
>
>         NSCSelectorIndex := (NSSendCache instVarNames indexOf: #selector)
> - 1.
>         NSCNumArgsIndex := (NSSendCache instVarNames indexOf: #numArgs) -
> 1.
>         NSCClassTagIndex := (NSSendCache instVarNames indexOf: #classTag)
> - 1.
>         NSCEnclosingObjectIndex := (NSSendCache instVarNames indexOf:
> #enclosingObject) - 1.
>         NSCTargetIndex := (NSSendCache instVarNames indexOf: #target) - 1.
>         NumOopsPerNSC := NSSendCache instVarNames size.
>
>         "Max size to alloca when compiling.
>          Mac OS X 10.6.8 segfaults approaching 8Mb.
>          Linux 2.6.9 segfaults above 11Mb.
>          WIndows XP segfaults approaching 2Mb."
>         MaxStackAllocSize := 1024 * 1024 * 3 / 2 !
>
> Item was changed:
>   ----- Method: Cogit>>CallRT:registersToBeSavedMask: (in category
> 'compile abstract instructions') -----
>   CallRT: callTarget registersToBeSavedMask: registersToBeSaved
>         <returnTypeC: #'AbstractInstruction *'>
>         | callerSavedRegsToBeSaved lastInst |
>         <var: 'lastInst' type: #'AbstractInstruction *'>
>         callerSavedRegsToBeSaved := callerSavedRegMask bitAnd:
> registersToBeSaved.
>
> +       backEnd maxAbstractGeneralPurposeReg to: backEnd
> minAbstractGeneralPurposeReg by: -1 do:
> -       GPRegMax to: GPRegMin by: -1 do:
>                 [:reg|
>                 (reg ~= TempReg
>                  and: [callerSavedRegsToBeSaved anyMask: (self
> registerMaskFor: reg)]) ifTrue:
>                         [self PushR: reg]].
>
>         lastInst := self CallRT: callTarget.
>
> +       backEnd minAbstractGeneralPurposeReg to: backEnd
> maxAbstractGeneralPurposeReg do:
> -       GPRegMin to: GPRegMax do:
>                 [:reg|
>                 (reg ~= TempReg
>                  and: [callerSavedRegsToBeSaved anyMask: (self
> registerMaskFor: reg)]) ifTrue:
>                         [lastInst := self PopR: reg]].
>
>         ^lastInst!
>
> Item was added:
> + ----- Method: Cogit>>registerMaskFor:and:and:and:and:and:and: (in
> category 'register management') -----
> + registerMaskFor: reg1 and: reg2 and: reg3 and: reg4 and: reg5 and: reg6
> and: reg7
> +       "Answer a bit mask identifying the symbolic registers.
> +        Registers are negative numbers."
> +       ^(((((1 << (1 - reg1) bitOr: 1 << (1 - reg2)) bitOr: 1 << (1 -
> reg3)) bitOr: 1 << (1 - reg4)) bitOr: 1 << (1 - reg5)) bitOr: 1 << (1 -
> reg6)) bitOr: 1 << (1 - reg7)!
>
> Item was added:
> + ----- Method: Cogit>>registerMaskFor:and:and:and:and:and:and:and: (in
> category 'register management') -----
> + registerMaskFor: reg1 and: reg2 and: reg3 and: reg4 and: reg5 and: reg6
> and: reg7 and: reg8
> +       "Answer a bit mask identifying the symbolic registers.
> +        Registers are negative numbers."
> +       ^((((((1 << (1 - reg1) bitOr: 1 << (1 - reg2)) bitOr: 1 << (1 -
> reg3)) bitOr: 1 << (1 - reg4)) bitOr: 1 << (1 - reg5)) bitOr: 1 << (1 -
> reg6)) bitOr: 1 << (1 - reg7)) bitOr: 1 << (1 - reg8)!
>
> Item was added:
> + ----- Method: Cogit>>registerMaskFor:and:and:and:and:and:and:and:and:
> (in category 'register management') -----
> + registerMaskFor: reg1 and: reg2 and: reg3 and: reg4 and: reg5 and: reg6
> and: reg7 and: reg8 and: reg9
> +       "Answer a bit mask identifying the symbolic registers.
> +        Registers are negative numbers."
> +       ^(((((((1 << (1 - reg1) bitOr: 1 << (1 - reg2)) bitOr: 1 << (1 -
> reg3)) bitOr: 1 << (1 - reg4)) bitOr: 1 << (1 - reg5)) bitOr: 1 << (1 -
> reg6)) bitOr: 1 << (1 - reg7)) bitOr: 1 << (1 - reg8)) bitOr: 1 << (1 -
> reg9)!
>
> Item was changed:
>   ----- Method: CurrentImageCoInterpreterFacade>>addLabel: (in category
> 'labels') -----
>   addLabel: l
>         (variables includesKey: l) ifFalse:
> +               [variables at: l put: variables size * objectMemory
> wordSize + 65536]!
> -               [variables at: l put: variables size * 4 + 65536]!
>
> Item was changed:
>   ----- Method: CurrentImageCoInterpreterFacade>>addressForLabel: (in
> category 'labels') -----
>   addressForLabel: l
> +       ^variables at: l ifAbsentPut: [variables size * objectMemory
> wordSize + self variablesBase]!
> -       ^variables at: l ifAbsentPut: [variables size * 4 + self
> variablesBase]!
>
> Item was added:
> + CurrentImageCoInterpreterFacadeForSpurObjectRepresentation subclass:
> #CurrentImageCoInterpreterFacadeFor64BitSpurObjectRepresentation
> +       instanceVariableNames: ''
> +       classVariableNames: ''
> +       poolDictionaries: ''
> +       category: 'VMMaker-Support'!
>
> Item was added:
> + ----- Method:
> CurrentImageCoInterpreterFacadeFor64BitSpurObjectRepresentation
> class>>objectMemoryClass (in category 'accessing class hierarchy') -----
> + objectMemoryClass
> +       ^Spur64BitCoMemoryManager!
>
> Item was added:
> + ----- Method:
> CurrentImageCoInterpreterFacadeFor64BitSpurObjectRepresentation
> class>>objectRepresentationClass (in category 'accessing class hierarchy')
> -----
> + objectRepresentationClass
> +       ^CogObjectRepresentationFor64BitSpur!
>
> Item was added:
> + Spur64BitCoMemoryManager subclass: #Spur64BitMMLECoSimulator
> +       instanceVariableNames: 'parent bootstrapping'
> +       classVariableNames: ''
> +       poolDictionaries: ''
> +       category: 'VMMaker-SpurMemoryManagerSimulation'!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>bootstrapping (in category
> 'accessing') -----
> + bootstrapping
> +       ^bootstrapping!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>bootstrapping: (in category
> 'accessing') -----
> + bootstrapping: aBoolean
> +       bootstrapping := aBoolean.
> +       segmentManager initForBootstrap!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>byteAt: (in category 'memory
> access') -----
> + byteAt: byteAddress
> +       | lowBits long32 |
> +       lowBits := byteAddress bitAnd: 3.
> +       long32 := self long32At: byteAddress - lowBits.
> +       ^(lowBits caseOf: {
> +               [0] -> [ long32 ].
> +               [1] -> [ long32 bitShift: -8  ].
> +               [2] -> [ long32 bitShift: -16 ].
> +               [3] -> [ long32 bitShift: -24 ].
> +       }) bitAnd: 16rFF!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>byteAt:put: (in category 'memory
> access') -----
> + byteAt: byteAddress put: byte
> +       | lowBits long32 longAddress |
> +       lowBits := byteAddress bitAnd: 3.
> +       longAddress := byteAddress - lowBits.
> +       long32 := self long32At: longAddress.
> +       long32 := (lowBits caseOf: {
> +               [0] -> [ (long32 bitAnd: 16rFFFFFF00) bitOr: byte ].
> +               [1] -> [ (long32 bitAnd: 16rFFFF00FF) bitOr: (byte
> bitShift: 8) ].
> +               [2] -> [ (long32 bitAnd: 16rFF00FFFF) bitOr: (byte
> bitShift: 16) ].
> +               [3] -> [ (long32 bitAnd: 16r00FFFFFF) bitOr: (byte
> bitShift: 24) ].
> +       }).
> +       self long32At: longAddress put: long32.
> +       ^byte!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>byteAtPointer: (in category
> 'memory access') -----
> + byteAtPointer: pointer
> +       "This gets implemented by Macros in C, where its types will also
> be checked.
> +        pointer is a raw address."
> +
> +       ^self byteAt: pointer!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>classTableFirstPage (in category
> 'debug support') -----
> + classTableFirstPage
> +       ^classTableFirstPage!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>coInterpreter:cogit: (in
> category 'initialization') -----
> + coInterpreter: aCoInterpreter cogit: aCogit
> +       coInterpreter := aCoInterpreter.
> +       cogit := aCogit.
> +       scavenger coInterpreter: aCoInterpreter!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>cogCodeBase (in category
> 'simulation only') -----
> + cogCodeBase
> +       ^Cogit guardPageSize!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>eek (in category 'debug
> support') -----
> + eek
> +       self halt!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>endianness (in category 'memory
> access') -----
> + endianness
> +       ^#little!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>fetchFloatAt:into: (in category
> 'float primitives') -----
> + fetchFloatAt: floatBitsAddress into: aFloat
> +       aFloat at: 2 put: (self long32At: floatBitsAddress).
> +       aFloat at: 1 put: (self long32At: floatBitsAddress+4)!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>fetchPointer:ofObject: (in
> category 'object access') -----
> + fetchPointer: fieldIndex ofObject: objOop
> +       self assert: (self isForwarded: objOop) not.
> +       self assert: (fieldIndex >= 0 and: [fieldIndex < (self
> numSlotsOfAny: objOop)
> +                               or: [fieldIndex = 0 "forwarders and free
> objs"]]).
> +       ^super fetchPointer: fieldIndex ofObject: objOop!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>firstIndexableField: (in
> category 'object format') -----
> + firstIndexableField: objOop
> +       "NOTE: overridden from SpurMemoryManager to add coercion to
> CArray, so please duplicate any changes.
> +        There are only two important cases, both for objects with named
> inst vars, i.e. formats 2,3 & 5.
> +        The first indexable field for formats 2 & 5 is the slot count (by
> convention, even though that's off the end
> +        of the object).  For 3 we must go to the class."
> +       | fmt classFormat |
> +       <returnTypeC: #'void *'>
> +       fmt := self formatOf: objOop.
> +       fmt <= self lastPointerFormat ifTrue: "pointer; may need to delve
> into the class format word"
> +               [(fmt between: self indexablePointersFormat and: self
> weakArrayFormat) ifTrue:
> +                       [classFormat := self formatOfClass: (self
> fetchClassOfNonImm: objOop).
> +                        ^self cCoerce: (self pointerForOop: objOop
> +
>                      + self baseHeaderSize
> +
>                      + ((self fixedFieldsOfClassFormat: classFormat) <<
> self shiftForWord))
> +                                       to: #'oop *'].
> +               ^self cCoerce: (self pointerForOop: objOop
> +
>              + self baseHeaderSize
> +
>              + ((self numSlotsOf: objOop) << self shiftForWord))
> +                               to: #'oop *'].
> +       "All bit objects, and indeed CompiledMethod, though this is a
> non-no, start at 0"
> +       self assert: (fmt >= self sixtyFourBitIndexableFormat and: [fmt <
> self firstCompiledMethodFormat]).
> +       ^self
> +               cCoerce: (self pointerForOop: objOop + self baseHeaderSize)
> +               to: (fmt < self firstByteFormat
> +                               ifTrue:
> +                                       [fmt = self
> sixtyFourBitIndexableFormat
> +                                               ifTrue: ["64 bit field
> objects" #'long long *']
> +                                               ifFalse:
> +                                                       [fmt < self
> firstShortFormat
> +                                                               ifTrue:
> ["32 bit field objects" #'int *']
> +                                                               ifFalse:
> ["16-bit field objects" #'short *']]]
> +                               ifFalse: ["byte objects (including
> CompiledMethod" #'char *'])!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>freeStart (in category
> 'accessing') -----
> + freeStart
> +       "freeStart = 16r1163E0 ifTrue: [self halt]."
> +       ^super freeStart!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>globalGarbageCollect (in
> category 'gc - global') -----
> + globalGarbageCollect
> +       "If we're /not/ a clone, clone the VM and push it over the cliff.
> +        If it survives, destroy the clone and continue.  We should be OK
> until next time."
> +       parent ifNil:
> +               [coInterpreter cr; print: 'GC number '; print:
> statFullGCs; tab; flush.
> +                coInterpreter cloneSimulation objectMemory
> globalGarbageCollect.
> +                Smalltalk garbageCollect].
> +       ^super globalGarbageCollect!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>growOldSpaceByAtLeast: (in
> category 'growing/shrinking memory') -----
> + growOldSpaceByAtLeast: minAmmount
> +       "Attempt to grow memory by at least minAmmount.
> +        Answer the size of the new segment, or nil if the attempt failed.
> +        Override to not grow during the Spur image bootstrap."
> +       ^bootstrapping ifFalse:
> +               [super growOldSpaceByAtLeast: minAmmount]!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>halfWordHighInLong32: (in
> category 'memory access') -----
> + halfWordHighInLong32: long32
> +       "Used by Balloon"
> +
> +       ^long32 bitAnd: 16rFFFF!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>halfWordLowInLong32: (in
> category 'memory access') -----
> + halfWordLowInLong32: long32
> +       "Used by Balloon"
> +
> +       ^long32 bitShift: -16!
>
> Item was added:
> + ----- Method:
> Spur64BitMMLECoSimulator>>headerForSlots:format:classIndex: (in category
> 'header format') -----
> + headerForSlots: numSlots format: formatField classIndex: classIndex
> +       "The header format in LSB is
> +        MSB:   | 2 bits                                |
> +                       | 22: identityHash      |
> +                       | 8: slotSize                   |
> +                       | 3 bits                                |
> +                       | 5: format                     |
> +                       | 2 bits                                |
> +                       | 22: classIndex                | : LSB"
> +       self assert: (numSlots bitAnd: self numSlotsMask) = numSlots.
> +       self assert: (formatField bitAnd: self formatMask) = formatField.
> +       self assert: (classIndex bitAnd: self classIndexMask) = classIndex.
> +       ^super headerForSlots: numSlots format: formatField classIndex:
> classIndex!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>heapMapAtWord: (in category
> 'debug support') -----
> + heapMapAtWord: address
> +       ^heapMap heapMapAtWord: address asInteger!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>initialize (in category
> 'initialization') -----
> + initialize
> +       super initialize.
> +       bootstrapping := false!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>intAt:put: (in category 'memory
> access') -----
> + intAt: byteAddress put: a64BitValue
> +       ^self long32At: byteAddress put: (a64BitValue bitAnd: 16rFFFFFFFF)!
>
> Item was added:
> + ----- Method:
> Spur64BitMMLECoSimulator>>loadImageSegmentFrom:outPointers: (in category
> 'image segment in/out') -----
> + loadImageSegmentFrom: segmentWordArray outPointers: outPointerArray
> +       self leakCheckImageSegments ifTrue:
> +               [self halt].
> +       ^super loadImageSegmentFrom: segmentWordArray outPointers:
> outPointerArray!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>long32At: (in category 'memory
> access') -----
> + long32At: byteAddress
> +       "Note: Adjusted for Smalltalk's 1-based array indexing."
> +       byteAddress \\ 4 ~= 0 ifTrue: [self unalignedAccessError].
> +       ^memory at: byteAddress // 4 + 1!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>long32At:put: (in category
> 'memory access') -----
> + long32At: byteAddress put: a32BitValue
> +       "Note: Adjusted for Smalltalk's 1-based array indexing."
> +       "(byteAddress = 16r183FB00 and: [a32BitValue = 16r3FFFFC]) ifTrue:
> +               [self halt]."
> +       "(byteAddress between: 16r33FBB8 and: 16r33FBCF) ifTrue:
> +               [self halt]."
> +       byteAddress \\ 4 ~= 0 ifTrue: [self unalignedAccessError].
> +       ^memory at: byteAddress // 4 + 1 put: a32BitValue!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>long64At: (in category 'memory
> access') -----
> + long64At: byteAddress
> +       "memory is a Bitmap, a 32-bit indexable array of bits"
> +       | hiWord loWord |
> +       byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
> +       loWord := memory at: byteAddress // 4 + 1.
> +       hiWord := memory at: byteAddress // 4 + 2.
> +       ^hiWord = 0
> +               ifTrue: [loWord]
> +               ifFalse: [(hiWord bitShift: 32) + loWord]!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>long64At:put: (in category
> 'memory access') -----
> + long64At: byteAddress put: a64BitValue
> +       byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
> +       self
> +               long32At: byteAddress put: (a64BitValue bitAnd:
> 16rffffffff);
> +               long32At: byteAddress + 4 put: a64BitValue >> 32.
> +       ^a64BitValue!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>longAt: (in category 'memory
> access') -----
> + longAt: byteAddress
> +       "Answer the 64-bit word at byteAddress which must be 0 mod 4."
> +
> +       ^self long64At: byteAddress!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>longAt:put: (in category 'memory
> access') -----
> + longAt: byteAddress put: a64BitValue
> +       "Store the 64-bit value at byteAddress which must be 0 mod 4."
> +       "byteAddress = 16r1F5AE8 ifTrue: [self halt]."
> +       ^self long64At: byteAddress put: a64BitValue!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>markAndTrace: (in category 'gc -
> global') -----
> + markAndTrace: objOop
> +       "objOop = 16rB26020 ifTrue: [self halt].
> +       objOop = 16rB25FD8 ifTrue: [self halt].
> +       objOop = 16rB26010 ifTrue: [self halt]."
> +       ^super markAndTrace: objOop!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>memoryBaseForImageRead (in
> category 'snapshot') -----
> + memoryBaseForImageRead
> +       "Answer the address to read the image into.  Override so that when
> bootstrapping,
> +        the segmentManager's segments are undisturbed in
> adjustSegmentSwizzlesBy:"
> +       ^bootstrapping
> +               ifTrue: [0]
> +               ifFalse: [super memoryBaseForImageRead]!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>nextLongFrom: (in category
> 'initialization') -----
> + nextLongFrom: aStream
> +       "Read a 32- or 64-bit quantity from the given (binary) stream."
> +
> +       ^aStream nextLittleEndianNumber: self wordSize!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>nextWord32From: (in category
> 'initialization') -----
> + nextWord32From: aStream
> +       "Read a 32-bit quantity from the given (binary) stream."
> +
> +       ^aStream nextLittleEndianNumber: 4!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>parent (in category 'accessing')
> -----
> + parent
> +
> +       ^ parent!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>parent: (in category
> 'accessing') -----
> + parent: anObject
> +
> +       parent := anObject!
>
> Item was added:
> + ----- Method:
> Spur64BitMMLECoSimulator>>return:restoringObjectsIn:savedHashes:and:savedHashes:
> (in category 'image segment in/out') -----
> + return: errCode restoringObjectsIn: firstArray savedHashes:
> firstSavedHashes and: secondArray savedHashes: secondSavedHashes
> +       self leakCheckImageSegments ifTrue:
> +               [self halt: errCode printString].
> +       ^super return: errCode restoringObjectsIn: firstArray savedHashes:
> firstSavedHashes and: secondArray savedHashes: secondSavedHashes!
>
> Item was added:
> + ----- Method:
> Spur64BitMMLECoSimulator>>runLeakCheckerFor:excludeUnmarkedNewSpaceObjs:classIndicesShouldBeValid:
> (in category 'debug support') -----
> + runLeakCheckerFor: gcModes excludeUnmarkedNewSpaceObjs:
> excludeUnmarkedNewSpaceObjs classIndicesShouldBeValid:
> classIndicesShouldBeValid
> +       (coInterpreter displayView isNil
> +        and: [gcModes anyMask: checkForLeaks]) ifTrue:
> +               [coInterpreter transcript nextPutAll: 'leak-checking...';
> flush].
> +       ^super
> +               runLeakCheckerFor: gcModes
> +               excludeUnmarkedNewSpaceObjs: excludeUnmarkedNewSpaceObjs
> +               classIndicesShouldBeValid: classIndicesShouldBeValid!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>scavengingGCTenuringIf: (in
> category 'generation scavenging') -----
> + scavengingGCTenuringIf: tenuringCriterion
> +       "Run the scavenger."
> +       "self halt: (statScavenges + 1) printString, ((statScavenges
> between: 9 and: 19)
> +
>                              ifTrue: ['th']
> +
>                              ifFalse: [#('st' 'nd' 'rd') at: (statScavenges
> + 1) \\ 10 ifAbsent: 'th']), ' scavenge'."
> +       ^super scavengingGCTenuringIf: tenuringCriterion!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>setFree: (in category 'free
> space') -----
> + setFree: o
> +       "o = 16rB34D40 ifTrue: [self halt]."
> +       super setFree: o!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>setIsMarkedOf:to: (in category
> 'header access') -----
> + setIsMarkedOf: objOop to: aBoolean
> +       "objOop = 16rB26020 ifTrue: [self halt]."
> +       super setIsMarkedOf: objOop to: aBoolean.
> +       "(aBoolean
> +        and: [(self isContextNonImm: objOop)
> +        and: [(coInterpreter
> +                       checkIsStillMarriedContext: objOop
> +                       currentFP: coInterpreter framePointer)
> +        and: [(coInterpreter stackPages stackPageFor: (coInterpreter
> frameOfMarriedContext: objOop)) trace = 0]]]) ifTrue:
> +               [self halt]"!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>shortAt: (in category 'memory
> access') -----
> + shortAt: byteAddress
> +     "Return the half-word at byteAddress which must be even."
> +       | lowBits long |
> +       lowBits := byteAddress bitAnd: 2.
> +       long := self long32At: byteAddress - lowBits.
> +       ^ lowBits = 2
> +               ifTrue: [ long bitShift: -16 ]
> +               ifFalse: [ long bitAnd: 16rFFFF ]!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>shortAt:put: (in category
> 'memory access') -----
> + shortAt: byteAddress put: a16BitValue
> +     "Return the half-word at byteAddress which must be even."
> +       | lowBits long longAddress |
> +       lowBits := byteAddress bitAnd: 2.
> +       lowBits = 0
> +               ifTrue: "storing into LS word"
> +                       [long := self long32At: byteAddress.
> +                        self long32At: byteAddress
> +                               put: ((long bitAnd: 16rFFFF0000) bitOr:
> a16BitValue)]
> +               ifFalse: "storing into MS word"
> +                       [longAddress := byteAddress - 2.
> +                       long := self long32At: longAddress.
> +                       self long32At: longAddress
> +                               put: ((long bitAnd: 16rFFFF) bitOr:
> (a16BitValue bitShift: 16))].
> +       ^a16BitValue!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>storeFloatAt:from: (in category
> 'float primitives') -----
> + storeFloatAt: floatBitsAddress from: aFloat
> +       self long32At: floatBitsAddress put: (aFloat at: 2).
> +       self long32At: floatBitsAddress+4 put: (aFloat at: 1)!
>
> Item was added:
> + ----- Method:
> Spur64BitMMLECoSimulator>>storeImageSegmentInto:outPointers:roots: (in
> category 'image segment in/out') -----
> + storeImageSegmentInto: segmentWordArray outPointers: outPointerArray
> roots: arrayOfRoots
> +       self leakCheckImageSegments ifTrue:
> +               [self halt].
> +       ^super storeImageSegmentInto: segmentWordArray outPointers:
> outPointerArray roots: arrayOfRoots!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>testObjStackDo (in category
> 'ad-hoc tests') -----
> + testObjStackDo
> +       | size them seqA seqB seqC rs |
> +       ExpensiveAsserts := true.
> +       self initializeWeaklingStack; emptyObjStack: weaklingStack.
> +       self assert: (self topOfObjStack: weaklingStack) isNil.
> +       self assert: (self capacityOfObjStack: weaklingStack) >=
> ObjStackLimit.
> +       seqA := (1 to: ObjStackLimit * 5 // 2) collect: [:i| self
> integerObjectOf: i].
> +       seqA do: [:it| self noCheckPush: it onObjStack: weaklingStack].
> +       them := Set new.
> +       size := self objStack: weaklingStack from: 0 do: [:it| them add:
> it].
> +       self assert: size = seqA size.
> +       self assert: (them asSortedCollection asArray = seqA).
> +       self assert: (self isValidObjStack: weaklingStack).
> +       seqB := (ObjStackLimit * 5 // 2 + 1 to: ObjStackLimit * 10 // 2)
> collect: [:i| self integerObjectOf: i].
> +       self assert: seqA size = seqB size.
> +       rs := seqB readStream.
> +       them := Set new.
> +       size := self objStack: weaklingStack from: 0 do:
> +                               [:it|
> +                               them add: it.
> +                               self noCheckPush: rs next onObjStack:
> weaklingStack].
> +       self assert: size = seqA size.
> +       self assert: rs atEnd.
> +       self objStack: weaklingStack from: size do:
> +               [:it| them add: it].
> +       seqC := (seqA, seqB) sort.
> +       self assert: them asSortedCollection asArray = seqC!
>
> Item was added:
> + ----- Method: Spur64BitMMLECoSimulator>>vmEndianness (in category
> 'memory access') -----
> + vmEndianness
> +       "1 = big, 0 = little"
> +       ^0!
>
> Item was changed:
>   ----- Method: Spur64BitMMLESimulator>>intAt:put: (in category 'memory
> access') -----
> + intAt: byteAddress put: a64BitValue
> +       ^self long32At: byteAddress put: (a64BitValue bitAnd: 16rFFFFFFFF)!
> - intAt: byteAddress put: a32BitValue
> -       ^self longAt: byteAddress put: (a32BitValue bitAnd: 16rFFFFFFFF)!
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20150924/40f1b896/attachment-0001.htm


More information about the Vm-dev mailing list