Skip to content

Commit

Permalink
RISC-V: implement helper #loadConstant64:into:
Browse files Browse the repository at this point in the history
This commit implements `TRRV64GCodeGenerator >> #loadConstant64:into:`
that loads 64bit signed integer into given register.

The code is almost literal translation of code in OMR, see
`compiler/riscv/codegen/OMRTreeEvaluator.cpp`, `loadConstant64()`.
  • Loading branch information
janvrany committed Jun 17, 2023
1 parent 755f1b1 commit 61c43fd
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/Tinyrossa-RISCV/TRRV64GCodeEvaluator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ TRRV64GCodeEvaluator >> evaluate_acmplt: node [
^ self evaluate_Xcmplt: node
]

{ #category : #evaluation }
TRRV64GCodeEvaluator >> evaluate_aconst: node [
^self evaluate_lconst: node

]

{ #category : #evaluation }
TRRV64GCodeEvaluator >> evaluate_aload: node [
^ self evaluate_lload: node
Expand Down Expand Up @@ -399,6 +405,19 @@ TRRV64GCodeEvaluator >> evaluate_lcmplt: node [
^ self evaluate_Xcmplt: node
]

{ #category : #evaluation }
TRRV64GCodeEvaluator >> evaluate_lconst: node [
| dstReg |

node constant == 0 ifTrue: [ ^ zero ].

dstReg := self codegen allocateRegister.

codegen loadConstant64: node constant into: dstReg.

^ dstReg
]

{ #category : #evaluation }
TRRV64GCodeEvaluator >> evaluate_lload: node [
| symbol dstReg |
Expand Down
58 changes: 58 additions & 0 deletions src/Tinyrossa-RISCV/TRRV64GCodeGenerator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,64 @@ TRRV64GCodeGenerator >> loadConstant32: value into: reg [
addiw: reg, reg, lo
].
]

{ #category : #utilities }
TRRV64GCodeGenerator >> loadConstant64: value into: reg [
self assert: (value between: INT64_MIN and: INT64_MAX).

"Code below is almost literal translation of code in OMR, see
compiler/riscv/codegen/OMRTreeEvaluator.cpp, loadConstant64()."

(value between: INT32_MIN and: INT32_MAX) ifTrue: [
self loadConstant32: value into: reg.
] ifFalse: [
| unsigned hi32 nbits toShift bits |

"Convert value to 'unsigned' (positive) integer - we need to do this
because extractBitsFrom:to: expect positive value."
unsigned := value < 0 ifTrue: [ value + "(1 << 64)hex"16r10000000000000000 ] ifFalse: [ value ].

hi32 := unsigned >> 32.

nbits := RISCV_IMM_BITS - 1.
toShift := 0.
bits := 0.

"Sigh, and convert hi32 back to signed since loadConstant32 takes
signed value!"
hi32 := hi32 > INT32_MAX ifTrue: [ hi32 - "(1 << 32)hex"16r100000000 ] ifFalse: [ hi32 ].
self loadConstant32: hi32 into: reg.


bits := unsigned extractBitsFrom: 31 - (0*nbits) to: 31 - (1*nbits) + 1.
toShift := toShift + (hi32 == 0 ifTrue:[ 0 ] ifFalse: [ nbits ]).
(bits ~~ 0) ifTrue: [
toShift ~~ 0 ifTrue: [
generate slli: reg, reg, toShift.
].
generate addi: reg, reg, bits.
toShift := 0.
].

bits := unsigned extractBitsFrom: 31 - (1*nbits) to: 31 - (2*nbits) + 1.
toShift := toShift + nbits.
(bits ~~ 0) ifTrue: [
toShift ~~ 0 ifTrue: [
generate slli: reg, reg, toShift.
].
generate addi: reg, reg, bits.
toShift := 0.
].

bits := unsigned extractBitsFrom: 31 - (2*nbits) to: 0.
toShift := toShift + (31 - (2*nbits) + 1).
toShift ~~ 0 ifTrue: [
generate slli: reg, reg, toShift.
].
(bits ~~ 0) ifTrue: [
generate addi: reg, reg, bits.
].
].
]

{ #category : #registers }
Expand Down
32 changes: 32 additions & 0 deletions src/Tinyrossa-Tests-POWER/TRPPC64CompilationTests.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,38 @@ TRPPC64CompilationTests >> test02_iconst_p [
self assert: (debugger getRegister: 'r4') equals: 16r7FEDCBA9.
]

{ #category : #tests }
TRPPC64CompilationTests >> test03_lconst_n [
| debugger |

self skip: 'Skipped since #loadConstant64:into: is not implemented for POWER'.

super test03_lconst_n.
debugger := shell debugger.
debugger memoryAt: shell nzone put: compilation codeBuffer bytes.
"
VDBDebuggerApplication openFor: debugger
"
debugger c.
self assert: (debugger getRegister: 'r4') hex equals: '-7AFEAFFECAFEAFFE'.
]

{ #category : #tests }
TRPPC64CompilationTests >> test03_lconst_p [
| debugger |

self skip: 'Skipped since #loadConstant64:into: is not implemented for POWER'.

super test03_lconst_p.
debugger := shell debugger.
debugger memoryAt: shell nzone put: compilation codeBuffer bytes.
"
VDBDebuggerApplication openFor: debugger
"
debugger c.
self assert: (debugger getRegister: 'r4') equals: 16r7AFEAFFECAFEAFFE.
]

{ #category : #'tests - examples' }
TRPPC64CompilationTests >> test_example01_meaningOfLife [
| debugger |
Expand Down
28 changes: 28 additions & 0 deletions src/Tinyrossa-Tests-RISCV/TRRV64GCompilationTests.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,34 @@ TRRV64GCompilationTests >> test02_iconst_p [
self assert: (debugger getRegister: 'a0') equals: 16r7FEDCBA9.
]

{ #category : #tests }
TRRV64GCompilationTests >> test03_lconst_n [
| debugger |

super test03_lconst_n.
debugger := shell debugger.
debugger memoryAt: shell nzone put: compilation codeBuffer bytes.
"
VDBDebuggerApplication openFor: debugger
"
debugger c.
self assert: (debugger getRegister: 'a0') hex equals: '-7AFEAFFECAFEAFFE'.
]

{ #category : #tests }
TRRV64GCompilationTests >> test03_lconst_p [
| debugger |

super test03_lconst_p.
debugger := shell debugger.
debugger memoryAt: shell nzone put: compilation codeBuffer bytes.
"
VDBDebuggerApplication openFor: debugger
"
debugger c.
self assert: (debugger getRegister: 'a0') equals: 16r7AFEAFFECAFEAFFE.
]

{ #category : #'tests - examples' }
TRRV64GCompilationTests >> test_example01_meaningOfLife [
| debugger |
Expand Down
42 changes: 42 additions & 0 deletions src/Tinyrossa-Tests/TRCompilationTestCase.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,45 @@ TRCompilationTestCase >> test02_iconst_p [
TRRV64GCompilationTests debug: #test02_iconst_p
TRPPC64CompilationTests debug: #test02_iconst_p"
]

{ #category : #tests }
TRCompilationTestCase >> test03_lconst_n [
| builder |

builder := compilation builder.
builder defineName: testSelector type: Int64.
builder lreturn:
{ builder lconst: -16r7AFEAFFECAFEAFFE }.

compilation optimize.

compilation compile.

compilation codeBuffer.

"
TRRV64GCompilationTests debug: #test03_lconst_n
TRPPC64CompilationTests debug: #test03_lconst_n
"
]

{ #category : #tests }
TRCompilationTestCase >> test03_lconst_p [
| builder |

builder := compilation builder.
builder defineName: testSelector type: Int64.
builder lreturn:
{ builder lconst: 16r7AFEAFFECAFEAFFE }.

compilation optimize.

compilation compile.

compilation codeBuffer.

"
TRRV64GCompilationTests debug: #test03_lconst_p
TRPPC64CompilationTests debug: #test03_lconst_p
"
]
22 changes: 22 additions & 0 deletions src/Tinyrossa/Integer.extension.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Extension { #name : #Integer }

{ #category : #'*Tinyrossa' }
Integer >> extractBitsFrom: hiBit to: loBit [
"Extracts (hiBit,loBit) from 64bit value, starting at bit 'hiBit'. Lowest bit is bit 0,
* highest bit is bit 63. This method assumes the receiver is 64bit unsigned integer value.
Return value is also 'unsigned', that is, greater than zero.
"

self assert: (self between: 0 and: 16rFFFFFFFFFFFFFFFF).
self assert: hiBit < 64.
self assert: (loBit between: 0 and: hiBit).

^ (self >> loBit) & (16rFFFFFFFFFFFFFFFF << (hiBit - loBit + 1)) bitInvert.

"
(16rCAFEBABE extractBitsFrom: 15 to: 8) hex
(16rCAFE00AFFE00BABE extractBitsFrom: 47 to: 24) hex
(16rCAFE00AFFE00BABE extractBitsFrom: 57 to: 57) hex
"
]
7 changes: 7 additions & 0 deletions src/Tinyrossa/TRCodeGenerator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ TRCodeGenerator >> loadConstant32: value into: reg [
self subclassResponsibility
]

{ #category : #utilities }
TRCodeGenerator >> loadConstant64: value into: reg [
"Loads 64bit signed integer constant into given register."

self subclassResponsibility
]

{ #category : #'code gen-phases' }
TRCodeGenerator >> mapStack [
"Godegen phase: compute frame size and map parameters, automatics
Expand Down

0 comments on commit 61c43fd

Please sign in to comment.