Skip to content

Commit

Permalink
branch prediction
Browse files Browse the repository at this point in the history
  • Loading branch information
JensDll committed May 3, 2024
1 parent 7c9b24d commit 17bdfa1
Show file tree
Hide file tree
Showing 9 changed files with 504 additions and 345 deletions.
126 changes: 100 additions & 26 deletions unix/.config/lldbdash/modules/assembly_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
from lldbdash.common import FONT_UNDERLINE, RESET_COLOR, Output
from lldbdash.dashboard import Dashboard as D

from .branch_map import BRANCH_MAP
from .on_change_output import on_change_output
from .register import RegisterReader, RflagsRegister


class Instruction:
Expand Down Expand Up @@ -44,6 +46,7 @@ def __init__(
if len(name) > 30:
name = name[:30] + "..."
self.name: str = name

self.offset: int = self.addr - symbol.GetStartAddress().GetLoadAddress(target)

@classmethod
Expand All @@ -53,37 +56,89 @@ def list(cls, symbol: lldb.SBSymbol, target: lldb.SBTarget):
)
return list(map(lambda inst: cls(target, symbol, inst), instructions))

def print(self, out: Output, dim: PrintDimensions):
color = D.settings["text-secondary"]
def print(
self,
out: Output,
dim: PrintDimensions,
flags: RflagsRegister,
reader: RegisterReader,
color: str,
mnemonic: str,
):
predict_branching = AssemblyModule.settings["predict-branching"].value
branch_taken_marker = AssemblyModule.settings["branch-taken-marker"].value
branch_not_taken_marker = AssemblyModule.settings[
"branch-not-taken-marker"
].value

does_branch = BRANCH_MAP.get(self.mnemonic)
does_branch_result = does_branch(flags, reader) if does_branch else False

# Address
out.write(f"{color}{self.addr:#0x}{RESET_COLOR} ")

# Opcode
if AssemblyModule.settings["show-opcode"].value:
out.write(f"{self.opcode:<{dim.opcode_width}} ")

out.write(
f"{color}{self.get_name():<{dim.name_width}}{RESET_COLOR} "
f"{AssemblyModule.settings['text-mnemonic']}{self.mnemonic:<{dim.mnemonic_width}}{RESET_COLOR} "
f"{self.operands}"
f"{AssemblyModule.settings['text-comment']}{self.comment}{RESET_COLOR}\n"
)
out.write(f"{self.opcode:<{dim.opcode_width}}{RESET_COLOR} ")

def print_highlight(self, out: Output, dim: PrintDimensions):
color = D.settings["text-highlight"]
# Name
out.write(f"{color}{self.get_name():<{dim.name_width}}{RESET_COLOR} ")

out.write(f"{color}{self.addr:#0x}{RESET_COLOR} ")
# Branching
if predict_branching:
if does_branch is not None:
out.write(
branch_taken_marker
if does_branch_result
else branch_not_taken_marker
)
out.write(" ")
else:
out.write(" ")

# Mnemonic
out.write(mnemonic)
out.write(" " * (dim.mnemonic_width - len(self.mnemonic) + 1))

# Operands
out.write(self.operands)

if AssemblyModule.settings["show-opcode"].value:
out.write(f"{self.opcode:<{dim.opcode_width}} ")
# Comment
out.write(AssemblyModule.settings["text-comment"].value)
out.write(self.comment)
out.write(RESET_COLOR)
out.write("\n")

out.write(f"{color}{self.get_name():<{dim.name_width}}{RESET_COLOR} ")
out.write(
f"{AssemblyModule.settings['text-mnemonic']}{FONT_UNDERLINE}{self.mnemonic}{RESET_COLOR} "
def print_normal(
self,
out: Output,
dim: PrintDimensions,
flags: RflagsRegister,
reader: RegisterReader,
):
self.print(
out=out,
dim=dim,
flags=flags,
color=D.settings["text-secondary"].value,
mnemonic=f"{AssemblyModule.settings['text-mnemonic']}{self.mnemonic}{RESET_COLOR}",
reader=reader,
)
out.write(" " * (dim.mnemonic_width - len(self.mnemonic)))
out.write(self.operands)
out.write(
f"{AssemblyModule.settings['text-comment']}{self.comment}{RESET_COLOR}\n"

def print_highlight(
self,
out: Output,
dim: PrintDimensions,
flags: RflagsRegister,
reader: RegisterReader,
):
self.print(
out=out,
dim=dim,
flags=flags,
color=D.settings["text-highlight"].value,
mnemonic=f"{AssemblyModule.settings['text-mnemonic']}{FONT_UNDERLINE}{self.mnemonic}{RESET_COLOR}",
reader=reader,
)

def get_name(self):
Expand Down Expand Up @@ -143,19 +198,28 @@ def print(self, out: Output):

dimensions = self.find_print_dimensions(start, end)

self.print_instructions(out, dimensions, start, pc_idx)
self.instructions[pc_idx].print_highlight(out, dimensions)
self.print_instructions(out, dimensions, pc_idx + 1, end)
reader = RegisterReader.new_or_cached(self.frame)
flags = reader.read_rflags()

self.print_instructions(out, dimensions, flags, reader, start, pc_idx)
self.instructions[pc_idx].print_highlight(
out=out, dim=dimensions, flags=flags, reader=reader
)
self.print_instructions(out, dimensions, flags, reader, pc_idx + 1, end)

def print_instructions(
self,
out: Output,
dimensions: Instruction.PrintDimensions,
flags: RflagsRegister,
reader: RegisterReader,
start: int,
end: int,
):
for i in range(start, end):
self.instructions[i].print(out, dimensions)
self.instructions[i].print_normal(
out=out, dim=dimensions, flags=flags, reader=reader
)

def fetch_blocks_start(self, pc_idx: int):
before = AssemblyModule.settings["instructions-before"].value - pc_idx
Expand Down Expand Up @@ -221,6 +285,9 @@ def fetch_blocks_end(self, pc_idx: int):
"show-opcode": lldbdash.commands.BoolCommand,
"text-comment": lldbdash.commands.StrCommand,
"text-mnemonic": lldbdash.commands.StrCommand,
"predict-branching": lldbdash.commands.BoolCommand,
"branch-taken-marker": lldbdash.commands.StrCommand,
"branch-not-taken-marker": lldbdash.commands.StrCommand,
"output": lldbdash.commands.StrCommand,
},
)
Expand All @@ -247,6 +314,13 @@ class AssemblyModule:
"text-mnemonic": lldbdash.commands.StrCommand(
"\033[38;2;17;168;193m", help="The color of instruction mnemonics."
),
"predict-branching": lldbdash.commands.BoolCommand(True),
"branch-taken-marker": lldbdash.commands.StrCommand(
f"\033[38;2;14;188;108my{RESET_COLOR}"
),
"branch-not-taken-marker": lldbdash.commands.StrCommand(
f"\033[38;2;215;89;76mn{RESET_COLOR}"
),
"output": lldbdash.commands.StrCommand(
"0",
help="The render location of the assembly module.",
Expand Down
74 changes: 74 additions & 0 deletions unix/.config/lldbdash/modules/branch_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import typing

from .register import RegisterReader, RflagsRegister

DoesBranch = typing.Callable[
[RflagsRegister, RegisterReader],
int,
]

BRANCH_MAP: dict[str, DoesBranch] = {
"ja": lambda flags, _: not flags.cf and not flags.zf,
"jae": lambda flags, _: not flags.cf,
"jb": lambda flags, _: flags.cf,
"jbe": lambda flags, _: flags.cf or flags.zf,
"jc": lambda flags, _: flags.cf,
"jcxz": lambda _, reader: reader.read_gp("cx").value == 0,
"jecxz": lambda _, reader: reader.read_gp("ecx").value == 0,
"jrcxz": lambda _, reader: reader.read_gp("rcx").value == 0,
"je": lambda flags, _: flags.zf,
"jg": lambda flags, _: not flags.zf and flags.sf == flags.of,
"jge": lambda flags, _: flags.sf == flags.of,
"jl": lambda flags, _: flags.sf != flags.of,
"jle": lambda flags, _: flags.zf or flags.sf != flags.of,
"jna": lambda flags, _: flags.cf or flags.zf,
"jnae": lambda flags, _: flags.cf,
"jnb": lambda flags, _: not flags.cf,
"jnbe": lambda flags, _: not flags.cf and not flags.zf,
"jnc": lambda flags, _: not flags.cf,
"jne": lambda flags, _: not flags.zf,
"jng": lambda flags, _: flags.zf or flags.sf != flags.of,
"jnge": lambda flags, _: flags.sf != flags.of,
"jnl": lambda flags, _: flags.sf == flags.of,
"jnle": lambda flags, _: not flags.zf and flags.sf == flags.of,
"jno": lambda flags, _: not flags.of,
"jnp": lambda flags, _: not flags.pf,
"jns": lambda flags, _: not flags.sf,
"jnz": lambda flags, _: not flags.zf,
"jo": lambda flags, _: flags.of,
"jp": lambda flags, _: flags.pf,
"jpe": lambda flags, _: flags.pf,
"jpo": lambda flags, _: not flags.pf,
"js": lambda flags, _: flags.sf,
"jz": lambda flags, _: flags.zf,
"cmova": lambda flags, _: not flags.cf and not flags.zf,
"cmovae": lambda flags, _: not flags.cf,
"cmovb": lambda flags, _: flags.cf,
"cmovbe": lambda flags, _: flags.cf or flags.zf,
"cmovc": lambda flags, _: flags.cf,
"cmove": lambda flags, _: flags.zf,
"cmovg": lambda flags, _: not flags.zf and flags.sf == flags.of,
"cmovge": lambda flags, _: flags.sf == flags.of,
"cmovl": lambda flags, _: flags.sf != flags.of,
"cmovle": lambda flags, _: flags.zf or flags.sf != flags.of,
"cmovna": lambda flags, _: flags.cf or flags.zf,
"cmovnae": lambda flags, _: flags.cf,
"cmovnb": lambda flags, _: not flags.cf,
"cmovnbe": lambda flags, _: not flags.cf and not flags.zf,
"cmovnc": lambda flags, _: not flags.cf,
"cmovne": lambda flags, _: not flags.zf,
"cmovng": lambda flags, _: flags.zf or flags.sf != flags.of,
"cmovnge": lambda flags, _: flags.sf != flags.of,
"cmovnl": lambda flags, _: flags.sf == flags.of,
"cmovnle": lambda flags, _: not flags.zf and flags.sf == flags.of,
"cmovno": lambda flags, _: not flags.of,
"cmovnp": lambda flags, _: not flags.pf,
"cmovns": lambda flags, _: not flags.sf,
"cmovnz": lambda flags, _: not flags.zf,
"cmovo": lambda flags, _: flags.of,
"cmovp": lambda flags, _: flags.pf,
"cmovpe": lambda flags, _: flags.pf,
"cmovpo": lambda flags, _: not flags.pf,
"cmovs": lambda flags, _: flags.sf,
"cmovz": lambda flags, _: flags.zf,
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from .reader import RegisterReader
from .register import (
AvxRegister,
GeneralPurposeRegister,
MxcsrRegister,
RflagsRegister,
SegmentRegister,
)
from .register_lookup import RegisterLookup
from .register_set import get_avx_reg_set, get_fp_reg_set, get_gp_reg_set
Loading

0 comments on commit 17bdfa1

Please sign in to comment.