diff options
Diffstat (limited to 'lib/Language/Elna/CodeGenerator.hs')
| -rw-r--r-- | lib/Language/Elna/CodeGenerator.hs | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/lib/Language/Elna/CodeGenerator.hs b/lib/Language/Elna/CodeGenerator.hs index 1a9151a..2e9b7a4 100644 --- a/lib/Language/Elna/CodeGenerator.hs +++ b/lib/Language/Elna/CodeGenerator.hs @@ -6,11 +6,12 @@ module Language.Elna.CodeGenerator import Data.ByteString (ByteString) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap +import Data.Int (Int32) import Data.Vector (Vector) import qualified Data.Vector as Vector import qualified Data.Text.Encoding as Text.Encoding import Language.Elna.Location (Identifier(..)) -import Language.Elna.Intermediate (Operand(..), Quadruple(..)) +import Language.Elna.Intermediate (Operand(..), Quadruple(..), Variable(..)) import qualified Language.Elna.Architecture.RiscV as RiscV import Language.Elna.SymbolTable (SymbolTable) import Data.Bits (Bits(..)) @@ -40,27 +41,12 @@ quadruple StartQuadruple = Vector.fromList , Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 4 RiscV.SW RiscV.SP RiscV.RA) , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.S0 RiscV.ADDI RiscV.SP 4) ] -quadruple (ParameterQuadruple (IntOperand intValue)) - = mappend go - $ Vector.fromList +quadruple (ParameterQuadruple operand1) = + let (operandRegister, statements) = loadImmediateOrRegister operand1 RiscV.A0 + in mappend statements $ Vector.fromList [ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.SP RiscV.ADDI RiscV.SP (negate 4)) - , Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 0 RiscV.SW RiscV.SP RiscV.A0) + , Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 0 RiscV.SW RiscV.SP operandRegister) ] - where - hi = intValue `shiftR` 12 - lo = intValue - go - | intValue >= -2048 - , intValue <= 2047 = Vector.singleton - $ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo) - | intValue .&. 0x800 /= 0 = Vector.fromList - [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U RiscV.A0 $ fromIntegral $ succ hi) - , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo) - ] - | otherwise = Vector.fromList - [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U RiscV.A0 $ fromIntegral hi) - , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo) - ] quadruple (CallQuadruple callName numberOfArguments) = Vector.fromList [ Instruction (RiscV.CallInstruction callName) , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.SP RiscV.ADDI RiscV.SP (numberOfArguments * 4)) @@ -71,3 +57,39 @@ quadruple StopQuadruple = 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 (TempVariable _)) = + let (operandRegister1, statements1) = loadImmediateOrRegister operand1 RiscV.A0 + (operandRegister2, statements2) = loadImmediateOrRegister operand2 RiscV.A1 + in Vector.snoc (statements1 <> statements2) + $ Instruction + $ RiscV.BaseInstruction RiscV.Op + $ RiscV.R RiscV.T0 RiscV.ADD operandRegister1 operandRegister2 (RiscV.Funct7 0b0000000) +quadruple (SubtractionQuadruple operand1 operand2 (TempVariable _)) = + let (operandRegister1, statements1) = loadImmediateOrRegister operand1 RiscV.A0 + (operandRegister2, statements2) = loadImmediateOrRegister operand2 RiscV.A1 + in Vector.snoc (statements1 <> statements2) + $ Instruction + $ RiscV.BaseInstruction RiscV.Op + $ RiscV.R RiscV.T0 RiscV.SUB operandRegister1 operandRegister2 (RiscV.Funct7 0b0100000) + +loadImmediateOrRegister :: Operand -> RiscV.XRegister -> (RiscV.XRegister, Vector Statement) +loadImmediateOrRegister (IntOperand intValue) targetRegister = + (targetRegister, lui intValue targetRegister) +loadImmediateOrRegister (VariableOperand _) _ = (RiscV.T0, 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 |
