[Vm-dev] VM Maker: VMMaker.oscog-eem.1506.mcz
commits at source.squeak.org
commits at source.squeak.org
Tue Nov 3 21:56:23 UTC 2015
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
==================== Summary ====================
Time: 3 November 2015, 1:54:20.959 pm
Oops! remember to comment the byte read convention in CogRTLOpcodes class>>initialize
=============== Diff against VMMaker.oscog-eem.1505 ===============
Item was changed:
----- Method: CogRTLOpcodes class>>initialize (in category 'class initialization') -----
"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.
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.
- 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).
- to use the cResultRegister as a scratch if required (e.g. on x64 where there is no direct 64-bit call or jump)."
+ Byte reads. If the concrete compiler class answers true to byteReadsZeroExtend then byte reads must zero-extend
+ the byte read into the destination register. If not, the other bits of the register should be left undisturbed and the
+ Cogit will add an instruction to zero the register as required. Under no circumstances should byte reads sign-extend."
| opcodeNames refs |
"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"
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.
"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.
LinkReg := -17.
RISCTempReg := -18. "Used to synthesize CISC instructions from multiple RISC instructions."
PCReg := -19.
VarBaseReg := -20. "If useful, points to base of interpreter variables."
DPFPReg0 := -21.
DPFPReg1 := -22.
DPFPReg2 := -23.
DPFPReg3 := -24.
DPFPReg4 := -25.
DPFPReg5 := -26.
DPFPReg6 := -27.
DPFPReg7 := -28.
opcodeNames := #("Noops & Pseudo Ops"
Literal "a word-sized literal"
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"
Call "call within the code zone"
CallFull "call anywhere within the full address space"
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"
"Data Movement; destination is always last operand"
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
"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"
CmpRR AddRR SubRR AndRR OrRR XorRR
CmpCqR AddCqR SubCqR AndCqR OrCqR TstCqR XorCqR
CmpCwR CmpC32R AddCwR SubCwR AndCwR OrCwR XorCwR
CmpRdRd AddRdRd SubRdRd MulRdRd DivRdRd SqrtRd
"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:
Undeclared declare: k from: classPool].
"Declare as class variables and number elements of opcodeArray above"
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]]!
More information about the Vm-dev