diff --git a/src/Tinyrossa-RISCV/TRRV64GCodeEvaluator.class.st b/src/Tinyrossa-RISCV/TRRV64GCodeEvaluator.class.st index 5dd6a6f..31466ba 100644 --- a/src/Tinyrossa-RISCV/TRRV64GCodeEvaluator.class.st +++ b/src/Tinyrossa-RISCV/TRRV64GCodeEvaluator.class.st @@ -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 @@ -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 | diff --git a/src/Tinyrossa-RISCV/TRRV64GCodeGenerator.class.st b/src/Tinyrossa-RISCV/TRRV64GCodeGenerator.class.st index 8b36446..335bfdf 100644 --- a/src/Tinyrossa-RISCV/TRRV64GCodeGenerator.class.st +++ b/src/Tinyrossa-RISCV/TRRV64GCodeGenerator.class.st @@ -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 } diff --git a/src/Tinyrossa-Tests-POWER/TRPPC64CompilationTests.class.st b/src/Tinyrossa-Tests-POWER/TRPPC64CompilationTests.class.st index c30a26a..2a0de93 100644 --- a/src/Tinyrossa-Tests-POWER/TRPPC64CompilationTests.class.st +++ b/src/Tinyrossa-Tests-POWER/TRPPC64CompilationTests.class.st @@ -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 | diff --git a/src/Tinyrossa-Tests-RISCV/TRRV64GCompilationTests.class.st b/src/Tinyrossa-Tests-RISCV/TRRV64GCompilationTests.class.st index 0fef959..e150852 100644 --- a/src/Tinyrossa-Tests-RISCV/TRRV64GCompilationTests.class.st +++ b/src/Tinyrossa-Tests-RISCV/TRRV64GCompilationTests.class.st @@ -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 | diff --git a/src/Tinyrossa-Tests/TRCompilationTestCase.class.st b/src/Tinyrossa-Tests/TRCompilationTestCase.class.st index b48e2de..d9c1eac 100644 --- a/src/Tinyrossa-Tests/TRCompilationTestCase.class.st +++ b/src/Tinyrossa-Tests/TRCompilationTestCase.class.st @@ -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 + " +] diff --git a/src/Tinyrossa/Integer.extension.st b/src/Tinyrossa/Integer.extension.st new file mode 100644 index 0000000..3182bfb --- /dev/null +++ b/src/Tinyrossa/Integer.extension.st @@ -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 + " +] diff --git a/src/Tinyrossa/TRCodeGenerator.class.st b/src/Tinyrossa/TRCodeGenerator.class.st index 579a4ae..3c7afbf 100644 --- a/src/Tinyrossa/TRCodeGenerator.class.st +++ b/src/Tinyrossa/TRCodeGenerator.class.st @@ -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