<commit_before>{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TupleSections #-}

-- | Opcode tables
module ViperVM.Arch.X86_64.Assembler.Tables
   ( opcodeMaps
   , buildOpcodeMaps
   , buildOpcodeMap
   , genEncodingOpcodeVariants
   , MapEntry (..)
   )
where

import ViperVM.Arch.X86_64.Assembler.Operand
import ViperVM.Arch.X86_64.Assembler.Insns

import Data.Bits
import Data.Maybe
import Data.Word
import qualified Data.Map as Map
import Data.Map (Map)
import qualified Data.Vector as V

data MapEntry = MapEntry
   { entryInsn     :: X86Insn  -- ^ Instruction
   , entryEncoding :: Encoding -- ^ Encoding
   }

-- | Some instructions store flags and values into the opcode byte. This method
-- returns the list of potential opcodes for an encoding
genEncodingOpcodeVariants :: Encoding -> [Word8]
genEncodingOpcodeVariants e = oc : (opoc ++ catMaybes [roc,szoc,seoc,fdoc,fpoc,fsoc])
   where
      -- the original opcode
      oc = encOpcode e
      -- reversed (check: can we have reversed + operand in opcode (or something
      -- else)?)
      roc = setBit oc <$> encReversableBit e
      -- sizable, sign-extended
      (szoc,seoc) = case (encSizableBit e, encSignExtendImmBit e) of
               (Nothing,Nothing) -> (Nothing,Nothing)
               (Just i, Nothing) -> (Just (setBit oc i),Nothing)
               (Just i, Just i2) -> (Just (setBit oc i), Just (setBit (setBit oc i2) i))
               (Nothing, Just i) ->  (Nothing,Just (setBit oc i))
      -- FPU dest
      fdoc = setBit oc <$> encFPUDestBit e
      -- FPU pop
      fpoc = setBit oc <$> encFPUPopBit e
      -- FPU sizable
      fsoc = setBit oc <$> encFPUSizableBit e
      -- operand stored in the opcode
      opoc = if OpcodeLow3 `elem` fmap opEnc (encParams e)
               then [oc + i | i <- [1..7]]
               else []


-- | Build an opcode map
buildOpcodeMap :: [MapEntry] -> V.Vector [MapEntry]
buildOpcodeMap entries = as
   where
      -- all pairs (opcode, MapEntry)
      es = [(oc,[e]) | e  <- entries
                     , oc <- genEncodingOpcodeVariants (entryEncoding e)
                     ]

      -- Map opcode [MapEntry]
      ks = Map.fromListWith (++) es

      -- Vector<commit_msg>Add missing opcode case<commit_after>{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TupleSections #-}

-- | Opcode tables
module ViperVM.Arch.X86_64.Assembler.Tables
   ( opcodeMaps
   , buildOpcodeMaps
   , buildOpcodeMap
   , genEncodingOpcodeVariants
   , MapEntry (..)
   )
where

import ViperVM.Arch.X86_64.Assembler.Operand
import ViperVM.Arch.X86_64.Assembler.Insns

import Data.Bits
import Data.Maybe
import Data.Word
import qualified Data.Map as Map
import Data.Map (Map)
import qualified Data.Vector as V

data MapEntry = MapEntry
   { entryInsn     :: X86Insn  -- ^ Instruction
   , entryEncoding :: Encoding -- ^ Encoding
   }

-- | Some instructions store flags and values into the opcode byte. This method
-- returns the list of potential opcodes for an encoding
genEncodingOpcodeVariants :: Encoding -> [Word8]
genEncodingOpcodeVariants e = oc : (opoc ++ catMaybes [roc,rsoc,szoc,seoc,fdoc,fpoc,fsoc])
   where
      -- the original opcode
      oc = encOpcode e
      -- reversed (check: can we have reversed + operand in opcode (or something
      -- else)?)
      (roc,rsoc) = case (encReversableBit e, encSizableBit e) of
               (Just i, Nothing) -> (Just (setBit oc i), Nothing)
               (Just i, Just i2) -> (Just (setBit oc i), Just (setBit (setBit oc i2) i))
               _                 -> (Nothing,Nothing)
      -- sizable, sign-extended
      (szoc,seoc) = case (encSizableBit e, encSignExtendImmBit e) of
               (Nothing,Nothing) -> (Nothing,Nothing)
               (Just i, Nothing) -> (Just (setBit oc i),Nothing)
               (Just i, Just i2) -> (Just (setBit oc i), Just (setBit (setBit oc i2) i))
               (Nothing, Just i) ->  (Nothing,Just (setBit oc i))
      -- FPU dest
      fdoc = setBit oc <$> encFPUDestBit e
      -- FPU pop
      fpoc = setBit oc <$> encFPUPopBit e
      -- FPU sizable
      fsoc = setBit oc <$> encFPUSizableBit e
      -- operand stored in the opcode
      opoc = if OpcodeLow3 `elem` fmap opEnc (encParams e)
               then [oc + i | i <- [1..7]]
               else []


-- | Build an opcode map
buildOpcodeMap :: [MapEntry] -> V.Vector [MapEntry]
buildOpcodeMap entries = as
   where
      -- all pairs (opcode, MapEntry)
      es = [(oc,[e]) | e  <- entries
                     , oc <- genEncodingOpcodeVariants (entryEncoding e)
                     ]

      -- Map opcode [MapEntry]
      ks = Map.fromListWith (++) es

      -- Vector
{'fraction_non_alphanumeric': 0.11108714408973253, 'fraction_numerical': 0.0090595340811044, 'mean_word_length': 2.2839943342776206, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5823591', 'n_tokens_mistral': 1523, 'n_tokens_neox': 1501, 'n_words': 449}