VM Maker: VMMaker.oscog-eem.2704.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker.oscog-eem.2704.mcz

commits-2
 
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2704.mcz

==================== Summary ====================

Name: VMMaker.oscog-eem.2704
Author: eem
Time: 4 February 2020, 12:40:26.365314 pm
UUID: 882402f6-7412-42ed-8cb4-e490f533f8f3
Ancestors: VMMaker.oscog-eem.2703

Fix a regression with sorting variables when I reverted back to putting private variables first but forgot to change an earlier guard to conform.

=============== Diff against VMMaker.oscog-eem.2702 ===============

Item was changed:
  ----- Method: AbstractInstructionTests>>runCmpRRJumpCond:on: (in category 'running') -----
  runCmpRRJumpCond: assertPrintBar on: aStream
  "Compile and evaluate as many combinations of CmpR:R: JumpCond: as possible, checking that they produce the
  expected result.  Answer an array of the number of comparisons and the number of them that succeeded."
  "self defaultTester runCmpRRJumpCond: false"
  | cogit nTests nGood |
  cogit := self cogitForTests.
  nTests := nGood := 0.
  self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do:
  [:sreg :srgetter :srsetter|
  self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do:
  [:dreg :drgetter :drsetter|
  (sreg ~= dreg "N.B. We do not expect the backEnd to provide CmpR: SPReg R: reg, only CmpR: reg R: SPReg"
  and: [drgetter ~= #sp]) ifTrue:
  [#( = ~=
  > > >= >=
  < < <= <=)
  with: #(JumpZero: JumpNonZero:
  JumpGreater: JumpAbove: JumpGreaterOrEqual: JumpAboveOrEqual:
  JumpLess: JumpBelow: JumpLessOrEqual: JumpBelowOrEqual:)
  do: [:comparison :instruction| | unsigned jmp memory |
  unsigned := (instruction includesSubstring: 'Above')
  or: [instruction includesSubstring: 'Below'].
  "(drgetter = #sp or: [srgetter = #sp]) ifTrue: [self halt]."
  cogit resetGen.
  cogit CmpR: dreg R: sreg.
  jmp := cogit perform: instruction with: 0.
  cogit
+ MoveCq: 0 R: cogit ABIResultReg;
- MoveCq: 0 R: cogit backEnd cResultRegister;
  Jump: 1536.
+ jmp jmpTarget: (cogit MoveCq: 1 R: cogit ABIResultReg).
- jmp jmpTarget: (cogit MoveCq: 1 R: cogit backEnd cResultRegister).
  cogit Jump: 1536.
  memory := self generatedCodeFrom: cogit.
  "self processor disassembleFrom: 1024 to: cogit codeSize - 1024 * 2 + 1024 in: memory ''"
  self pairs: { -1 << 30. "-1 << 16." -1 << 8. 0. 1 << 8. "1 << 16." 1 << 30 } do:
  [:a :b| | bogus error expected nInsts |
  nTests := nTests + 1.
  error := false.
  nInsts := 0.
  self processor
  reset;
  pc: self defaultCodeStart;
  perform: srsetter with: (processor convertIntegerToInternal: a);
  perform: drsetter with: (processor convertIntegerToInternal: b).
  [[processor pc ~= 1536 and: [nInsts < 16]] whileTrue:
  [processor singleStepIn: memory. nInsts := nInsts + 1]]
  on: Error
  do: [:ex| error := true].
  nInsts >= 16 ifTrue: [error := true].
  "self processor disassembleInstructionAt: 0 In: memory"
  bogus := (processor pc = 1536 and: [#[0 1] includes: processor cResultRegister]) not.
  assertPrintBar ifTrue: [self deny: bogus].
  expected := unsigned
  ifTrue: [(a bitAnd: 1 << 32 - 1) perform: comparison with: (b bitAnd: 1 << 32 - 1)]
  ifFalse: [a perform: comparison with: b].
  (bogus or: [error or: [self processor cResultRegister = 1 ~= expected]]) ifFalse: [nGood := nGood + 1].
  assertPrintBar
  ifTrue: [self assert: self processor cResultRegister = 1 equals: expected]
  ifFalse:
  [self processor cResultRegister = 1 ~= expected ifTrue:
  [aStream nextPutAll: srgetter; space; nextPutAll: comparison; space; nextPutAll: drgetter.
  unsigned ifTrue: [aStream nextPutAll: ' (unsigned)'].
  aStream nextPutAll: (error ifTrue: [' ERRORED'] ifFalse: [' is incorrect']); cr; flush.
  bogus ifTrue:
  [self processor printRegistersOn: aStream.
  aStream nextPutAll: (self processor disassembleInstructionAt: 0 In: memory); cr; flush]]]]]]]].
  assertPrintBar ifFalse:
  [aStream print: nTests; nextPutAll: ' tests; '; print: nGood; nextPutAll: ' good'; cr].
  ^{nTests. nGood}!

Item was changed:
  ----- Method: CCodeGenerator>>segregateByGroupingSizeAndVisibility: (in category 'utilities') -----
  segregateByGroupingSizeAndVisibility: variables
  "Sort variables by grouping (clusteredVariables first), by size (pointer & integer
  vars sorted from defaultWordSize to bytes), and finally by size, public last.  The
  intent is to group smaller variables together for better locality (because we can)."
  | clusteredVariableNames streams defaultStream defaultWordSize groupedBySize privateStream publicStream |
  defaultWordSize := vmClass ifNotNil: [vmClass objectMemoryClass wordSize] ifNil: 8. "We now live in a 64-bit"
+ clusteredVariableNames := ([vmClass clusteredVariableNames select: [:cvn| variables includes: cvn]]
- clusteredVariableNames := ([vmClass clusteredVariableNames]
  on: MessageNotUnderstood
  do: [:ex| #()]).
  streams := (1 to: 8) collect: [:i| i isPowerOfTwo ifTrue: [(Array new: variables size // 2) writeStream]].
  streams at: 6 put: (streams at: defaultWordSize). "In plugin land sqInt has size 6..."
  defaultStream := (Array new: variables size // 2) writeStream.
  variables do:
  [:varName| | type |
  (clusteredVariableNames includes: varName) ifFalse:
  [type := variableDeclarations
  at: varName
  ifPresent: [:decl| self extractTypeFor: varName fromDeclaration: decl]
  ifAbsent: [#sqInt].
  ((self isSimpleType: type)
  ifTrue: [streams at: ((self isPointerCType: type)
  ifTrue: [defaultWordSize]
  ifFalse: [self sizeOfIntegralCType: type])]
  ifFalse: [defaultStream])
  nextPut: varName]].
  groupedBySize := Array new: variables size streamContents:
  [:varStream|
  varStream
  nextPutAll: clusteredVariableNames;
  nextPutAll: (streams at: defaultWordSize) contents;
  nextPutAll: (streams at: (defaultWordSize = 8 ifTrue: [4] ifFalse: [8])) contents;
  nextPutAll: (streams at: 2) contents;
  nextPutAll: (streams at: 1) contents;
  nextPutAll: defaultStream contents].
  publicStream := (Array new: variables size // 2) writeStream.
  privateStream := (Array new: variables size // 2) writeStream.
  groupedBySize do:
  [:varName|
+ ((self mustBeGlobal: varName) ifTrue: [publicStream] ifFalse: [privateStream]) nextPut: varName].
- (((self mustBeGlobal: varName) or: [clusteredVariableNames includes: varName])
- ifTrue: [publicStream]
- ifFalse: [privateStream]) nextPut: varName].
  ^privateStream contents, publicStream contents!

Item was changed:
  ----- Method: CoInterpreter class>>clusteredVariableNames (in category 'translation') -----
  clusteredVariableNames
  "Insist that these variables are present early in the list of variables, and in this order,
  so that e.g. they are conveniently accessed via the VarBaseReg if it is available."
  ^#(stackPointer framePointer CStackPointer CFramePointer
+ stackLimit scavengeThreshold freeStart needGCFlag specialObjectsOop
  primFailCode newMethod instructionPointer argumentCount nextProfileTick
  nativeSP nativeStackPointer shadowCallStackPointer)!

Item was removed:
- ----- Method: CogARMCompiler>>cResultRegister (in category 'abi') -----
- cResultRegister
- "Answer the register through which C functions return integral results."
- <inline: true>
- ^R0!

Item was added:
+ ----- Method: CogARMCompiler>>flushDCacheFrom:to: (in category 'inline cacheing') -----
+ flushDCacheFrom: startAddress "<Integer>" to: endAddress "<Integer>"
+ "If there is a dual mapped code zone (the normal zone but marked with read/execute, and a
+ read/write zone codeToDataDelta bytes away) then flush the data cache for the corresponding
+ range in the read/write zone and invalidate the data cache for the read/execute zone."
+ <cmacro: '(me,startAddress,endAddress) 0'>
+ "Currently we don't know whether a dual zone on a 32-bit ARM would require cache
+ flushing to ensure coherence.  So for now this is a no op."!

Item was changed:
  ----- Method: CogAbstractInstruction class>>initializeAbstractRegisters (in category 'class initialization') -----
  initializeAbstractRegisters
  "Assign the abstract registers with the identities/indices of the relevant concrete registers,
  and assign CallerSavedRegisterMask appropriately.
  First set all abstract registers to #undefined via CogAbstractRegisters initialize, and then,
  each subclasses assigns the subset they choose with values of specific concrete registers."
 
  CogAbstractRegisters initialize.
 
  CogCompilerClass ifNotNil:
  [(CogCompilerClass withAllSuperclasses copyUpTo: CogAbstractInstruction) reverseDo:
  [:compilerClass| compilerClass initialize; initializeAbstractRegisters]].
 
  NativeSPReg == #undefined ifTrue:
  [NativeSPReg := SPReg].
+ (ABIResultReg == #undefined and: [TempReg = 0]) ifTrue:
+ [ABIResultReg := TempReg].
 
  self assert: Arg0Reg isInteger.
  self assert: ClassReg isInteger.
  self assert: ReceiverResultReg isInteger.
  self assert: SendNumArgsReg isInteger.
  self assert: TempReg isInteger.
  self assert: FPReg isInteger.
  self assert: SPReg isInteger.
 
+ self assert: ABICalleeSavedRegisterMask isInteger.
  self assert: ABICallerSavedRegisterMask isInteger.
  self assert: CallerSavedRegisterMask isInteger.
+ self assert: ABIResultReg isInteger.
 
  self assert: (VarBaseReg = #undefined or: [SimpleStackBasedCogit basicNew register: VarBaseReg isInMask: ABICalleeSavedRegisterMask])!

Item was removed:
- ----- Method: CogAbstractInstruction>>cResultRegister (in category 'accessing') -----
- cResultRegister
- "Answer the register through which C funcitons return integral results."
- <inline: true>
- self subclassResponsibility!

Item was changed:
  ----- Method: CogAbstractInstruction>>genWriteCResultIntoReg: (in category 'abi') -----
  genWriteCResultIntoReg: abstractRegister
  (abstractRegister ~= NoReg
+ and: [abstractRegister ~= ABIResultReg]) ifTrue:
+ [cogit gen: MoveRR operand: ABIResultReg operand: abstractRegister]!
- and: [abstractRegister ~= self cResultRegister]) ifTrue:
- [cogit gen: MoveRR operand: self cResultRegister operand: abstractRegister]!

Item was changed:
  SharedPool subclass: #CogAbstractRegisters
  instanceVariableNames: ''
+ classVariableNames: 'ABICalleeSavedRegisterMask ABICallerSavedRegisterMask ABIResultReg ABIResultRegHigh Arg0Reg Arg1Reg CallerSavedRegisterMask ClassReg DPFPReg0 DPFPReg1 DPFPReg10 DPFPReg11 DPFPReg12 DPFPReg13 DPFPReg14 DPFPReg15 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6 DPFPReg7 DPFPReg8 DPFPReg9 Extra0Reg Extra1Reg Extra2Reg Extra3Reg Extra4Reg Extra5Reg Extra6Reg Extra7Reg Extra8Reg FPReg LinkReg NativeSPReg NoReg NumFloatRegisters NumRegisters PCReg RISCTempReg ReceiverResultReg SPReg SendNumArgsReg TempReg VarBaseReg'
- classVariableNames: 'ABICalleeSavedRegisterMask ABICallerSavedRegisterMask Arg0Reg Arg1Reg CallerSavedRegisterMask ClassReg DPFPReg0 DPFPReg1 DPFPReg10 DPFPReg11 DPFPReg12 DPFPReg13 DPFPReg14 DPFPReg15 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6 DPFPReg7 DPFPReg8 DPFPReg9 Extra0Reg Extra1Reg Extra2Reg Extra3Reg Extra4Reg Extra5Reg Extra6Reg Extra7Reg Extra8Reg FPReg LinkReg NativeSPReg NoReg NumFloatRegisters NumRegisters PCReg RISCTempReg ReceiverResultReg SPReg SendNumArgsReg TempReg VarBaseReg'
  poolDictionaries: ''
  category: 'VMMaker-JIT'!
 
+ !CogAbstractRegisters commentStamp: 'eem 2/4/2020 11:44' prior: 0!
- !CogAbstractRegisters commentStamp: 'eem 2/1/2020 12:44' prior: 0!
  I am a pool for the abstract register set that the Cogit uses to define its model of Smalltalk compiled to machine code.  My values are defined by each processor's CogAbstractInstruction subclass (e.g. CogIA32Compiler for x86).  See each class side initializeAbstractRegisters method.  Each register's value is an integer if it is available on the processor, or is the symbol #undefined if it is not.
 
  NoReg
  a value that cannot be confused with a register.  The registers below are given values from 0 to N, corresponding to their meaning in the processor's ISA.
  The numbers used may overlap, e.g. floating point registers are numbered from 0 to N and overlap the integer registers numbered from 0 to N
 
  NumFloatRegisters
  the number of floating point registers (DPFPReg0 on up) that the processor provides
 
  NumRegisters
  the number of integer registers that the processor provides
 
  ABICalleeSavedRegisterMask
  this is the callee saved registers as defined by the platform ABI as a register mask (1 << regM bitOr: 1 << regN etc)
  ABICallerSavedRegisterMask
  this is the caller saved registers as defined by the platform ABI as a register mask (1 << regM bitOr: 1 << regN etc)
  CallerSavedRegisterMask
  this is the intersection of the ABICallerSavedRegisterMask and the fixed use registers (Arg0Reg, Arg1Reg, ClassReg, ReceiverResultReg, and SendNumArgsReg)
  i.e. these are the registers that must be preserved when calling a run-time routine that returns
+ ABIResultReg
+ the register through which word-sized integral results are retrned according to the platform's ABI; this is the C result register for vanilla calls.  On most platforms it is the same as TempReg.
+ ABIResultRegHigh
+ the register through which the high-word of double-word-sized integral results are retrned according to the platform's ABI
 
  Fixed use Smalltalk registers:
  Arg0Reg
  the register used to pass the zero'th argument in one or two argument sends (on V3 only one argument sends; see CogObjectRepresentation>>numRegArgs)
  Arg1Reg
  the register used to pass the zero'th argument in one or two argument sends (on V3 unused)
  ClassReg
  the register used to pass either the selector (or selector index) in an unlinked send, or the class tag in a linked send, used for checking inline cache sends
  ReceiverResultReg
  the register holding the receiver on send, the result on return, and typically used to hold self when a method is accessing inst vars
  SendNumArgsReg
  the register that passes the number of arguments if the arith of the send is greater than two (see ceSendNArgs et al)
  TempReg
+ a generic temporary, that can usefully be equated with the C result register ABIResultReg.
- a generic temporary, that can usefully be equated with the C result register
 
  Dual use Smalltalk registers:
  FPReg
  a register (which is ideally the processor's frame pointer register) used as the frame pointer in frameful methods
  SPReg
  a register (which is ideally the processor's stack pointer register) used as the stack pointer in generated machine code
  NativeSPReg
  the processor's native stack pointer register, which may or may not be equal to SPReg
 
  Allocatable registers
  Extra0Reg through Extra8Reg
  registers allocatable by the code generator. This is work-in-progress.  These should be able to be assigned for temporaries by RegisterAllocatingCogit et al
 
  Code Generator registers
  RISCTempReg
  a register reserved by a code generator for a RISC (e.g. CogARMCompiler) that is used to synthesize complex instructions
 
  VarBaseReg
  if enough registers are available then this is a register that holds the base address of the CoInterpreter's variables such as stackPointer, newMethod, etc.
  VarBaseReg allows much more concise code accessing those variables from generated machine code
 
  Floating point registers
  DPFPReg0 through DPFPReg15
  the available floating point registers (note that ARMv8 has 32, and that the code generator only uses DPFPReg0 & DPFPReg1).  The processor defines as many as it has
 
  Processor registers
  FPReg
  the processor's frame pointer register (or a register that is used as the Smalltalk frame pointer)
  SPReg
  the processor's stack pointer register
  LinkReg
  if a RISC then the processor's link register, which is loaded with the return address by a call instruction
  PCReg
  if a RISC with an explicit PC register that is one of its general purpose integer registers (as for example does 32-bit ARM, but /not/ 64-bit ARMv8), then this is the register!

Item was changed:
  ----- Method: CogAbstractRegisters class>>initialize (in category 'class initialization') -----
  initialize
  "Define a fixed set of abstract register names used in code generation for Smalltalk code.
  These are given concrete values by the currently in-use back end, which is a subclass of
+ CogAbstractInstruction; see implementors of initializeAbstractRegisters & this class's comment.
- CogAbstractInstruction; see implementors of initializeAbstractRegisters.
 
  We assume concrete registers defined by the back ends are in the range 0 to N, possibly
  with integer registers and floating-point registers using overlapping ranges of indices.
  Here we initialize all registers to #undefined, leaving it to initializeAbstractRegisters to
  initialize the subset of the abstract registers that a platform actually uses."
 
  "NoReg encodes no register, e.g. for parameters that supply an optional register.
  Being negative it is distinct from abstract and concrete registers in the 0 to N range."
  NoReg := -1.
 
  ABICalleeSavedRegisterMask := ABICallerSavedRegisterMask := CallerSavedRegisterMask := 0.
+ ABIResultReg := ABIResultRegHigh := #undefined.
 
  "The core set of abstract registers that define the Cogit's model of Smalltalk code
  provide for a register-based calling convention oriented towards inline cacheing and
  executing a core set of machine code primitives in registers.  The set is composed of
  8 registers, dictated by the available registers on IA32."
  "Smalltalk machine code executes on stack pages in the stack zone, requiring frame and stack pointers."
  FPReg := #undefined. "A frame pointer is used for Smalltalk frames."
  SPReg := #undefined.
  ReceiverResultReg := #undefined. "The receiver at point of send, and return value of a send"
  ClassReg := #undefined. "The inline send cache class tag is in this register, loaded at the send site"
  SendNumArgsReg := #undefined. "Sends > 2 args set the arg count in this reg"
  Arg0Reg := #undefined. "In the StackToRegisterMappingCogit 1 & 2 arg sends marshall into these registers."
  Arg1Reg := #undefined.
  TempReg := #undefined.
 
  "A small fixed set of abstract scratch registers for register-rich machines (ARM can use 1, x64 can use 6 or 7)."
  Extra0Reg := #undefined.
  Extra1Reg := #undefined.
  Extra2Reg := #undefined.
  Extra3Reg := #undefined.
  Extra4Reg := #undefined.
  Extra5Reg := #undefined.
  Extra6Reg := #undefined.
  Extra7Reg := #undefined.
  Extra8Reg := #undefined.
 
  "processor-specific registers"
  NativeSPReg := #undefined.
 
  "RISC-specific registers"
  LinkReg := #undefined.
  RISCTempReg := #undefined. "Used to synthesize CISC instructions from multiple RISC instructions."
  PCReg := #undefined. "If the processor has an assignable pc, e.g. ARM"
  VarBaseReg := #undefined. "If useful, points to base of interpreter variables."
 
  NumRegisters := #undefined. "Number of basic/integer regsiters (we don't do M68k ;-) )"
 
  "Up to 16 floating-point registers. e.g. IA32+SSE2 can use 8, x64 can use 16."
  DPFPReg0 := #undefined.
  DPFPReg1 := #undefined.
  DPFPReg2 := #undefined.
  DPFPReg3 := #undefined.
  DPFPReg4 := #undefined.
  DPFPReg5 := #undefined.
  DPFPReg6 := #undefined.
  DPFPReg7 := #undefined.
  DPFPReg8 := #undefined.
  DPFPReg9 := #undefined.
  DPFPReg10 := #undefined.
  DPFPReg11 := #undefined.
  DPFPReg12 := #undefined.
  DPFPReg13 := #undefined.
  DPFPReg14 := #undefined.
  DPFPReg15 := #undefined.
 
  NumFloatRegisters := #undefined. "Number of floating-point registers (we don;t do single-precision; we don't do xmm high (yet)."
 
  classPool keysAndValuesDo:
  [:k :value|
  self assert: value == (#(-1 0 0 0) at: (#(NoReg ABICalleeSavedRegisterMask ABICallerSavedRegisterMask CallerSavedRegisterMask) indexOf: k) ifAbsent: [#undefined])]!

Item was removed:
- ----- Method: CogIA32Compiler>>cResultRegister (in category 'accessing') -----
- cResultRegister
- "Answer the register through which C funcitons return integral results."
- <inline: true>
- ^EAX!

Item was removed:
- ----- Method: CogIA32Compiler>>cResultRegisterLow (in category 'accessing') -----
- cResultRegisterLow
- "Answer the abstract register for the C result register.
- Only partially implemented.  Works on x86 since TempReg = EAX = C result reg."
- ^ EAX!

Item was added:
+ ----- Method: CogIA32Compiler>>flushDCacheFrom:to: (in category 'inline cacheing') -----
+ flushDCacheFrom: startAddress "<Integer>" to: endAddress "<Integer>"
+ "If there is a dual mapped code zone (the normal zone but marked with read/execute, and a
+ read/write zone codeToDataDelta bytes away) then flush the data cache for the corresponding
+ range in the read/write zone and invalidate the data cache for the read/execute zone."
+ <cmacro: '(me,startAddress,endAddress) 0'>
+ "Currently we don't know whether a dual zone on an Intel x86/x86-64 would require cache
+ flushing to ensure coherence.  So for now this is a no op."!

Item was changed:
  ----- Method: CogMIPSELCompiler class>>initializeAbstractRegisters (in category 'class initialization') -----
  initializeAbstractRegisters
  "Assign the abstract registers with the identities/indices of the relevant concrete registers."
 
  "See MIPSConstants>>initializeRegisters for a description of the C ABI."
 
  "Note we can fit all of the abstract registers in C preserved registers, and
  not need to save or restore them at runtime calls."
 
  ReceiverResultReg := S0.
  Arg0Reg := S1.
  Arg1Reg := S2.
  ClassReg := S3.
  SendNumArgsReg := S4.
  TempReg := S5.
  VarBaseReg := S6. "Must be callee saved"
  SPReg := SP.
  FPReg := FP.
  RISCTempReg := AT.
  LinkReg := RA.
 
  self flag: #OABI. "see e.g. http://refspecs.linuxbase.org/elf/mipsabi.pdf"
  ABICalleeSavedRegisterMask := self
  registerMaskFor: S0 and: S1 and: S2 and: S3
  and: S4 and: S5 and: S6 and: S7.
  ABICallerSavedRegisterMask := self
  registerMaskFor: T0 and: T1 and: T2 and: T3
  and: T4 and: T5 and: T6 and: T7 and: T8 and: T9.
  CallerSavedRegisterMask := ABICallerSavedRegisterMask
  bitAnd: (self registerMaskFor: ClassReg and: ReceiverResultReg and: SendNumArgsReg and: Arg0Reg and: Arg1Reg).
+ ABIResultReg := V0.
 
  NumRegisters := 32.
 
  self flag: #todo.
  "Extra0Reg := ??.
  Extra1Reg := ??.
  Extra2Reg := ??.
  Extra3Reg := ??.
  Extra4Reg := ??.
  Extra5Reg := ??.
  Extra6Reg := ??.
  Extra7Reg := ??."
 
  self flag: #todo.
  "DPFPReg0 := ??.
  DPFPReg1 := ??.
  DPFPReg2 := ??.
  DPFPReg3 := ??.
  DPFPReg4 := ??.
  DPFPReg5 := ??.
  DPFPReg6 := ??.
  DPFPReg7 := ??.
  DPFPReg8 := ??.
  DPFPReg9 := ??.
  DPFPReg10 := ??.
  DPFPReg11 := ??.
  DPFPReg12 := ??.
  DPFPReg13 := ??.
  DPFPReg14 := ??.
  DPFPReg15 := ??"!

Item was removed:
- ----- Method: CogMIPSELCompiler>>cResultRegister (in category 'generate machine code') -----
- cResultRegister
- "Answer the register through which C funcitons return integral results."
- <inline: true>
- ^V0!

Item was changed:
  ----- Method: CogMIPSELCompiler>>computeMaximumSize (in category 'generate machine code') -----
  computeMaximumSize
  "Each MIPS instruction has 4 bytes. Many abstract opcodes need more than one
  instruction. Instructions that refer to constants and/or literals depend on literals
  being stored in-line or out-of-line.
 
  N.B.  The ^N forms are to get around the bytecode compiler's long branch
  limits which are exceeded when each case jumps around the otherwise."
 
  opcode
  caseOf: {
  [BrEqualRR] -> [^8].
  [BrNotEqualRR] -> [^8].
  [BrUnsignedLessRR] -> [^12].
  [BrUnsignedLessEqualRR] -> [^12].
  [BrUnsignedGreaterRR] -> [^12].
  [BrUnsignedGreaterEqualRR] -> [^12].
  [BrSignedLessRR] -> [^12].
  [BrSignedLessEqualRR] -> [^12].
  [BrSignedGreaterRR] -> [^12].
  [BrSignedGreaterEqualRR] -> [^12].
  [BrLongEqualRR] -> [^16].
  [BrLongNotEqualRR] -> [^16].
  [MulRR] -> [^4].
  [DivRR] -> [^4].
  [MoveLowR] -> [^4].
  [MoveHighR] -> [^4].
 
  "Noops & Pseudo Ops"
  [Label] -> [^0].
  [Literal] -> [^4].
  [AlignmentNops] -> [^(operands at: 0) - 4].
  [Fill32] -> [^4].
  [Nop] -> [^4].
  "Control"
  [Call] -> [^self literalLoadInstructionBytes + 8].
  [CallFull] -> [^self literalLoadInstructionBytes + 8].
  [JumpR] -> [^8].
  [Jump] -> [^8].
  [JumpFull] -> [^self literalLoadInstructionBytes + 8].
  [JumpLong] -> [^self literalLoadInstructionBytes + 8].
  [JumpZero] -> [^8].
  [JumpNonZero] -> [^8].
  [JumpNegative] -> [^8].
  [JumpNonNegative] -> [^8].
  [JumpOverflow] -> [^8].
  [JumpNoOverflow] -> [^8].
  [JumpCarry] -> [^8].
  [JumpNoCarry] -> [^8].
  [JumpLess] -> [^8].
  [JumpGreaterOrEqual] -> [^8].
  [JumpGreater] -> [^8].
  [JumpLessOrEqual] -> [^8].
  [JumpBelow] -> [^8].
  [JumpAboveOrEqual] -> [^8].
  [JumpAbove] -> [^8].
  [JumpBelowOrEqual] -> [^8].
  [JumpLongZero] -> [^self literalLoadInstructionBytes + 8].
  [JumpLongNonZero] -> [^self literalLoadInstructionBytes + 8].
  [JumpFPEqual] -> [^8].
  [JumpFPNotEqual] -> [^8].
  [JumpFPLess] -> [^8].
  [JumpFPGreaterOrEqual]-> [^8].
  [JumpFPGreater] -> [^8].
  [JumpFPLessOrEqual] -> [^8].
  [JumpFPOrdered] -> [^8].
  [JumpFPUnordered] -> [^8].
  [RetN] -> [^8].
  [Stop] -> [^4].
 
  "Arithmetic"
+ [AddCqR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
+ [AndCqR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
+ [AndCqRR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
+ [OrCqR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
+ [OrCqRR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
- [AddCqR] -> [^12].
- [AndCqR] -> [^16].
- [OrCqR] -> [^16].
- [AndCqRR] -> [^12].
  [CmpCqR] -> [^28].
+ [SubCqR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
+ [TstCqR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
- [OrCqR] -> [^12].
- [SubCqR] -> [^12].
- [TstCqR] -> [^12].
  [XorCqR] -> [^12].
  [AddCwR] -> [^12].
  [AndCwR] -> [^12].
  [CmpCwR] -> [^28].
  [OrCwR] -> [^12].
  [SubCwR] -> [^12].
  [XorCwR] -> [^12].
+ [AddRR] -> [^4].
+ [AndRR] -> [^4].
- [AddRR] -> [^4].
- [AndRR] -> [^4].
  [CmpRR] -> [^20].
  [OrRR] -> [^4].
  [XorRR] -> [^4].
+ [SubRR] -> [^4].
- [SubRR] -> [^4].
  [NegateR] -> [^4].
+ [AddRRR] -> [^4].
+ [SubRRR] -> [^4].
+ [LoadEffectiveAddressMwrR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [12]].
- [LoadEffectiveAddressMwrR] -> [^12].
  [LogicalShiftLeftCqR] -> [^4].
  [LogicalShiftRightCqR] -> [^4].
  [ArithmeticShiftRightCqR] -> [^4].
  [LogicalShiftLeftRR] -> [^4].
  [LogicalShiftRightRR] -> [^4].
  [ArithmeticShiftRightRR] -> [^4].
  [AddRdRd] -> [^4].
  [CmpRdRd] -> [^4].
  [SubRdRd] -> [^4].
  [MulRdRd] -> [^4].
  [DivRdRd] -> [^4].
  [SqrtRd] -> [^4].
  [AddCheckOverflowCqR] -> [^28].
  [AddCheckOverflowRR] -> [^20].
  [SubCheckOverflowCqR] -> [^28].
  [SubCheckOverflowRR] -> [^20].
  [MulCheckOverflowRR] -> [^20].
  [ClzRR] -> [^4].
  "Data Movement"
+ [MoveCqR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [8]].
- [MoveCqR] -> [^8 "or 4"].
  [MoveCwR] -> [^8].
  [MoveRR] -> [^4].
  [MoveRdRd] -> [^4].
  [MoveAwR] -> [^(self isAddressRelativeToVarBase: (operands at: 0))
  ifTrue: [4]
  ifFalse: [self literalLoadInstructionBytes + 4]].
  [MoveRAw] -> [^(self isAddressRelativeToVarBase: (operands at: 1))
  ifTrue: [4]
  ifFalse: [self literalLoadInstructionBytes + 4]].
  [MoveAbR] -> [^(self isAddressRelativeToVarBase: (operands at: 0))
  ifTrue: [4]
  ifFalse: [self literalLoadInstructionBytes + 4]].
  [MoveRAb] -> [^(self isAddressRelativeToVarBase: (operands at: 1))
  ifTrue: [4]
  ifFalse: [self literalLoadInstructionBytes + 4]].
+ [MoveRMwr] -> [^4].
- [MoveRMwr] -> [^16].
  [MoveRdM64r] -> [^self literalLoadInstructionBytes + 4].
  [MoveMbrR] -> [^4].
  [MoveRMbr] -> [^4].
  [MoveM16rR] -> [^4].
  [MoveRM16r] -> [^4].
  [MoveM64rRd] -> [^self literalLoadInstructionBytes + 4].
+ [MoveMwrR] -> [^(self isShortOffset: (operands at: 0)) ifTrue: [4] ifFalse: [16]].
- [MoveMwrR] -> [^16].
  [MoveXbrRR] -> [^8].
  [MoveRXbrR] -> [^8].
  [MoveXwrRR] -> [^12].
  [MoveRXwrR] -> [^12].
  [PopR] -> [^8].
  [PushR] -> [^8].
  [PushCw] -> [^16].
  [PushCq] -> [^16].
  [PrefetchAw] -> [^12].
  "Conversion"
  [ConvertRRd] -> [^8].
  }.
  ^0 "to keep C compiler quiet"
  !

Item was changed:
  ----- Method: CogMIPSELCompiler>>concretizeAddCqR (in category 'generate machine code - concretize') -----
  concretizeAddCqR
  | destReg leftReg rightImm |
  rightImm := operands at: 0.
  destReg := leftReg := operands at: 1.
 
+ (self isShortOffset: rightImm) ifFalse: [^self concretizeAddCwR].
- (rightImm between: -16r8000 and: 16r7FFF) ifFalse: [^self concretizeAddCwR].
 
  self machineCodeAt: 0 put: (self addiuR: destReg R: leftReg C: rightImm).
  ^4!

Item was removed:
- ----- Method: CogMIPSELCompiler>>concretizeAddRR (in category 'generate machine code - concretize') -----
- concretizeAddRR
- | destReg leftReg rightReg |
- rightReg := operands at: 0.
- destReg := leftReg := operands at: 1.
- self machineCodeAt: 0 put: (self adduR: destReg R: leftReg R: rightReg).
- ^4!

Item was added:
+ ----- Method: CogMIPSELCompiler>>concretizeAddRRDest: (in category 'generate machine code - concretize') -----
+ concretizeAddRRDest: destReg
+ | leftReg rightReg |
+ rightReg := operands at: 0.
+ leftReg := operands at: 1.
+ self machineCodeAt: 0 put: (self adduR: destReg R: leftReg R: rightReg).
+ ^4!

Item was changed:
  ----- Method: CogMIPSELCompiler>>concretizeAndCqR (in category 'generate machine code - concretize') -----
  concretizeAndCqR
  | destReg leftReg rightImm |
  rightImm := operands at: 0.
  destReg := leftReg := operands at: 1.
 
+ (self isShortOffset: rightImm) ifFalse: [^self concretizeAndCwR].
- (rightImm between: -16r8000 and: 16r7FFF) ifFalse: [^self concretizeAndCwR].
 
  self machineCodeAt: 0 put: (self andiR: destReg R: leftReg C: rightImm).
  ^4!

Item was added:
+ ----- Method: CogMIPSELCompiler>>concretizeAndCqRDest: (in category 'generate machine code - concretize') -----
+ concretizeAndCqRDest: destReg
+ | value srcReg |
+ value := operands at: 0.
+ srcReg := operands at: 1.
+ (value between: 0 and: 16rFFFF) ifTrue:
+ [self machineCodeAt: 0 put: (self andiR: destReg R: srcReg C: value).
+ ^4].
+
+ self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: value)).
+ self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: value)).
+ self machineCodeAt: 8 put: (self andR: destReg R: srcReg R: AT).
+ ^12!

Item was changed:
  ----- Method: CogMIPSELCompiler>>concretizeMoveCqR (in category 'generate machine code - concretize') -----
  concretizeMoveCqR
  <var: #word type: #sqInt>
  | word reg |
  word := operands at: 0.
  reg := operands at: 1.
 
+ (self isShortOffset: word) ifFalse: [^self concretizeMoveCwR].
- (word between: -16r8000 and: 16r7FFF) ifFalse: [^self concretizeMoveCwR].
  "Could also load up to 16rFFFF with ori or 16rXXXX0000 with lui"
 
  self machineCodeAt: 0 put: (self addiuR: reg R: ZR C: word).
  ^4!

Item was changed:
  ----- Method: CogMIPSELCompiler>>concretizeSubCqR (in category 'generate machine code - concretize') -----
  concretizeSubCqR
  | destReg leftReg rightImm |
  rightImm := operands at: 0.
  destReg := leftReg := operands at: 1.
 
+ (self isShortOffset: rightImm negated) ifFalse: [^self concretizeSubCwR].
- (rightImm negated between: -16r8000 and: 16r7FFF) ifFalse: [^self concretizeSubCwR].
 
  self machineCodeAt: 0 put: (self addiuR: destReg R: leftReg C: rightImm negated).
  ^4!

Item was removed:
- ----- Method: CogMIPSELCompiler>>concretizeSubRR (in category 'generate machine code - concretize') -----
- concretizeSubRR
- | destReg leftReg rightReg |
- rightReg := operands at: 0.
- destReg := leftReg := operands at: 1.
- self machineCodeAt: 0 put: (self subuR: destReg R: leftReg R: rightReg).
- ^4!

Item was added:
+ ----- Method: CogMIPSELCompiler>>concretizeSubRRDest: (in category 'generate machine code - concretize') -----
+ concretizeSubRRDest: destReg
+ | leftReg rightReg |
+ rightReg := operands at: 0.
+ leftReg := operands at: 1.
+ self machineCodeAt: 0 put: (self subuR: destReg R: leftReg R: rightReg).
+ ^4!

Item was changed:
  ----- Method: CogMIPSELCompiler>>concretizeTstCqR (in category 'generate machine code - concretize') -----
  concretizeTstCqR
  | leftReg rightImm |
  rightImm := operands at: 0.
  leftReg := operands at: 1.
 
+ (self isShortOffset: rightImm) ifFalse: [^self concretizeTstCwR].
- (rightImm between: -16r8000 and: 16r7FFF) ifFalse: [^self concretizeTstCwR].
 
  self machineCodeAt: 0 put: (self andiR: Cmp R: leftReg C: rightImm).
  ^4!

Item was changed:
  ----- Method: CogMIPSELCompiler>>dispatchConcretize (in category 'generate machine code') -----
  dispatchConcretize
  "Attempt to generate concrete machine code for the instruction at address.
  This is the inner dispatch of concretizeAt: actualAddress which exists only
  to get around the branch size limits in the SqueakV3 (blue book derived)
  bytecode set."
  opcode caseOf: {
  [BrEqualRR] -> [^self concretizeBrEqualRR].
  [BrNotEqualRR] -> [^self concretizeBrNotEqualRR].
  [BrUnsignedLessRR] -> [^self concretizeBrUnsignedLessRR].
  [BrUnsignedLessEqualRR] -> [^self concretizeBrUnsignedLessEqualRR].
  [BrUnsignedGreaterRR] -> [^self concretizeBrUnsignedGreaterRR].
  [BrUnsignedGreaterEqualRR] -> [^self concretizeBrUnsignedGreaterEqualRR].
  [BrSignedLessRR] -> [^self concretizeBrSignedLessRR].
  [BrSignedLessEqualRR] -> [^self concretizeBrSignedLessEqualRR].
  [BrSignedGreaterRR] -> [^self concretizeBrSignedGreaterRR].
  [BrSignedGreaterEqualRR] -> [^self concretizeBrSignedGreaterEqualRR].
  [BrLongEqualRR] -> [^self concretizeBrLongEqualRR].
  [BrLongNotEqualRR] -> [^self concretizeBrLongNotEqualRR].
  [MulRR] -> [^self concretizeUnimplemented].
  [DivRR] -> [^self concretizeDivRR].
  [MoveLowR] -> [^self concretizeMoveLowR].
  [MoveHighR] -> [^self concretizeMoveHighR].
 
 
  "Noops & Pseudo Ops"
  [Label] -> [^self concretizeLabel].
  [AlignmentNops] -> [^self concretizeAlignmentNops].
  [Fill32] -> [^self concretizeFill32].
  [Nop] -> [^self concretizeNop].
  "Control"
  [Call] -> [^self concretizeCall]. "call code within code space"
  [CallFull] -> [^self concretizeCallFull]. "call code anywhere in address space"
  [JumpR] -> [^self concretizeJumpR].
  [JumpFull] -> [^self concretizeJumpFull]."jump within address space"
  [JumpLong] -> [^self concretizeJumpLong]."jumps witihn code space"
  [JumpLongZero] -> [^self concretizeJumpLongZero].
  [JumpLongNonZero] -> [^self concretizeJumpLongNonZero].
  [Jump] -> [^self concretizeJump].
  [JumpZero] -> [^self concretizeJumpZero].
  [JumpNonZero] -> [^self concretizeJumpNonZero].
  [JumpNegative] -> [^self concretizeUnimplemented].
  [JumpNonNegative] -> [^self concretizeUnimplemented].
  [JumpOverflow] -> [^self concretizeJumpOverflow].
  [JumpNoOverflow] -> [^self concretizeJumpNoOverflow].
  [JumpCarry] -> [^self concretizeUnimplemented].
  [JumpNoCarry] -> [^self concretizeUnimplemented].
  [JumpLess] -> [^self concretizeJumpSignedLessThan].
  [JumpGreaterOrEqual] -> [^self concretizeJumpSignedGreaterEqual].
  [JumpGreater] -> [^self concretizeJumpSignedGreaterThan].
  [JumpLessOrEqual] -> [^self concretizeJumpSignedLessEqual].
  [JumpBelow] -> [^self concretizeJumpUnsignedLessThan].
  [JumpAboveOrEqual] -> [^self concretizeJumpUnsignedGreaterEqual].
  [JumpAbove] -> [^self concretizeJumpUnsignedGreaterThan].
  [JumpBelowOrEqual] -> [^self concretizeJumpUnsignedLessEqual].
  [JumpFPEqual] -> [^self concretizeUnimplemented].
  [JumpFPNotEqual] -> [^self concretizeUnimplemented].
  [JumpFPLess] -> [^self concretizeUnimplemented].
  [JumpFPGreaterOrEqual] -> [^self concretizeUnimplemented].
  [JumpFPGreater] -> [^self concretizeUnimplemented].
  [JumpFPLessOrEqual] -> [^self concretizeUnimplemented].
  [JumpFPOrdered] -> [^self concretizeUnimplemented].
  [JumpFPUnordered] -> [^self concretizeUnimplemented].
  [RetN] -> [^self concretizeRetN].
  [Stop] -> [^self concretizeStop].
  "Arithmetic"
  [AddCqR] -> [^self concretizeAddCqR].
+ [AndCqR] -> [^self concretizeAndCqRDest: (operands at: 1)].
+ [AndCqRR] -> [^self concretizeAndCqRDest: (operands at: 2)].
+ [OrCqRR] -> [^self concretizeOrCqRR].
- [AndCqR] -> [^self concretizeAndCqR].
- [AndCqRR] -> [^self concretizeAndCqRR].
- [AndCqRR] -> [^self concretizeOrCqRR].
  [CmpCqR] -> [^self concretizeCmpCqR].
  [OrCqR] -> [^self concretizeOrCqR].
  [SubCqR] -> [^self concretizeSubCqR].
  [TstCqR] -> [^self concretizeTstCqR].
  [XorCqR] -> [^self concretizeUnimplemented].
  [AddCwR] -> [^self concretizeAddCwR].
  [AndCwR] -> [^self concretizeAndCwR].
  [CmpCwR] -> [^self concretizeCmpCwR].
  [OrCwR] -> [^self concretizeOrCwR].
  [SubCwR] -> [^self concretizeSubCwR].
  [XorCwR] -> [^self concretizeXorCwR].
+ [AddRR] -> [^self concretizeAddRRDest: (operands at: 1)].
+ [AndRR] -> [^self concretizeAndRR].
- [AddRR] -> [^self concretizeAddRR].
- [AndRR] -> [^self concretizeAndRR].
  [CmpRR] -> [^self concretizeCmpRR].
  [OrRR] -> [^self concretizeOrRR].
+ [SubRR] -> [^self concretizeSubRRDest: (operands at: 1)].
- [SubRR] -> [^self concretizeSubRR].
  [XorRR] -> [^self concretizeXorRR].
+ [AddRRR] -> [^self concretizeAddRRDest: (operands at: 2)].
+ [SubRRR] -> [^self concretizeSubRRDest: (operands at: 2)].
  [AddRdRd] -> [^self concretizeUnimplemented].
  [CmpRdRd] -> [^self concretizeUnimplemented].
  [DivRdRd] -> [^self concretizeUnimplemented].
  [MulRdRd] -> [^self concretizeUnimplemented].
  [SubRdRd] -> [^self concretizeUnimplemented].
  [SqrtRd] -> [^self concretizeUnimplemented].
  [NegateR] -> [^self concretizeNegateR].
  [LoadEffectiveAddressMwrR] -> [^self concretizeLoadEffectiveAddressMwrR].
  [ArithmeticShiftRightCqR] -> [^self concretizeArithmeticShiftRightCqR].
  [LogicalShiftRightCqR] -> [^self concretizeLogicalShiftRightCqR].
  [LogicalShiftLeftCqR] -> [^self concretizeLogicalShiftLeftCqR].
  [ArithmeticShiftRightRR] -> [^self concretizeArithmeticShiftRightRR].
  [LogicalShiftLeftRR] -> [^self concretizeLogicalShiftLeftRR].
  [LogicalShiftRightRR] -> [^self concretizeLogicalShiftRightRR].
  [ClzRR] -> [^self concretizeClzRR].
  "Data Movement"
  [MoveCqR] -> [^self concretizeMoveCqR].
  [MoveCwR] -> [^self concretizeMoveCwR].
  [MoveRR] -> [^self concretizeMoveRR].
  [MoveAwR] -> [^self concretizeMoveAwR].
  [MoveRAw] -> [^self concretizeMoveRAw].
  [MoveAbR] -> [^self concretizeMoveAbR].
  [MoveRAb] -> [^self concretizeMoveRAb].
  [MoveMbrR] -> [^self concretizeMoveMbrR].
  [MoveRMbr] -> [^self concretizeUnimplemented].
  [MoveM16rR] -> [^self concretizeMoveM16rR].
  [MoveRM16r] -> [^self concretizeMoveRM16r].
  [MoveM64rRd] -> [^self concretizeUnimplemented].
  [MoveMwrR] -> [^self concretizeMoveMwrR].
  [MoveXbrRR] -> [^self concretizeMoveXbrRR].
  [MoveRXbrR] -> [^self concretizeMoveRXbrR].
  [MoveXwrRR] -> [^self concretizeMoveXwrRR].
  [MoveRXwrR] -> [^self concretizeMoveRXwrR].
  [MoveRMwr] -> [^self concretizeMoveRMwr].
  [MoveRdM64r] -> [^self concretizeUnimplemented].
  [PopR] -> [^self concretizePopR].
  [PushR] -> [^self concretizePushR].
  [PushCq] -> [^self concretizePushCq].
  [PushCw] -> [^self concretizePushCw].
  [PrefetchAw] -> [^self concretizePrefetchAw].
  [AddCheckOverflowCqR] -> [^self concretizeAddCheckOverflowCqR].
  [AddCheckOverflowRR] -> [^self concretizeAddCheckOverflowRR].
  [SubCheckOverflowCqR] -> [^self concretizeSubCheckOverflowCqR].
  [SubCheckOverflowRR] -> [^self concretizeSubCheckOverflowRR].
  [MulCheckOverflowRR] -> [^self concretizeMulCheckOverflowRR].
  "Conversion"
  [ConvertRRd] -> [^self concretizeUnimplemented]}.
 
  ^0 "keep Slang happy"!

Item was added:
+ ----- Method: CogMIPSELCompiler>>flushDCacheFrom:to: (in category 'inline cacheing') -----
+ flushDCacheFrom: startAddress "<Integer>" to: endAddress "<Integer>"
+ "If there is a dual mapped code zone (the normal zone but marked with read/execute, and a
+ read/write zone codeToDataDelta bytes away) then flush the data cache for the corresponding
+ range in the read/write zone and invalidate the data cache for the read/execute zone."
+ <cmacro: '(me,startAddress,endAddress) 0'>
+ "Currently we don't know whether a dual zone on a 32-bit MIPS would require cache
+ flushing to ensure coherence.  So for now this is a no op."!

Item was changed:
  ----- Method: CogMIPSELCompiler>>itype:rs:rt:signedImmediate: (in category 'encoding') -----
  itype: op rs: rs rt: rt signedImmediate: immediate
  self assert: (op between: 0 and: 63).
  self assert: (rs between: 0 and: 31).
  self assert: (rt between: 0 and: 31).
+ self assert: (self isShortOffset: immediate).
- self assert: (immediate between: -16r8000 and: 16r7FFF).
  "signedImmediate < 0
  ifTrue: [unsignedImmediate := signedImmediate + 16r10000]
  ifFalse: [unsignedImmediate := signedImmediate].
  self assert: (unsignedImmediate between: 0 and: 16rFFFF)."
  ^(((op << 26) bitOr: (rs << 21)) bitOr: (rt << 16)) bitOr: (immediate bitAnd: 16rFFFF)!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genStoreCheckTrampoline (in category 'initialization') -----
  genStoreCheckTrampoline
  | jumpSC |
  <var: #jumpSC type: #'AbstractInstruction *'>
  <inline: true>
  CheckRememberedInTrampoline ifTrue:
  [cogit zeroOpcodeIndex.
+ jumpSC := self genCheckRememberedBitOf: ReceiverResultReg scratch: cogit ABIResultReg.
- jumpSC := self genCheckRememberedBitOf: ReceiverResultReg scratch: cogit backEnd cResultRegister.
  self assert: jumpSC opcode = JumpNonZero.
  jumpSC opcode: JumpZero.
  cogit RetN: 0.
  jumpSC jmpTarget: cogit Label].
  ^cogit
  genTrampolineFor: #remember:
  called: 'ceStoreCheckTrampoline'
  numArgs: 1
  arg: ReceiverResultReg
  arg: nil
  arg: nil
  arg: nil
  regsToSave: (CallerSavedRegisterMask bitClear: (cogit registerMaskFor: ReceiverResultReg))
  pushLinkReg: true
  resultReg: cogit returnRegForStoreCheck
  appendOpcodes: CheckRememberedInTrampoline!

Item was removed:
- ----- Method: CogX64Compiler>>cResultRegister (in category 'accessing') -----
- cResultRegister
- "Answer the register through which C functions return integral results."
- <inline: true>
- ^RAX!

Item was added:
+ ----- Method: CogX64Compiler>>flushDCacheFrom:to: (in category 'inline cacheing') -----
+ flushDCacheFrom: startAddress "<Integer>" to: endAddress "<Integer>"
+ "If there is a dual mapped code zone (the normal zone but marked with read/execute, and a
+ read/write zone codeToDataDelta bytes away) then flush the data cache for the corresponding
+ range in the read/write zone and invalidate the data cache for the read/execute zone."
+ <cmacro: '(me,startAddress,endAddress) 0'>
+ "Currently we don't know whether a dual zone on an Intel x86/x86-64 would require cache
+ flushing to ensure coherence.  So for now this is a no op."!

Item was changed:
  ----- Method: CogX64Compiler>>flushICacheFrom:to: (in category 'inline cacheing') -----
  flushICacheFrom: startAddress "<Integer>" to: endAddress "<Integer>"
  "Flush the instruction cache from (startAddress to endAddress].
  If there is a dual mapped code zone (the normal zone but marked with read/execute, and a
  read/write zone codeToDataDelta bytes away) then also flush the data cache for the corresp-
  onding range in the read/write zone and invalidate the data cache for the read/execute zone."
  <cmacro: '(me,startAddress,endAddress) 0'>
  "On Intel processors where code and data have the same linear address, no
+ special action is required to flush the instruction cache.  One only needs to
- special action is required to flush the instruciton cache.  One only needs to
  execute a serializing instruction (e.g. CPUID) if code and data are at different
  virtual addresses (e.g. a debugger using memory-mapping to access a debugee).
  Using the macro avoids an unnecessary call."!

Item was added:
+ ----- Method: Cogit class>>choose32BitISA (in category 'accessing class hierarchy') -----
+ choose32BitISA
+ ^[:choices| choices at: (UIManager default chooseFrom: choices) ifAbsent: [^nil]]
+ value: (CogAbstractInstruction allSubclasses select: [:c| c wordSize = 4] thenCollect: [:ea| ea ISA]) asSet asArray sorted!

Item was added:
+ ----- Method: Cogit class>>choose64BitISA (in category 'accessing class hierarchy') -----
+ choose64BitISA
+ ^[:choices| choices at: (UIManager default chooseFrom: choices) ifAbsent: [^nil]]
+ value: (CogAbstractInstruction allSubclasses select: [:c| c wordSize = 8] thenCollect: [:ea| ea ISA]) asSet asArray sorted!

Item was changed:
  ----- Method: Cogit class>>initializedInstanceForTests: (in category 'in-image compilation support') -----
  initializedInstanceForTests: optionsDictionaryOrArray
  "Answer an instance of a Cogit suitable for running tests that has initialized
  its method zone (generated trampolines etc)"
  | cogit coInterpreter |
  cogit := self instanceForTests: optionsDictionaryOrArray.
  coInterpreter := CurrentImageCoInterpreterFacade forCogit: cogit.
+ [| rumpStackSize |
+ rumpStackSize := 1024 * 4.
+ cogit
- [cogit
  setInterpreter: coInterpreter;
  singleStep: true;
+ initializeCodeZoneFrom: 1024 upTo: coInterpreter memory byteSize - rumpStackSize.
- initializeCodeZoneFrom: 1024 upTo: coInterpreter memory byteSize.
  cogit methodZone freeStart: (cogit methodZone freeStart roundUpTo: 1024)]
  on: Notification
  do: [:ex|
  (ex messageText beginsWith: 'cannot find receiver for') ifTrue:
  [ex resume: coInterpreter].
  ex pass].
  ^cogit!

Item was removed:
- ----- Method: Cogit>>genGetLeafCallStackPointer (in category 'initialization') -----
- genGetLeafCallStackPointer
- "Generate a routine that answers the stack pointer immedately
- after a leaf call, used for checking stack pointer alignment."
- | startAddress |
- <inline: false>
- self allocateOpcodes: 4 bytecodes: 0.
- startAddress := methodZoneBase.
- self
- MoveR: FPReg R: backEnd cResultRegister;
- RetN: 0.
- self outputInstructionsForGeneratedRuntimeAt: startAddress.
- self recordGeneratedRunTime: 'ceGetFP' address: startAddress.
- ceGetFP := self cCoerceSimple: startAddress to: #'usqIntptr_t (*)(void)'.
- startAddress := methodZoneBase.
- self zeroOpcodeIndex.
- self MoveR: SPReg R: backEnd cResultRegister.
- backEnd leafCallStackPointerDelta ~= 0 ifTrue:
- [self AddCq: backEnd leafCallStackPointerDelta R: backEnd cResultRegister].
- self RetN: 0.
- self outputInstructionsForGeneratedRuntimeAt: startAddress.
- self recordGeneratedRunTime: 'ceGetSP' address: startAddress.
- ceGetSP := self cCoerceSimple: startAddress to: #'usqIntptr_t (*)(void)'!

Item was added:
+ ----- Method: Cogit>>genGetLeafCallStackPointers (in category 'initialization') -----
+ genGetLeafCallStackPointers
+ "Generate a pair of routines that answer the frame pointer, and the stack pointer immediately
+ after a leaf call, used for checking stack pointer alignment, frame pointer usage, etc. N.B.
+ these are exported to the CoInterpreter et al via Cogit class>>mustBeGlobal:."
+ | startAddress |
+ <inline: false>
+ self allocateOpcodes: 4 bytecodes: 0.
+ startAddress := methodZoneBase.
+ self
+ MoveR: FPReg R: ABIResultReg;
+ RetN: 0.
+ self outputInstructionsForGeneratedRuntimeAt: startAddress.
+ self recordGeneratedRunTime: 'ceGetFP' address: startAddress.
+ ceGetFP := self cCoerceSimple: startAddress to: #'usqIntptr_t (*)(void)'.
+ startAddress := methodZoneBase.
+ self zeroOpcodeIndex.
+ self MoveR: NativeSPReg R: ABIResultReg.
+ backEnd leafCallStackPointerDelta ~= 0 ifTrue:
+ [self AddCq: backEnd leafCallStackPointerDelta R: ABIResultReg].
+ self RetN: 0.
+ self outputInstructionsForGeneratedRuntimeAt: startAddress.
+ self recordGeneratedRunTime: 'ceGetSP' address: startAddress.
+ ceGetSP := self cCoerceSimple: startAddress to: #'usqIntptr_t (*)(void)'!

Item was changed:
  ----- Method: Cogit>>initializeCodeZoneFrom:upTo: (in category 'initialization') -----
  initializeCodeZoneFrom: startAddress upTo: endAddress
  <api>
  self initializeBackend.
  self sqMakeMemoryExecutableFrom: startAddress
  To: endAddress
  CodeToDataDelta: (self addressOf: codeToDataDelta put: [:v| codeToDataDelta := v]).
  backEnd stopsFrom: startAddress to: endAddress - 1.
  self cCode: '' inSmalltalk:
  [self initializeProcessor.
  backEnd stopsFrom: 0 to: guardPageSize - 1].
  codeBase := methodZoneBase := startAddress.
  minValidCallAddress := (codeBase min: coInterpreter interpretAddress)
  min: coInterpreter primitiveFailAddress.
  methodZone manageFrom: methodZoneBase to: endAddress.
  self assertValidDualZone.
  self maybeGenerateCheckFeatures.
  self maybeGenerateCheckLZCNT.
  self maybeGenerateCacheFlush.
  self generateVMOwnerLockFunctions.
+ self genGetLeafCallStackPointers.
- self genGetLeafCallStackPointer.
  self generateStackPointerCapture.
  self generateTrampolines.
  self computeEntryOffsets.
  self computeFullBlockEntryOffsets.
  self generateClosedPICPrototype.
  self alignMethodZoneBase.
 
  "None of the above is executed beyond ceCheckFeatures & ceCheckLZCNTFunction,
  so a bulk flush now is the leanest thing to do."
  self maybeFlushWritableZoneFrom: startAddress to: methodZoneBase asUnsignedInteger.
  "repeat so that now the methodZone ignores the generated run-time"
  methodZone manageFrom: methodZoneBase to: endAddress.
  "N.B. this is assumed to be the last thing done in initialization; see Cogit>>initialized"
  self generateOpenPICPrototype!

Item was added:
+ ----- Method: CurrentImageCoInterpreterFacade class>>clusteredVariableNames (in category 'translation') -----
+ clusteredVariableNames
+ ^CoInterpreter clusteredVariableNames!

Item was changed:
  ----- Method: CurrentImageCoInterpreterFacade>>addressForLabel: (in category 'labels') -----
  addressForLabel: l
+ ^variables at: l ifAbsentPut: [variables size + 1 * objectMemory wordSize + self variablesBase]!
- ^variables at: l ifAbsentPut: [variables size * objectMemory wordSize + self variablesBase]!

Item was changed:
  ----- Method: CurrentImageCoInterpreterFacade>>cogit: (in category 'initialize-release') -----
  cogit: aCogit
  cogit := aCogit.
  cogit objectMemory ifNil:
  [cogit instVarNamed: 'objectMemory' put: objectMemory].
  coInterpreter cogit: aCogit.
  (objectMemory respondsTo: #cogit:) ifTrue:
  [objectMemory cogit: aCogit].
  (objectMemory respondsTo: #coInterpreter:) ifTrue:
  [objectMemory coInterpreter: coInterpreter].
  coInterpreter setUpForUseByFacade: self.
  objectMemory setUpForUseByFacade: self.
+ coInterpreter class clusteredVariableNames do:
+ [:var| self perform: ((var first = $C ifTrue: ['c', var allButFirst] ifFalse: [var]), 'Address') asSymbol].
- #('stackLimit') do:
- [:l| self addressForLabel: l].
  self initializeObjectMap!

Item was added:
+ ----- Method: CurrentImageCoInterpreterFacade>>nativeSPAddress (in category 'accessing') -----
+ nativeSPAddress
+ ^self addressForLabel: #nativeSP!

Item was added:
+ ----- Method: CurrentImageCoInterpreterFacade>>shadowCallStackPointerAddress (in category 'accessing') -----
+ shadowCallStackPointerAddress
+ ^self addressForLabel: #shadowCallStackPointer!

Item was changed:
+ ----- Method: CurrentImageCoInterpreterFacade>>stackLimitAddress (in category 'accessing') -----
- ----- Method: CurrentImageCoInterpreterFacade>>stackLimitAddress (in category 'labels') -----
  stackLimitAddress
+ ^self addressForLabel: #stackLimit!
- ^variables at: 'stackLimit'!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>compileMachineCodeInterpreterPrimitive: (in category 'primitive generators') -----
  compileMachineCodeInterpreterPrimitive: primitiveRoutine
  "Compile a call to a machine-code convention interpreter primitive.  Call the C routine
  on the Smalltalk stack, assuming it consumes little or no stack space."
  <var: #primitiveRoutine declareC: 'void (*primitiveRoutine)(void)'>
  | jmpFail liveRegsMask |
  "for now handle functions with less than 4 arguments; our C call marshalling machinery
  extends up to 4 arguments only, and the first argument of an mcprim is the receiver."
  self assert: methodOrBlockNumArgs <= 3.
  liveRegsMask := (methodOrBlockNumArgs > self numRegArgs
    or: [methodOrBlockNumArgs = 0])
  ifTrue:
  [self registerMaskFor: ReceiverResultReg]
  ifFalse:
  [(self numRegArgs > 1 and: [methodOrBlockNumArgs > 1])
  ifFalse: [self registerMaskFor: ReceiverResultReg and: Arg0Reg]
  ifTrue: [self registerMaskFor: ReceiverResultReg and: Arg0Reg and: Arg1Reg]].
  backEnd genSaveRegs: (liveRegsMask bitAnd: CallerSavedRegisterMask).
  methodOrBlockNumArgs > self numRegArgs ifTrue:
  ["Wrangle args into Arg0Reg, Arg1Reg, SendNumArgsReg & ClassReg"
  "offset := self bitCountOf: (liveRegsMask bitAnd: CallerSavedRegisterMask)."
  self shouldBeImplemented].
  backEnd
  genMarshallNArgs: methodOrBlockNumArgs + 1
  arg: ReceiverResultReg
  arg: Arg0Reg
  arg: Arg1Reg
  arg: SendNumArgsReg
  "arg: ClassReg (when we extend C call marshalling to support 5 args for replaceFrom:to:with:startingAt:".
  backEnd saveAndRestoreLinkRegUsingCalleeSavedRegNotLiveAtPointOfSendAround:
  [self CallFullRT: primitiveRoutine asInteger].
  backEnd
  genRemoveNArgsFromStack: methodOrBlockNumArgs + 1;
  genRestoreRegs: (liveRegsMask bitAnd: CallerSavedRegisterMask).
+ self CmpCq: 0 R: ABIResultReg.
- self CmpCq: 0 R: backEnd cResultRegister.
  jmpFail := self JumpZero: 0.
  backEnd genWriteCResultIntoReg: ReceiverResultReg.
  self RetN: (methodOrBlockNumArgs > self numRegArgs
  ifTrue: [methodOrBlockNumArgs + 1 * objectMemory wordSize]
  ifFalse: [0]).
  jmpFail jmpTarget: self Label.
  ^0!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>returnRegForStoreCheck (in category 'trampolines') -----
  returnRegForStoreCheck
  "We must ensure the ReceiverResultReg is live across the store check so that
  receiver inst vars can be stored into in a frameless method since self exists only
  in ReceiverResultReg in a frameless method.  So if ReceiverResultReg is caller-saved
  we use the fact that ceStoreCheck:/remember: answer their argument to reload
  ReceiverResultReg cheaply.  Otherwise we don't care about the result and use the
  cResultRegister, effectively a no-op (see compileTrampoline...)."
  <inline: true>
  ^(self isCallerSavedReg: ReceiverResultReg)
  ifTrue: [ReceiverResultReg]
+ ifFalse: [ABIResultReg]!
- ifFalse: [backEnd cResultRegister]!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallIndirectInt32 (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallIndirectInt32
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  self ssNativeTop nativeStackPopToReg: TempReg.
  self ssNativePop: 1.
  self callSwitchToCStack.
  self CallRT: ceFFICalloutTrampoline.
  self annotateBytecode: self Label.
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
 
  ^ 0
 
  !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallIndirectInt64 (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallIndirectInt64
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  self ssNativeTop nativeStackPopToReg: TempReg.
  self ssNativePop: 1.
  self callSwitchToCStack.
  self CallRT: ceFFICalloutTrampoline.
+ self annotateBytecode: (self MoveR: ABIResultReg R: ReceiverResultReg).
+ BytesPerWord = 4
+ ifTrue:
+ [self MoveR: ABIResultRegHigh R: Arg0Reg.
+ self ssPushNativeRegister: ReceiverResultReg secondRegister: Arg0Reg]
+ ifFalse:
+ [self MoveR: ABIResultReg R: ReceiverResultReg.
+ self ssPushNativeRegister: ReceiverResultReg].
+ ^0!
- self annotateBytecode: self Label.
- BytesPerWord = 4 ifTrue: [
- self MoveR: backEnd cResultRegisterLow R: ReceiverResultReg.
- self MoveR: backEnd cResultRegisterHigh R: Arg0Reg.
- self ssPushNativeRegister: ReceiverResultReg secondRegister: Arg0Reg.
- ] ifFalse: [
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
- self ssPushNativeRegister: ReceiverResultReg.
- ].
-
- ^ 0
-
- !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallIndirectPointer (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallIndirectPointer
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  self ssNativeTop nativeStackPopToReg: TempReg.
  self ssNativePop: 1.
  self callSwitchToCStack.
  self CallRT: ceFFICalloutTrampoline.
  self annotateBytecode: self Label.
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
 
  ^ 0
 
  !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallIndirectStructure (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallIndirectStructure
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  "Push the result space"
  self ssNativeTop nativeStackPopToReg: TempReg.
  self ssNativePop: 1.
  self PushR: TempReg.
  "Fetch the function pointer"
  self ssNativeTop nativeStackPopToReg: TempReg.
  self ssNativePop: 1.
  "Call the function"
  self callSwitchToCStack.
  self CallRT: ceFFICalloutTrampoline.
  self annotateBytecode: self Label.
  "Fetch the result"
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
  extA := 0.
 
  ^ 0
 
  !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallInt32 (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallInt32
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  self callSwitchToCStack.
  self MoveCw: extA R: TempReg.
  self CallRT: ceFFICalloutTrampoline.
  self annotateBytecode: self Label.
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
  extA := 0.
 
  ^ 0
 
  !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallInt64 (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallInt64
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  self callSwitchToCStack.
  self MoveCw: extA R: TempReg.
- self CallRT: ceFFICalloutTrampoline.
- self annotateBytecode: self Label.
- BytesPerWord = 4 ifTrue: [
- self MoveR: backEnd cResultRegisterLow R: ReceiverResultReg.
- self MoveR: backEnd cResultRegisterHigh R: Arg0Reg.
- self ssPushNativeRegister: ReceiverResultReg secondRegister: Arg0Reg.
- ] ifFalse: [
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
- self ssPushNativeRegister: ReceiverResultReg.
- ].
  extA := 0.
+ self CallRT: ceFFICalloutTrampoline.
+ self annotateBytecode: (self MoveR: ABIResultReg R: ReceiverResultReg).
+ BytesPerWord = 4
+ ifTrue:
+ [self MoveR: ABIResultRegHigh R: Arg0Reg.
+ self ssPushNativeRegister: ReceiverResultReg secondRegister: Arg0Reg]
+ ifFalse:
+ [self MoveR: ABIResultReg R: ReceiverResultReg.
+ self ssPushNativeRegister: ReceiverResultReg].
+ ^0!
-
- ^ 0
-
- !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallPointer (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallPointer
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  self callSwitchToCStack.
  self MoveCw: extA R: TempReg.
  self CallRT: ceFFICalloutTrampoline.
  self annotateBytecode: self Label.
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
  extA := 0.
 
  ^ 0
 
  !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePerformCallStructure (in category 'inline primitive generators generated code') -----
  genLowcodePerformCallStructure
  <option: #LowcodeVM> "Lowcode instruction generator"
 
  "Push the result space"
  self ssNativeTop nativeStackPopToReg: TempReg.
  self ssNativePop: 1.
  self PushR: TempReg.
  "Call the function"
  self callSwitchToCStack.
  self MoveCw: extA R: TempReg.
  self CallRT: ceFFICalloutTrampoline.
  self annotateBytecode: self Label.
  "Fetch the result"
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
  extA := 0.
  extB := 0.
  numExtB := 0.
 
  ^ 0
 
  !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePushCalloutResultInt32 (in category 'inline primitive generators generated code') -----
  genLowcodePushCalloutResultInt32
  <option: #LowcodeVM>
  <inline: true>
  "Generated by the Lowcode instruction generator."
 
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
 
  ^ 0
 
  !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePushCalloutResultInt64 (in category 'inline primitive generators generated code') -----
  genLowcodePushCalloutResultInt64
  <option: #LowcodeVM>
  <inline: true>
- "Generated by the Lowcode instruction generator."
 
+ self MoveR: ABIResultReg R: ReceiverResultReg.
+ BytesPerWord = 4
+ ifTrue:
+ [self MoveR: ABIResultRegHigh R: Arg0Reg.
+ self ssPushNativeRegister: ReceiverResultReg secondRegister: Arg0Reg]
+ ifFalse:
+ [self MoveR: ABIResultReg R: ReceiverResultReg.
+ self ssPushNativeRegister: ReceiverResultReg].
+ ^0!
- BytesPerWord = 4 ifTrue: [
- self MoveR: backEnd cResultRegisterLow R: ReceiverResultReg.
- self MoveR: backEnd cResultRegisterHigh R: Arg0Reg.
- self ssPushNativeRegister: ReceiverResultReg secondRegister: Arg0Reg.
- ] ifFalse: [
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
- self ssPushNativeRegister: ReceiverResultReg.
- ].
-
- ^ 0
-
- !

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genLowcodePushCalloutResultPointer (in category 'inline primitive generators generated code') -----
  genLowcodePushCalloutResultPointer
  <option: #LowcodeVM>
  <inline: true>
  "Generated by the Lowcode instruction generator."
 
+ self MoveR: ABIResultReg R: ReceiverResultReg.
- self MoveR: backEnd cResultRegister R: ReceiverResultReg.
  self ssPushNativeRegister: ReceiverResultReg.
 
  ^ 0
 
  !