asm/AJx86Registers.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 17 Jun 2016 17:25:15 +0100
changeset 26 8eb6716029aa
parent 23 d2d9a2d4d6bf
permissions -rw-r--r--
Merge

"
    Copyright (c) 2012-2016 Igor Stasenko
                            Martin McClure
                            Damien Pollet
                            Camillo Bruni
                            Guido Chari
                   2016-now Jan Vrany <jan.vrany [at] fit . cvut . cz>

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the 'Software'), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
"
"{ Package: 'jv:dragonfly/asm' }"

"{ NameSpace: Smalltalk }"

SharedPool subclass:#AJx86Registers
	instanceVariableNames:''
	classVariableNames:'AH AL AX BH BL BP BPL BX CH CL CX Codes DH DI DIL DL DX EAX EBP
		EBX ECX EDI EDX EIP ESI ESP IP MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7
		R10 R10B R10D R10W R11 R11B R11D R11W R12 R12B R12D R12W R13 R13B
		R13D R13W R14 R14B R14D R14W R15 R15B R15D R15W R8 R8B R8D R8W R9
		R9B R9D R9W RAX RBP RBX RCX RDI RDX RIP RSI RSP SI SIL SP SPL ST0
		ST1 ST2 ST3 ST4 ST5 ST6 ST7 XMM0 XMM1 XMM10 XMM11 XMM12 XMM13
		XMM14 XMM15 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 XMM9'
	poolDictionaries:'AJConstants'
	category:'AsmJit-x86'
!

AJx86Registers comment:'I am a SHaredPool which initializes all the registers needed by the Assmbler.'
!

!AJx86Registers class methodsFor:'documentation'!

copyright
"
    Copyright (c) 2012-2016 Igor Stasenko
                            Martin McClure
                            Damien Pollet
                            Camillo Bruni
                            Guido Chari
                   2016-now Jan Vrany <jan.vrany [at] fit . cvut . cz>

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the 'Software'), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.

"
! !

!AJx86Registers class methodsFor:'initialization'!

initialize
    "AJx86Registers initialize"
        
    self classPool at: #Codes put: IdentityDictionary new. 
    
    self initializeGeneralPurpose8BitRegisters.
    self initializeGeneralPurpose16BitRegisters.
    self initializeGeneralPurpose32BitRegisters.
    self initializeGeneralPurpose64BitRegisters.
    
    self initializeInstructionPointerRegisters.
    
    self initializeX87Registers.
    self initializeMMXRegisters.
    self initializeSSERegisters.
!

initializeGeneralPurpose16BitRegisters
    "initialize general purpose 16 bit registers "

    self
        registerBase: 16r10
            class: AJx86GPRegister
            rex: #dontCare
            values: #(#AX #CX #DX #BX #SP #BP #SI #DI);
        registerBase: 16r18
            class: AJx86GPRegister
            rex: #required
            values: #(#R8W #R9W #R10W #R11W #R12W #R13W #R14W #R15W)
!

initializeGeneralPurpose32BitRegisters
    "initialize general purpose 32 bit registers "

    self
        registerBase: 16r20
            class: AJx86GPRegister
            rex: #dontCare
            values: #(#EAX #ECX #EDX #EBX #ESP #EBP #ESI #EDI);
        registerBase: 16r28
            class: AJx86GPRegister
            rex: #required
            values: #(#R8D #R9D #R10D #R11D #R12D #R13D #R14D #R15D)
!

initializeGeneralPurpose64BitRegisters
    "initialize general purpose 64 bit registers"
    
    self
        registerBase: 16r30
            class: AJx86GPRegister
            rex: #dontCare
            values: #(#RAX #RCX #RDX #RBX #RSP #RBP #RSI #RDI);
        registerBase: 16r38
            class: AJx86GPRegister
            rex: #required
            values: #(#R8 #R9 #R10 #R11 #R12 #R13 #R14 #R15)
!

initializeGeneralPurpose8BitRegisters
    "general purpose 8 bit registers "

    self
        registerBase: 0
            class: AJx86GPRegister
            rex: #dontCare
            values: #(#AL #CL #DL #BL);
        registerBase: 4
            class: AJx86GPRegister
            rex: #prohibited
            values: #(#AH #CH #DH #BH);
        registerBase: 4
            class: AJx86GPRegister
            rex: #required
            values: #(#SPL #BPL #SIL #DIL #R8B #R9B #R10B #R11B #R12B #R13B #R14B #R15B)
!

initializeInstructionPointerRegisters
    | ip eip rip |
    
    ip := AJx64RipRegister code: SI code name: #IP.
    eip := AJx64RipRegister code: ESI code name: #EIP.
    rip := AJx64RipRegister code: RSI code name: #RIP.
    
    Codes 
        at: SI code negated put: #IP;
        at: ESI code negated put: #EIP;
        at: RSI code negated put: #RIP.
    
    self classPool 
        at: #IP put: ip;
        at: #EIP put: eip;
        at: #RIP put: rip.
!

initializeMMXRegisters

    " MMX registers "
    self registerBase: 16r60  class: AJMMRegister values: #(
        #MM0 #MM1   #MM2   #MM3   #MM4   #MM5   #MM6   #MM7 ).
!

initializeSSERegisters
    " SSE registers "
    self registerBase: 16r70 class: AJxMMRegister  values: #(
        #XMM0 #XMM1  #XMM2  #XMM3  #XMM4  #XMM5  #XMM6  #XMM7 
        #XMM8 #XMM9  #XMM10 #XMM11 #XMM12 #XMM13 #XMM14 #XMM15).
!

initializeX87Registers
    "X87 registers"
    self registerBase: 16r50 class: AJx87Register values: #(
        #ST0 #ST1 #ST2 #ST3 #ST4 #ST5 #ST6 #ST7 ).
!

registerBase: base class: regClass rex: rexSymbol values: names 
    | val |
    val := 0.
    rexSymbol == #required
        ifTrue: [ val := 16r100 ].
    rexSymbol == #prohibited
        ifTrue: [ val := 16r200 ].
    val := val + base.
    names
        do: [ :regName | 
            | reg |
            reg := regClass code: val name: regName.
            self classPool at: regName put: reg.
            Codes at: val put: regName.
            val := val + 1 ]
!

registerBase: base class: regClass values: names

    | val |
    val := base.
    names do: [ :regName | | reg |
        reg := regClass code: val name: regName.
        self classPool at: regName put: reg. 
        Codes at: val put: regName.
        val := val + 1].
!

sortRegistersByIndex: aRegisterCollection
    ^ aRegisterCollection sort: [ :regA :regB| regA index < regB index ].
! !

!AJx86Registers class methodsFor:'accessing'!

all
    ^ Codes values collect: [ :each| self classPool at: each ]
!

all16
    ^ self all select: [:reg| reg is16 ]
!

all32
    ^ self all select: [:reg| reg is32 ]
!

all64
    ^ self all select: [:reg| reg is64 ]
!

all8
    ^ self all select: [:reg| reg is8 ]
!

at: aRegisterIdentifierSymbol
    ^ self classPool at: aRegisterIdentifierSymbol
!

code: registerCode
    "Access a register by its code.
    Example:
        RBP == (self code: RBP code)"
    | registerName |
    self flag: 'XXX now this is some ugly code... add an instance variable for the requiresRex boolean instead of encoding it in #code'.
    registerName := Codes at: registerCode ifAbsent: [ 
                Codes at: registerCode + 16r100 ifAbsent: [ 
                    Codes at: registerCode + 16r200 ifAbsent: [  KeyNotFound signalFor: registerCode ] ] ].
    ^ self classPool at: registerName
!

doesNotUnderstand: aMessage
    self classPool at: aMessage selector ifPresent: [:val| ^ val ].
    ^ super doesNotUnderstand: aMessage
!

generalPurpose
    ^ self all select: [ :reg| reg isGeneralPurpose ]
!

generalPurpose16
    ^ self sortRegistersByIndex: (self generalPurpose select: [:reg| reg is16 ])
!

generalPurpose32
    ^ self sortRegistersByIndex: (self generalPurpose select: [:reg| reg is32 ])
!

generalPurpose64
    ^ self sortRegistersByIndex: (self generalPurpose select: [:reg| reg is64 ])
!

generalPurpose8
    ^ self sortRegistersByIndex: (self generalPurpose select: [:reg| reg is8 ])
!

generalPurposeWithIndex: index size: numBytes requiresRex: requiresRex prohibitsRex: prohibitsRex
    "Access a register by its properties.
    Example:
        RBP == (self generalPurposeWithIndex: RBP index size: RBP size requiresRex: RBP requiresRex prohibitsRex: RBP prohibitsRex )"

    | type code |
    type := numBytes = 1
        ifTrue: [ 0 ]
        ifFalse: [ 
            numBytes = 2
                ifTrue: [ 16r10 ]
                ifFalse: [ 
                    numBytes = 4
                        ifTrue: [ 16r20 ]
                        ifFalse: [ 
                            numBytes = 8
                                ifTrue: [ 16r30 ]
                                ifFalse: [ self error: 'Size must be 1, 2, 4, or 8 bytes' ] ] ] ].
    code := type + index.
    requiresRex
        ifTrue: [ code := code + RegRequiresRexMask ].
    prohibitsRex
        ifTrue: [ code := code + RegProhibitsRexMask ].
    ^ self classPool at: (Codes at: code)
! !

!AJx86Registers class methodsFor:'accessing registers'!

AH
    "A 8bit general purpose register
    This register overlaps with AH, AX, EAX, RAX"
    ^ self at: #AH
!

AL
    "A 8bit general purpose register
    This register overlaps with AL, AX, EAX, RAX"
    ^ self at: #AL
!

AX
    "A 16bit general purpose register
    This register overlaps with AL, AX, EAX, RAX"
    ^ self at: #AX
!

BH
    "A 8bit general purpose register
    This register overlaps with BH, BX, EBX, RBX"
    ^ self at: #BH
!

BL
    "A 8bit general purpose register
    This register overlaps with BL, BX, EBX, RBX"
    ^ self at: #BL
!

BP
    "A 16bit general purpose register
    This register overlaps with CH, CX, ECX, RCX"
    ^ self at: #BP
!

BX
    "A 16bit general purpose register
    This register overlaps with BL, BX, EBX, RBX"
    ^ self at: #BX
!

CH
    "A 8bit general purpose register
    This register overlaps with CH, CX, ECX, RCX"
    ^ self at: #CH
!

CL
    "A 8bit general purpose register
    This register overlaps with CL, CX, ECX, RCX"
    ^ self at: #CL
!

CX
    "A 16bit general purpose register
    This register overlaps with CL, CX, ECX, RCX"
    ^ self at: #CX
!

DH
    "A 8bit general purpose register
    This register overlaps with DH, DX, EDX, RDX"
    ^ self at: #DH
!

DI
    "A 16bit general purpose register
    This register overlaps with BH, BX, EBX, RBX"
    ^ self at: #DI
!

DL
    "A 8bit general purpose register
    This register overlaps with DL, DX, EDX, RDX"
    ^ self at: #DL
!

DX
    "A 16bit general purpose register
    This register overlaps with DL, DX, EDX, RDX"
    ^ self at: #DX
!

EAX
    "A 32bit general purpose register
    This register overlaps with AL, AX, EAX, RAX"
    ^ self at: #EAX
!

EBP
    "A 32bit general purpose register
    This register overlaps with CH, CX, ECX, RCX"
    ^ self at: #EBP
!

EBX
    "A 32bit general purpose register
    This register overlaps with BL, BX, EBX, RBX"
    ^ self at: #EBX
!

ECX
    "A 32bit general purpose register
    This register overlaps with CL, CX, ECX, RCX"
    ^ self at: #ECX
!

EDI
    "A 32bit general purpose register
    This register overlaps with BH, BX, EBX, RBX"
    ^ self at: #EDI
!

EDX
    "A 32bit general purpose register
    This register overlaps with DL, DX, EDX, RDX"
    ^ self at: #EDX
!

EIP
    "A 32bit instruction pointer register
    This register overlaps with IP, EIP, RIP"
    ^ self at: #EIP
!

ESI
    "A 32bit general purpose register
    This register overlaps with DH, DX, EDX, RDX"
    ^ self at: #ESI
!

ESP
    "A 32bit general purpose register
    This register overlaps with AH, AX, EAX, RAX"
    ^ self at: #ESP
!

IP
    "A 16bit instruction pointer register
    This register overlaps with IP, EIP, RIP"
    ^ self at: #IP
!

MM0
    "An MMX register"
    ^ self at: #MM0
!

MM1
    "An MMX register"
    ^ self at: #MM1
!

MM2
    "An MMX register"
    ^ self at: #MM2
!

MM3
    "An MMX register"
    ^ self at: #MM3
!

MM4
    "An MMX register"
    ^ self at: #MM4
!

MM5
    "An MMX register"
    ^ self at: #MM5
!

MM6
    "An MMX register"
    ^ self at: #MM6
!

MM7
    "An MMX register"
    ^ self at: #MM7
!

R10
    "A 64bit general purpose register
    This register overlaps with R10B, R10W, R10D, R10"
    ^ self at: #R10
!

R10B
    "A 8bit general purpose register
    This register overlaps with R10B, R10W, R10D, R10"
    ^ self at: #R10B
!

R10D
    "A 32bit general purpose register
    This register overlaps with R10B, R10W, R10D, R10"
    ^ self at: #R10D
!

R10W
    "A 16bit general purpose register
    This register overlaps with R10B, R10W, R10D, R10"
    ^ self at: #R10W
!

R11
    "A 64bit general purpose register
    This register overlaps with R11B, R11W, R11D, R11"
    ^ self at: #R11
!

R11B
    "A 8bit general purpose register
    This register overlaps with R11B, R11W, R11D, R11"
    ^ self at: #R11B
!

R11D
    "A 32bit general purpose register
    This register overlaps with R11B, R11W, R11D, R11"
    ^ self at: #R11D
!

R11W
    "A 16bit general purpose register
    This register overlaps with R11B, R11W, R11D, R11"
    ^ self at: #R11W
!

R12
    "A 64bit general purpose register
    This register overlaps with R12B, R12W, R12D, R12"
    ^ self at: #R12
!

R12B
    "A 8bit general purpose register
    This register overlaps with R12B, R12W, R12D, R12"
    ^ self at: #R12B
!

R12D
    "A 32bit general purpose register
    This register overlaps with R12B, R12W, R12D, R12"
    ^ self at: #R12D
!

R12W
    "A 16bit general purpose register
    This register overlaps with R12B, R12W, R12D, R12"
    ^ self at: #R12W
!

R13
    "A 64bit general purpose register
    This register overlaps with R13B, R13W, R13D, R13"
    ^ self at: #R13
!

R13B
    "A 8bit general purpose register
    This register overlaps with R13B, R13W, R13D, R13"
    ^ self at: #R13B
!

R13D
    "A 32bit general purpose register
    This register overlaps with R13B, R13W, R13D, R13"
    ^ self at: #R13D
!

R13W
    "A 16bit general purpose register
    This register overlaps with R13B, R13W, R13D, R13"
    ^ self at: #R13W
!

R14
    "A 64bit general purpose register
    This register overlaps with R14B, R14W, R14D, R14"
    ^ self at: #R14
!

R14B
    "A 8bit general purpose register
    This register overlaps with R14B, R14W, R14D, R14"
    ^ self at: #R14B
!

R14D
    "A 32bit general purpose register
    This register overlaps with R14B, R14W, R14D, R14"
    ^ self at: #R14D
!

R14W
    "A 16bit general purpose register
    This register overlaps with R14B, R14W, R14D, R14"
    ^ self at: #R14W
!

R15
    "A 64bit general purpose register
    This register overlaps with R15B, R15W, R15D, R15"
    ^ self at: #R15
!

R15B
    "A 8bit general purpose register
    This register overlaps with R15B, R15W, R15D, R15"
    ^ self at: #R15B
!

R15D
    "A 32bit general purpose register
    This register overlaps with R15B, R15W, R15D, R15"
    ^ self at: #R15D
!

R15W
    "A 16bit general purpose register
    This register overlaps with R15B, R15W, R15D, R15"
    ^ self at: #R15W
!

R8
    "A 64bit general purpose register
    This register overlaps with R8B, R8W, R8D, R8"
    ^ self at: #R8
!

R8B
    "A 8bit general purpose register
    This register overlaps with R8B, R8W, R8D, R8"
    ^ self at: #R8B
!

R8D
    "A 32bit general purpose register
    This register overlaps with R8B, R8W, R8D, R8"
    ^ self at: #R8D
!

R8W
    "A 16bit general purpose register
    This register overlaps with R8B, R8W, R8D, R8"
    ^ self at: #R8W
!

R9
    "A 64bit general purpose register
    This register overlaps with R9B, R9W, R9D, R9"
    ^ self at: #R9
!

R9B
    "A 8bit general purpose register
    This register overlaps with R9B, R9W, R9D, R9"
    ^ self at: #R9B
!

R9D
    "A 32bit general purpose register
    This register overlaps with R9B, R9W, R9D, R9"
    ^ self at: #R9D
!

R9W
    "A 16bit general purpose register
    This register overlaps with R9B, R9W, R9D, R9"
    ^ self at: #R9W
!

RAX
    "A 64bit general purpose register
    This register overlaps with AL, AX, EAX, RAX"
    ^ self at: #RAX
!

RBP
    "A 64bit general purpose register
    This register overlaps with CH, CX, ECX, RCX"
    ^ self at: #RBP
!

RBX
    "A 64bit general purpose register
    This register overlaps with BL, BX, EBX, RBX"
    ^ self at: #RBX
!

RCX
    "A 64bit general purpose register
    This register overlaps with CL, CX, ECX, RCX"
    ^ self at: #RCX
!

RDI
    "A 64bit general purpose register
    This register overlaps with BH, BX, EBX, RBX"
    ^ self at: #RDI
!

RDX
    "A 64bit general purpose register
    This register overlaps with DL, DX, EDX, RDX"
    ^ self at: #RDX
!

RIP
    "A 64bit instruction pointer register
    This register overlaps with IP, EIP, RIP"
    ^ self at: #RIP
!

RSI
    "A 64bit general purpose register
    This register overlaps with DH, DX, EDX, RDX"
    ^ self at: #RSI
!

RSP
    "A 64bit general purpose register
    This register overlaps with AH, AX, EAX, RAX"
    ^ self at: #RSP
!

SI
    "A 16bit general purpose register
    This register overlaps with DH, DX, EDX, RDX"
    ^ self at: #SI
!

SP
    "A 16bit general purpose register
    This register overlaps with AH, AX, EAX, RAX"
    ^ self at: #SP
!

ST0
    "A floating point register"
    ^ self at: #ST0
!

ST1
    "A floating point register"
    ^ self at: #ST1
!

ST2
    "A floating point register"
    ^ self at: #ST2
!

ST3
    "A floating point register"
    ^ self at: #ST3
!

ST4
    "A floating point register"
    ^ self at: #ST4
!

ST5
    "A floating point register"
    ^ self at: #ST5
!

ST6
    "A floating point register"
    ^ self at: #ST6
!

ST7
    "A floating point register"
    ^ self at: #ST7
!

XMM0
    "An SSE register"
    ^ self at: #XMM0
!

XMM1
    "An SSE register"
    ^ self at: #XMM1
!

XMM10
    "An SSE register"
    ^ self at: #XMM10
!

XMM11
    "An SSE register"
    ^ self at: #XMM11
!

XMM12
    "An SSE register"
    ^ self at: #XMM12
!

XMM13
    "An SSE register"
    ^ self at: #XMM13
!

XMM14
    "An SSE register"
    ^ self at: #XMM14
!

XMM15
    "An SSE register"
    ^ self at: #XMM15
!

XMM2
    "An SSE register"
    ^ self at: #XMM2
!

XMM3
    "An SSE register"
    ^ self at: #XMM3
!

XMM4
    "An SSE register"
    ^ self at: #XMM4
!

XMM5
    "An SSE register"
    ^ self at: #XMM5
!

XMM6
    "An SSE register"
    ^ self at: #XMM6
!

XMM7
    "An SSE register"
    ^ self at: #XMM7
!

XMM8
    "An SSE register"
    ^ self at: #XMM8
!

XMM9
    "An SSE register"
    ^ self at: #XMM9
! !

!AJx86Registers class methodsFor:'method compilation'!

installRegister: register accessorCategory: registerAccessorsCategory

    ^ self class
        compile:(String streamContents: [ :s | 
            s nextPutAll: register name; crtab.
            self printRegister: register descriptionOn: s.
            s crtab; nextPutAll: '^ self at: #'; nextPutAll: register name ])
        classified: registerAccessorsCategory
!

installRegister: register accessorCategory: registerAccessorsCategory on: aClass
    
    aClass 
        compile: (String	streamContents: [ :s | 
            s nextPutAll: register name; crtab.
            self printRegister: register descriptionOn: s.
            s crtab; nextPutAll: '^ '; nextPutAll: register name ])
        classified: registerAccessorsCategory 
!

installRegisterAccessors
    "this method creates simple accessors for all registers"

    | registerAccessorsCategory |
    
    registerAccessorsCategory := 'accessing registers'.	
    
    "remove all methods in the 'accessing register' category"
    self class methodDict values
        select: [ :method | method category = registerAccessorsCategory ]
        thenDo: [ :method | self class removeSelector: method selector ].
        
    self all 
        do: [ :register | | method |
            "install the direct accessor on this class"
            self installRegister: register accessorCategory: registerAccessorsCategory.
            "install the accessor on the assembler"
            self 
                installRegister: register 
                accessorCategory: registerAccessorsCategory
                on: (register isX86 ifTrue: [ AJx86Assembler ]  ifFalse: [ AJx64Assembler ])]
        displayingProgress: [ :each| each name ].
!

printRegister: register descriptionOn: s

    s nextPut: $".
    register descriptionOn: s.
    register influencingRegisters ifNotEmpty: [ :registers|
        s crtab nextPutAll: 'This register overlaps with '.
        registers do: [ :reg| s nextPutAll: reg name ] separatedBy: [ s nextPutAll: ', ']].
    s nextPut: $"
! !

!AJx86Registers class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
! !


AJx86Registers initialize!