summaryrefslogtreecommitdiff
path: root/lib/Language/Elna/RiscV
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2024-11-14 19:55:30 +0100
committerEugen Wissner <belka@caraus.de>2024-11-14 19:55:30 +0100
commit1ec34678308709f7f6103bd4d67347ad859479c8 (patch)
tree816abb7b59a5e6bc5b302e846e585626cb908954 /lib/Language/Elna/RiscV
parent060496fc6ee331e2710ff8ade23317a0a79cbd6c (diff)
downloadelna-1ec34678308709f7f6103bd4d67347ad859479c8.tar.gz
Map local variables in IR to their original names
Diffstat (limited to 'lib/Language/Elna/RiscV')
-rw-r--r--lib/Language/Elna/RiscV/CodeGenerator.hs453
1 files changed, 203 insertions, 250 deletions
diff --git a/lib/Language/Elna/RiscV/CodeGenerator.hs b/lib/Language/Elna/RiscV/CodeGenerator.hs
index c082812..a2ff71e 100644
--- a/lib/Language/Elna/RiscV/CodeGenerator.hs
+++ b/lib/Language/Elna/RiscV/CodeGenerator.hs
@@ -14,7 +14,12 @@ import Data.Vector (Vector)
import qualified Data.Vector as Vector
import qualified Language.Elna.Architecture.RiscV as RiscV
import Language.Elna.Backend.Allocator (MachineConfiguration(..), Store(..))
-import Language.Elna.Backend.Intermediate (Label(..), Operand(..), Quadruple(..))
+import Language.Elna.Backend.Intermediate
+ ( Label(..)
+ , Operand(..)
+ , ProcedureQuadruples(..)
+ , Quadruple(..)
+ )
import Language.Elna.Location (Identifier(..))
import Data.Bits (Bits(..))
import Data.Foldable (Foldable(..), foldlM)
@@ -80,13 +85,13 @@ createLabel = do
$ Text.Builder.toLazyText
$ Text.Builder.decimal currentCounter
-generateRiscV :: HashMap Identifier (Vector RiscVQuadruple) -> Vector Statement
+generateRiscV :: HashMap Identifier (ProcedureQuadruples RiscVStore) -> Vector Statement
generateRiscV = flip evalState 0
. runRiscVGenerator
. foldlM go Vector.empty
. HashMap.toList
where
- go accumulator (Identifier key, value) =
+ go accumulator (Identifier key, ProcedureQuadruples{ quadruples = value }) =
let code = Vector.cons (JumpLabel key [GlobalDirective, FunctionDirective])
. fold <$> mapM quadruple value
in (accumulator <>) <$> code
@@ -114,198 +119,228 @@ quadruple StopQuadruple = pure $ Vector.fromList
, Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.SP RiscV.ADDI RiscV.SP 4)
, Instruction (RiscV.BaseInstruction RiscV.Jalr $ RiscV.I RiscV.RA RiscV.JALR RiscV.Zero 0)
]
-quadruple (AddQuadruple operand1 operand2 (Store register))
+quadruple (AddQuadruple operand1 operand2 store) =
+ commutativeBinary (+) RiscV.ADD (RiscV.Funct7 0b0000000) (operand1, operand2) store
+quadruple (ProductQuadruple operand1 operand2 store) =
+ commutativeBinary (*) RiscV.MUL (RiscV.Funct7 0b0000001) (operand1, operand2) store
+quadruple (SubtractionQuadruple operand1 operand2 store)
| IntOperand immediateOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
- pure $ lui (immediateOperand1 + immediateOperand2) register
+ let (storeRegister, storeStatements) = storeToStore store
+ in pure $ lui (immediateOperand1 - immediateOperand2) storeRegister <> storeStatements
| VariableOperand variableOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 =
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
- in pure $ Vector.singleton $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.ADD operandRegister1 operandRegister2 (RiscV.Funct7 0b0000000)
- | VariableOperand variableOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- addImmediateRegister variableOperand1 immediateOperand2
- | IntOperand immediateOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 =
- addImmediateRegister variableOperand2 immediateOperand1
- where
- addImmediateRegister variableOperand immediateOperand =
- let statements = lui immediateOperand register
- Store operandRegister = variableOperand
- in pure $ Vector.snoc statements
- $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.ADD register operandRegister
- $ RiscV.Funct7 0b0000000
-quadruple (SubtractionQuadruple operand1 operand2 (Store register))
- | IntOperand immediateOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- pure $ lui (immediateOperand1 - immediateOperand2) register
- | VariableOperand variableOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 =
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
- in pure $ Vector.singleton $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.SUB operandRegister1 operandRegister2
- $ RiscV.Funct7 0b0100000
+ let (storeRegister, storeStatements) = storeToStore store
+ (operandRegister1, statements1) = loadFromStore variableOperand1
+ (operandRegister2, statements2) = loadFromStore variableOperand2
+ instruction = Instruction
+ $ RiscV.BaseInstruction RiscV.Op
+ $ RiscV.R storeRegister RiscV.SUB operandRegister1 operandRegister2
+ $ RiscV.Funct7 0b0100000
+ in pure $ statements1 <> statements2 <> Vector.cons instruction storeStatements
| IntOperand immediateOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 =
- let statements1 = lui immediateOperand1 register
- Store operandRegister2 = variableOperand2
- in pure $ Vector.snoc statements1
- $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.SUB register operandRegister2
- $ RiscV.Funct7 0b0100000
+ let (storeRegister, storeStatements) = storeToStore store
+ statements1 = lui immediateOperand1 storeRegister
+ (operandRegister2, statements2) = loadFromStore variableOperand2
+ instruction = Instruction
+ $ RiscV.BaseInstruction RiscV.Op
+ $ RiscV.R storeRegister RiscV.SUB storeRegister operandRegister2
+ $ RiscV.Funct7 0b0100000
+ in pure $ statements1 <> statements2 <> Vector.cons instruction storeStatements
| VariableOperand variableOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
- let statements2 = lui (negate immediateOperand2) register
- Store operandRegister1 = variableOperand1
- in pure $ Vector.snoc statements2
- $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.ADD register operandRegister1
- $ RiscV.Funct7 0b0000000
-quadruple (NegationQuadruple operand1 (Store register))
+ let (storeRegister, storeStatements) = storeToStore store
+ statements2 = lui (negate immediateOperand2) storeRegister
+ (operandRegister1, statements1) = loadFromStore variableOperand1
+ instruction = Instruction
+ $ RiscV.BaseInstruction RiscV.Op
+ $ RiscV.R storeRegister RiscV.ADD storeRegister operandRegister1
+ $ RiscV.Funct7 0b0000000
+ in pure $ statements1 <> statements2 <> Vector.cons instruction storeStatements
+quadruple (NegationQuadruple operand1 store)
| IntOperand immediateOperand1 <- operand1 =
- pure $ lui (negate immediateOperand1) register
+ let (storeRegister, storeStatements) = storeToStore store
+ in pure $ lui (negate immediateOperand1) storeRegister <> storeStatements
| VariableOperand variableOperand1 <- operand1 =
- let Store operandRegister1 = variableOperand1
- in pure $ Vector.singleton
- $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.SUB RiscV.Zero operandRegister1
- $ RiscV.Funct7 0b0100000
-quadruple (ProductQuadruple operand1 operand2 (Store register))
- | IntOperand immediateOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- pure $ lui (immediateOperand1 * immediateOperand2) register
- | VariableOperand variableOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 =
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
- in pure $ Vector.singleton $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.MUL operandRegister1 operandRegister2 (RiscV.Funct7 0b0000001)
- | VariableOperand variableOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- multiplyImmediateRegister variableOperand1 immediateOperand2
- | IntOperand immediateOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 =
- multiplyImmediateRegister variableOperand2 immediateOperand1
- where
- multiplyImmediateRegister variableOperand immediateOperand =
- let statements = lui immediateOperand register
- Store operandRegister = variableOperand
- in pure $ Vector.snoc statements
- $ Instruction
- $ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.MUL register operandRegister
- $ RiscV.Funct7 0b0000001
-quadruple (DivisionQuadruple operand1 operand2 (Store register))
+ let (storeRegister, storeStatements) = storeToStore store
+ (operandRegister1, statements1) = loadFromStore variableOperand1
+ instruction = Instruction
+ $ RiscV.BaseInstruction RiscV.Op
+ $ RiscV.R storeRegister RiscV.SUB RiscV.Zero operandRegister1
+ $ RiscV.Funct7 0b0100000
+ in pure $ statements1 <> Vector.cons instruction storeStatements
+quadruple (DivisionQuadruple operand1 operand2 store)
| IntOperand immediateOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
if immediateOperand2 == 0
then pure $ Vector.singleton
$ Instruction (RiscV.CallInstruction "_divide_by_zero_error")
- else pure $ lui (quot immediateOperand1 immediateOperand2) register
+ else
+ let (storeRegister, storeStatements) = storeToStore store
+ in pure $ lui (quot immediateOperand1 immediateOperand2) storeRegister <> storeStatements
| VariableOperand variableOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 = do
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
+ let (storeRegister, storeStatements) = storeToStore store
+ (operandRegister1, statements1) = loadFromStore variableOperand1
+ (operandRegister2, statements2) = loadFromStore variableOperand2
divisionInstruction = Instruction
$ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.DIV operandRegister1 operandRegister2 (RiscV.Funct7 0b0000001)
+ $ RiscV.R storeRegister RiscV.DIV operandRegister1 operandRegister2 (RiscV.Funct7 0b0000001)
branchLabel <- createLabel
let branchInstruction = Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch branchLabel RiscV.BNE RiscV.Zero operandRegister2
- pure $ Vector.fromList
+ pure $ statements1 <> statements2 <> Vector.fromList
[ branchInstruction
, Instruction (RiscV.CallInstruction "_divide_by_zero_error")
, JumpLabel branchLabel []
, divisionInstruction
- ]
+ ] <> storeStatements
| VariableOperand variableOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
- let statements2 = lui immediateOperand2 register
- Store operandRegister1 = variableOperand1
+ let (storeRegister, storeStatements) = storeToStore store
+ statements2 = lui immediateOperand2 storeRegister
+ (operandRegister1, statements1) = loadFromStore variableOperand1
operationInstruction
| immediateOperand2 == 0 =
RiscV.CallInstruction "_divide_by_zero_error"
| otherwise = RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.DIV operandRegister1 register
+ $ RiscV.R storeRegister RiscV.DIV operandRegister1 storeRegister
$ RiscV.Funct7 0b0000001
- in pure $ Vector.snoc statements2
- $ Instruction operationInstruction
+ in pure $ statements1 <> statements2
+ <> Vector.cons (Instruction operationInstruction) storeStatements
| IntOperand immediateOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 = do
- let statements1 = lui immediateOperand1 register
- Store operandRegister2 = variableOperand2
+ let (storeRegister, storeStatements) = storeToStore store
+ statements1 = lui immediateOperand1 storeRegister
+ (operandRegister2, statements2) = loadFromStore variableOperand2
divisionInstruction = Instruction
$ RiscV.BaseInstruction RiscV.Op
- $ RiscV.R register RiscV.DIV register operandRegister2 (RiscV.Funct7 0b0000001)
+ $ RiscV.R storeRegister RiscV.DIV storeRegister operandRegister2 (RiscV.Funct7 0b0000001)
branchLabel <- createLabel
let branchInstruction = Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch branchLabel RiscV.BNE RiscV.Zero operandRegister2
- pure $ mappend statements1 $ Vector.fromList
+ pure $ statements1 <> statements2 <> Vector.fromList
[ branchInstruction
, Instruction (RiscV.CallInstruction "_divide_by_zero_error")
, JumpLabel branchLabel []
, divisionInstruction
- ]
+ ] <> storeStatements
quadruple (LabelQuadruple (Label label)) = pure $ Vector.singleton $ JumpLabel label mempty
quadruple (GoToQuadruple label) = pure $ Vector.singleton $ unconditionalJal label
-quadruple (EqualQuadruple operand1 operand2 goToLabel)
+quadruple (EqualQuadruple operand1 operand2 goToLabel) =
+ commutativeComparison (==) RiscV.BEQ (operand1, operand2) goToLabel
+quadruple (NonEqualQuadruple operand1 operand2 goToLabel) =
+ commutativeComparison (/=) RiscV.BNE (operand1, operand2) goToLabel
+quadruple (LessQuadruple operand1 operand2 goToLabel) =
+ lessThan (operand1, operand2) goToLabel
+quadruple (GreaterQuadruple operand1 operand2 goToLabel) =
+ lessThan (operand2, operand1) goToLabel
+quadruple (LessOrEqualQuadruple operand1 operand2 goToLabel) =
+ lessOrEqualThan (operand1, operand2) goToLabel
+quadruple (GreaterOrEqualQuadruple operand1 operand2 goToLabel) =
+ lessOrEqualThan (operand2, operand1) goToLabel
+quadruple (AssignQuadruple operand1 store)
+ | IntOperand immediateOperand1 <- operand1 =
+ let (storeRegister, storeStatements) = storeToStore store
+ in pure $ lui immediateOperand1 storeRegister <> storeStatements
+ | VariableOperand variableOperand1 <- operand1 =
+ let (operandRegister1, statements1) = loadFromStore variableOperand1
+ (storeRegister, storeStatements) = storeToStore store
+ instruction = Instruction
+ $ RiscV.BaseInstruction RiscV.OpImm
+ $ RiscV.I storeRegister RiscV.ADDI operandRegister1 0
+ in pure $ statements1 <> Vector.cons instruction storeStatements
+
+unconditionalJal :: Label -> Statement
+unconditionalJal (Label goToLabel) = Instruction
+ $ RiscV.RelocatableInstruction RiscV.Jal
+ $ RiscV.RJal RiscV.Zero goToLabel
+
+loadImmediateOrRegister :: RiscVOperand -> RiscV.XRegister -> (RiscV.XRegister, Vector Statement)
+loadImmediateOrRegister (IntOperand intValue) targetRegister =
+ (targetRegister, lui intValue targetRegister)
+loadImmediateOrRegister (VariableOperand store) _ = loadFromStore store
+
+lui :: Int32 -> RiscV.XRegister -> Vector Statement
+lui intValue targetRegister
+ | intValue >= -2048
+ , intValue <= 2047 = Vector.singleton
+ $ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I targetRegister RiscV.ADDI RiscV.Zero lo)
+ | intValue .&. 0x800 /= 0 = Vector.fromList
+ [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U targetRegister $ fromIntegral $ succ hi)
+ , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I targetRegister RiscV.ADDI targetRegister lo)
+ ]
+ | otherwise = Vector.fromList
+ [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U targetRegister $ fromIntegral hi)
+ , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I targetRegister RiscV.ADDI targetRegister lo)
+ ]
+ where
+ hi = intValue `shiftR` 12
+ lo = fromIntegral intValue
+
+commutativeBinary
+ :: (Int32 -> Int32 -> Int32)
+ -> RiscV.Funct3
+ -> RiscV.Funct7
+ -> (Operand RiscVStore, Operand RiscVStore)
+ -> Store RiscV.XRegister
+ -> RiscVGenerator (Vector Statement)
+commutativeBinary immediateOperation funct3 funct7 (operand1, operand2) store
| IntOperand immediateOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
- if immediateOperand1 == immediateOperand2
- then pure $ Vector.singleton $ unconditionalJal goToLabel
- else pure Vector.empty
+ let (storeRegister, storeStatements) = storeToStore store
+ immediateOperation' = immediateOperation immediateOperand1 immediateOperand2
+ in pure $ lui immediateOperation' storeRegister <> storeStatements
| VariableOperand variableOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 = do
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
- Label goToLabel' = goToLabel
- pure $ Vector.singleton
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BEQ operandRegister1 operandRegister2
+ , VariableOperand variableOperand2 <- operand2 =
+ let (operandRegister1, statements1) = loadFromStore variableOperand1
+ (operandRegister2, statements2) = loadFromStore variableOperand2
+ (storeRegister, storeStatements) = storeToStore store
+ instruction = Instruction $ RiscV.BaseInstruction RiscV.Op
+ $ RiscV.R storeRegister funct3 operandRegister1 operandRegister2 funct7
+ in pure $ statements1 <> statements2
+ <> Vector.cons instruction storeStatements
| VariableOperand variableOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
- compareImmediateRegister variableOperand1 immediateOperand2
+ commutativeImmediateRegister variableOperand1 immediateOperand2
| IntOperand immediateOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 =
- compareImmediateRegister variableOperand2 immediateOperand1
+ commutativeImmediateRegister variableOperand2 immediateOperand1
where
- compareImmediateRegister variableOperand immediateOperand =
- let statements = lui immediateOperand immediateRegister
- Store operandRegister = variableOperand
- Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BEQ operandRegister immediateRegister
-quadruple (NonEqualQuadruple operand1 operand2 goToLabel)
+ commutativeImmediateRegister variableOperand immediateOperand =
+ let (storeRegister, storeStatements) = storeToStore store
+ immediateStatements = lui immediateOperand storeRegister
+ (operandRegister, registerStatements) = loadFromStore variableOperand
+ instruction = Instruction
+ $ RiscV.BaseInstruction RiscV.Op
+ $ RiscV.R storeRegister funct3 storeRegister operandRegister funct7
+ in pure $ immediateStatements <> registerStatements
+ <> Vector.cons instruction storeStatements
+
+commutativeComparison
+ :: (Int32 -> Int32 -> Bool)
+ -> RiscV.Funct3
+ -> (Operand RiscVStore, Operand RiscVStore)
+ -> Label
+ -> RiscVGenerator (Vector Statement)
+commutativeComparison immediateOperation funct3 (operand1, operand2) goToLabel
| IntOperand immediateOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
- if immediateOperand1 /= immediateOperand2
+ if immediateOperation immediateOperand1 immediateOperand2
then pure $ Vector.singleton $ unconditionalJal goToLabel
else pure Vector.empty
| VariableOperand variableOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 = do
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
+ let (operandRegister1, statements1) = loadFromStore variableOperand1
+ (operandRegister2, statements2) = loadFromStore variableOperand2
Label goToLabel' = goToLabel
- pure $ Vector.singleton
+ pure $ Vector.snoc (statements1 <> statements2)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BNE operandRegister1 operandRegister2
+ $ RiscV.RBranch goToLabel' funct3 operandRegister1 operandRegister2
| VariableOperand variableOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
compareImmediateRegister variableOperand1 immediateOperand2
@@ -314,14 +349,16 @@ quadruple (NonEqualQuadruple operand1 operand2 goToLabel)
compareImmediateRegister variableOperand2 immediateOperand1
where
compareImmediateRegister variableOperand immediateOperand =
- let statements = lui immediateOperand immediateRegister
- Store operandRegister = variableOperand
+ let immediateStatements = lui immediateOperand immediateRegister
+ (operandRegister, registerStatements) = loadFromStore variableOperand
Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements
+ in pure $ Vector.snoc (immediateStatements <> registerStatements)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BNE operandRegister immediateRegister
-quadruple (LessQuadruple operand1 operand2 goToLabel)
+ $ RiscV.RBranch goToLabel' funct3 operandRegister immediateRegister
+
+lessThan :: (Operand RiscVStore, Operand RiscVStore) -> Label -> RiscVGenerator (Vector Statement)
+lessThan (operand1, operand2) goToLabel
| IntOperand immediateOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
if immediateOperand1 < immediateOperand2
@@ -329,65 +366,34 @@ quadruple (LessQuadruple operand1 operand2 goToLabel)
else pure Vector.empty
| VariableOperand variableOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 = do
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
+ let (operandRegister1, statements1) = loadFromStore variableOperand1
+ (operandRegister2, statements2) = loadFromStore variableOperand2
Label goToLabel' = goToLabel
- pure $ Vector.singleton
+ pure $ Vector.snoc (statements1 <> statements2)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch goToLabel' RiscV.BLT operandRegister1 operandRegister2
| VariableOperand variableOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
let statements2 = lui immediateOperand2 immediateRegister
- Store operandRegister1 = variableOperand1
+ (operandRegister1, statements1) = loadFromStore variableOperand1
Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements2
+ in pure $ Vector.snoc (statements1 <> statements2)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch goToLabel' RiscV.BLT operandRegister1 immediateRegister
| IntOperand immediateOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 =
let statements1 = lui immediateOperand1 immediateRegister
- Store operandRegister2 = variableOperand2
+ (operandRegister2, statements2) = loadFromStore variableOperand2
Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements1
+ in pure $ Vector.snoc (statements1 <> statements2)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch goToLabel' RiscV.BLT immediateRegister operandRegister2
-quadruple (GreaterQuadruple operand1 operand2 goToLabel)
- | IntOperand immediateOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- if immediateOperand1 > immediateOperand2
- then pure $ Vector.singleton $ unconditionalJal goToLabel
- else pure Vector.empty
- | VariableOperand variableOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 = do
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
- Label goToLabel' = goToLabel
- pure $ Vector.singleton
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BLT operandRegister2 operandRegister1
- | VariableOperand variableOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- let statements2 = lui immediateOperand2 immediateRegister
- Store operandRegister1 = variableOperand1
- Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements2
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BLT immediateRegister operandRegister1
- | IntOperand immediateOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 =
- let statements1 = lui immediateOperand1 immediateRegister
- Store operandRegister2 = variableOperand2
- Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements1
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BLT operandRegister2 immediateRegister
-quadruple (LessOrEqualQuadruple operand1 operand2 goToLabel)
+
+lessOrEqualThan :: (Operand RiscVStore, Operand RiscVStore) -> Label -> RiscVGenerator (Vector Statement)
+lessOrEqualThan (operand1, operand2) goToLabel
| IntOperand immediateOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
if immediateOperand1 <= immediateOperand2
@@ -395,97 +401,44 @@ quadruple (LessOrEqualQuadruple operand1 operand2 goToLabel)
else pure Vector.empty
| VariableOperand variableOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 = do
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
+ let (operandRegister1, statements1) = loadFromStore variableOperand1
+ (operandRegister2, statements2) = loadFromStore variableOperand2
Label goToLabel' = goToLabel
- pure $ Vector.singleton
+ pure $ Vector.snoc (statements1 <> statements2)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch goToLabel' RiscV.BGE operandRegister2 operandRegister1
| VariableOperand variableOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
let statements2 = lui immediateOperand2 immediateRegister
- Store operandRegister1 = variableOperand1
+ (operandRegister1, statements1) = loadFromStore variableOperand1
Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements2
+ in pure $ Vector.snoc (statements1 <> statements2)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch goToLabel' RiscV.BGE immediateRegister operandRegister1
| IntOperand immediateOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 =
let statements1 = lui immediateOperand1 immediateRegister
- Store operandRegister2 = variableOperand2
+ (operandRegister2, statements2) = loadFromStore variableOperand2
Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements1
+ in pure $ Vector.snoc (statements1 <> statements2)
$ Instruction
$ RiscV.RelocatableInstruction RiscV.Branch
$ RiscV.RBranch goToLabel' RiscV.BGE operandRegister2 immediateRegister
-quadruple (GreaterOrEqualQuadruple operand1 operand2 goToLabel)
- | IntOperand immediateOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- if immediateOperand1 >= immediateOperand2
- then pure $ Vector.singleton $ unconditionalJal goToLabel
- else pure Vector.empty
- | VariableOperand variableOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 =
- let Store operandRegister1 = variableOperand1
- Store operandRegister2 = variableOperand2
- Label goToLabel' = goToLabel
- in pure $ Vector.singleton
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BGE operandRegister1 operandRegister2
- | VariableOperand variableOperand1 <- operand1
- , IntOperand immediateOperand2 <- operand2 =
- let statements2 = lui immediateOperand2 immediateRegister
- Store operandRegister1 = variableOperand1
- Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements2
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BGE operandRegister1 immediateRegister
- | IntOperand immediateOperand1 <- operand1
- , VariableOperand variableOperand2 <- operand2 =
- let statements1 = lui immediateOperand1 immediateRegister
- Store operandRegister2 = variableOperand2
- Label goToLabel' = goToLabel
- in pure $ Vector.snoc statements1
- $ Instruction
- $ RiscV.RelocatableInstruction RiscV.Branch
- $ RiscV.RBranch goToLabel' RiscV.BGE immediateRegister operandRegister2
-quadruple (AssignQuadruple operand1 (Store register))
- | IntOperand immediateOperand1 <- operand1 = pure
- $ lui immediateOperand1 register
- | VariableOperand variableOperand1 <- operand1 =
- let Store operandRegister1 = variableOperand1
- in pure $ Vector.singleton
- $ Instruction
- $ RiscV.BaseInstruction RiscV.OpImm
- $ RiscV.I register RiscV.ADDI operandRegister1 0
-unconditionalJal :: Label -> Statement
-unconditionalJal (Label goToLabel) = Instruction
- $ RiscV.RelocatableInstruction RiscV.Jal
- $ RiscV.RJal RiscV.Zero goToLabel
+loadFromStore :: RiscVStore -> (RiscV.XRegister, Vector Statement)
+loadFromStore (RegisterStore register) = (register, mempty)
+loadFromStore (StackStore offset register) =
+ let loadInstruction = Instruction
+ $ RiscV.BaseInstruction RiscV.Load
+ $ RiscV.I register RiscV.LW RiscV.SP offset
+ in (register, Vector.singleton loadInstruction)
-loadImmediateOrRegister :: RiscVOperand -> RiscV.XRegister -> (RiscV.XRegister, Vector Statement)
-loadImmediateOrRegister (IntOperand intValue) targetRegister =
- (targetRegister, lui intValue targetRegister)
-loadImmediateOrRegister (VariableOperand (Store register)) _ = (register, Vector.empty)
-
-lui :: Int32 -> RiscV.XRegister -> Vector Statement
-lui intValue targetRegister
- | intValue >= -2048
- , intValue <= 2047 = Vector.singleton
- $ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I targetRegister RiscV.ADDI RiscV.Zero lo)
- | intValue .&. 0x800 /= 0 = Vector.fromList
- [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U targetRegister $ fromIntegral $ succ hi)
- , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I targetRegister RiscV.ADDI targetRegister lo)
- ]
- | otherwise = Vector.fromList
- [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U targetRegister $ fromIntegral hi)
- , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I targetRegister RiscV.ADDI targetRegister lo)
- ]
- where
- hi = intValue `shiftR` 12
- lo = fromIntegral intValue
+storeToStore :: RiscVStore -> (RiscV.XRegister, Vector Statement)
+storeToStore (RegisterStore register) = (register, mempty)
+storeToStore (StackStore offset register) =
+ let storeInstruction = Instruction
+ $ RiscV.BaseInstruction RiscV.Store
+ $ RiscV.S offset RiscV.SW RiscV.SP register
+ in (register, Vector.singleton storeInstruction)