soyuz-0.0.0: DCPU16/Instructions/Time.hs
-- | DCPU-16 instruction execution time in cycles.
module DCPU16.Instructions.Time
( time
) where
import DCPU16.Instructions
import Data.List (elem)
import Data.Word
-- | Instruction execution time in cycles.
--
-- Depends on the instruction, and type of operands used.
--
-- There's also a 1-cycle cost for unsuccessful IF? comparisons, but that can't
-- be predicted without running the code. As such, this prediction is
-- optimistic and assumes all comparisons succeed.
--
-- Since the most cycle-efficient way to write loops, is to jump back on a
-- successful comparison, this prediction should be close to accurate.
time :: Instruction -> Int
time (Basic op a b) = baseCost op + opc a + opc b
time (NonBasic JSR a) = 2 + opc a
-- | Cycle cost regardless of operands.
--
-- Doesn't take 1-cycle failed comparison penalty into account for IF?.
baseCost :: BasicOp -> Int
baseCost op | op `elem` [SET,AND,BOR,XOR, IFE,IFN,IFG,IFB] = 1
| op `elem` [ADD,SUB,MUL,SHR,SHL] = 2
| op `elem` [DIV,MOD] = 3
-- | Operand cycle cost.
--
-- Anything that extends instruction length has an extra cycle cost.
--
-- Oddly, there is no cost for accessing indirect addresses. Either a
-- simplification or oversight.
opc :: Operand -> Int
opc (Offset _ _) = 1
opc (IndirectLiteral _) = 1
opc (DirectLiteral _) = 1
opc _ = 0