Compare commits
6 Commits
b6c629baad
...
7299da7bdb
Author | SHA1 | Date | |
---|---|---|---|
7299da7bdb | |||
8a300ba4c6 | |||
3de43f84bd | |||
8190f04973 | |||
5d0735498a | |||
4a165d02ed |
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,4 +2,6 @@ __pycache__
|
|||||||
*.o
|
*.o
|
||||||
*.elf
|
*.elf
|
||||||
*.bin
|
*.bin
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.d
|
||||||
|
c/main
|
285
ast_to_c_source.py
Normal file
285
ast_to_c_source.py
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from parser import Tree
|
||||||
|
from lexer import Identifier, Punctuator, IntegerConstant
|
||||||
|
import identifier_substitution
|
||||||
|
|
||||||
|
def argument_list(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ", "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def _is_new_temporary(tree):
|
||||||
|
return (
|
||||||
|
type(tree) is Identifier
|
||||||
|
and tree.token not in identifier_substitution.mapping
|
||||||
|
and tree.token not in ctx.identifiers
|
||||||
|
)
|
||||||
|
|
||||||
|
def assignment_list(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ", "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def assignment(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " = "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def bit_extraction(tree):
|
||||||
|
yield "bit_extract("
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ", "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
yield ")"
|
||||||
|
|
||||||
|
def bitwise_and(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " & "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def bitwise_or(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " | "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def bitwise_xor(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " ^ "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def block_item_list(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def compound_statement(tree):
|
||||||
|
yield "\n{\n"
|
||||||
|
if tree.children:
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield "}\n"
|
||||||
|
|
||||||
|
def expression_statement(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ";\n"
|
||||||
|
|
||||||
|
def for_expression(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ", "
|
||||||
|
if len(tree.children) > 1:
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
else:
|
||||||
|
yield "1"
|
||||||
|
|
||||||
|
def function_call(tree):
|
||||||
|
assert len(tree.children) in {1, 2}
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield "("
|
||||||
|
if len(tree.children) == 2:
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
yield ")"
|
||||||
|
|
||||||
|
def grouping(tree):
|
||||||
|
yield "("
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ")"
|
||||||
|
|
||||||
|
def _if(tree):
|
||||||
|
yield "if ("
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ") "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def if_else(tree):
|
||||||
|
yield "if ("
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ") "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
yield "else "
|
||||||
|
yield from generate(tree.children[2])
|
||||||
|
|
||||||
|
def logical_and(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " && "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def logical_or(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " || "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def member(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield "."
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def subscript(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield "["
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
yield "]"
|
||||||
|
|
||||||
|
def throw(tree):
|
||||||
|
yield "return "
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield "(state);\n"
|
||||||
|
|
||||||
|
def throw_arg(tree):
|
||||||
|
yield "return "
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield "(state, "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
yield ");\n"
|
||||||
|
|
||||||
|
def unary_complement(tree):
|
||||||
|
yield from "~"
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
|
||||||
|
def unary_int(tree):
|
||||||
|
yield "unary_int("
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield ")"
|
||||||
|
|
||||||
|
def unary_negation(tree):
|
||||||
|
yield "-"
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
|
||||||
|
def unary_not(tree):
|
||||||
|
yield "!"
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
|
||||||
|
#
|
||||||
|
def addition(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " + "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def division(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " / "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def equality_equal(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " == "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def equality_not_equal(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " != "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def greater_than(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " > "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def greater_than_equal(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " >= "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def left_shift(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
# hack for left shift by LHS constant
|
||||||
|
if type(tree.children[0]) is IntegerConstant:
|
||||||
|
yield "LL"
|
||||||
|
yield " << "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def less_than(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " < "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def less_than_equal(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " <= "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def multiplication(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " * "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def right_shift(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " >> "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def subtraction(tree):
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " - "
|
||||||
|
yield from generate(tree.children[1])
|
||||||
|
|
||||||
|
def declaration(tree):
|
||||||
|
assert len(tree.children) >= 2, tree
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
yield " "
|
||||||
|
for child in tree.children[1:-1]:
|
||||||
|
yield from generate(child)
|
||||||
|
yield ", "
|
||||||
|
yield from generate(tree.children[-1])
|
||||||
|
|
||||||
|
def unary_reference(tree):
|
||||||
|
yield "&"
|
||||||
|
assert len(tree.children) == 1
|
||||||
|
yield from generate(tree.children[0])
|
||||||
|
|
||||||
|
def identifier(token):
|
||||||
|
yield token.token
|
||||||
|
|
||||||
|
def constant(elem):
|
||||||
|
yield elem.token.lower()
|
||||||
|
|
||||||
|
def generate(elem):
|
||||||
|
mapping = {
|
||||||
|
"argument_list": argument_list,
|
||||||
|
"assignment_list": assignment_list,
|
||||||
|
"assignment": assignment,
|
||||||
|
"bit_extraction": bit_extraction,
|
||||||
|
"bitwise_and": bitwise_and,
|
||||||
|
"bitwise_or": bitwise_or,
|
||||||
|
"bitwise_xor": bitwise_xor,
|
||||||
|
"block_item_list": block_item_list,
|
||||||
|
"compound_statement": compound_statement,
|
||||||
|
"expression_statement": expression_statement,
|
||||||
|
"for_expression": for_expression,
|
||||||
|
"function_call": function_call,
|
||||||
|
"grouping": grouping,
|
||||||
|
"if": _if,
|
||||||
|
"if_else": if_else,
|
||||||
|
"logical_and": logical_and,
|
||||||
|
"logical_or": logical_or,
|
||||||
|
"member": member,
|
||||||
|
"subscript": subscript,
|
||||||
|
"throw": throw,
|
||||||
|
"throw_arg": throw_arg,
|
||||||
|
"unary_complement": unary_complement,
|
||||||
|
"unary_int": unary_int,
|
||||||
|
"unary_negation": unary_negation,
|
||||||
|
"unary_not": unary_not,
|
||||||
|
#
|
||||||
|
"addition": addition,
|
||||||
|
"division": division,
|
||||||
|
"equality_equal": equality_equal,
|
||||||
|
"equality_not_equal": equality_not_equal,
|
||||||
|
"greater_than": greater_than,
|
||||||
|
"greater_than_equal": greater_than_equal,
|
||||||
|
"left_shift": left_shift,
|
||||||
|
"less_than": less_than,
|
||||||
|
"less_than_equal": less_than_equal,
|
||||||
|
"multiplication": multiplication,
|
||||||
|
"right_shift": right_shift,
|
||||||
|
"subtraction": subtraction,
|
||||||
|
#
|
||||||
|
"declaration": declaration,
|
||||||
|
"unary_reference": unary_reference,
|
||||||
|
}
|
||||||
|
if type(elem) is Tree:
|
||||||
|
yield from mapping[elem.operation](elem)
|
||||||
|
elif type(elem) is Identifier:
|
||||||
|
yield from identifier(elem)
|
||||||
|
elif type(elem) is IntegerConstant:
|
||||||
|
yield from constant(elem)
|
||||||
|
else:
|
||||||
|
assert False, type(elem)
|
194
ast_transformers.py
Normal file
194
ast_transformers.py
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
from parser import Tree
|
||||||
|
from lexer import Identifier, Punctuator, IntegerConstant
|
||||||
|
|
||||||
|
import identifier_substitution
|
||||||
|
|
||||||
|
def find_locals__walk_assignment_lhs(tree):
|
||||||
|
if type(tree) is Tree:
|
||||||
|
for child in tree.children:
|
||||||
|
yield from find_locals__walk_assignment_lhs(child)
|
||||||
|
elif type(tree) is Identifier:
|
||||||
|
token = tree
|
||||||
|
if token.token not in {'m', 'n', 'i', 'd'}:
|
||||||
|
if token.token.lower() == token.token:
|
||||||
|
assert token.token not in identifier_substitution.mapping, token.token
|
||||||
|
yield token.token
|
||||||
|
|
||||||
|
def find_locals__walk_assignment(tree):
|
||||||
|
if type(tree) is Tree:
|
||||||
|
if tree.operation == "assignment":
|
||||||
|
yield from find_locals__walk_assignment_lhs(tree.children[0])
|
||||||
|
for child in tree.children[1:]:
|
||||||
|
yield from find_locals__walk_assignment(child)
|
||||||
|
else:
|
||||||
|
for child in tree.children:
|
||||||
|
yield from find_locals__walk_assignment(child)
|
||||||
|
|
||||||
|
def transform_assignment_list__collect_identifiers(tree, operation):
|
||||||
|
if type(tree) == Tree:
|
||||||
|
assert tree.operation == operation, pprint(tree)
|
||||||
|
for child in tree.children:
|
||||||
|
yield from transform_assignment_list__collect_identifiers(child, operation)
|
||||||
|
elif type(tree) == Identifier:
|
||||||
|
yield tree.token
|
||||||
|
|
||||||
|
def transform_assignment_list__assignment(tree):
|
||||||
|
assert tree.operation == "assignment", tree
|
||||||
|
# first, collect the lhs
|
||||||
|
if type(tree.children[0]) is not Tree or tree.children[0].operation != 'assignment_list':
|
||||||
|
return tree
|
||||||
|
|
||||||
|
lhs = transform_assignment_list__collect_identifiers(tree.children[0], "assignment_list")
|
||||||
|
|
||||||
|
assert tree.children[1].operation == "function_call", (tree.children[1].operation, pprint(tree))
|
||||||
|
function_call = tree.children[1]
|
||||||
|
rhs = list(transform_assignment_list__collect_identifiers(function_call.children[1], "argument_list"))
|
||||||
|
|
||||||
|
common = []
|
||||||
|
lhs_only = []
|
||||||
|
for l_token in lhs:
|
||||||
|
if l_token in rhs:
|
||||||
|
common.append(l_token)
|
||||||
|
else:
|
||||||
|
lhs_only.append(l_token)
|
||||||
|
|
||||||
|
def gen_argument_list(tree):
|
||||||
|
if type(tree) is Tree:
|
||||||
|
assert tree.operation == 'argument_list'
|
||||||
|
return Tree(
|
||||||
|
operation=tree.operation,
|
||||||
|
children=[gen_argument_list(child) for child in tree.children]
|
||||||
|
)
|
||||||
|
elif type(tree) is Identifier:
|
||||||
|
if tree.token in common:
|
||||||
|
return Tree(
|
||||||
|
operation="unary_reference",
|
||||||
|
children=[tree]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return tree
|
||||||
|
else:
|
||||||
|
return tree
|
||||||
|
|
||||||
|
def gen_function_call():
|
||||||
|
return Tree(
|
||||||
|
operation="function_call",
|
||||||
|
children=[
|
||||||
|
function_call.children[0],
|
||||||
|
gen_argument_list(function_call.children[1]),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(lhs_only) == 0:
|
||||||
|
return gen_function_call()
|
||||||
|
elif len(lhs_only) == 1:
|
||||||
|
return Tree(
|
||||||
|
operation="assignment",
|
||||||
|
children=[Identifier(line=-1, token=lhs_only[0]), gen_function_call()]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert False, (lhs_only, common, pprint(tree))
|
||||||
|
|
||||||
|
def transform_assignment_list(tree):
|
||||||
|
if type(tree) is Tree:
|
||||||
|
if tree.operation == "assignment":
|
||||||
|
return transform_assignment_list__assignment(tree)
|
||||||
|
else:
|
||||||
|
return Tree(
|
||||||
|
operation=tree.operation,
|
||||||
|
children=[
|
||||||
|
transform_assignment_list(child)
|
||||||
|
for child in tree.children
|
||||||
|
]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return tree
|
||||||
|
|
||||||
|
def transform_local_declarations(statements):
|
||||||
|
all_locals = []
|
||||||
|
for statement in statements:
|
||||||
|
all_locals.extend(find_locals__walk_assignment(statement))
|
||||||
|
|
||||||
|
set_locals = []
|
||||||
|
for local in all_locals:
|
||||||
|
if not any(s.token == local for s in set_locals):
|
||||||
|
set_locals.append(Identifier(line=-1, token=local))
|
||||||
|
|
||||||
|
if set_locals:
|
||||||
|
yield Tree(operation="expression_statement",
|
||||||
|
children=[Tree(operation="declaration",
|
||||||
|
children=[Identifier(line=-1, token="int64_t"), *set_locals])])
|
||||||
|
|
||||||
|
def transform_identifiers(tree):
|
||||||
|
if type(tree) is Tree:
|
||||||
|
return Tree(
|
||||||
|
operation=tree.operation,
|
||||||
|
children=[transform_identifiers(child) for child in tree.children]
|
||||||
|
)
|
||||||
|
elif type(tree) is Identifier:
|
||||||
|
token = tree
|
||||||
|
if token.token in identifier_substitution.mapping:
|
||||||
|
return Identifier(
|
||||||
|
line=token.line,
|
||||||
|
token=identifier_substitution.mapping[token.token]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return token
|
||||||
|
else:
|
||||||
|
return tree
|
||||||
|
|
||||||
|
require_extra_arguments = {
|
||||||
|
"IsDelaySlot": "state",
|
||||||
|
"SLEEP": "state",
|
||||||
|
"OCBP" : "state",
|
||||||
|
"WriteMemory8" : "map",
|
||||||
|
"WriteMemory16": "map",
|
||||||
|
"WriteMemory32": "map",
|
||||||
|
"ReadMemory8" : "map",
|
||||||
|
"ReadMemory16" : "map",
|
||||||
|
"ReadMemory32" : "map",
|
||||||
|
}
|
||||||
|
|
||||||
|
def transform_function_arguments(tree):
|
||||||
|
def arguments(arg):
|
||||||
|
identifier = Identifier(line=tree.children[0].line, token=arg)
|
||||||
|
if len(tree.children) == 1:
|
||||||
|
return identifier
|
||||||
|
else:
|
||||||
|
assert len(tree.children) == 2, tree
|
||||||
|
return Tree(
|
||||||
|
operation='argument_list',
|
||||||
|
children=[
|
||||||
|
identifier,
|
||||||
|
transform_function_arguments(tree.children[1])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if type(tree) is Tree:
|
||||||
|
if tree.operation == "function_call":
|
||||||
|
assert type(tree.children[0]) is Identifier
|
||||||
|
if tree.children[0].token in require_extra_arguments:
|
||||||
|
return Tree(
|
||||||
|
operation=tree.operation,
|
||||||
|
children=[
|
||||||
|
tree.children[0],
|
||||||
|
arguments(require_extra_arguments[tree.children[0].token])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return Tree(
|
||||||
|
operation=tree.operation,
|
||||||
|
children=[transform_function_arguments(child) for child in tree.children]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return tree
|
||||||
|
|
||||||
|
def transform_statements(statements):
|
||||||
|
yield from transform_local_declarations(statements)
|
||||||
|
|
||||||
|
for statement in statements:
|
||||||
|
statement = transform_assignment_list(statement)
|
||||||
|
statement = transform_function_arguments(statement)
|
||||||
|
statement = transform_identifiers(statement)
|
||||||
|
yield statement
|
3
build.sh
Normal file
3
build.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
PYTHONPATH=python/ python generate_impl.py c/impl.c c/impl.h
|
||||||
|
PYTHONPATH=python/ python generate_decoder.py c/decode_execute.c c/decode_print.c
|
||||||
|
PYTHONPATH=python/ python generate_bits.py > c/status_bits.h
|
30
c/Makefile
Normal file
30
c/Makefile
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
DEBUG = -g -gdwarf-4
|
||||||
|
|
||||||
|
AFLAGS += --fatal-warnings
|
||||||
|
|
||||||
|
CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums
|
||||||
|
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=dangling-else
|
||||||
|
CFLAGS += -std=c2x
|
||||||
|
|
||||||
|
DEPFLAGS = -MMD -MP
|
||||||
|
|
||||||
|
CC = $(TARGET)gcc
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
decode_execute.o \
|
||||||
|
decode_print.o \
|
||||||
|
exception.o \
|
||||||
|
execute.o \
|
||||||
|
impl.o \
|
||||||
|
main.o \
|
||||||
|
ram.o
|
||||||
|
|
||||||
|
all: main
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CARCH) $(CFLAGS) $(OPT) $(DEBUG) $(DEPFLAGS) -MF ${<}.d -c $< -o $@
|
||||||
|
|
||||||
|
main: $(OBJS)
|
||||||
|
$(CC) $^ -o $@
|
||||||
|
|
||||||
|
-include $(shell find -type f -name '*.d')
|
6
c/decode.h
Normal file
6
c/decode.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum decode_status {
|
||||||
|
DECODE__DEFINED,
|
||||||
|
DECODE__UNDEFINED
|
||||||
|
};
|
937
c/decode_execute.c
Normal file
937
c/decode_execute.c
Normal file
@ -0,0 +1,937 @@
|
|||||||
|
#include "decode_execute.h"
|
||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
enum decode_status decode_and_execute_instruction(struct architectural_state * state, struct memory_map * map, uint16_t code)
|
||||||
|
{
|
||||||
|
switch (code & 0b1111000000000000) {
|
||||||
|
case 0b0001000000000000: // MOV.L Rm,@(disp,Rn)
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__store_register_indirect_with_displacement(state, map, m, d, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0101000000000000: // MOV.L @(disp,Rm),Rn
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 4) - 1);
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__load_register_indirect_with_displacement(state, map, d, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0111000000000000: // ADD #imm,Rn
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
add__immediate(state, map, i, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1001000000000000: // MOV.W @(disp,PC),Rn
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_w__pc_relative_with_displacement(state, map, d, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1010000000000000: // BRA label
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 12) - 1);
|
||||||
|
bra__pc_relative(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1011000000000000: // BSR label
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 12) - 1);
|
||||||
|
bsr__pc_relative(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1101000000000000: // MOV.L @(disp,PC),Rn
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__pc_relative_with_displacement(state, map, d, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1110000000000000: // MOV #imm,Rn
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov__immediate(state, map, i, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (code & 0b1111000000001111) {
|
||||||
|
case 0b0000000000000100: // MOV.B Rm,@(R0,Rn)
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_b__store_indexed_register_indirect(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000000101: // MOV.W Rm,@(R0,Rn)
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_w__store_indexed_register_indirect(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000000110: // MOV.L Rm,@(R0,Rn)
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__store_indexed_register_indirect(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000000111: // MUL.L Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mul_l__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000001100: // MOV.B @(R0,Rm),Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_b__load_indexed_register_indirect(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000001101: // MOV.W @(R0,Rm),Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_w__load_indexed_register_indirect(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000001110: // MOV.L @(R0,Rm),Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__load_indexed_register_indirect(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000001111: // MAC.L @Rm+,@Rn+
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mac_l__multiply_and_accumulate_operation(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000000000: // MOV.B Rm,@Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_b__store_register_direct_data_transfer(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000000001: // MOV.W Rm,@Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_w__store_register_direct_data_transfer(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000000010: // MOV.L Rm,@Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__store_register_direct_data_transfer(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000000100: // MOV.B Rm,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_b__store_direct_data_transfer_from_register(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000000101: // MOV.W Rm,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_w__store_direct_data_transfer_from_register(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000000110: // MOV.L Rm,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__store_direct_data_transfer_from_register(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000000111: // DIV0S Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
div0s__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001000: // TST Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
tst__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001001: // AND Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
and__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001010: // XOR Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
xor__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001011: // OR Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
or__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001100: // CMP/STR Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_str__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001101: // XTRCT Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
xtrct__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001110: // MULU.W Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mulu_w__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0010000000001111: // MULS.W Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
muls_w__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000000000: // CMP/EQ Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_eq__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000000010: // CMP/HS Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_hs__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000000011: // CMP/GE Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_ge__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000000100: // DIV1 Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
div1__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000000101: // DMULU.L Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
dmulu_l__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000000110: // CMP/HI Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_hi__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000000111: // CMP/GT Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_gt__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000001000: // SUB Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sub__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000001010: // SUBC Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
subc__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000001011: // SUBV Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
subv__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000001100: // ADD Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
add__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000001101: // DMULS.L Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
dmuls_l__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000001110: // ADDC Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
addc__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0011000000001111: // ADDV Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
addv__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001111: // MAC.W @Rm+,@Rn+
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mac_w__multiply_and_accumulate_operation(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000000: // MOV.B @Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_b__load_register_direct_data_transfer(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000001: // MOV.W @Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_w__load_register_direct_data_transfer(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000010: // MOV.L @Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__load_register_direct_data_transfer(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000011: // MOV Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000100: // MOV.B @Rm+,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_b__load_direct_data_transfer_from_register(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000101: // MOV.W @Rm+,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_w__load_direct_data_transfer_from_register(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000110: // MOV.L @Rm+,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
mov_l__load_direct_data_transfer_from_register(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000000111: // NOT Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
not__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001000: // SWAP.B Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
swap_b__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001001: // SWAP.W Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
swap_w__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001010: // NEGC Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
negc__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001011: // NEG Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
neg__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001100: // EXTU.B Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
extu_b__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001101: // EXTU.W Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
extu_w__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001110: // EXTS.B Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
exts_b__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0110000000001111: // EXTS.W Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
exts_w__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (code & 0b1111111100000000) {
|
||||||
|
case 0b1000000000000000: // MOV.B R0,@(disp,Rn)
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
mov_b__store_register_indirect_with_displacement(state, map, d, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000000100000000: // MOV.W R0,@(disp,Rn)
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
mov_w__store_register_indirect_with_displacement(state, map, d, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000010000000000: // MOV.B @(disp,Rm),R0
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 4) - 1);
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
mov_b__load_register_indirect_with_displacement(state, map, d, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000010100000000: // MOV.W @(disp,Rm),R0
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 4) - 1);
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
mov_w__load_register_indirect_with_displacement(state, map, d, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000100000000000: // CMP/EQ #imm,R0
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
cmp_eq__immediate(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000100100000000: // BT label
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
bt__pc_relative(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000101100000000: // BF label
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
bf__pc_relative(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000110100000000: // BT/S label
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
bt_s__pc_relative(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1000111100000000: // BF/S label
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
bf_s__pc_relative(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100000000000000: // MOV.B R0,@(disp,GBR)
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
mov_b__store_gbr_indirect_with_displacement(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100000100000000: // MOV.W R0,@(disp,GBR)
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
mov_w__store_gbr_indirect_with_displacement(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100001000000000: // MOV.L R0,@(disp,GBR)
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
mov_l__store_gbr_indirect_with_displacement(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100001100000000: // TRAPA #imm
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
trapa__immediate(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100010000000000: // MOV.B @(disp,GBR),R0
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
mov_b__load_gbr_indirect_with_displacement(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100010100000000: // MOV.W @(disp,GBR),R0
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
mov_w__load_gbr_indirect_with_displacement(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100011000000000: // MOV.L @(disp,GBR),R0
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
mov_l__load_gbr_indirect_with_displacement(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100011100000000: // MOVA @(disp,PC),R0
|
||||||
|
{
|
||||||
|
uint32_t d = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
mova__pc_relative_with_displacement(state, map, d);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100100000000000: // TST #imm,R0
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
tst__immediate(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100100100000000: // AND #imm,R0
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
and__immediate(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100101000000000: // XOR #imm,R0
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
xor__immediate(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100101100000000: // OR #imm,R0
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
or__immediate(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100110000000000: // TST.B #imm,@(R0,GBR)
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
tst_b__store_indexed_gbr_indirect(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100110100000000: // AND.B #imm,@(R0,GBR)
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
and_b__store_indexed_gbr_indirect(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100111000000000: // XOR.B #imm,@(R0,GBR)
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
xor_b__store_indexed_gbr_indirect(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b1100111100000000: // OR.B #imm,@(R0,GBR)
|
||||||
|
{
|
||||||
|
uint32_t i = (code >> 0) & ((1 << 8) - 1);
|
||||||
|
or_b__store_indexed_gbr_indirect(state, map, i);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (code & 0b1111000011111111) {
|
||||||
|
case 0b0000000000000010: // STC SR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_sr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000000011: // BSRF Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
bsrf__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000001010: // STS MACH,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts__transfer_from_mach(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000010010: // STC GBR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_gbr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000011010: // STS MACL,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts__transfer_from_macl(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000100010: // STC VBR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_vbr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000100011: // BRAF Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
braf__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000101001: // MOVT Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
movt__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000101010: // STS PR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts__transfer_from_pr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000000: // SHLL Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shll__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000001: // SHLR Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shlr__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000010: // STS.L MACH,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts_l__store_from_mach(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000011: // STC.L SR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_sr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000100: // ROTL Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
rotl__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000101: // ROTR Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
rotr__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000110: // LDS.L @Rm+,MACH
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds_l__load_to_mach(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000000111: // LDC.L @Rm+,SR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc_l__load_to_sr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001000: // SHLL2 Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shll2__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001001: // SHLR2 Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shlr2__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001010: // LDS Rm,MACH
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds__transfer_to_mach(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001011: // JSR @Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
jsr__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001110: // LDC Rm,SR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc__transfer_to_sr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000010000: // DT Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
dt__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000010001: // CMP/PZ Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_pz__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000010010: // STS.L MACL,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts_l__store_from_macl(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000010011: // STC.L GBR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_gbr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000010101: // CMP/PL Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
cmp_pl__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000010110: // LDS.L @Rm+,MACL
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds_l__load_to_macl(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000010111: // LDC.L @Rm+,GBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc_l__load_to_gbr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000011000: // SHLL8 Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shll8__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000011001: // SHLR8 Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shlr8__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000011010: // LDS Rm,MACL
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds__transfer_to_macl(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000011011: // TAS.B @Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
tas_b__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000011110: // LDC Rm,GBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc__transfer_to_gbr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100000: // SHAL Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shal__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100001: // SHAR Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shar__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100010: // STS.L PR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts_l__store_from_pr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100011: // STC.L VBR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_vbr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100100: // ROTCL Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
rotcl__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100101: // ROTCR Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
rotcr__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100110: // LDS.L @Rm+,PR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds_l__load_to_pr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000100111: // LDC.L @Rm+,VBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc_l__load_to_vbr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000101000: // SHLL16 Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shll16__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000101001: // SHLR16 Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shlr16__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000101010: // LDS Rm,PR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds__transfer_to_pr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000101011: // JMP @Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
jmp__destination_operand_only(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000101110: // LDC Rm,VBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc__transfer_to_vbr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (code & 0b1111111111111111) {
|
||||||
|
case 0b0000000000001000: // CLRT
|
||||||
|
{
|
||||||
|
clrt__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000001001: // NOP
|
||||||
|
{
|
||||||
|
nop__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000001011: // RTS
|
||||||
|
{
|
||||||
|
rts__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000011000: // SETT
|
||||||
|
{
|
||||||
|
sett__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000011001: // DIV0U
|
||||||
|
{
|
||||||
|
div0u__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000011011: // SLEEP
|
||||||
|
{
|
||||||
|
sleep__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000101000: // CLRMAC
|
||||||
|
{
|
||||||
|
clrmac__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000101011: // RTE
|
||||||
|
{
|
||||||
|
rte__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001001000: // CLRS
|
||||||
|
{
|
||||||
|
clrs__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001011000: // SETS
|
||||||
|
{
|
||||||
|
sets__no_operand(state, map);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DECODE__UNDEFINED;
|
||||||
|
}
|
9
c/decode_execute.h
Normal file
9
c/decode_execute.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "memory_map.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "decode.h"
|
||||||
|
|
||||||
|
enum decode_status decode_and_execute_instruction(struct architectural_state * state, struct memory_map * map, uint16_t code);
|
1082
c/decode_print.c
Normal file
1082
c/decode_print.c
Normal file
File diff suppressed because it is too large
Load Diff
9
c/decode_print.h
Normal file
9
c/decode_print.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "memory_map.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "decode.h"
|
||||||
|
|
||||||
|
enum decode_status decode_and_print_instruction(struct architectural_state * state, struct memory_map * map, uint16_t code, char const ** instruction_buf, char * operand_buf, uint32_t size);
|
391
c/exception.c
Normal file
391
c/exception.c
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "exception.h"
|
||||||
|
|
||||||
|
#define SR state->sr.bits
|
||||||
|
#define _SR state->sr.value
|
||||||
|
#define VBR state->vbr
|
||||||
|
#define PC state->pc[0] = state->pc[1]
|
||||||
|
#define SPC state->spc
|
||||||
|
#define SSR state->ssr
|
||||||
|
#define SGR state->sgr
|
||||||
|
#define R15 state->general_register[15]
|
||||||
|
|
||||||
|
#define BL bl
|
||||||
|
#define FD fd
|
||||||
|
#define IMASK imask
|
||||||
|
#define MD md
|
||||||
|
#define RB rb
|
||||||
|
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
|
#define EXPEVT int32_t expevt
|
||||||
|
#define INTEVT int32_t intevt
|
||||||
|
#define TEA int32_t tea
|
||||||
|
#define TRA int32_t tra
|
||||||
|
|
||||||
|
#define EXCEPTION_ADDRESS 0
|
||||||
|
|
||||||
|
void exception(struct architectural_state * state, const char * name)
|
||||||
|
{
|
||||||
|
printf("exception: %s\n", name);
|
||||||
|
state->is_delay_slot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void POWERON(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "POWERON");
|
||||||
|
//Initialize_Module(PowerOn);
|
||||||
|
EXPEVT = 0x00000000;
|
||||||
|
VBR = 0x00000000;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
SR.IMASK = 0xF;
|
||||||
|
SR.FD = 0;
|
||||||
|
PC = 0xA0000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MANRESET(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "MANRESET");
|
||||||
|
//Initialize_Module(Manual);
|
||||||
|
EXPEVT = 0x00000020;
|
||||||
|
VBR = 0x00000000;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
SR.IMASK = 0xF;
|
||||||
|
SR.FD = 0;
|
||||||
|
PC = 0xA0000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HUIDRESET(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "HUIDRESET");
|
||||||
|
//Initialize_Module(PowerOn);
|
||||||
|
EXPEVT = 0x00000000;
|
||||||
|
VBR = 0x00000000;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
SR.IMASK = 0xF;
|
||||||
|
SR.FD = 0;
|
||||||
|
PC = 0xA0000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITLBMULTIHIT(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "ITLBMULTIHIT");
|
||||||
|
//Initialize_Module(Manual);
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
EXPEVT = 0x00000140;
|
||||||
|
VBR = 0x00000000;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
SR.IMASK = 0xF;
|
||||||
|
SR.FD = 0;
|
||||||
|
PC = 0xA0000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTLBMULTIHIT(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "OTLBMULTIHIT");
|
||||||
|
//Initialize_Module(Manual);
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
EXPEVT = 0x00000140;
|
||||||
|
VBR = 0x00000000;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
SR.IMASK = 0xF;
|
||||||
|
SR.FD = 0;
|
||||||
|
PC = 0xA0000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* General exceptions */
|
||||||
|
|
||||||
|
void RTLBMISS(struct architectural_state * state, int32_t op1)
|
||||||
|
{
|
||||||
|
exception(state, "RTLBMISS");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000040;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000400;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WTLBMISS(struct architectural_state * state, int32_t op1)
|
||||||
|
{
|
||||||
|
exception(state, "WTLBMISS");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000060;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000400;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITLBMISS(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "ITLBMISS");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000040;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000400;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIRSTWRITE(struct architectural_state * state, int32_t op1)
|
||||||
|
{
|
||||||
|
exception(state, "FIRSTWRITE");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000080;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void READPROT(struct architectural_state * state, int32_t op1)
|
||||||
|
{
|
||||||
|
exception(state, "READPROT");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000000A0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WRITEPROT(struct architectural_state * state, int32_t op1)
|
||||||
|
{
|
||||||
|
exception(state, "WRITEPROT");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000000C0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXECPROT(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "EXECPROT");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEH.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000000A0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RADDERR(struct architectural_state * state, int32_t op1)
|
||||||
|
{
|
||||||
|
exception(state, "RADDERR");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEN.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000000E0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WADDERR(struct architectural_state * state, int32_t op1)
|
||||||
|
{
|
||||||
|
exception(state, "WADDERR");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEN.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000100;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IADDERR(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "IADDERR");
|
||||||
|
TEA = EXCEPTION_ADDRESS;
|
||||||
|
//PTEN.VPN = PAGE_NUMBER;
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000000E0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TRAP(struct architectural_state * state, int32_t imm)
|
||||||
|
{
|
||||||
|
exception(state, "TRAP");
|
||||||
|
SPC = PC + 2;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
TRA = imm << 2;
|
||||||
|
EXPEVT = 0x00000160;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RESINST(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "RESINST");
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000180;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILLSLOT(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "ILLSLOT");
|
||||||
|
SPC = PC - 2;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000001A0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPUDIS(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "FPUDIS");
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000800;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SLOTFPUDIS(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "SLOTFPUDIS");
|
||||||
|
SPC = PC - 2;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000820;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UBRKBEFORE(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "UBRKBEFORE");
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000001E0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
//PC = (BRCR.UBDE==1 ? DBR : VBR + H00000100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UBRKAFTER(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "UBRKAFTER");
|
||||||
|
SPC = PC + 2;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x000001E0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
//PC = (BRCR.UBDE==1 ? DBR : VBR + H00000100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPUEXC(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "FPUEXC");
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
EXPEVT = 0x00000120;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interrupts */
|
||||||
|
|
||||||
|
void NMI(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "NMI");
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
INTEVT = 0x000001C0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000600;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRLINT(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
exception(state, "IRLINT");
|
||||||
|
SPC = PC;
|
||||||
|
SSR = _SR;
|
||||||
|
SGR = R15;
|
||||||
|
//INTEVT = 0x00000200 ~ 0x000003C0;
|
||||||
|
SR.MD = 1;
|
||||||
|
SR.RB = 1;
|
||||||
|
SR.BL = 1;
|
||||||
|
PC = VBR + 0x00000600;
|
||||||
|
}
|
31
c/exception.h
Normal file
31
c/exception.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
void POWERON(struct architectural_state * state);
|
||||||
|
void MANRESET(struct architectural_state * state);
|
||||||
|
void HUIDRESET(struct architectural_state * state);
|
||||||
|
void ITLBMULTIHIT(struct architectural_state * state);
|
||||||
|
void OTLBMULTIHIT(struct architectural_state * state);
|
||||||
|
void RTLBMISS(struct architectural_state * state, int32_t op1);
|
||||||
|
void WTLBMISS(struct architectural_state * state, int32_t op1);
|
||||||
|
void ITLBMISS(struct architectural_state * state);
|
||||||
|
void FIRSTWRITE(struct architectural_state * state, int32_t op1);
|
||||||
|
void READPROT(struct architectural_state * state, int32_t op1);
|
||||||
|
void WRITEPROT(struct architectural_state * state, int32_t op1);
|
||||||
|
void EXECPROT(struct architectural_state * state);
|
||||||
|
void RADDERR(struct architectural_state * state, int32_t op1);
|
||||||
|
void WADDERR(struct architectural_state * state, int32_t op1);
|
||||||
|
void IADDERR(struct architectural_state * state);
|
||||||
|
void TRAP(struct architectural_state * state, int32_t imm);
|
||||||
|
void RESINST(struct architectural_state * state);
|
||||||
|
void ILLSLOT(struct architectural_state * state);
|
||||||
|
void FPUDIS(struct architectural_state * state);
|
||||||
|
void SLOTFPUDIS(struct architectural_state * state);
|
||||||
|
void UBRKBEFORE(struct architectural_state * state);
|
||||||
|
void UBRKAFTER(struct architectural_state * state);
|
||||||
|
void FPUEXC(struct architectural_state * state);
|
||||||
|
void NMI(struct architectural_state * state);
|
||||||
|
void IRLINT(struct architectural_state * state);
|
69
c/execute.c
Normal file
69
c/execute.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "execute.h"
|
||||||
|
#include "operations.h"
|
||||||
|
#include "state_helpers.h"
|
||||||
|
#include "decode_execute.h"
|
||||||
|
#include "exception.h"
|
||||||
|
|
||||||
|
uint16_t fetch(struct architectural_state * state, struct memory_map * map)
|
||||||
|
{
|
||||||
|
uint32_t address = zero_extend32(sign_extend32(state->pc[0]));
|
||||||
|
assert((address & 0b1) == 0);
|
||||||
|
return read_memory16(map, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(struct architectural_state * state, struct memory_map * map)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 3 Fetch the instruction bytes from the address in memory, as
|
||||||
|
* indicated by the current program counter, 2 bytes need to be
|
||||||
|
* fetched for each instruction.
|
||||||
|
*/
|
||||||
|
uint16_t instruction_code = fetch(state, map);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 4 Calculate the default values of PC’ and PR’. PC’ is set to the
|
||||||
|
* value of PC”, PR’ is set to the value of PR”.
|
||||||
|
*/
|
||||||
|
state->pc[1] = state->pc[2];
|
||||||
|
state->pr[1] = state->pr[2];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 5 Calculate the default values of PC” and PR” assuming continued
|
||||||
|
* sequential execution without procedure call or mode switch: PC”
|
||||||
|
* is PC’+2, while PR” is unchanged.
|
||||||
|
*/
|
||||||
|
state->pc[2] = state->pc[1] + 2;
|
||||||
|
state->pr[2] = state->pr[2]; // unchanged
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 6 Decode and execute the instruction. This includes checks for
|
||||||
|
* synchronous events, such as exceptions and panics, and
|
||||||
|
* initiation of handling if required. Synchronous events are not
|
||||||
|
* accepted between a delayed branch and a delay slot. They are
|
||||||
|
* detected either before the delayed branch or after the delay
|
||||||
|
* slot.
|
||||||
|
*/
|
||||||
|
enum decode_status status = decode_and_execute_instruction(state, map, instruction_code);
|
||||||
|
switch (status) {
|
||||||
|
case DECODE__DEFINED:
|
||||||
|
break;
|
||||||
|
case DECODE__UNDEFINED: // undefined instruction
|
||||||
|
if (state->is_delay_slot)
|
||||||
|
ILLSLOT(state);
|
||||||
|
else
|
||||||
|
RESINST(state);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 7 Set the current program counter (PC) to the value of the next
|
||||||
|
* program counter (PC’) and PR to the value of PR’.
|
||||||
|
*/
|
||||||
|
state->pc[0] = state->pc[1];
|
||||||
|
state->pr[0] = state->pr[1];
|
||||||
|
}
|
7
c/execute.h
Normal file
7
c/execute.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "memory_map.h"
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
uint16_t fetch(struct architectural_state * state, struct memory_map * map);
|
||||||
|
void step(struct architectural_state * state, struct memory_map * mem);
|
349
c/impl.h
Normal file
349
c/impl.h
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
#include "memory_map.h"
|
||||||
|
|
||||||
|
/* MOV #imm,Rn */
|
||||||
|
void mov__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i, const uint32_t n);
|
||||||
|
/* MOV.W @(disp,PC),Rn */
|
||||||
|
void mov_w__pc_relative_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d, const uint32_t n);
|
||||||
|
/* MOV.L @(disp,PC),Rn */
|
||||||
|
void mov_l__pc_relative_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d, const uint32_t n);
|
||||||
|
/* MOV Rm,Rn */
|
||||||
|
void mov__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B Rm,@Rn */
|
||||||
|
void mov_b__store_register_direct_data_transfer(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.W Rm,@Rn */
|
||||||
|
void mov_w__store_register_direct_data_transfer(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.L Rm,@Rn */
|
||||||
|
void mov_l__store_register_direct_data_transfer(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B @Rm,Rn */
|
||||||
|
void mov_b__load_register_direct_data_transfer(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.W @Rm,Rn */
|
||||||
|
void mov_w__load_register_direct_data_transfer(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.L @Rm,Rn */
|
||||||
|
void mov_l__load_register_direct_data_transfer(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B Rm,@-Rn */
|
||||||
|
void mov_b__store_direct_data_transfer_from_register(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.W Rm,@-Rn */
|
||||||
|
void mov_w__store_direct_data_transfer_from_register(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.L Rm,@-Rn */
|
||||||
|
void mov_l__store_direct_data_transfer_from_register(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B @Rm+,Rn */
|
||||||
|
void mov_b__load_direct_data_transfer_from_register(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.W @Rm+,Rn */
|
||||||
|
void mov_w__load_direct_data_transfer_from_register(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.L @Rm+,Rn */
|
||||||
|
void mov_l__load_direct_data_transfer_from_register(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B R0,@(disp,Rn) */
|
||||||
|
void mov_b__store_register_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d, const uint32_t n);
|
||||||
|
/* MOV.W R0,@(disp,Rn) */
|
||||||
|
void mov_w__store_register_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d, const uint32_t n);
|
||||||
|
/* MOV.L Rm,@(disp,Rn) */
|
||||||
|
void mov_l__store_register_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t d, const uint32_t n);
|
||||||
|
/* MOV.B @(disp,Rm),R0 */
|
||||||
|
void mov_b__load_register_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d, const uint32_t m);
|
||||||
|
/* MOV.W @(disp,Rm),R0 */
|
||||||
|
void mov_w__load_register_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d, const uint32_t m);
|
||||||
|
/* MOV.L @(disp,Rm),Rn */
|
||||||
|
void mov_l__load_register_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B Rm,@(R0,Rn) */
|
||||||
|
void mov_b__store_indexed_register_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.W Rm,@(R0,Rn) */
|
||||||
|
void mov_w__store_indexed_register_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.L Rm,@(R0,Rn) */
|
||||||
|
void mov_l__store_indexed_register_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B @(R0,Rm),Rn */
|
||||||
|
void mov_b__load_indexed_register_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.W @(R0,Rm),Rn */
|
||||||
|
void mov_w__load_indexed_register_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.L @(R0,Rm),Rn */
|
||||||
|
void mov_l__load_indexed_register_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MOV.B R0,@(disp,GBR) */
|
||||||
|
void mov_b__store_gbr_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* MOV.W R0,@(disp,GBR) */
|
||||||
|
void mov_w__store_gbr_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* MOV.L R0,@(disp,GBR) */
|
||||||
|
void mov_l__store_gbr_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* MOV.B @(disp,GBR),R0 */
|
||||||
|
void mov_b__load_gbr_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* MOV.W @(disp,GBR),R0 */
|
||||||
|
void mov_w__load_gbr_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* MOV.L @(disp,GBR),R0 */
|
||||||
|
void mov_l__load_gbr_indirect_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* MOVA @(disp,PC),R0 */
|
||||||
|
void mova__pc_relative_with_displacement(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* MOVT Rn */
|
||||||
|
void movt__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SWAP.B Rm,Rn */
|
||||||
|
void swap_b__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* SWAP.W Rm,Rn */
|
||||||
|
void swap_w__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* XTRCT Rm,Rn */
|
||||||
|
void xtrct__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* ADD Rm,Rn */
|
||||||
|
void add__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* ADD #imm,Rn */
|
||||||
|
void add__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i, const uint32_t n);
|
||||||
|
/* ADDC Rm,Rn */
|
||||||
|
void addc__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* ADDV Rm,Rn */
|
||||||
|
void addv__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* CMP/EQ #imm,R0 */
|
||||||
|
void cmp_eq__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* CMP/EQ Rm,Rn */
|
||||||
|
void cmp_eq__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* CMP/HS Rm,Rn */
|
||||||
|
void cmp_hs__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* CMP/GE Rm,Rn */
|
||||||
|
void cmp_ge__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* CMP/HI Rm,Rn */
|
||||||
|
void cmp_hi__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* CMP/GT Rm,Rn */
|
||||||
|
void cmp_gt__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* CMP/PZ Rn */
|
||||||
|
void cmp_pz__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* CMP/PL Rn */
|
||||||
|
void cmp_pl__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* CMP/STR Rm,Rn */
|
||||||
|
void cmp_str__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* DIV1 Rm,Rn */
|
||||||
|
void div1__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* DIV0S Rm,Rn */
|
||||||
|
void div0s__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* DIV0U */
|
||||||
|
void div0u__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* DMULS.L Rm,Rn */
|
||||||
|
void dmuls_l__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* DMULU.L Rm,Rn */
|
||||||
|
void dmulu_l__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* DT Rn */
|
||||||
|
void dt__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* EXTS.B Rm,Rn */
|
||||||
|
void exts_b__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* EXTS.W Rm,Rn */
|
||||||
|
void exts_w__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* EXTU.B Rm,Rn */
|
||||||
|
void extu_b__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* EXTU.W Rm,Rn */
|
||||||
|
void extu_w__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MAC.L @Rm+,@Rn+ */
|
||||||
|
void mac_l__multiply_and_accumulate_operation(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MAC.W @Rm+,@Rn+ */
|
||||||
|
void mac_w__multiply_and_accumulate_operation(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MUL.L Rm,Rn */
|
||||||
|
void mul_l__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MULS.W Rm,Rn */
|
||||||
|
void muls_w__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* MULU.W Rm,Rn */
|
||||||
|
void mulu_w__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* NEG Rm,Rn */
|
||||||
|
void neg__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* NEGC Rm,Rn */
|
||||||
|
void negc__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* SUB Rm,Rn */
|
||||||
|
void sub__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* SUBC Rm,Rn */
|
||||||
|
void subc__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* SUBV Rm,Rn */
|
||||||
|
void subv__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* AND Rm,Rn */
|
||||||
|
void and__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* AND #imm,R0 */
|
||||||
|
void and__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* AND.B #imm,@(R0,GBR) */
|
||||||
|
void and_b__store_indexed_gbr_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* NOT Rm,Rn */
|
||||||
|
void not__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* OR Rm,Rn */
|
||||||
|
void or__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* OR #imm,R0 */
|
||||||
|
void or__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* OR.B #imm,@(R0,GBR) */
|
||||||
|
void or_b__store_indexed_gbr_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* TAS.B @Rn */
|
||||||
|
void tas_b__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* TST Rm,Rn */
|
||||||
|
void tst__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* TST #imm,R0 */
|
||||||
|
void tst__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* TST.B #imm,@(R0,GBR) */
|
||||||
|
void tst_b__store_indexed_gbr_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* XOR Rm,Rn */
|
||||||
|
void xor__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* XOR #imm,R0 */
|
||||||
|
void xor__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* XOR.B #imm,@(R0,GBR) */
|
||||||
|
void xor_b__store_indexed_gbr_indirect(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* ROTL Rn */
|
||||||
|
void rotl__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* ROTR Rn */
|
||||||
|
void rotr__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* ROTCL Rn */
|
||||||
|
void rotcl__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* ROTCR Rn */
|
||||||
|
void rotcr__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHAD Rm,Rn */
|
||||||
|
void shad__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* SHAL Rn */
|
||||||
|
void shal__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHAR Rn */
|
||||||
|
void shar__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLD Rm,Rn */
|
||||||
|
void shld__source_and_destination_operands(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* SHLL Rn */
|
||||||
|
void shll__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLR Rn */
|
||||||
|
void shlr__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLL2 Rn */
|
||||||
|
void shll2__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLR2 Rn */
|
||||||
|
void shlr2__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLL8 Rn */
|
||||||
|
void shll8__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLR8 Rn */
|
||||||
|
void shlr8__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLL16 Rn */
|
||||||
|
void shll16__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* SHLR16 Rn */
|
||||||
|
void shlr16__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* BF label */
|
||||||
|
void bf__pc_relative(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* BF/S label */
|
||||||
|
void bf_s__pc_relative(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* BT label */
|
||||||
|
void bt__pc_relative(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* BT/S label */
|
||||||
|
void bt_s__pc_relative(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* BRA label */
|
||||||
|
void bra__pc_relative(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* BRAF Rn */
|
||||||
|
void braf__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* BSR label */
|
||||||
|
void bsr__pc_relative(struct architectural_state * state, struct memory_map * map, const uint32_t d);
|
||||||
|
/* BSRF Rn */
|
||||||
|
void bsrf__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* JMP @Rn */
|
||||||
|
void jmp__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* JSR @Rn */
|
||||||
|
void jsr__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* RTS */
|
||||||
|
void rts__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* CLRMAC */
|
||||||
|
void clrmac__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* CLRS */
|
||||||
|
void clrs__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* CLRT */
|
||||||
|
void clrt__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* LDC Rm,SR */
|
||||||
|
void ldc__transfer_to_sr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC Rm,GBR */
|
||||||
|
void ldc__transfer_to_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC Rm,VBR */
|
||||||
|
void ldc__transfer_to_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC Rm,SSR */
|
||||||
|
void ldc__transfer_to_ssr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC Rm,SPC */
|
||||||
|
void ldc__transfer_to_spc(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC Rm,DBR */
|
||||||
|
void ldc__transfer_to_dbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC Rm,Rn_BANK */
|
||||||
|
void ldc__transfer_to_rn_bank(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* LDC.L @Rm+,SR */
|
||||||
|
void ldc_l__load_to_sr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC.L @Rm+,GBR */
|
||||||
|
void ldc_l__load_to_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC.L @Rm+,VBR */
|
||||||
|
void ldc_l__load_to_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC.L @Rm+,SSR */
|
||||||
|
void ldc_l__load_to_ssr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC.L @Rm+,SPC */
|
||||||
|
void ldc_l__load_to_spc(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC.L @Rm+,DBR */
|
||||||
|
void ldc_l__load_to_dbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDC.L @Rm+,Rn_BANK */
|
||||||
|
void ldc_l__load_to_rn_bank(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* LDS Rm,MACH */
|
||||||
|
void lds__transfer_to_mach(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS Rm,MACL */
|
||||||
|
void lds__transfer_to_macl(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS Rm,PR */
|
||||||
|
void lds__transfer_to_pr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS.L @Rm+,MACH */
|
||||||
|
void lds_l__load_to_mach(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS.L @Rm+,MACL */
|
||||||
|
void lds_l__load_to_macl(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS.L @Rm+,PR */
|
||||||
|
void lds_l__load_to_pr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* NOP */
|
||||||
|
void nop__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* RTE */
|
||||||
|
void rte__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* SETS */
|
||||||
|
void sets__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* SETT */
|
||||||
|
void sett__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* SLEEP */
|
||||||
|
void sleep__no_operand(struct architectural_state * state, struct memory_map * map);
|
||||||
|
/* STC SR,Rn */
|
||||||
|
void stc__transfer_from_sr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC GBR,Rn */
|
||||||
|
void stc__transfer_from_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC VBR,Rn */
|
||||||
|
void stc__transfer_from_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC SSR,Rn */
|
||||||
|
void stc__transfer_from_ssr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC SPC,Rn */
|
||||||
|
void stc__transfer_from_spc(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC SGR,Rn */
|
||||||
|
void stc__transfer_from_sgr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC DBR,Rn */
|
||||||
|
void stc__transfer_from_dbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC Rm_BANK,Rn */
|
||||||
|
void stc__transfer_from_rm_bank(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* STC.L SR,@-Rn */
|
||||||
|
void stc_l__store_from_sr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC.L GBR,@-Rn */
|
||||||
|
void stc_l__store_from_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC.L VBR,@-Rn */
|
||||||
|
void stc_l__store_from_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC.L SSR,@-Rn */
|
||||||
|
void stc_l__store_from_ssr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC.L SPC,@-Rn */
|
||||||
|
void stc_l__store_from_spc(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC.L SGR,@-Rn */
|
||||||
|
void stc_l__store_from_sgr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC.L DBR,@-Rn */
|
||||||
|
void stc_l__store_from_dbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STC.L Rm_BANK,@-Rn */
|
||||||
|
void stc_l__store_from_rm_bank(struct architectural_state * state, struct memory_map * map, const uint32_t m, const uint32_t n);
|
||||||
|
/* STS MACH,Rn */
|
||||||
|
void sts__transfer_from_mach(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS MACL,Rn */
|
||||||
|
void sts__transfer_from_macl(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS PR,Rn */
|
||||||
|
void sts__transfer_from_pr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS.L MACH,@-Rn */
|
||||||
|
void sts_l__store_from_mach(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS.L MACL,@-Rn */
|
||||||
|
void sts_l__store_from_macl(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS.L PR,@-Rn */
|
||||||
|
void sts_l__store_from_pr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* TRAPA #imm */
|
||||||
|
void trapa__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
||||||
|
/* LDS Rm,FPSCR */
|
||||||
|
void lds__transfer_to_fpscr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS Rm,FPUL */
|
||||||
|
void lds__transfer_to_fpul(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS.L @Rm+,FPSCR */
|
||||||
|
void lds_l__load_to_fpscr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* LDS.L @Rm+,FPUL */
|
||||||
|
void lds_l__load_to_fpul(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
|
/* STS FPSCR,Rn */
|
||||||
|
void sts__transfer_from_fpscr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS FPUL,Rn */
|
||||||
|
void sts__transfer_from_fpul(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS.L FPSCR,@-Rn */
|
||||||
|
void sts_l__store_from_fpscr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
|
/* STS.L FPUL,@-Rn */
|
||||||
|
void sts_l__store_from_fpul(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
60
c/main.c
Normal file
60
c/main.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "memory_map.h"
|
||||||
|
#include "ram.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "exception.h"
|
||||||
|
#include "execute.h"
|
||||||
|
#include "decode_print.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
assert(argc > 1);
|
||||||
|
FILE * f = fopen(argv[1], "r");
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf(stderr, "fopen %s\n", argv[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int ret = fseek(f, 0, SEEK_END);
|
||||||
|
assert(ret == 0);
|
||||||
|
uint32_t read_size = ftell(f);
|
||||||
|
ret = fseek(f, 0, SEEK_SET);
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
uint32_t rom_size = ((read_size + 3) & ~3);
|
||||||
|
uint32_t buf[rom_size / 4];
|
||||||
|
uint32_t ret_size = fread(buf, 1, read_size, f);
|
||||||
|
assert(ret_size == read_size);
|
||||||
|
|
||||||
|
ret = fclose(f);
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
struct memory_map map = { .length = 0 };
|
||||||
|
map.entry[map.length++] = (struct memory_map_entry){
|
||||||
|
.start = 0x0000'0000,
|
||||||
|
.size = rom_size,
|
||||||
|
.mem = (void *)buf,
|
||||||
|
.access = ram__memory_access,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct architectural_state state = { 0 };
|
||||||
|
POWERON(&state);
|
||||||
|
|
||||||
|
char const * instruction_buf;
|
||||||
|
char operand_buf[128];
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint32_t instruction_code = fetch(&state, &map);
|
||||||
|
decode_and_print_instruction(&state, &map, instruction_code, &instruction_buf, operand_buf, 128);
|
||||||
|
printf("pc %08x %-7s %-20s\n", state.pc[0], instruction_buf, operand_buf);
|
||||||
|
|
||||||
|
if (physical_address(state.pc[0]) == 0x38)
|
||||||
|
break;
|
||||||
|
|
||||||
|
step(&state, &map);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("part1 %d\n", state.gbr);
|
||||||
|
printf("part2 %d %d\n", state.mach, state.macl);
|
||||||
|
}
|
53
c/memory_map.h
Normal file
53
c/memory_map.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// 0x1F000000 - 0x1FFFFFFF
|
||||||
|
// 0xFF000000 - 0xFFFFFFFF
|
||||||
|
|
||||||
|
struct memory_access {
|
||||||
|
uint8_t (* read_memory8 )(void * mem, uint32_t address);
|
||||||
|
uint16_t (* read_memory16 )(void * mem, uint32_t address);
|
||||||
|
uint32_t (* read_memory32 )(void * mem, uint32_t address);
|
||||||
|
void (* write_memory8 )(void * mem, uint32_t address, uint8_t value);
|
||||||
|
void (* write_memory16)(void * mem, uint32_t address, uint16_t value);
|
||||||
|
void (* write_memory32)(void * mem, uint32_t address, uint32_t value);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct memory_map_entry {
|
||||||
|
uint32_t start;
|
||||||
|
uint32_t size;
|
||||||
|
void * mem;
|
||||||
|
struct memory_access access;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define memory_map_max_length 16
|
||||||
|
|
||||||
|
struct memory_map {
|
||||||
|
uint32_t length;
|
||||||
|
struct memory_map_entry entry[memory_map_max_length];
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint32_t physical_address(uint32_t address)
|
||||||
|
{
|
||||||
|
if (address < 0xe0000000)
|
||||||
|
return address & (~(0b111 << 29)); // P0 P1 P2 P3 region
|
||||||
|
else
|
||||||
|
return address; // P4 region
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct memory_map_entry * find_entry(struct memory_map * map, uint32_t address)
|
||||||
|
{
|
||||||
|
uint32_t physical = physical_address(address);
|
||||||
|
assert(map->length <= memory_map_max_length);
|
||||||
|
for (int i = 0; i < map->length; i++) {
|
||||||
|
uint32_t entry_start = map->entry[i].start;
|
||||||
|
uint32_t entry_end = map->entry[i].start + map->entry[i].size;
|
||||||
|
if (physical >= entry_start && physical < entry_end)
|
||||||
|
return &map->entry[i];
|
||||||
|
}
|
||||||
|
return (struct memory_map_entry *)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef memory_map_max_length
|
136
c/operations.h
Normal file
136
c/operations.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// sign_extend
|
||||||
|
//
|
||||||
|
|
||||||
|
static inline int32_t sign_extend(uint32_t x, uint32_t b)
|
||||||
|
{
|
||||||
|
const uint32_t m = 1UL << (b - 1);
|
||||||
|
x = x & ((1UL << b) - 1);
|
||||||
|
const int32_t r = (x ^ m) - m;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t sign_extend64(uint64_t x)
|
||||||
|
{
|
||||||
|
return (int64_t)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t sign_extend32(uint32_t x)
|
||||||
|
{
|
||||||
|
return (int32_t)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t sign_extend16(uint32_t x)
|
||||||
|
{
|
||||||
|
return sign_extend(x, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t sign_extend12(uint32_t x)
|
||||||
|
{
|
||||||
|
return sign_extend(x, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t sign_extend8(uint32_t x)
|
||||||
|
{
|
||||||
|
return sign_extend(x, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// zero_extend
|
||||||
|
//
|
||||||
|
|
||||||
|
static inline uint32_t zero_extend(uint32_t x, uint32_t b)
|
||||||
|
{
|
||||||
|
x = x & ((1ULL << b) - 1);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t zero_extend32(uint32_t x)
|
||||||
|
{
|
||||||
|
return (uint32_t)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t zero_extend16(uint32_t x)
|
||||||
|
{
|
||||||
|
return zero_extend(x, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t zero_extend8(uint32_t x)
|
||||||
|
{
|
||||||
|
return zero_extend(x, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t zero_extend5(uint32_t x)
|
||||||
|
{
|
||||||
|
return zero_extend(x, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t zero_extend4(uint32_t x)
|
||||||
|
{
|
||||||
|
return zero_extend(x, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t zero_extend1(uint32_t x)
|
||||||
|
{
|
||||||
|
return zero_extend(x, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// signed_saturate
|
||||||
|
//
|
||||||
|
|
||||||
|
static inline uint64_t signed_saturate(uint64_t x, uint32_t b)
|
||||||
|
{
|
||||||
|
const int64_t upper = (1LL << (b - 1)) - 1;
|
||||||
|
const int64_t lower = -(1LL << (b - 1));
|
||||||
|
static_assert(-(1LL << (48 - 1)) < 0);
|
||||||
|
|
||||||
|
if (x > upper)
|
||||||
|
return upper;
|
||||||
|
else if (x < lower)
|
||||||
|
return lower;
|
||||||
|
else
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t signed_saturate48(uint64_t x)
|
||||||
|
{
|
||||||
|
return signed_saturate(x, 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t signed_saturate32(uint32_t x)
|
||||||
|
{
|
||||||
|
return signed_saturate(x, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// "convenience" functions
|
||||||
|
//
|
||||||
|
|
||||||
|
static inline uint32_t _register(uint32_t x)
|
||||||
|
{
|
||||||
|
return zero_extend(x, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t bit(uint32_t x)
|
||||||
|
{
|
||||||
|
return zero_extend(x, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// "operations"
|
||||||
|
//
|
||||||
|
|
||||||
|
static inline int32_t unary_int(int64_t x)
|
||||||
|
{
|
||||||
|
return x != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t bit_extract(int64_t n, int64_t b, int64_t m)
|
||||||
|
{
|
||||||
|
return (n >> b) & ((1 << m) - 1);
|
||||||
|
}
|
64
c/ram.c
Normal file
64
c/ram.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "ram.h"
|
||||||
|
|
||||||
|
#define TARGET_ENDIAN __ORDER_LITTLE_ENDIAN__
|
||||||
|
|
||||||
|
uint8_t ram__read_memory8(void * data, uint32_t address)
|
||||||
|
{
|
||||||
|
uint8_t * mem = (uint8_t *)data;
|
||||||
|
return mem[address];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ram__read_memory16(void * data, uint32_t address)
|
||||||
|
{
|
||||||
|
uint16_t * mem = (uint16_t *)data;
|
||||||
|
uint16_t value = mem[address >> 1];
|
||||||
|
#if __BYTE_ORDER__ == TARGET_ENDIAN
|
||||||
|
return value;
|
||||||
|
#else
|
||||||
|
return __builtin_bswap16(value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ram__read_memory32(void * data, uint32_t address)
|
||||||
|
{
|
||||||
|
uint32_t * mem = (uint32_t *)data;
|
||||||
|
uint32_t value = mem[address >> 2];
|
||||||
|
#if __BYTE_ORDER__ == TARGET_ENDIAN
|
||||||
|
return value;
|
||||||
|
#else
|
||||||
|
return __builtin_bswap32(value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ram__write_memory8(void * data, uint32_t address, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t * mem = (uint8_t *)data;
|
||||||
|
mem[address] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ram__write_memory16(void * data, uint32_t address, uint16_t value)
|
||||||
|
{
|
||||||
|
uint16_t * mem = (uint16_t *)data;
|
||||||
|
#if __BYTE_ORDER__ != TARGET_ENDIAN
|
||||||
|
value = __builtin_bswap16(value);
|
||||||
|
#endif
|
||||||
|
mem[address >> 1] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ram__write_memory32(void * data, uint32_t address, uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t * mem = (uint32_t *)data;
|
||||||
|
#if __BYTE_ORDER__ != TARGET_ENDIAN
|
||||||
|
value = __builtin_bswap32(value);
|
||||||
|
#endif
|
||||||
|
mem[address >> 2] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct memory_access ram__memory_access = {
|
||||||
|
.read_memory8 = &ram__read_memory8,
|
||||||
|
.read_memory16 = &ram__read_memory16,
|
||||||
|
.read_memory32 = &ram__read_memory32,
|
||||||
|
.write_memory8 = &ram__write_memory8,
|
||||||
|
.write_memory16 = &ram__write_memory16,
|
||||||
|
.write_memory32 = &ram__write_memory32
|
||||||
|
};
|
14
c/ram.h
Normal file
14
c/ram.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "memory_map.h"
|
||||||
|
|
||||||
|
uint8_t ram__read_memory8(void * data, uint32_t address);
|
||||||
|
uint16_t ram__read_memory16(void * data, uint32_t address);
|
||||||
|
uint32_t ram__read_memory32(void * data, uint32_t address);
|
||||||
|
void ram__write_memory8(void * data, uint32_t address, uint8_t value);
|
||||||
|
void ram__write_memory16(void * data, uint32_t address, uint16_t value);
|
||||||
|
void ram__write_memory32(void * data, uint32_t address, uint32_t value);
|
||||||
|
|
||||||
|
extern struct memory_access ram__memory_access;
|
92
c/state.h
Normal file
92
c/state.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "status_bits.h"
|
||||||
|
|
||||||
|
#define SR__RB (1 << 29)
|
||||||
|
#define SR__MD (1 << 30)
|
||||||
|
|
||||||
|
#define BANK(sr) (((sr) & SR__RB) && ((sr) & SR__MD))
|
||||||
|
#define REGN(sr, x) (((x) & (1 << 3)) ? (x) : ((x) ^ (BANK(sr) << 4)))
|
||||||
|
#define REG(state, x) ((state)->general_register[REGN((state)->sr.value, (x))])
|
||||||
|
#define REGN_BANK(sr, x) (((x) & (1 << 3)) ? (x) : ((x) ^ ((!BANK(sr)) << 4)))
|
||||||
|
#define REG_BANK(state, x) ((state)->general_register[REGN_BANK((state)->sr.value, (x))])
|
||||||
|
|
||||||
|
static_assert(REGN(0, 0 ) == 0 );
|
||||||
|
static_assert(REGN(0, 7 ) == 7 );
|
||||||
|
static_assert(REGN(0, 8 ) == 8 );
|
||||||
|
static_assert(REGN(0, 15) == 15);
|
||||||
|
static_assert(REGN(SR__MD | SR__RB, 0 ) == 16);
|
||||||
|
static_assert(REGN(SR__MD | SR__RB, 7 ) == 23);
|
||||||
|
static_assert(REGN(SR__MD | SR__RB, 8 ) == 8 );
|
||||||
|
static_assert(REGN(SR__MD | SR__RB, 15) == 15);
|
||||||
|
|
||||||
|
static_assert(REGN_BANK(0, 0 ) == 16);
|
||||||
|
static_assert(REGN_BANK(0, 7 ) == 23);
|
||||||
|
static_assert(REGN_BANK(0, 8 ) == 8 );
|
||||||
|
static_assert(REGN_BANK(0, 15) == 15);
|
||||||
|
static_assert(REGN_BANK(SR__MD | SR__RB, 0 ) == 0 );
|
||||||
|
static_assert(REGN_BANK(SR__MD | SR__RB, 7 ) == 7 );
|
||||||
|
static_assert(REGN_BANK(SR__MD | SR__RB, 8 ) == 8 );
|
||||||
|
static_assert(REGN_BANK(SR__MD | SR__RB, 15) == 15);
|
||||||
|
|
||||||
|
union floating_point_registers {
|
||||||
|
uint32_t fr[32];
|
||||||
|
uint32_t fp[16][2];
|
||||||
|
uint64_t dr[16];
|
||||||
|
uint32_t fv[8][4];
|
||||||
|
uint32_t fm[2][16];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert((sizeof (union floating_point_registers)) == 32 * 4);
|
||||||
|
|
||||||
|
#define FR_N(state, x) ((x) ^ ((state)->fpscr.fr << 4))
|
||||||
|
#define FR_(state, x) ((state)->floating_point_register.fr[FR_N(state, x)])
|
||||||
|
#define FP_N(state, x) ((x) ^ ((state)->fpscr.fr << 3))
|
||||||
|
#define FP_(state, x) ((state)->floating_point_register.fp[FP_N(state, x)])
|
||||||
|
#define DR2_N(state, x) ((x) ^ ((state)->fpscr.fr << 3))
|
||||||
|
#define DR2_(state, x) ((state)->floating_point_register.dr[DR2_N(state, x)])
|
||||||
|
#define XD2_N(state, x) ((x) ^ ((!(state)->fpscr.fr) << 3))
|
||||||
|
#define XD2_(state, x) ((state)->floating_point_register.dr[XD2_N(state, x)])
|
||||||
|
#define FV4_N(state, x) ((x) ^ ((state)->fpscr.fr << 2))
|
||||||
|
#define FV4_(state, x) ((state)->floating_point_register.dr[FV4_N(state, x)])
|
||||||
|
#define XMTRX_N(state) (!(state)->fpscr.fr)
|
||||||
|
#define XMTRX(state) ((state)->floating_point_register.fm[XMTRX_N(state)])
|
||||||
|
|
||||||
|
struct architectural_state {
|
||||||
|
uint32_t general_register[24];
|
||||||
|
|
||||||
|
// system_register
|
||||||
|
uint32_t mach;
|
||||||
|
uint32_t macl;
|
||||||
|
uint32_t pr[3];
|
||||||
|
uint32_t pc[3];
|
||||||
|
union {
|
||||||
|
struct fpscr_bits bits;
|
||||||
|
uint32_t value;
|
||||||
|
} fpscr;
|
||||||
|
uint32_t fpul;
|
||||||
|
//
|
||||||
|
|
||||||
|
// control_register
|
||||||
|
union {
|
||||||
|
struct sr_bits bits;
|
||||||
|
uint32_t value;
|
||||||
|
} sr;
|
||||||
|
uint32_t ssr;
|
||||||
|
uint32_t spc;
|
||||||
|
uint32_t gbr;
|
||||||
|
uint32_t vbr;
|
||||||
|
uint32_t sgr;
|
||||||
|
uint32_t dbr;
|
||||||
|
//
|
||||||
|
|
||||||
|
union floating_point_registers floating_point_register;
|
||||||
|
|
||||||
|
bool is_delay_slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
88
c/state_helpers.h
Normal file
88
c/state_helpers.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
#include "memory_map.h"
|
||||||
|
#include "status_bits.h"
|
||||||
|
|
||||||
|
static inline bool is_delay_slot(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
return state->is_delay_slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct sr_bits _sr_bits(uint32_t sr)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
struct sr_bits bits;
|
||||||
|
uint32_t value;
|
||||||
|
} sr_union;
|
||||||
|
sr_union.value = sr;
|
||||||
|
return sr_union.bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool fpu_is_disabled(uint32_t sr)
|
||||||
|
{
|
||||||
|
return _sr_bits(sr).fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sleep(struct architectural_state * state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ocbp(struct architectural_state * state, uint32_t address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t read_memory8(struct memory_map * map, uint32_t address)
|
||||||
|
{
|
||||||
|
struct memory_map_entry * entry = find_entry(map, address);
|
||||||
|
if (entry == NULL) return 0;
|
||||||
|
uint32_t relative_address = physical_address(address) - entry->start;
|
||||||
|
return entry->access.read_memory8(entry->mem, relative_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t read_memory16(struct memory_map * map, uint32_t address)
|
||||||
|
{
|
||||||
|
assert((address & 0b1) == 0);
|
||||||
|
struct memory_map_entry * entry = find_entry(map, address);
|
||||||
|
if (entry == NULL) return 0;
|
||||||
|
uint32_t relative_address = physical_address(address) - entry->start;
|
||||||
|
return entry->access.read_memory16(entry->mem, relative_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t read_memory32(struct memory_map * map, uint32_t address)
|
||||||
|
{
|
||||||
|
assert((address & 0b11) == 0);
|
||||||
|
struct memory_map_entry * entry = find_entry(map, address);
|
||||||
|
if (entry == NULL) return 0;
|
||||||
|
uint32_t relative_address = physical_address(address) - entry->start;
|
||||||
|
return entry->access.read_memory32(entry->mem, relative_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write_memory8(struct memory_map * map, uint32_t address, uint8_t value)
|
||||||
|
{
|
||||||
|
struct memory_map_entry * entry = find_entry(map, address);
|
||||||
|
if (entry == NULL) return;
|
||||||
|
uint32_t relative_address = physical_address(address) - entry->start;
|
||||||
|
entry->access.write_memory8(entry->mem, relative_address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write_memory16(struct memory_map * map, uint32_t address, uint16_t value)
|
||||||
|
{
|
||||||
|
assert((address & 0b1) == 0);
|
||||||
|
struct memory_map_entry * entry = find_entry(map, address);
|
||||||
|
if (entry == NULL) return;
|
||||||
|
uint32_t relative_address = physical_address(address) - entry->start;
|
||||||
|
entry->access.write_memory16(entry->mem, relative_address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write_memory32(struct memory_map * map, uint32_t address, uint32_t value)
|
||||||
|
{
|
||||||
|
assert((address & 0b11) == 0);
|
||||||
|
struct memory_map_entry * entry = find_entry(map, address);
|
||||||
|
if (entry == NULL) return;
|
||||||
|
uint32_t relative_address = physical_address(address) - entry->start;
|
||||||
|
entry->access.write_memory32(entry->mem, relative_address, value);
|
||||||
|
}
|
96
c/status_bits.h
Normal file
96
c/status_bits.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct sr_bits {
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
uint32_t t : 1;
|
||||||
|
uint32_t s : 1;
|
||||||
|
uint32_t _res0 : 2;
|
||||||
|
uint32_t imask : 4;
|
||||||
|
uint32_t _res1 : 3;
|
||||||
|
uint32_t q : 1;
|
||||||
|
uint32_t m : 1;
|
||||||
|
uint32_t _res2 : 5;
|
||||||
|
uint32_t fd : 1;
|
||||||
|
uint32_t _res3 : 12;
|
||||||
|
uint32_t bl : 1;
|
||||||
|
uint32_t rb : 1;
|
||||||
|
uint32_t md : 1;
|
||||||
|
uint32_t _res4 : 1;
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
uint32_t _res4 : 1;
|
||||||
|
uint32_t md : 1;
|
||||||
|
uint32_t rb : 1;
|
||||||
|
uint32_t bl : 1;
|
||||||
|
uint32_t _res3 : 12;
|
||||||
|
uint32_t fd : 1;
|
||||||
|
uint32_t _res2 : 5;
|
||||||
|
uint32_t m : 1;
|
||||||
|
uint32_t q : 1;
|
||||||
|
uint32_t _res1 : 3;
|
||||||
|
uint32_t imask : 4;
|
||||||
|
uint32_t _res0 : 2;
|
||||||
|
uint32_t s : 1;
|
||||||
|
uint32_t t : 1;
|
||||||
|
#else
|
||||||
|
# error "unsupported endianness"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct fpscr_bits {
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
uint32_t rm : 1;
|
||||||
|
uint32_t _res0 : 1;
|
||||||
|
uint32_t flag_inexact : 1;
|
||||||
|
uint32_t flag_underflow : 1;
|
||||||
|
uint32_t flag_overflow : 1;
|
||||||
|
uint32_t flag_division_by_zero : 1;
|
||||||
|
uint32_t flag_invalid_operation : 1;
|
||||||
|
uint32_t enable_inexact : 1;
|
||||||
|
uint32_t enable_underflow : 1;
|
||||||
|
uint32_t enable_overflow : 1;
|
||||||
|
uint32_t enable_division_by_zero : 1;
|
||||||
|
uint32_t enable_invalid : 1;
|
||||||
|
uint32_t cause_inexact : 1;
|
||||||
|
uint32_t cause_underflow : 1;
|
||||||
|
uint32_t cause_overflow : 1;
|
||||||
|
uint32_t cause_division_by_zero : 1;
|
||||||
|
uint32_t cause_invalid : 1;
|
||||||
|
uint32_t cause_fpu_error : 1;
|
||||||
|
uint32_t dn : 1;
|
||||||
|
uint32_t pr : 1;
|
||||||
|
uint32_t sz : 1;
|
||||||
|
uint32_t fr : 1;
|
||||||
|
uint32_t _res1 : 10;
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
uint32_t _res1 : 10;
|
||||||
|
uint32_t fr : 1;
|
||||||
|
uint32_t sz : 1;
|
||||||
|
uint32_t pr : 1;
|
||||||
|
uint32_t dn : 1;
|
||||||
|
uint32_t cause_fpu_error : 1;
|
||||||
|
uint32_t cause_invalid : 1;
|
||||||
|
uint32_t cause_division_by_zero : 1;
|
||||||
|
uint32_t cause_overflow : 1;
|
||||||
|
uint32_t cause_underflow : 1;
|
||||||
|
uint32_t cause_inexact : 1;
|
||||||
|
uint32_t enable_invalid : 1;
|
||||||
|
uint32_t enable_division_by_zero : 1;
|
||||||
|
uint32_t enable_overflow : 1;
|
||||||
|
uint32_t enable_underflow : 1;
|
||||||
|
uint32_t enable_inexact : 1;
|
||||||
|
uint32_t flag_invalid_operation : 1;
|
||||||
|
uint32_t flag_division_by_zero : 1;
|
||||||
|
uint32_t flag_overflow : 1;
|
||||||
|
uint32_t flag_underflow : 1;
|
||||||
|
uint32_t flag_inexact : 1;
|
||||||
|
uint32_t _res0 : 1;
|
||||||
|
uint32_t rm : 1;
|
||||||
|
#else
|
||||||
|
# error "unsupported endianness"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
23
exception.txt
Normal file
23
exception.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
POWERON 1 1 0xA0000000 - 0x000
|
||||||
|
MANRESET 1 2 0xA0000000 - 0x020
|
||||||
|
HUDIRESET 1 1 0xA0000000 - 0x000
|
||||||
|
ITLBMULTIHIT 1 3 0xA0000000 - 0x140
|
||||||
|
OTLBMULTIHIT 1 4 0xA0000000 - 0x140
|
||||||
|
UBRKBEFORE 2 0 (VBR/DBR) 0x100/- 0x1E0
|
||||||
|
IADDERR 2 1 (VBR) 0x100 0x0E0
|
||||||
|
ITLBMISS 2 2 (VBR) 0x400 0x040
|
||||||
|
EXECPROT 2 3 (VBR) 0x100 0x0A0
|
||||||
|
RESINST 2 4 (VBR) 0x100 0x180
|
||||||
|
ILLSLOT 2 4 (VBR) 0x100 0x1A0
|
||||||
|
FPUDIS 2 4 (VBR) 0x100 0x800
|
||||||
|
SLOTFPUDIS 2 4 (lVBR) 0x100 0x820
|
||||||
|
RADDERR 2 5 (VBR) 0x100 0x0E0
|
||||||
|
WADDERR 2 5 (VBR) 0x100 0x100
|
||||||
|
RTLBMISS 2 6 (VBR) 0x400 0x040
|
||||||
|
WTLBMISS 2 6 (VBR) 0x400 0x060
|
||||||
|
READPROT 2 7 (VBR) 0x100 0x0A0
|
||||||
|
WRITEPROT 2 7 (VBR) 0x100 0x0C0
|
||||||
|
FPUEXC 2 8 (VBR) 0x100 0x120
|
||||||
|
FIRSTWRITE 2 9 (VBR) 0x100 0x080
|
||||||
|
TRAP 2 4 (VBR) 0x100 0x160
|
||||||
|
UBRKAFTER 2 10 (VBR/DBR) 0x100/- 0x1E0
|
35
generate.py
Normal file
35
generate.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import io
|
||||||
|
|
||||||
|
def should_autonewline(line):
|
||||||
|
return (
|
||||||
|
"static_assert" not in line
|
||||||
|
and "extern" not in line
|
||||||
|
and (len(line.split()) < 2 or line.split()[1] != '=') # hacky; meh
|
||||||
|
)
|
||||||
|
|
||||||
|
def _render(out, lines):
|
||||||
|
indent = " "
|
||||||
|
level = 0
|
||||||
|
for l in lines:
|
||||||
|
if l and (l[0] == "}" or l[0] == ")"):
|
||||||
|
level -= 2
|
||||||
|
assert level >= 0, out.getvalue()
|
||||||
|
|
||||||
|
if len(l) == 0:
|
||||||
|
out.write("\n")
|
||||||
|
else:
|
||||||
|
out.write(indent * level + l + "\n")
|
||||||
|
|
||||||
|
if l and (l[-1] == "{" or l[-1] == "("):
|
||||||
|
level += 2
|
||||||
|
|
||||||
|
if level == 0 and l and l[-1] == ";":
|
||||||
|
if should_autonewline(l):
|
||||||
|
out.write("\n")
|
||||||
|
return out
|
||||||
|
|
||||||
|
def renderer():
|
||||||
|
out = io.StringIO()
|
||||||
|
def render(lines):
|
||||||
|
return _render(out, lines)
|
||||||
|
return render, out
|
79
generate_bits.py
Normal file
79
generate_bits.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
sr_bits = (
|
||||||
|
("T" , 0 , 1), # true/false condition
|
||||||
|
("S" , 1 , 1), # saturation
|
||||||
|
("IMASK", 4 , 4), # interrupt mask level, 4 bits
|
||||||
|
("Q" , 8 , 1), # state for divide step
|
||||||
|
("M" , 9 , 1), # state for divide step
|
||||||
|
("FD" , 15, 1), # FPU disable
|
||||||
|
("BL" , 28, 1), # Exception/interrupt block bit
|
||||||
|
("RB" , 29, 1), # General register bank specifier in privileged mode
|
||||||
|
("MD" , 30, 1), # Processor mode
|
||||||
|
)
|
||||||
|
|
||||||
|
fpscr_bits = (
|
||||||
|
("RM" , 0, 1), # Rounding mode
|
||||||
|
("FLAG_INEXACT" , 2, 1),
|
||||||
|
("FLAG_UNDERFLOW" , 3, 1),
|
||||||
|
("FLAG_OVERFLOW" , 4, 1),
|
||||||
|
("FLAG_DIVISION_BY_ZERO" , 5, 1),
|
||||||
|
("FLAG_INVALID_OPERATION" , 6, 1),
|
||||||
|
("ENABLE_INEXACT" , 7, 1),
|
||||||
|
("ENABLE_UNDERFLOW" , 8, 1),
|
||||||
|
("ENABLE_OVERFLOW" , 9, 1),
|
||||||
|
("ENABLE_DIVISION_BY_ZERO", 10, 1),
|
||||||
|
("ENABLE_INVALID" , 11, 1),
|
||||||
|
("CAUSE_INEXACT" , 12, 1),
|
||||||
|
("CAUSE_UNDERFLOW" , 13, 1),
|
||||||
|
("CAUSE_OVERFLOW" , 14, 1),
|
||||||
|
("CAUSE_DIVISION_BY_ZERO" , 15, 1),
|
||||||
|
("CAUSE_INVALID" , 16, 1),
|
||||||
|
("CAUSE_FPU_ERROR" , 17, 1),
|
||||||
|
("DN" , 18, 1), # Denormalization mode
|
||||||
|
("PR" , 19, 1), # Precision mode
|
||||||
|
("SZ" , 20, 1), # Transfer size mode
|
||||||
|
("FR" , 21, 1), # Floating-point register bank
|
||||||
|
)
|
||||||
|
|
||||||
|
def generate_bitfield(bits, start=0, end=31):
|
||||||
|
res = 0
|
||||||
|
current = start
|
||||||
|
for name, index, length in bits:
|
||||||
|
if index != current:
|
||||||
|
size = index - current
|
||||||
|
yield f"_res{res}", size
|
||||||
|
res += 1
|
||||||
|
yield name, length
|
||||||
|
current = index + 1
|
||||||
|
|
||||||
|
end_len = end + 1
|
||||||
|
if current != end_len:
|
||||||
|
yield f"_res{res}", end_len - current
|
||||||
|
|
||||||
|
def generate_bitfield_little(bits):
|
||||||
|
return generate_bitfield(bits)
|
||||||
|
|
||||||
|
def generate_bitfield_big(bits):
|
||||||
|
return reversed(list(generate_bitfield(bits)))
|
||||||
|
|
||||||
|
def generate(struct_name, bits):
|
||||||
|
yield ""
|
||||||
|
yield f"struct {struct_name} {{"
|
||||||
|
yield "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__"
|
||||||
|
for name, size in generate_bitfield_little(bits):
|
||||||
|
yield f" uint32_t {name.lower()} : {size};"
|
||||||
|
yield "#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__"
|
||||||
|
for name, size in generate_bitfield_big(bits):
|
||||||
|
yield f" uint32_t {name.lower()} : {size};"
|
||||||
|
yield "#else"
|
||||||
|
yield '# error "unsupported endianness"'
|
||||||
|
yield "#endif"
|
||||||
|
yield "};"
|
||||||
|
yield ""
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("#pragma once")
|
||||||
|
print()
|
||||||
|
print("#include <stdint.h>")
|
||||||
|
print()
|
||||||
|
print('\n'.join(generate("sr_bits", sr_bits)))
|
||||||
|
print('\n'.join(generate("fpscr_bits", fpscr_bits)))
|
108
generate_decoder.py
Normal file
108
generate_decoder.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
from instruction_table import untabulate_instructions_sh4
|
||||||
|
from instruction_table import untabulate_instructions_sh2
|
||||||
|
from instruction_function_name import instruction_function_name
|
||||||
|
from generate import renderer
|
||||||
|
|
||||||
|
def b16(n):
|
||||||
|
bits = []
|
||||||
|
for i in range(16):
|
||||||
|
bits.append((n >> i) & 1)
|
||||||
|
return '0b' + ''.join(map(str, reversed(bits)))
|
||||||
|
|
||||||
|
def format_variables(ins):
|
||||||
|
s = ins.operands
|
||||||
|
for i, name in enumerate(ins.variables):
|
||||||
|
if 'disp' in s and name == 'd':
|
||||||
|
name = 'disp'
|
||||||
|
if 'imm' in s and name == 'i':
|
||||||
|
name = 'imm'
|
||||||
|
if 'label' in s and name == 'd':
|
||||||
|
name = 'label'
|
||||||
|
s = s.replace(name, "%d")
|
||||||
|
return s
|
||||||
|
|
||||||
|
def render_print(ins):
|
||||||
|
variable_args = ", " + ", ".join(ins.variables) if ins.variables else ""
|
||||||
|
operands = format_variables(ins)
|
||||||
|
if operands:
|
||||||
|
yield f'snprintf(operand_buf, size, "{operands}"{variable_args});'
|
||||||
|
else:
|
||||||
|
yield "operand_buf[0] = 0;";
|
||||||
|
|
||||||
|
yield f'*instruction_buf = "{ins.instruction}";'
|
||||||
|
|
||||||
|
def render_execute(ins):
|
||||||
|
function_name = instruction_function_name(ins)
|
||||||
|
variable_args = ", " + ", ".join(ins.variables) if ins.variables else ""
|
||||||
|
yield f"{function_name}(state, map{variable_args});"
|
||||||
|
|
||||||
|
def render_mask_switch(body_func, mask, instructions):
|
||||||
|
yield f"switch (code & {b16(mask)}) {{"
|
||||||
|
for ins in instructions:
|
||||||
|
yield f"case {b16(ins.code.code_bits)}: // {ins.instruction} {ins.operands}"
|
||||||
|
yield "{"
|
||||||
|
for variable in ins.variables:
|
||||||
|
operand_var = ins.code.operands[variable]
|
||||||
|
yield f"uint32_t {variable} = (code >> {operand_var.lsb}) & ((1 << {operand_var.length}) - 1);"
|
||||||
|
yield from body_func(ins)
|
||||||
|
yield f"return DECODE__DEFINED;"
|
||||||
|
yield "}"
|
||||||
|
yield "}"
|
||||||
|
|
||||||
|
def render_mask_switches(body_func, by_mask):
|
||||||
|
yield "{"
|
||||||
|
for mask, instructions in by_mask.items():
|
||||||
|
instructions = sorted(instructions, key=lambda i: i.code.code_bits)
|
||||||
|
yield from render_mask_switch(body_func, mask, instructions)
|
||||||
|
yield "return DECODE__UNDEFINED;"
|
||||||
|
yield "}"
|
||||||
|
|
||||||
|
def render_decode_and_execute(by_mask):
|
||||||
|
yield f"enum decode_status decode_and_execute_instruction(struct architectural_state * state, struct memory_map * map, uint16_t code)"
|
||||||
|
yield from render_mask_switches(render_execute, by_mask)
|
||||||
|
|
||||||
|
def render_decode_and_print(by_mask):
|
||||||
|
yield f"enum decode_status decode_and_print_instruction(struct architectural_state * state, struct memory_map * map, uint16_t code, char const ** instruction_buf, char * operand_buf, uint32_t size)"
|
||||||
|
yield from render_mask_switches(render_print, by_mask)
|
||||||
|
|
||||||
|
def header_execute():
|
||||||
|
yield '#include "decode_execute.h"'
|
||||||
|
yield '#include "impl.h"'
|
||||||
|
yield ""
|
||||||
|
|
||||||
|
def header_print():
|
||||||
|
yield '#include <stdio.h>'
|
||||||
|
yield ""
|
||||||
|
yield '#include "decode_print.h"'
|
||||||
|
yield ""
|
||||||
|
|
||||||
|
def main():
|
||||||
|
by_mask = defaultdict(list)
|
||||||
|
masks = []
|
||||||
|
|
||||||
|
sh2_instructions = set((ins.instruction, ins.operands) for ins in untabulate_instructions_sh2())
|
||||||
|
for ins in untabulate_instructions_sh4():
|
||||||
|
if (ins.instruction, ins.operands) not in sh2_instructions:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ins.code.mask_bits not in masks:
|
||||||
|
masks.append(ins.code.mask_bits)
|
||||||
|
by_mask[ins.code.mask_bits].append(ins)
|
||||||
|
|
||||||
|
render, out = renderer()
|
||||||
|
render(header_execute())
|
||||||
|
render(render_decode_and_execute(by_mask))
|
||||||
|
with open(sys.argv[1], 'w') as f:
|
||||||
|
f.write(out.getvalue())
|
||||||
|
|
||||||
|
render, out = renderer()
|
||||||
|
render(header_print())
|
||||||
|
render(render_decode_and_print(by_mask))
|
||||||
|
with open(sys.argv[2], 'w') as f:
|
||||||
|
f.write(out.getvalue())
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
161
generate_impl.py
Normal file
161
generate_impl.py
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
from lexer import Lexer
|
||||||
|
from parser import Parser
|
||||||
|
from ast_to_c_source import generate
|
||||||
|
from ast_transformers import transform_statements
|
||||||
|
|
||||||
|
from instruction_table import untabulate_instructions_sh4
|
||||||
|
from instruction_table import untabulate_instructions_sh2
|
||||||
|
from instruction_function_name import instruction_function_name
|
||||||
|
from instruction_file_name import instruction_file_name
|
||||||
|
from instruction_properties import has_delay_slot
|
||||||
|
|
||||||
|
def is_instruction_descriptor(s):
|
||||||
|
return all(c in {'0', '1', 'n', 'm', 'i', 'd'} for c in s)
|
||||||
|
|
||||||
|
def parse_file(path):
|
||||||
|
with open(path) as f:
|
||||||
|
buf = f.read()
|
||||||
|
|
||||||
|
lines = buf.split('\n', maxsplit=2)
|
||||||
|
assert len(lines[0]) == 16 and is_instruction_descriptor(lines[0]), lines[0]
|
||||||
|
|
||||||
|
if lines[1].startswith('Available only when'):
|
||||||
|
buf = lines[2]
|
||||||
|
else:
|
||||||
|
if len(lines) >= 3:
|
||||||
|
buf = '\n'.join([lines[1], lines[2]])
|
||||||
|
else:
|
||||||
|
buf = lines[1]
|
||||||
|
|
||||||
|
lexer = Lexer(buf)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
token = lexer.next_token()
|
||||||
|
except IndexError:
|
||||||
|
break
|
||||||
|
yield token
|
||||||
|
|
||||||
|
def generate_function_declaration(instruction_name, function_name, variables):
|
||||||
|
args = ", ".join([
|
||||||
|
"struct architectural_state * state",
|
||||||
|
"struct memory_map * map",
|
||||||
|
*[
|
||||||
|
f"const uint32_t {x}"
|
||||||
|
for x in variables
|
||||||
|
]
|
||||||
|
])
|
||||||
|
|
||||||
|
yield f"/* {instruction_name} */"
|
||||||
|
yield f"void {function_name}({args})"
|
||||||
|
|
||||||
|
def generate_file(instruction_name, function_name, variables, delay_slot, src_path):
|
||||||
|
print(instruction_name)
|
||||||
|
tokens = list(parse_file(src_path))
|
||||||
|
parser = Parser(tokens)
|
||||||
|
statements = []
|
||||||
|
while parser.tokens[parser.pos:]:
|
||||||
|
statements.append(parser.statement())
|
||||||
|
|
||||||
|
statements = transform_statements(statements)
|
||||||
|
|
||||||
|
yield from generate_function_declaration(instruction_name, function_name, variables)
|
||||||
|
yield "{"
|
||||||
|
output = []
|
||||||
|
for statement in statements:
|
||||||
|
src = "".join(generate(statement))
|
||||||
|
output.append(src)
|
||||||
|
|
||||||
|
for line in "".join(output).rstrip().split('\n'):
|
||||||
|
yield f" {line}"
|
||||||
|
yield ""
|
||||||
|
yield f" state->is_delay_slot = {delay_slot};"
|
||||||
|
yield "}"
|
||||||
|
yield ""
|
||||||
|
yield ""
|
||||||
|
|
||||||
|
def main():
|
||||||
|
output = [
|
||||||
|
'#include "impl.h"',
|
||||||
|
'#include "operations.h"',
|
||||||
|
'#include "exception.h"',
|
||||||
|
'#include "state_helpers.h"',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
header_output = [
|
||||||
|
'#pragma once',
|
||||||
|
'',
|
||||||
|
'#include "state.h"',
|
||||||
|
'#include "memory_map.h"',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
skip = [
|
||||||
|
"FLDS",
|
||||||
|
"FSTS",
|
||||||
|
"FABS",
|
||||||
|
"FADD",
|
||||||
|
"FCMP/EQ",
|
||||||
|
"FCMP/GT",
|
||||||
|
"FDIV",
|
||||||
|
"FLOAT",
|
||||||
|
"FMAC",
|
||||||
|
"FMUL",
|
||||||
|
"FNEG",
|
||||||
|
"FSQRT",
|
||||||
|
"FSUB",
|
||||||
|
"FTRC",
|
||||||
|
"FCNVDS",
|
||||||
|
"FCNVSD",
|
||||||
|
"FRCHG",
|
||||||
|
"FSCHG",
|
||||||
|
"FCSA",
|
||||||
|
"FSRRA",
|
||||||
|
"FIPR",
|
||||||
|
"FTRV",
|
||||||
|
|
||||||
|
"FLDI0",
|
||||||
|
"FLDI1",
|
||||||
|
"FMOV",
|
||||||
|
"FMOV.S",
|
||||||
|
|
||||||
|
"LDTLB",
|
||||||
|
"OCBI",
|
||||||
|
"OCBP",
|
||||||
|
"OCBWB",
|
||||||
|
"PREF",
|
||||||
|
|
||||||
|
"MOVCA.L",
|
||||||
|
"BRK",
|
||||||
|
]
|
||||||
|
|
||||||
|
for ins in untabulate_instructions_sh4():
|
||||||
|
if ins.instruction in skip:
|
||||||
|
continue
|
||||||
|
|
||||||
|
_name = [ins.instruction, ins.operands] if ins.operands else [ins.instruction]
|
||||||
|
instruction_name = " ".join(_name)
|
||||||
|
function_name = instruction_function_name(ins)
|
||||||
|
file_name = instruction_file_name(ins)
|
||||||
|
src_path = os.path.join("sh4", file_name)
|
||||||
|
delay_slot = "true" if has_delay_slot(ins) else "false"
|
||||||
|
gen = generate_file(instruction_name, function_name, ins.variables, delay_slot, src_path)
|
||||||
|
output.extend(gen)
|
||||||
|
|
||||||
|
gen = generate_function_declaration(instruction_name, function_name, ins.variables)
|
||||||
|
lgen = list(gen)
|
||||||
|
lgen[-1] += ';'
|
||||||
|
header_output.extend(lgen)
|
||||||
|
|
||||||
|
with open(sys.argv[1], "w") as f:
|
||||||
|
f.write("\n".join(output))
|
||||||
|
|
||||||
|
with open(sys.argv[2], "w") as f:
|
||||||
|
f.write("\n".join(header_output))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
181
identifier_substitution.py
Normal file
181
identifier_substitution.py
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
mapping = {
|
||||||
|
"ReadMemory8" : "read_memory8",
|
||||||
|
"ReadMemory16" : "read_memory16",
|
||||||
|
"ReadMemory32" : "read_memory32",
|
||||||
|
"WriteMemory8" : "write_memory8",
|
||||||
|
"WriteMemory16" : "write_memory16",
|
||||||
|
"WriteMemory32" : "write_memory32",
|
||||||
|
"ZeroExtend1" : "zero_extend1",
|
||||||
|
"ZeroExtend4" : "zero_extend4",
|
||||||
|
"ZeroExtend5" : "zero_extend5",
|
||||||
|
"ZeroExtend8" : "zero_extend8",
|
||||||
|
"ZeroExtend16" : "zero_extend16",
|
||||||
|
"ZeroExtend32" : "zero_extend32",
|
||||||
|
"SignedSaturate32": "signed_saturate32",
|
||||||
|
"SignedSaturate48": "signed_saturate48",
|
||||||
|
"SignExtend8" : "sign_extend8",
|
||||||
|
"SignExtend12" : "sign_extend12",
|
||||||
|
"SignExtend16" : "sign_extend16",
|
||||||
|
"SignExtend32" : "sign_extend32",
|
||||||
|
"Register" : "_register",
|
||||||
|
"Bit" : "bit",
|
||||||
|
|
||||||
|
"MACH" : "state->mach",
|
||||||
|
"MACL" : "state->macl",
|
||||||
|
"PR" : "state->pr[0]",
|
||||||
|
"PR’" : "state->pr[1]",
|
||||||
|
"PR’’" : "state->pr[2]",
|
||||||
|
"PC" : "state->pc[0]",
|
||||||
|
"PC’" : "state->pc[1]",
|
||||||
|
"PC’’" : "state->pc[2]",
|
||||||
|
"FPSCR" : "state->fpscr.value",
|
||||||
|
"FPUL" : "state->fpul",
|
||||||
|
|
||||||
|
"SR" : "state->sr.value",
|
||||||
|
"SSR" : "state->ssr",
|
||||||
|
"SPC" : "state->spc",
|
||||||
|
"GBR" : "state->gbr",
|
||||||
|
"VBR" : "state->vbr",
|
||||||
|
"SGR" : "state->sgr",
|
||||||
|
"DBR" : "state->dbr",
|
||||||
|
|
||||||
|
"R0" : "REG(state, 0)",
|
||||||
|
"Rm" : "REG(state, m)",
|
||||||
|
"Rm_BANK" : "REG_BANK(state, m)",
|
||||||
|
"Rn" : "REG(state, n)",
|
||||||
|
"Rn_BANK" : "REG_BANK(state, n)",
|
||||||
|
|
||||||
|
"T" : "state->sr.bits.t",
|
||||||
|
"S" : "state->sr.bits.s",
|
||||||
|
"Q" : "state->sr.bits.q",
|
||||||
|
"M" : "state->sr.bits.m",
|
||||||
|
"MD" : "state->sr.bits.md",
|
||||||
|
|
||||||
|
"NOP" : "",
|
||||||
|
|
||||||
|
"BREAK" : "BREAK",
|
||||||
|
"FIRSTWRITE" : "FIRSTWRITE",
|
||||||
|
"FPUDIS" : "FPUDIS",
|
||||||
|
"FPUEXC" : "FPUEXC",
|
||||||
|
"ILLSLOT" : "ILLSLOT",
|
||||||
|
"RADDERR" : "RADDERR",
|
||||||
|
"READPROT" : "READPROT",
|
||||||
|
"RESINST" : "RESINST",
|
||||||
|
"RTLBMISS" : "RTLBMISS",
|
||||||
|
"SLOTFPUDIS" : "SLOTFPUDIS",
|
||||||
|
"TRAP" : "TRAP",
|
||||||
|
"WADDERR" : "WADDERR",
|
||||||
|
"WRITEPROT" : "WRITEPROT",
|
||||||
|
"WTLBMISS" : "WTLBMISS",
|
||||||
|
|
||||||
|
"IsDelaySlot" : "is_delay_slot",
|
||||||
|
"SLEEP" : "sleep",
|
||||||
|
"OCBP" : "ocbp",
|
||||||
|
|
||||||
|
"ASID" : "ASID",
|
||||||
|
"VPN" : "VPN",
|
||||||
|
"PPN" : "PPN",
|
||||||
|
"SZ" : "SZ",
|
||||||
|
"SZ0" : "SZ0",
|
||||||
|
"SZ1" : "SZ1",
|
||||||
|
"SH" : "SH",
|
||||||
|
"WT" : "WT",
|
||||||
|
"C" : "C",
|
||||||
|
"D" : "D",
|
||||||
|
"V" : "V",
|
||||||
|
|
||||||
|
"ALLOCO" : "ALLOCO",
|
||||||
|
"MMU" : "MMU",
|
||||||
|
"MMUCR" : "MMUCR",
|
||||||
|
"OCBI" : "OCBI",
|
||||||
|
"OCBWB" : "OCBWB",
|
||||||
|
"PREF" : "PREF",
|
||||||
|
"PTEH" : "PTEH",
|
||||||
|
"PTEL" : "PTEL",
|
||||||
|
"URC" : "URC",
|
||||||
|
"UTLB" : "UTLB",
|
||||||
|
|
||||||
|
"AddressUnavailable": "address_unavailable",
|
||||||
|
"DataAccessMiss" : "data_access_miss",
|
||||||
|
"DirtyBit" : "dirty_bit",
|
||||||
|
"ReadProhibited" : "read_prohibited",
|
||||||
|
"WriteProhibited" : "write_prohibited",
|
||||||
|
|
||||||
|
"FR0" : "FR_(state, 0)",
|
||||||
|
"FRm" : "FR_(state, m)",
|
||||||
|
"FRn" : "FR_(state, n)",
|
||||||
|
"FP2m" : "FP2_(state, m)",
|
||||||
|
"FP2n" : "FP2_(state, n)",
|
||||||
|
"DR2m" : "DR2_(state, m)",
|
||||||
|
"DR2n" : "DR2_(state, n)",
|
||||||
|
"XD2m" : "XD2_(state, m)",
|
||||||
|
"XD2n" : "XD2_(state, n)",
|
||||||
|
"FV4n" : "FV4_(state, n)",
|
||||||
|
"FV4m" : "FV4_(state, m)",
|
||||||
|
"XMTRX" : "XMTRX(state)",
|
||||||
|
|
||||||
|
"FR" : "fr",
|
||||||
|
|
||||||
|
"ReadMemoryPair32" : "read_memory_pair32",
|
||||||
|
"WriteMemoryPair32" : "write_memory_pair32",
|
||||||
|
|
||||||
|
"FloatRegister32" : "float_register32",
|
||||||
|
"FloatRegister64" : "float_register64",
|
||||||
|
"FloatRegisterPair32" : "float_register_pair32",
|
||||||
|
"FloatRegisterVector32": "float_register_vector32",
|
||||||
|
"FloatValue32" : "float_value32",
|
||||||
|
"FloatValue64" : "float_value64",
|
||||||
|
"FloatValuePair32" : "float_value_pair32",
|
||||||
|
"FloatValueVector32" : "float_value_vector32",
|
||||||
|
"FloatValueMatrix32" : "float_value_matrix32",
|
||||||
|
|
||||||
|
"FADD_S" : "fadd_s",
|
||||||
|
"FADD_D" : "fadd_d",
|
||||||
|
"FSUB_S" : "fsub_s",
|
||||||
|
"FSUB_D" : "fsub_d",
|
||||||
|
"FMUL_S" : "fmul_s",
|
||||||
|
"FMUL_D" : "fmul_d",
|
||||||
|
"FDIV_S" : "fdiv_s",
|
||||||
|
"FDIV_D" : "fdiv_d",
|
||||||
|
|
||||||
|
"FABS_S" : "fabs_s",
|
||||||
|
"FABS_D" : "fabs_d",
|
||||||
|
"FNEG_S" : "fneg_s",
|
||||||
|
"FNEG_D" : "fneg_d",
|
||||||
|
"FSQRT_S" : "fsqrt_s",
|
||||||
|
"FSQRT_D" : "fsqrt_d",
|
||||||
|
|
||||||
|
"FCMPEQ_S" : "fcmpeq_s",
|
||||||
|
"FCMPEQ_D" : "fcmpeq_d",
|
||||||
|
"FCMPGT_S" : "fcmpgt_s",
|
||||||
|
"FCMPGT_D" : "fcmpgt_d",
|
||||||
|
|
||||||
|
"FCNV_SD" : "fcnv_sd",
|
||||||
|
"FCNV_DS" : "fcnv_ds",
|
||||||
|
"FTRC_SL" : "ftrc_sl",
|
||||||
|
"FTRC_DL" : "ftrc_dl",
|
||||||
|
"FLOAT_LS" : "float_ls",
|
||||||
|
"FLOAT_LD" : "float_ld",
|
||||||
|
|
||||||
|
"FMAC_S" : "fmac_s",
|
||||||
|
"FIPR_S" : "fipr_s",
|
||||||
|
"FTRV_S" : "ftrv_s",
|
||||||
|
|
||||||
|
"FpuIsDisabled" : "fpu_is_disabled",
|
||||||
|
"FpuFlagI" : "fpu_flag_I",
|
||||||
|
"FpuFlagU" : "fpu_flag_U",
|
||||||
|
"FpuFlagO" : "fpu_flag_O",
|
||||||
|
"FpuFlagZ" : "fpu_flag_Z",
|
||||||
|
"FpuFlagV" : "fpu_flag_V",
|
||||||
|
"FpuCauseI" : "fpu_cause_I",
|
||||||
|
"FpuCauseU" : "fpu_cause_U",
|
||||||
|
"FpuCauseO" : "fpu_cause_O",
|
||||||
|
"FpuCauseZ" : "fpu_cause_Z",
|
||||||
|
"FpuCauseV" : "fpu_cause_V",
|
||||||
|
"FpuCauseE" : "fpu_cause_E",
|
||||||
|
"FpuEnableI" : "fpu_enable_I",
|
||||||
|
"FpuEnableU" : "fpu_enable_U",
|
||||||
|
"FpuEnableO" : "fpu_enable_O",
|
||||||
|
"FpuEnableZ" : "fpu_enable_Z",
|
||||||
|
"FpuEnableV" : "fpu_enable_V",
|
||||||
|
}
|
171
lexer.py
Normal file
171
lexer.py
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
"""
|
||||||
|
token:
|
||||||
|
keyword
|
||||||
|
identifier
|
||||||
|
constant
|
||||||
|
punctuator
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_nondigit(c):
|
||||||
|
return c in {
|
||||||
|
"_",
|
||||||
|
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||||
|
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||||
|
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
||||||
|
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
||||||
|
"’",
|
||||||
|
}
|
||||||
|
|
||||||
|
def is_digit(c):
|
||||||
|
return c in {
|
||||||
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
|
}
|
||||||
|
|
||||||
|
def is_hexadecimal_digit(c):
|
||||||
|
return c in {
|
||||||
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
|
"a", "b", "c", "d", "e", "f",
|
||||||
|
"A", "B", "C", "D", "E", "F",
|
||||||
|
}
|
||||||
|
|
||||||
|
def is_punctuator(c):
|
||||||
|
return c in {
|
||||||
|
"[", "]", "(", ")", "{", "}", ".",
|
||||||
|
"+", "-", "~", "!",
|
||||||
|
"<<", ">>",
|
||||||
|
"<", ">",
|
||||||
|
"≤", "≥",
|
||||||
|
"≠", "=",
|
||||||
|
"∨", "∧", "⊕",
|
||||||
|
"×", "/",
|
||||||
|
"|", ";", ",",
|
||||||
|
"←",
|
||||||
|
}
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Identifier:
|
||||||
|
line: int
|
||||||
|
token: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class IntegerConstant:
|
||||||
|
line: int
|
||||||
|
token: str
|
||||||
|
value: int
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Punctuator:
|
||||||
|
line: int
|
||||||
|
token: str
|
||||||
|
|
||||||
|
class Lexer:
|
||||||
|
def __init__(self, buf):
|
||||||
|
self.buf = buf
|
||||||
|
self.start = 0
|
||||||
|
self.end = 0
|
||||||
|
self.line = 0
|
||||||
|
|
||||||
|
def peek(self):
|
||||||
|
return self.buf[self.end]
|
||||||
|
|
||||||
|
def match(self, c):
|
||||||
|
if self.buf[self.end] == c:
|
||||||
|
self.end += 1
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def slice(self, offset=0):
|
||||||
|
return self.buf[self.start:self.end+offset]
|
||||||
|
|
||||||
|
def advance(self):
|
||||||
|
c = self.buf[self.end]
|
||||||
|
self.end += 1
|
||||||
|
return c
|
||||||
|
|
||||||
|
def advance_whitespace(self):
|
||||||
|
if self.match('\n'):
|
||||||
|
self.line += 1
|
||||||
|
return True
|
||||||
|
elif self.match('\n'):
|
||||||
|
return True
|
||||||
|
elif self.match('\t'):
|
||||||
|
return True
|
||||||
|
elif self.match(' '):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def identifier(self):
|
||||||
|
while True:
|
||||||
|
c = self.peek()
|
||||||
|
if is_digit(c) or is_nondigit(c):
|
||||||
|
self.advance()
|
||||||
|
else:
|
||||||
|
return Identifier(self.line, self.slice())
|
||||||
|
|
||||||
|
def hexadecimal_constant(self):
|
||||||
|
n = 0
|
||||||
|
while True:
|
||||||
|
c = self.peek()
|
||||||
|
if is_hexadecimal_digit(c):
|
||||||
|
self.advance()
|
||||||
|
n *= 16
|
||||||
|
i = ord(c)
|
||||||
|
if i >= ord('0') and i <= ord('9'):
|
||||||
|
n += i - ord('0')
|
||||||
|
elif i >= ord('a') and i <= ord('f'):
|
||||||
|
n += 10 + (i - ord('a'))
|
||||||
|
elif i >= ord('A') and i <= ord('F'):
|
||||||
|
n += 10 + (i - ord('A'))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
else:
|
||||||
|
return IntegerConstant(self.line, self.slice(), n)
|
||||||
|
|
||||||
|
def decimal_constant(self):
|
||||||
|
n = 0
|
||||||
|
while True:
|
||||||
|
c = self.peek()
|
||||||
|
if is_digit(c):
|
||||||
|
self.advance()
|
||||||
|
n *= 10
|
||||||
|
i = ord(c)
|
||||||
|
if i >= ord('0') and i <= ord('9'):
|
||||||
|
n += i - ord('0')
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
else:
|
||||||
|
return IntegerConstant(self.line, self.slice(), n)
|
||||||
|
|
||||||
|
def punctuator(self):
|
||||||
|
while True:
|
||||||
|
if self.end < len(self.buf) and is_punctuator(self.slice(1)):
|
||||||
|
self.advance()
|
||||||
|
else:
|
||||||
|
assert is_punctuator(self.slice())
|
||||||
|
return Punctuator(self.line, self.slice())
|
||||||
|
|
||||||
|
def integer_constant(self):
|
||||||
|
if self.buf[self.start] == '0' and (self.match('x') or self.match('X')):
|
||||||
|
return self.hexadecimal_constant()
|
||||||
|
else:
|
||||||
|
self.end -= 1
|
||||||
|
return self.decimal_constant()
|
||||||
|
|
||||||
|
def next_token(self):
|
||||||
|
while self.advance_whitespace():
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.start = self.end
|
||||||
|
|
||||||
|
c = self.advance()
|
||||||
|
|
||||||
|
if is_nondigit(c):
|
||||||
|
return self.identifier()
|
||||||
|
elif is_digit(c):
|
||||||
|
return self.integer_constant()
|
||||||
|
elif is_punctuator(c):
|
||||||
|
return self.punctuator()
|
||||||
|
else:
|
||||||
|
raise ValueError(c)
|
472
parser.py
Normal file
472
parser.py
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from lexer import Identifier, Punctuator, IntegerConstant
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Tree:
|
||||||
|
operation: str
|
||||||
|
children: list
|
||||||
|
|
||||||
|
class Parser:
|
||||||
|
def __init__(self, tokens):
|
||||||
|
self.pos = 0
|
||||||
|
self.tokens = tokens
|
||||||
|
|
||||||
|
def advance(self, offset=1):
|
||||||
|
token = self.tokens[self.pos]
|
||||||
|
self.pos += offset
|
||||||
|
return token
|
||||||
|
|
||||||
|
def check(self, t, offset=0):
|
||||||
|
if self.pos + offset < len(self.tokens):
|
||||||
|
token = self.tokens[self.pos + offset]
|
||||||
|
return type(token) is t
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_punctuator(self, p, offset=0):
|
||||||
|
if self.pos + offset < len(self.tokens):
|
||||||
|
token = self.tokens[self.pos + offset]
|
||||||
|
return type(token) is Punctuator and token.token == p
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_identifier(self, p, offset=0):
|
||||||
|
if self.pos + offset < len(self.tokens):
|
||||||
|
token = self.tokens[self.pos + offset]
|
||||||
|
return type(token) is Identifier and token.token == p
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def match(self, t):
|
||||||
|
ret = self.check(t)
|
||||||
|
if ret:
|
||||||
|
self.advance()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def match_punctuator(self, p):
|
||||||
|
ret = self.check_punctuator(p)
|
||||||
|
if ret:
|
||||||
|
self.advance()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def match_identifier(self, p):
|
||||||
|
ret = self.check_identifier(p)
|
||||||
|
if ret:
|
||||||
|
self.advance()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def previous(self):
|
||||||
|
return self.tokens[self.pos - 1]
|
||||||
|
|
||||||
|
def primary_expression(self):
|
||||||
|
aa = ' '.join(t.token for t in self.tokens[self.pos:])
|
||||||
|
if self.match(Identifier):
|
||||||
|
return self.previous()
|
||||||
|
elif self.match(IntegerConstant):
|
||||||
|
return self.previous()
|
||||||
|
elif self.match_punctuator("("):
|
||||||
|
expr = self.expression()
|
||||||
|
assert self.match_punctuator(")"), self.advance()
|
||||||
|
return Tree(
|
||||||
|
operation="grouping",
|
||||||
|
children=[expr]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert False, self.advance()
|
||||||
|
|
||||||
|
def argument_expression_list(self):
|
||||||
|
expr = self.assignment_expression()
|
||||||
|
while True:
|
||||||
|
if self.match_punctuator(","):
|
||||||
|
right = self.assignment_expression()
|
||||||
|
expr = Tree(
|
||||||
|
operation="argument_list",
|
||||||
|
children=[expr, right]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def for_expression(self):
|
||||||
|
left = self.primary_expression()
|
||||||
|
assert self.match_identifier("FOR"), self.advance()
|
||||||
|
right = self.primary_expression()
|
||||||
|
return Tree(
|
||||||
|
operation="for_expression",
|
||||||
|
children=[left, right]
|
||||||
|
)
|
||||||
|
|
||||||
|
def postfix_expression(self):
|
||||||
|
expr = self.primary_expression()
|
||||||
|
while True:
|
||||||
|
if self.match_punctuator("["):
|
||||||
|
right = self.expression()
|
||||||
|
assert self.match_punctuator("]"), self.advance()
|
||||||
|
expr = Tree(
|
||||||
|
operation="subscript",
|
||||||
|
children=[expr, right]
|
||||||
|
)
|
||||||
|
elif self.match_punctuator("("):
|
||||||
|
if self.match_punctuator(")"):
|
||||||
|
right = []
|
||||||
|
else:
|
||||||
|
right = [self.argument_expression_list()]
|
||||||
|
assert self.match_punctuator(")"), self.advance()
|
||||||
|
expr = Tree(
|
||||||
|
operation="function_call",
|
||||||
|
children=[expr, *right]
|
||||||
|
)
|
||||||
|
elif self.match_punctuator("<"):
|
||||||
|
backtrack = self.pos - 1
|
||||||
|
try:
|
||||||
|
right = self.for_expression()
|
||||||
|
except AssertionError:
|
||||||
|
self.pos = backtrack
|
||||||
|
break
|
||||||
|
assert self.match_punctuator(">"), self.advance()
|
||||||
|
expr = Tree(
|
||||||
|
operation="bit_extraction",
|
||||||
|
children=[expr, right]
|
||||||
|
)
|
||||||
|
elif self.match_punctuator("."):
|
||||||
|
assert self.match(Identifier), self.advance()
|
||||||
|
right = self.previous()
|
||||||
|
expr = Tree(
|
||||||
|
operation="member",
|
||||||
|
children=[expr, right]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def unary_expression(self):
|
||||||
|
if self.match_identifier("NOT"):
|
||||||
|
return Tree(
|
||||||
|
operation="unary_not",
|
||||||
|
children = [
|
||||||
|
self.unary_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
elif self.match_identifier("INT"):
|
||||||
|
return Tree(
|
||||||
|
operation="unary_int",
|
||||||
|
children = [
|
||||||
|
self.unary_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
elif self.match_punctuator("~"):
|
||||||
|
return Tree(
|
||||||
|
operation="unary_complement",
|
||||||
|
children = [
|
||||||
|
self.unary_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
elif self.match_punctuator("-"):
|
||||||
|
return Tree(
|
||||||
|
operation="unary_negation",
|
||||||
|
children = [
|
||||||
|
self.unary_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
# elif self.match_punctuator("|"):
|
||||||
|
# expr = self.unary_expression()
|
||||||
|
# assert self.match_punctuator("|"), self.advance()
|
||||||
|
# return Tree(
|
||||||
|
# operation="unary_absolute_value",
|
||||||
|
# children = [
|
||||||
|
# expr
|
||||||
|
# ]
|
||||||
|
# )
|
||||||
|
else:
|
||||||
|
return self.postfix_expression()
|
||||||
|
|
||||||
|
def multiplicative_expression(self):
|
||||||
|
expr = self.unary_expression()
|
||||||
|
while self.match_punctuator("×") or self.match_punctuator("/"):
|
||||||
|
operation = {
|
||||||
|
"×": "multiplication",
|
||||||
|
"/": "division",
|
||||||
|
}[self.previous().token]
|
||||||
|
expr = Tree(
|
||||||
|
operation=operation,
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.unary_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def additive_expression(self):
|
||||||
|
expr = self.multiplicative_expression()
|
||||||
|
while self.match_punctuator("+") or self.match_punctuator("-"):
|
||||||
|
operation = {
|
||||||
|
"+": "addition",
|
||||||
|
"-": "subtraction",
|
||||||
|
}[self.previous().token]
|
||||||
|
expr = Tree(
|
||||||
|
operation=operation,
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.multiplicative_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def shift_expression(self):
|
||||||
|
expr = self.additive_expression()
|
||||||
|
while self.match_punctuator("<<") or self.match_punctuator(">>"):
|
||||||
|
operation = {
|
||||||
|
"<<": "left_shift",
|
||||||
|
">>": "right_shift",
|
||||||
|
}[self.previous().token]
|
||||||
|
expr = Tree(
|
||||||
|
operation=operation,
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.additive_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def relational_expression(self):
|
||||||
|
expr = self.shift_expression()
|
||||||
|
while self.match_punctuator("<") or self.match_punctuator(">") \
|
||||||
|
or self.match_punctuator("≤") or self.match_punctuator("≥"):
|
||||||
|
operation = {
|
||||||
|
"<": "less_than",
|
||||||
|
">": "greater_than",
|
||||||
|
"≤": "less_than_equal",
|
||||||
|
"≥": "greater_than_equal",
|
||||||
|
}[self.previous().token]
|
||||||
|
expr = Tree(
|
||||||
|
operation=operation,
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.shift_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def equality_expression(self):
|
||||||
|
expr = self.relational_expression()
|
||||||
|
while self.match_punctuator("=") or self.match_punctuator("≠"):
|
||||||
|
operation = {
|
||||||
|
"≠": "equality_not_equal",
|
||||||
|
"=": "equality_equal",
|
||||||
|
}[self.previous().token]
|
||||||
|
expr = Tree(
|
||||||
|
operation=operation,
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.relational_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def bitwise_and_expression(self):
|
||||||
|
expr = self.equality_expression()
|
||||||
|
while self.match_punctuator("∧"):
|
||||||
|
expr = Tree(
|
||||||
|
operation="bitwise_and",
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.equality_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def bitwise_xor_expression(self):
|
||||||
|
expr = self.bitwise_and_expression()
|
||||||
|
while self.match_punctuator("⊕"):
|
||||||
|
expr = Tree(
|
||||||
|
operation="bitwise_xor",
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.bitwise_and_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def bitwise_or_expression(self):
|
||||||
|
expr = self.bitwise_xor_expression()
|
||||||
|
while self.match_punctuator("∨"):
|
||||||
|
expr = Tree(
|
||||||
|
operation="bitwise_or",
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.bitwise_xor_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def logical_and_expression(self):
|
||||||
|
expr = self.bitwise_or_expression()
|
||||||
|
while self.match_identifier('AND'):
|
||||||
|
expr = Tree(
|
||||||
|
operation="logical_and",
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.bitwise_or_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def logical_xor_expression(self):
|
||||||
|
# expr = self.logical_and_expression()
|
||||||
|
# while self.match_identifier('XOR'):
|
||||||
|
# expr = Tree(
|
||||||
|
# operation="logical_xor",
|
||||||
|
# children=[
|
||||||
|
# expr,
|
||||||
|
# self.logical_and_expression()
|
||||||
|
# ]
|
||||||
|
# )
|
||||||
|
# return expr
|
||||||
|
return self.logical_and_expression()
|
||||||
|
|
||||||
|
def logical_or_expression(self):
|
||||||
|
expr = self.logical_xor_expression()
|
||||||
|
while self.match_identifier('OR'):
|
||||||
|
expr = Tree(
|
||||||
|
operation="logical_or",
|
||||||
|
children=[
|
||||||
|
expr,
|
||||||
|
self.logical_xor_expression()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def assignment_list(self):
|
||||||
|
expr = self.unary_expression()
|
||||||
|
while True:
|
||||||
|
if self.match_punctuator(","):
|
||||||
|
right = self.unary_expression()
|
||||||
|
expr = Tree(
|
||||||
|
operation="assignment_list",
|
||||||
|
children=[expr, right]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def assignment_expression(self):
|
||||||
|
backtrack = self.pos
|
||||||
|
try:
|
||||||
|
left = self.assignment_list()
|
||||||
|
except AssertionError:
|
||||||
|
self.pos = backtrack
|
||||||
|
return self.logical_or_expression()
|
||||||
|
|
||||||
|
if self.match_punctuator("←"):
|
||||||
|
right = self.assignment_expression()
|
||||||
|
return Tree(
|
||||||
|
operation="assignment",
|
||||||
|
children=[left, right],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.pos = backtrack
|
||||||
|
return self.logical_or_expression()
|
||||||
|
|
||||||
|
def expression(self):
|
||||||
|
return self.assignment_expression()
|
||||||
|
|
||||||
|
def statement(self):
|
||||||
|
return self.unlabeled_statement()
|
||||||
|
|
||||||
|
def unlabeled_statement(self):
|
||||||
|
backtrack = self.pos
|
||||||
|
try:
|
||||||
|
return self.expression_statement()
|
||||||
|
except AssertionError:
|
||||||
|
self.pos = backtrack
|
||||||
|
return self.primary_block()
|
||||||
|
|
||||||
|
def expression_statement(self):
|
||||||
|
expr = self.expression()
|
||||||
|
assert self.match_punctuator(";"), self.advance()
|
||||||
|
return Tree(
|
||||||
|
operation="expression_statement",
|
||||||
|
children=[expr]
|
||||||
|
)
|
||||||
|
|
||||||
|
def primary_block(self):
|
||||||
|
if self.check_punctuator("{"):
|
||||||
|
return self.compound_statement()
|
||||||
|
elif self.check_identifier("IF"):
|
||||||
|
return self.selection_statement()
|
||||||
|
elif self.check_identifier("THROW"):
|
||||||
|
return self.throw_statement()
|
||||||
|
else:
|
||||||
|
assert False, self.advance()
|
||||||
|
|
||||||
|
def secondary_block(self):
|
||||||
|
return self.statement()
|
||||||
|
|
||||||
|
def compound_statement(self):
|
||||||
|
assert self.match_punctuator("{"), self.advance()
|
||||||
|
if self.match_punctuator("}"):
|
||||||
|
return Tree(
|
||||||
|
operation="compound_statement",
|
||||||
|
children=[],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
expr = self.block_item_list()
|
||||||
|
assert self.match_punctuator("}"), self.advance()
|
||||||
|
return Tree(
|
||||||
|
operation="compound_statement",
|
||||||
|
children=[expr]
|
||||||
|
)
|
||||||
|
|
||||||
|
def block_item_list(self):
|
||||||
|
expr = self.block_item()
|
||||||
|
while True:
|
||||||
|
backtrack = self.pos
|
||||||
|
try:
|
||||||
|
right = self.block_item()
|
||||||
|
expr = Tree(
|
||||||
|
operation="block_item_list",
|
||||||
|
children=[expr, right]
|
||||||
|
)
|
||||||
|
except AssertionError:
|
||||||
|
self.pos = backtrack
|
||||||
|
break
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def block_item(self):
|
||||||
|
return self.unlabeled_statement()
|
||||||
|
|
||||||
|
def selection_statement(self):
|
||||||
|
assert self.match_identifier("IF"), self.advance()
|
||||||
|
assert self.match_punctuator("("), self.advance()
|
||||||
|
cond_expr = self.expression()
|
||||||
|
assert self.match_punctuator(")"), self.advance()
|
||||||
|
true_block = self.secondary_block()
|
||||||
|
if self.match_identifier("ELSE"):
|
||||||
|
else_block = self.secondary_block()
|
||||||
|
return Tree(
|
||||||
|
operation="if_else",
|
||||||
|
children=[cond_expr, true_block, else_block]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return Tree(
|
||||||
|
operation="if",
|
||||||
|
children=[cond_expr, true_block]
|
||||||
|
)
|
||||||
|
|
||||||
|
def throw_statement(self):
|
||||||
|
assert self.match_identifier("THROW"), self.advance()
|
||||||
|
block = self.primary_expression()
|
||||||
|
if self.match_punctuator(","):
|
||||||
|
arg = self.primary_expression()
|
||||||
|
assert self.match_punctuator(";"), self.advance()
|
||||||
|
return Tree(
|
||||||
|
operation="throw_arg",
|
||||||
|
children=[block, arg]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert self.match_punctuator(";"), self.advance()
|
||||||
|
return Tree(
|
||||||
|
operation="throw",
|
||||||
|
children=[block]
|
||||||
|
)
|
@ -1,82 +0,0 @@
|
|||||||
"""
|
|
||||||
#define EI_NIDENT 16
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned char e_ident[EI_NIDENT];
|
|
||||||
uint16_t e_type;
|
|
||||||
uint16_t e_machine;
|
|
||||||
uint32_t e_version;
|
|
||||||
ElfN_Addr e_entry;
|
|
||||||
ElfN_Off e_phoff;
|
|
||||||
ElfN_Off e_shoff;
|
|
||||||
uint32_t e_flags;
|
|
||||||
uint16_t e_ehsize;
|
|
||||||
uint16_t e_phentsize;
|
|
||||||
uint16_t e_phnum;
|
|
||||||
uint16_t e_shentsize;
|
|
||||||
uint16_t e_shnum;
|
|
||||||
uint16_t e_shstrndx;
|
|
||||||
} ElfN_Ehdr;
|
|
||||||
"""
|
|
||||||
@dataclass
|
|
||||||
class ElfEhdr:
|
|
||||||
e_ident: bytes
|
|
||||||
e_type: int
|
|
||||||
e_machine: int
|
|
||||||
e_version: int
|
|
||||||
e_entry: int
|
|
||||||
e_phoff: int
|
|
||||||
e_shoff: int
|
|
||||||
e_flags: int
|
|
||||||
e_ehsize: int
|
|
||||||
e_phentsize: int
|
|
||||||
e_phnum: int
|
|
||||||
e_shentsize: int
|
|
||||||
e_shnum: int
|
|
||||||
e_shstrndx: int
|
|
||||||
|
|
||||||
ELFMAG0 = 0x7f
|
|
||||||
ELFMAG1 = ord('E')
|
|
||||||
ELFMAG2 = ord('L')
|
|
||||||
ELFMAG3 = ord('F')
|
|
||||||
|
|
||||||
EI_NIDENT = 16
|
|
||||||
|
|
||||||
elf_ident_fields = [
|
|
||||||
("EI_MAG0", 0),
|
|
||||||
("EI_MAG1", 1),
|
|
||||||
("EI_MAG2", 2),
|
|
||||||
("EI_MAG3", 3),
|
|
||||||
("EI_CLASS", 4),
|
|
||||||
("EI_DATA", 5),
|
|
||||||
("EI_VERSION", 6),
|
|
||||||
("EI_OSABI", 7),
|
|
||||||
("EI_ABIVERSION", 8),
|
|
||||||
("EI_PAD", 9),
|
|
||||||
]
|
|
||||||
|
|
||||||
class ElfClass(IntEnum):
|
|
||||||
NONE = 0
|
|
||||||
CLASS32 = 1
|
|
||||||
CLASS64 = 2
|
|
||||||
|
|
||||||
class ElfData(IntEnum):
|
|
||||||
NONE = 0
|
|
||||||
LSB = 1
|
|
||||||
MSB = 2
|
|
||||||
|
|
||||||
class OsABI(IntEnum):
|
|
||||||
NONE = 0
|
|
||||||
HPUX = 1
|
|
||||||
NETBSD = 2
|
|
||||||
GNU = 3
|
|
||||||
SOLARIS = 6
|
|
||||||
AIX = 7
|
|
||||||
IRIX = 8
|
|
||||||
FREEBSD = 9
|
|
||||||
TRU64 = 10
|
|
||||||
MODESTO = 11
|
|
||||||
OPENBSD = 12
|
|
||||||
ARM_AEABI = 64
|
|
||||||
ARM = 97
|
|
||||||
STANDALONE = 255
|
|
@ -1,6 +1,5 @@
|
|||||||
import instruction_properties
|
from emulator import impl
|
||||||
import impl2
|
from emulator.operations import zero_extend32, sign_extend32
|
||||||
from operations import zero_extend32, sign_extend32
|
|
||||||
from decode import decode_instruction, decode_variables
|
from decode import decode_instruction, decode_variables
|
||||||
|
|
||||||
def delay_slot_state(cpu, ins):
|
def delay_slot_state(cpu, ins):
|
||||||
@ -37,7 +36,7 @@ def step(cpu, mem):
|
|||||||
# slot.
|
# slot.
|
||||||
ins = decode_instruction(instruction)
|
ins = decode_instruction(instruction)
|
||||||
variables = decode_variables(instruction, ins)
|
variables = decode_variables(instruction, ins)
|
||||||
func = impl2.lookup[(ins.instruction, ins.operands)]
|
func = impl.lookup[(ins.instruction, ins.operands)]
|
||||||
func(cpu, mem, *variables)
|
func(cpu, mem, *variables)
|
||||||
delay_slot_state(cpu, ins)
|
delay_slot_state(cpu, ins)
|
||||||
|
|
@ -1,5 +1,4 @@
|
|||||||
from operations import *
|
from emulator.operations import *
|
||||||
from log import log
|
|
||||||
|
|
||||||
class ILLSLOT(Exception):
|
class ILLSLOT(Exception):
|
||||||
pass
|
pass
|
||||||
@ -661,7 +660,6 @@ def mac_w__multiply_and_accumulate_operation(cpu, mem, m, n):
|
|||||||
if s == 1:
|
if s == 1:
|
||||||
macl = sign_extend32(macl) + mul
|
macl = sign_extend32(macl) + mul
|
||||||
temp = signed_saturate32(macl)
|
temp = signed_saturate32(macl)
|
||||||
log(value1, value2, macl)
|
|
||||||
if macl == temp:
|
if macl == temp:
|
||||||
result = (mach << 32) | zero_extend32(macl)
|
result = (mach << 32) | zero_extend32(macl)
|
||||||
else:
|
else:
|
@ -22,7 +22,7 @@ __all__ = [
|
|||||||
def sign_extend(x, b):
|
def sign_extend(x, b):
|
||||||
m = 1 << (b - 1)
|
m = 1 << (b - 1)
|
||||||
x = x & ((1 << b) - 1)
|
x = x & ((1 << b) - 1)
|
||||||
r = (x ^ m) - m;
|
r = (x ^ m) - m
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def sign_extend64(x):
|
def sign_extend64(x):
|
@ -3,16 +3,16 @@ import curses.panel
|
|||||||
from curses.textpad import Textbox, rectangle
|
from curses.textpad import Textbox, rectangle
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from sh2 import SH2
|
|
||||||
from impl2 import ILLSLOT, TRAP
|
|
||||||
from mem import Memory
|
|
||||||
import sys
|
import sys
|
||||||
from execute import step
|
|
||||||
from decode import decode_instruction, decode_variables
|
|
||||||
from operations import sign_extend32
|
|
||||||
|
|
||||||
from log import get_log, log, raw_log
|
from emulator.sh2 import SH2
|
||||||
|
from emulator.impl import ILLSLOT, TRAP
|
||||||
|
from emulator.mem import Memory
|
||||||
|
from emulator.execute import step
|
||||||
|
from emulator.operations import sign_extend32
|
||||||
|
from emulator.log import get_log, log, raw_log
|
||||||
|
|
||||||
|
from decode import decode_instruction, decode_variables
|
||||||
|
|
||||||
last_seen1 = {}
|
last_seen1 = {}
|
||||||
last_seen = {}
|
last_seen = {}
|
@ -1,88 +0,0 @@
|
|||||||
from instruction_table import untabulate_instructions
|
|
||||||
|
|
||||||
mode_name = {
|
|
||||||
'': 'no_operand',
|
|
||||||
'Rn': 'destination_operand_only',
|
|
||||||
'Rm': 'destination_operand_only',
|
|
||||||
'Rm,Rn': 'source_and_destination_operands',
|
|
||||||
'Rm,SR': 'transfer_to_sr',
|
|
||||||
'Rm,GBR': 'transfer_to_gbr',
|
|
||||||
'Rm,VBR': 'transfer_to_vbr',
|
|
||||||
'Rm,MACH': 'transfer_to_mach',
|
|
||||||
'Rm,MACL': 'transfer_to_macl',
|
|
||||||
'Rm,PR': 'transfer_to_pr',
|
|
||||||
'SR,Rn': 'transfer_from_sr',
|
|
||||||
'GBR,Rn': 'transfer_from_gbr',
|
|
||||||
'VBR,Rn': 'transfer_from_vbr',
|
|
||||||
'MACH,Rn': 'transfer_from_mach',
|
|
||||||
'MACL,Rn': 'transfer_from_macl',
|
|
||||||
'PR,Rn': 'transfer_from_pr',
|
|
||||||
'@Rn': 'destination_operand_only',
|
|
||||||
'Rm,@Rn': 'store_register_direct_data_transfer',
|
|
||||||
'@Rm,Rn': 'load_register_direct_data_transfer',
|
|
||||||
'@Rm+,@Rn+': 'multiply_and_accumulate_operation',
|
|
||||||
'@Rm+,Rn': 'load_direct_data_transfer_from_register',
|
|
||||||
'@Rm+,SR': 'load_to_sr',
|
|
||||||
'@Rm+,GBR': 'load_to_gbr',
|
|
||||||
'@Rm+,VBR': 'load_to_vbr',
|
|
||||||
'@Rm+,MACH': 'load_to_mach',
|
|
||||||
'@Rm+,MACL': 'load_to_macl',
|
|
||||||
'@Rm+,PR': 'load_to_pr',
|
|
||||||
'Rm,@–Rn': 'store_direct_data_transfer_from_register',
|
|
||||||
'SR,@–Rn': 'store_from_sr',
|
|
||||||
'GBR,@–Rn': 'store_from_gbr',
|
|
||||||
'VBR,@–Rn': 'store_from_vbr',
|
|
||||||
'MACH,@–Rn': 'store_from_mach',
|
|
||||||
'MACL,@–Rn': 'store_from_macl',
|
|
||||||
'PR,@–Rn': 'store_from_pr',
|
|
||||||
'R0,@(disp,Rn)': 'store_register_indirect_with_displacement',
|
|
||||||
'Rm,@(disp,Rn)': 'store_register_indirect_with_displacement',
|
|
||||||
'@(disp,Rm),R0': 'load_register_indirect_with_displacement',
|
|
||||||
'@(disp,Rm),Rn': 'load_register_indirect_with_displacement',
|
|
||||||
'Rm,@(R0,Rn)': 'store_indexed_register_indirect',
|
|
||||||
'@(R0,Rm),Rn': 'load_indexed_register_indirect',
|
|
||||||
'R0,@(disp,GBR)': 'store_gbr_indirect_with_displacement',
|
|
||||||
'@(disp,GBR),R0': 'load_gbr_indirect_with_displacement',
|
|
||||||
'#imm,@(R0,GBR)': 'store_indexed_gbr_indirect',
|
|
||||||
'@(R0,GBR),#imm': 'load_indexed_gbr_indirect',
|
|
||||||
'@(disp,PC),Rn': 'pc_relative_with_displacement',
|
|
||||||
'@(disp,PC),R0': 'pc_relative_with_displacement',
|
|
||||||
'label': 'pc_relative',
|
|
||||||
'#imm,Rn': 'immediate',
|
|
||||||
'#imm,R0': 'immediate',
|
|
||||||
'#imm': 'immediate',
|
|
||||||
}
|
|
||||||
|
|
||||||
def sanitize_instruction(ins):
|
|
||||||
name = ins.instruction.replace('.', '_').replace('/', '_').lower()
|
|
||||||
assert ins.operands in mode_name, (ins.instruction, ins.operands)
|
|
||||||
mode = mode_name[ins.operands]
|
|
||||||
return '__'.join([name, mode])
|
|
||||||
|
|
||||||
def main():
|
|
||||||
function_names = {}
|
|
||||||
instruction_table = untabulate_instructions()
|
|
||||||
for ins in instruction_table:
|
|
||||||
function_name = sanitize_instruction(ins)
|
|
||||||
instruction_operands = (ins.instruction, ins.operands)
|
|
||||||
assert function_name not in function_names, (instruction_operands, names[name])
|
|
||||||
function_names[function_name] = instruction_operands
|
|
||||||
if ins.variables:
|
|
||||||
args = f', {", ".join(ins.variables)}'
|
|
||||||
else:
|
|
||||||
args = ''
|
|
||||||
print(f"def {function_name}(cpu, mem{args}):")
|
|
||||||
print(f" # {ins.instruction} {ins.operands}")
|
|
||||||
print(f" raise NotImplementedError()")
|
|
||||||
print()
|
|
||||||
|
|
||||||
print("lookup = {")
|
|
||||||
for ins in instruction_table:
|
|
||||||
function_name = sanitize_instruction(ins)
|
|
||||||
i_space = ' ' * (len('CMP/STR') - len(ins.instruction))
|
|
||||||
o_space = ' ' * (len('@(disp,GBR),R0') - len(ins.operands))
|
|
||||||
print(f" ('{ins.instruction}'{i_space}, '{ins.operands}'{o_space}): {function_name},")
|
|
||||||
print("}")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
30
python/generate_python.py
Normal file
30
python/generate_python.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from instruction_table import untabulate_instructions_sh2
|
||||||
|
from instruction_function_name import instruction_function_name
|
||||||
|
|
||||||
|
def main():
|
||||||
|
function_names = {}
|
||||||
|
instruction_table = untabulate_instructions_sh2()
|
||||||
|
for ins in instruction_table:
|
||||||
|
function_name = instruction_function_name(ins)
|
||||||
|
instruction_operands = (ins.instruction, ins.operands)
|
||||||
|
assert function_name not in function_names, (instruction_operands, function_names[function_name])
|
||||||
|
function_names[function_name] = instruction_operands
|
||||||
|
if ins.variables:
|
||||||
|
args = f', {", ".join(ins.variables)}'
|
||||||
|
else:
|
||||||
|
args = ''
|
||||||
|
print(f"def {function_name}(cpu, mem{args}):")
|
||||||
|
print(f" # {ins.instruction} {ins.operands}")
|
||||||
|
print(f" raise NotImplementedError()")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("lookup = {")
|
||||||
|
for ins in instruction_table:
|
||||||
|
function_name = instruction_function_name(ins)
|
||||||
|
i_space = ' ' * (len('CMP/STR') - len(ins.instruction))
|
||||||
|
o_space = ' ' * (len('@(disp,GBR),R0') - len(ins.operands))
|
||||||
|
print(f" ('{ins.instruction}'{i_space}, '{ins.operands}'{o_space}): {function_name},")
|
||||||
|
print("}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
14
python/generate_sh4_directory.py
Normal file
14
python/generate_sh4_directory.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from instruction_table import untabulate_instructions_sh4
|
||||||
|
from instruction_file_name import instruction_file_name
|
||||||
|
|
||||||
|
for ins in untabulate_instructions_sh4():
|
||||||
|
code = list(f'{ins.code.code_bits:016b}')
|
||||||
|
for operand in ins.code.operands.values():
|
||||||
|
for i in range(operand.lsb, operand.lsb + operand.length):
|
||||||
|
code[15 - i] = operand.operand
|
||||||
|
|
||||||
|
file_name = instruction_file_name(ins)
|
||||||
|
path = os.path.join("sh4", file_name)
|
||||||
|
assert not os.path.exists(path)
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
f.write(''.join(code) + '\n')
|
7
python/instruction_file_name.py
Normal file
7
python/instruction_file_name.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
def instruction_file_name(ins):
|
||||||
|
if ins.operands:
|
||||||
|
file_name = ' '.join([ins.instruction, ins.operands])
|
||||||
|
else:
|
||||||
|
file_name = ins.instruction
|
||||||
|
file_name = file_name.replace('/', '_')
|
||||||
|
return file_name
|
118
python/instruction_function_name.py
Normal file
118
python/instruction_function_name.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
mode_name = {
|
||||||
|
'': 'no_operand',
|
||||||
|
'Rn': 'destination_operand_only',
|
||||||
|
'Rm': 'destination_operand_only',
|
||||||
|
'Rm,Rn': 'source_and_destination_operands',
|
||||||
|
'Rm,SR': 'transfer_to_sr',
|
||||||
|
'Rm,SSR': 'transfer_to_ssr',
|
||||||
|
'Rm,SPC': 'transfer_to_spc',
|
||||||
|
'Rm,GBR': 'transfer_to_gbr',
|
||||||
|
'Rm,VBR': 'transfer_to_vbr',
|
||||||
|
'Rm,DBR': 'transfer_to_dbr',
|
||||||
|
'Rm,MACH': 'transfer_to_mach',
|
||||||
|
'Rm,MACL': 'transfer_to_macl',
|
||||||
|
'Rm,Rn_BANK': 'transfer_to_rn_bank',
|
||||||
|
'Rm,PR': 'transfer_to_pr',
|
||||||
|
'SR,Rn': 'transfer_from_sr',
|
||||||
|
'SSR,Rn': 'transfer_from_ssr',
|
||||||
|
'SPC,Rn': 'transfer_from_spc',
|
||||||
|
'GBR,Rn': 'transfer_from_gbr',
|
||||||
|
'VBR,Rn': 'transfer_from_vbr',
|
||||||
|
'DBR,Rn': 'transfer_from_dbr',
|
||||||
|
'SGR,Rn': 'transfer_from_sgr',
|
||||||
|
'MACH,Rn': 'transfer_from_mach',
|
||||||
|
'MACL,Rn': 'transfer_from_macl',
|
||||||
|
'Rm_BANK,Rn': 'transfer_from_rm_bank',
|
||||||
|
'PR,Rn': 'transfer_from_pr',
|
||||||
|
'@Rn': 'destination_operand_only',
|
||||||
|
'Rm,@Rn': 'store_register_direct_data_transfer',
|
||||||
|
'R0,@Rn': 'r0_store_register_direct_data_transfer',
|
||||||
|
'@Rm,Rn': 'load_register_direct_data_transfer',
|
||||||
|
'@Rm+,@Rn+': 'multiply_and_accumulate_operation',
|
||||||
|
'@Rm+,Rn': 'load_direct_data_transfer_from_register',
|
||||||
|
'@Rm+,SR': 'load_to_sr',
|
||||||
|
'@Rm+,SSR': 'load_to_ssr',
|
||||||
|
'@Rm+,SPC': 'load_to_spc',
|
||||||
|
'@Rm+,GBR': 'load_to_gbr',
|
||||||
|
'@Rm+,VBR': 'load_to_vbr',
|
||||||
|
'@Rm+,DBR': 'load_to_dbr',
|
||||||
|
'@Rm+,MACH': 'load_to_mach',
|
||||||
|
'@Rm+,MACL': 'load_to_macl',
|
||||||
|
'@Rm+,Rn_BANK': 'load_to_rn_bank',
|
||||||
|
'@Rm+,PR': 'load_to_pr',
|
||||||
|
'Rm,@-Rn': 'store_direct_data_transfer_from_register',
|
||||||
|
'SR,@-Rn': 'store_from_sr',
|
||||||
|
'SSR,@-Rn': 'store_from_ssr',
|
||||||
|
'SPC,@-Rn': 'store_from_spc',
|
||||||
|
'GBR,@-Rn': 'store_from_gbr',
|
||||||
|
'VBR,@-Rn': 'store_from_vbr',
|
||||||
|
'DBR,@-Rn': 'store_from_dbr',
|
||||||
|
'SGR,@-Rn': 'store_from_sgr',
|
||||||
|
'MACH,@-Rn': 'store_from_mach',
|
||||||
|
'MACL,@-Rn': 'store_from_macl',
|
||||||
|
'Rm_BANK,@-Rn': 'store_from_rm_bank',
|
||||||
|
'PR,@-Rn': 'store_from_pr',
|
||||||
|
'R0,@(disp,Rn)': 'store_register_indirect_with_displacement',
|
||||||
|
'Rm,@(disp,Rn)': 'store_register_indirect_with_displacement',
|
||||||
|
'@(disp,Rm),R0': 'load_register_indirect_with_displacement',
|
||||||
|
'@(disp,Rm),Rn': 'load_register_indirect_with_displacement',
|
||||||
|
'Rm,@(R0,Rn)': 'store_indexed_register_indirect',
|
||||||
|
'@(R0,Rm),Rn': 'load_indexed_register_indirect',
|
||||||
|
'R0,@(disp,GBR)': 'store_gbr_indirect_with_displacement',
|
||||||
|
'@(disp,GBR),R0': 'load_gbr_indirect_with_displacement',
|
||||||
|
'#imm,@(R0,GBR)': 'store_indexed_gbr_indirect',
|
||||||
|
'@(R0,GBR),#imm': 'load_indexed_gbr_indirect',
|
||||||
|
'@(disp,PC),Rn': 'pc_relative_with_displacement',
|
||||||
|
'@(disp,PC),R0': 'pc_relative_with_displacement',
|
||||||
|
'label': 'pc_relative',
|
||||||
|
'#imm,Rn': 'immediate',
|
||||||
|
'#imm,R0': 'immediate',
|
||||||
|
'#imm': 'immediate',
|
||||||
|
# floating point
|
||||||
|
'FRn': 'destination_operand_only',
|
||||||
|
'DRn': 'destination_operand_only_double',
|
||||||
|
'FRm,FRn': 'source_and_destination_operands',
|
||||||
|
'DRm,DRn': 'source_and_destination_operands_double',
|
||||||
|
'XDm,XDn': 'source_and_destination_operands_bank',
|
||||||
|
'DRm,XDn': 'double_to_bank',
|
||||||
|
'XDm,DRn': 'bank_to_double',
|
||||||
|
'@Rm,FRn': 'load_register_direct_data_transfer',
|
||||||
|
'@Rm,DRn': 'load_register_direct_data_transfer_double',
|
||||||
|
'@Rm,XDn': 'load_register_direct_data_transfer_bank',
|
||||||
|
'@(R0,Rm),FRn': 'load_indexed_register_indirect',
|
||||||
|
'@(R0,Rm),DRn': 'load_indexed_register_indirect_double',
|
||||||
|
'@(R0,Rm),XDn': 'load_indexed_register_indirect_bank',
|
||||||
|
'@Rm+,FRn': 'load_direct_data_transfer_from_register',
|
||||||
|
'@Rm+,DRn': 'load_direct_data_transfer_from_register_double',
|
||||||
|
'@Rm+,XDn': 'load_direct_data_transfer_from_register_bank',
|
||||||
|
'FRm,@Rn': 'store_register_direct_data_transfer',
|
||||||
|
'DRm,@Rn': 'store_register_direct_data_transfer_double',
|
||||||
|
'XDm,@Rn': 'store_register_direct_data_transfer_bank',
|
||||||
|
'FRm,@-Rn': 'store_direct_data_transfer_from_register',
|
||||||
|
'DRm,@-Rn': 'store_direct_data_transfer_from_register_double',
|
||||||
|
'XDm,@-Rn': 'store_direct_data_transfer_from_register_bank',
|
||||||
|
'FRm,@(R0,Rn)': 'store_indexed_register_indirect',
|
||||||
|
'DRm,@(R0,Rn)': 'store_indexed_register_indirect_double',
|
||||||
|
'XDm,@(R0,Rn)': 'store_indexed_register_indirect_bank',
|
||||||
|
'FRm,FPUL': 'frm_to_fpul',
|
||||||
|
'DRm,FPUL': 'drm_to_fpul',
|
||||||
|
'FPUL,FRn': 'fpul_to_frn',
|
||||||
|
'FPUL,DRn': 'fpul_to_drn',
|
||||||
|
'FR0,FRm,FRn': 'fr0_frm_frn',
|
||||||
|
'Rm,FPSCR': 'transfer_to_fpscr',
|
||||||
|
'Rm,FPUL': 'transfer_to_fpul',
|
||||||
|
'@Rm+,FPSCR': 'load_to_fpscr',
|
||||||
|
'@Rm+,FPUL': 'load_to_fpul',
|
||||||
|
'FPSCR,Rn': 'transfer_from_fpscr',
|
||||||
|
'FPUL,Rn': 'transfer_from_fpul',
|
||||||
|
'FPUL,@-Rn': 'store_from_fpul',
|
||||||
|
'FPSCR,@-Rn': 'store_from_fpscr',
|
||||||
|
'FVm,FVn': 'fvm_fvn',
|
||||||
|
'XMTRX,FVn': 'xmtrx_fvn',
|
||||||
|
}
|
||||||
|
|
||||||
|
def instruction_function_name(ins):
|
||||||
|
name = ins.instruction.replace('.', '_').replace('/', '_').lower()
|
||||||
|
assert ins.operands in mode_name, (ins.instruction, ins.operands)
|
||||||
|
mode = mode_name[ins.operands]
|
||||||
|
return '__'.join([name, mode])
|
@ -223,7 +223,7 @@ def untabulate_instructions_sh2():
|
|||||||
("t_bit" , 102)
|
("t_bit" , 102)
|
||||||
]))
|
]))
|
||||||
|
|
||||||
return untabulate_instructions(os.path.join(directory, "sh2.txt"), columns)
|
return untabulate_instructions(os.path.join(directory, "..", "sh2.txt"), columns)
|
||||||
|
|
||||||
def untabulate_instructions_sh4():
|
def untabulate_instructions_sh4():
|
||||||
columns = dict(column_bounds([
|
columns = dict(column_bounds([
|
||||||
@ -235,20 +235,4 @@ def untabulate_instructions_sh4():
|
|||||||
("t_bit" , 116)
|
("t_bit" , 116)
|
||||||
]))
|
]))
|
||||||
|
|
||||||
return untabulate_instructions(os.path.join(directory, "sh4.txt"), columns)
|
return untabulate_instructions(os.path.join(directory, "..", "sh4.txt"), columns)
|
||||||
|
|
||||||
l = untabulate_instructions_sh4()
|
|
||||||
from pprint import pprint
|
|
||||||
for ins in list(l):
|
|
||||||
if ins.operands:
|
|
||||||
fn = ' '.join([ins.instruction, ins.operands])
|
|
||||||
else:
|
|
||||||
fn = ins.instruction
|
|
||||||
fn = fn.replace('/', '_')
|
|
||||||
code = list(f'{ins.code.code_bits:016b}')
|
|
||||||
for operand in ins.code.operands.values():
|
|
||||||
for i in range(operand.lsb, operand.lsb + operand.length):
|
|
||||||
code[15 - i] = operand.operand
|
|
||||||
|
|
||||||
with open(os.path.join(directory, "sh4", fn), 'w') as f:
|
|
||||||
f.write(''.join(code) + '\n')
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
0111nnnniiiiiiii
|
0111nnnniiiiiiii
|
||||||
imm ← SignExtend8(s);
|
imm ← SignExtend8(i);
|
||||||
op2 ← SignExtend32(Rn);
|
op2 ← SignExtend32(Rn);
|
||||||
op2 ← op2 + imm;
|
op2 ← op2 + imm;
|
||||||
Rn ← Register(op2);
|
Rn ← Register(op2);
|
@ -3,7 +3,7 @@ t ← ZeroExtend1(T);
|
|||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
newpc ← SignExtend32(PC’);
|
newpc ← SignExtend32(PC’);
|
||||||
delayedpc ← SignExtend32(PC’’);
|
delayedpc ← SignExtend32(PC’’);
|
||||||
label ← SignExtend8(s) << 1;
|
label ← SignExtend8(d) << 1;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
IF (t = 0)
|
IF (t = 0)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
t ← ZeroExtend1(T);
|
t ← ZeroExtend1(T);
|
||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
delayedpc ← SignExtend32(PC’’);
|
delayedpc ← SignExtend32(PC’’);
|
||||||
label ← SignExtend8(s) << 1;
|
label ← SignExtend8(d) << 1;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
IF (t = 0)
|
IF (t = 0)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
1010dddddddddddd
|
1010dddddddddddd
|
||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
label ← SignExtend12(s) << 1;
|
label ← SignExtend12(d) << 1;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
temp ← ZeroExtend32(pc + 4 + label);
|
temp ← ZeroExtend32(pc + 4 + label);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
1011dddddddddddd
|
1011dddddddddddd
|
||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
label ← SignExtend12(s) << 1;
|
label ← SignExtend12(d) << 1;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
delayedpr ← pc + 4;
|
delayedpr ← pc + 4;
|
||||||
|
@ -3,7 +3,7 @@ t ← ZeroExtend1(T);
|
|||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
newpc ← SignExtend32(PC’);
|
newpc ← SignExtend32(PC’);
|
||||||
delayedpc ← SignExtend32(PC’’);
|
delayedpc ← SignExtend32(PC’’);
|
||||||
label ← SignExtend8(s) << 1;
|
label ← SignExtend8(d) << 1;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
IF (t = 1)
|
IF (t = 1)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
t ← ZeroExtend1(T);
|
t ← ZeroExtend1(T);
|
||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
delayedpc ← SignExtend32(PC’’);
|
delayedpc ← SignExtend32(PC’’);
|
||||||
label ← SignExtend8(s) << 1;
|
label ← SignExtend8(d) << 1;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
IF (t = 1)
|
IF (t = 1)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
10001000iiiiiiii
|
10001000iiiiiiii
|
||||||
r0 ← SignExtend32(R0);
|
r0 ← SignExtend32(R0);
|
||||||
imm ← SignExtend8(s);
|
imm ← SignExtend8(i);
|
||||||
t ← INT (r0 = imm);
|
t ← INT (r0 = imm);
|
||||||
T ← Bit(t);
|
T ← Bit(t);
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
op1 ← SignExtend32(Rm);
|
op1 ← SignExtend32(Rm);
|
||||||
op2 ← SignExtend32(Rn);
|
op2 ← SignExtend32(Rn);
|
||||||
q ← op2< 31 FOR 1 >;
|
q ← op2< 31 FOR 1 >;
|
||||||
m ← op1< 31 FOR 1 >;
|
_m ← op1< 31 FOR 1 >;
|
||||||
t ← m ⊕ q;
|
t ← _m ⊕ q;
|
||||||
Q ← Bit(q);
|
Q ← Bit(q);
|
||||||
M ← Bit(m);
|
M ← Bit(_m);
|
||||||
T ← Bit(t);
|
T ← Bit(t);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
0000000000011001
|
0000000000011001
|
||||||
q ← 0;
|
q ← 0;
|
||||||
m ← 0;
|
_m ← 0;
|
||||||
t ← 0;
|
t ← 0;
|
||||||
Q ← Bit(q);
|
Q ← Bit(q);
|
||||||
M ← Bit(m);
|
M ← Bit(_m);
|
||||||
T ← Bit(t);
|
T ← Bit(t);
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
0011nnnnmmmm0100
|
0011nnnnmmmm0100
|
||||||
q ← ZeroExtend1(Q);
|
q ← ZeroExtend1(Q);
|
||||||
m ← ZeroExtend1(M);
|
_m ← ZeroExtend1(M);
|
||||||
t ← ZeroExtend1(T);
|
t ← ZeroExtend1(T);
|
||||||
op1 ← ZeroExtend32(SignExtend32(Rm));
|
op1 ← ZeroExtend32(SignExtend32(Rm));
|
||||||
op2 ← ZeroExtend32(SignExtend32(Rn));
|
op2 ← ZeroExtend32(SignExtend32(Rn));
|
||||||
oldq ← q;
|
oldq ← q;
|
||||||
q ← op2< 31 FOR 1 >;
|
q ← op2< 31 FOR 1 >;
|
||||||
op2 ← ZeroExtend32(op2 << 1) ∨ t;
|
op2 ← ZeroExtend32(op2 << 1) ∨ t;
|
||||||
IF (oldq = m)
|
IF (oldq = _m)
|
||||||
op2 ← op2 - op1;
|
op2 ← op2 - op1;
|
||||||
ELSE
|
ELSE
|
||||||
op2 ← op2 + op1;
|
op2 ← op2 + op1;
|
||||||
q ← (q ⊕ m) ⊕ op2< 32 FOR 1 >;
|
q ← (q ⊕ _m) ⊕ op2< 32 FOR 1 >;
|
||||||
t ← 1 - (q ⊕ m);
|
t ← 1 - (q ⊕ _m);
|
||||||
Rn ← Register(op2);
|
Rn ← Register(op2);
|
||||||
Q ← Bit(q);
|
Q ← Bit(q);
|
||||||
T ← Bit(t);
|
T ← Bit(t);
|
||||||
|
@ -8,7 +8,7 @@ IF (FpuIsDisabled(sr) AND IsDelaySlot())
|
|||||||
THROW SLOTFPUDIS;
|
THROW SLOTFPUDIS;
|
||||||
IF (FpuIsDisabled(sr))
|
IF (FpuIsDisabled(sr))
|
||||||
THROW FPUDIS;
|
THROW FPUDIS;
|
||||||
op2[3], fps ← FIPR_S(op1, op2, fps);
|
op2, fps ← FIPR_S(op1, op2, fps);
|
||||||
IF (FpuEnableV(fps) AND FpuCauseV(fps))
|
IF (FpuEnableV(fps) AND FpuCauseV(fps))
|
||||||
THROW FPUEXC, fps;
|
THROW FPUEXC, fps;
|
||||||
IF ((FpuEnableI(fps) OR FpuEnableO(fps)) OR FpuEnableU(fps))
|
IF ((FpuEnableI(fps) OR FpuEnableO(fps)) OR FpuEnableU(fps))
|
||||||
|
@ -9,4 +9,4 @@ IF (FpuIsDisabled(sr))
|
|||||||
THROW FPUDIS;
|
THROW FPUDIS;
|
||||||
address ← ZeroExtend32(op1);
|
address ← ZeroExtend32(op1);
|
||||||
op2 ← ReadMemory32(address);
|
op2 ← ReadMemory32(address);
|
||||||
FR2n ← FloatRegister32(op2);
|
FRn ← FloatRegister32(op2);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
1111001111111101
|
1111001111111101
|
||||||
Available only when PR=0
|
Available only when PR=0
|
||||||
sr ← ZeroExtend32(SR);
|
sr ← ZeroExtend32(SR);
|
||||||
sz ← ZeroExtend1(SR.SZ);
|
sz ← ZeroExtend1(FPSCR.SZ);
|
||||||
IF (FpuIsDisabled(sr) AND IsDelaySlot())
|
IF (FpuIsDisabled(sr) AND IsDelaySlot())
|
||||||
THROW SLOTFPUDIS;
|
THROW SLOTFPUDIS;
|
||||||
IF (FpuIsDisabled(sr))
|
IF (FpuIsDisabled(sr))
|
||||||
THROW FPUDIS;
|
THROW FPUDIS;
|
||||||
sz ← sz ⊕ 1;
|
sz ← sz ⊕ 1;
|
||||||
SR.SZ ← Bit(sz);
|
FPSCR.SZ ← Bit(sz);
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
op1 ← SignExtend32(Rm);
|
op1 ← SignExtend32(Rm);
|
||||||
dbr← op1;
|
dbr ← op1;
|
||||||
DBR ← Register(dbr);
|
DBR ← Register(dbr);
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
op1 ← SignExtend32(Rm);
|
op1 ← SignExtend32(Rm);
|
||||||
vbr← op1;
|
vbr ← op1;
|
||||||
VBR ← Register(vbr);
|
VBR ← Register(vbr);
|
||||||
|
@ -5,8 +5,4 @@ IF (FpuIsDisabled(sr) AND IsDelaySlot())
|
|||||||
THROW SLOTFPUDIS;
|
THROW SLOTFPUDIS;
|
||||||
IF (FpuIsDisabled(sr))
|
IF (FpuIsDisabled(sr))
|
||||||
THROW FPUDIS;
|
THROW FPUDIS;
|
||||||
fps, pr, sz, fr ← UnpackFPSCR(op1);
|
FPSCR ← ZeroExtend32(op1);
|
||||||
FPSCR ← ZeroExtend32(fps);
|
|
||||||
SR.PR ← Bit(pr);
|
|
||||||
SR.SZ ← Bit(sz);
|
|
||||||
SR.FR ← Bit(fr);
|
|
||||||
|
@ -7,10 +7,6 @@ IF (FpuIsDisabled(sr))
|
|||||||
THROW FPUDIS;
|
THROW FPUDIS;
|
||||||
address ← ZeroExtend32(op1);
|
address ← ZeroExtend32(op1);
|
||||||
value ← ReadMemory32(address);
|
value ← ReadMemory32(address);
|
||||||
fps, pr, sz, fr ← UnpackFPSCR(value);
|
|
||||||
op1 ← op1 + 4;
|
op1 ← op1 + 4;
|
||||||
Rm ← Register(op1);
|
Rm ← Register(op1);
|
||||||
FPSCR ← ZeroExtend32(fps);
|
FPSCR ← ZeroExtend32(value);
|
||||||
SR.PR ← Bit(pr);
|
|
||||||
SR.SZ ← Bit(sz);
|
|
||||||
SR.FR ← Bit(fr);
|
|
||||||
|
20
sh4/LDTLB
20
sh4/LDTLB
@ -2,13 +2,13 @@
|
|||||||
md ← ZeroExtend1(MD);
|
md ← ZeroExtend1(MD);
|
||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
UTLB[MMUCR.URC].ASID ← PTEH.ASID
|
UTLB[MMUCR.URC].ASID ← PTEH.ASID;
|
||||||
UTLB[MMUCR.URC].VPN ← PTEH.VPN
|
UTLB[MMUCR.URC].VPN ← PTEH.VPN;
|
||||||
UTLB[MMUCR.URC].PPN ← PTEH.PPN
|
UTLB[MMUCR.URC].PPN ← PTEH.PPN;
|
||||||
UTLB[MMUCR.URC].SZ ← PTEL.SZ1<<1 + PTEL.SZ0
|
UTLB[MMUCR.URC].SZ ← PTEL.SZ1<<1 + PTEL.SZ0;
|
||||||
UTLB[MMUCR.URC].SH ← PTEL.SH
|
UTLB[MMUCR.URC].SH ← PTEL.SH;
|
||||||
UTLB[MMUCR.URC].PR ← PTEL.PR
|
UTLB[MMUCR.URC].PR ← PTEL.PR;
|
||||||
UTLB[MMUCR.URC].WT ← PTEL.WT
|
UTLB[MMUCR.URC].WT ← PTEL.WT;
|
||||||
UTLB[MMUCR.URC].C ← PTEL.C
|
UTLB[MMUCR.URC].C ← PTEL.C;
|
||||||
UTLB[MMUCR.URC].D ← PTEL.D
|
UTLB[MMUCR.URC].D ← PTEL.D;
|
||||||
UTLB[MMUCR.URC].V ← PTEL.V
|
UTLB[MMUCR.URC].V ← PTEL.V;
|
||||||
|
@ -16,6 +16,7 @@ n_address ← n_address + 2;
|
|||||||
value1 ← SignExtend16(ReadMemory16(ZeroExtend32(m_address)));
|
value1 ← SignExtend16(ReadMemory16(ZeroExtend32(m_address)));
|
||||||
m_address ← m_address + 2;
|
m_address ← m_address + 2;
|
||||||
mul ← value2 × value1;
|
mul ← value2 × value1;
|
||||||
|
result ← 0;
|
||||||
IF (s = 1)
|
IF (s = 1)
|
||||||
{
|
{
|
||||||
macl ← SignExtend32(macl) + mul;
|
macl ← SignExtend32(macl) + mul;
|
||||||
@ -23,7 +24,7 @@ temp ← SignedSaturate32(macl);
|
|||||||
IF (macl = temp)
|
IF (macl = temp)
|
||||||
result ← (mach << 32) ∨ ZeroExtend32(macl);
|
result ← (mach << 32) ∨ ZeroExtend32(macl);
|
||||||
ELSE
|
ELSE
|
||||||
result ← (0x1 << 32) ∨ ZeroExtend32(temp);
|
result ← (1 << 32) ∨ ZeroExtend32(temp);
|
||||||
}
|
}
|
||||||
ELSE
|
ELSE
|
||||||
result ← ((mach << 32) + macl) + mul;
|
result ← ((mach << 32) + macl) + mul;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
1110nnnniiiiiiii
|
1110nnnniiiiiiii
|
||||||
imm ← SignExtend8(s);
|
imm ← SignExtend8(i);
|
||||||
op2 ← imm;
|
op2 ← imm;
|
||||||
Rn ← Register(op2);
|
Rn ← Register(op2);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
11000100dddddddd
|
11000100dddddddd
|
||||||
gbr ← SignExtend32(GBR);
|
gbr ← SignExtend32(GBR);
|
||||||
disp ← ZeroExtend8(i);
|
disp ← ZeroExtend8(d);
|
||||||
address ← ZeroExtend32(disp + gbr);
|
address ← ZeroExtend32(disp + gbr);
|
||||||
r0 ← SignExtend8(ReadMemory8(address));
|
r0 ← SignExtend8(ReadMemory8(address));
|
||||||
R0 ← Register(r0);
|
R0 ← Register(r0);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
10000100mmmmdddd
|
10000100mmmmdddd
|
||||||
disp ← ZeroExtend4(i);
|
disp ← ZeroExtend4(d);
|
||||||
op2 ← SignExtend32(Rm);
|
op2 ← SignExtend32(Rm);
|
||||||
address ← ZeroExtend32(disp + op2);
|
address ← ZeroExtend32(disp + op2);
|
||||||
r0 ← SignExtend8(ReadMemory8(address));
|
r0 ← SignExtend8(ReadMemory8(address));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
11000000dddddddd
|
11000000dddddddd
|
||||||
gbr ← SignExtend32(GBR);
|
gbr ← SignExtend32(GBR);
|
||||||
r0 ← SignExtend32(R0);
|
r0 ← SignExtend32(R0);
|
||||||
disp ← ZeroExtend8(i);
|
disp ← ZeroExtend8(d);
|
||||||
address ← ZeroExtend32(disp + gbr);
|
address ← ZeroExtend32(disp + gbr);
|
||||||
WriteMemory8(address, r0);
|
WriteMemory8(address, r0);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
10000000nnnndddd
|
10000000nnnndddd
|
||||||
r0 ← SignExtend32(R0);
|
r0 ← SignExtend32(R0);
|
||||||
disp ← ZeroExtend4(i);
|
disp ← ZeroExtend4(d);
|
||||||
op2 ← SignExtend32(Rn);
|
op2 ← SignExtend32(Rn);
|
||||||
address ← ZeroExtend32(disp + op2);
|
address ← ZeroExtend32(disp + op2);
|
||||||
WriteMemory8(address, r0);
|
WriteMemory8(address, r0);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
11000110dddddddd
|
11000110dddddddd
|
||||||
gbr ← SignExtend32(GBR);
|
gbr ← SignExtend32(GBR);
|
||||||
disp ← ZeroExtend8(i) << 2;
|
disp ← ZeroExtend8(d) << 2;
|
||||||
address ← ZeroExtend32(disp + gbr);
|
address ← ZeroExtend32(disp + gbr);
|
||||||
r0 ← SignExtend32(ReadMemory32(address));
|
r0 ← SignExtend32(ReadMemory32(address));
|
||||||
R0 ← Register(r0);
|
R0 ← Register(r0);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
1101nnnndddddddd
|
1101nnnndddddddd
|
||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
disp ← ZeroExtend8(i) << 2;
|
disp ← ZeroExtend8(d) << 2;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
address ← ZeroExtend32(disp + ((pc + 4) ∧ (~ 0x3)));
|
address ← ZeroExtend32(disp + ((pc + 4) ∧ (~ 0x3)));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
0101nnnnmmmmdddd
|
0101nnnnmmmmdddd
|
||||||
disp ← ZeroExtend4(i) << 2;
|
disp ← ZeroExtend4(d) << 2;
|
||||||
op2 ← SignExtend32(Rm);
|
op2 ← SignExtend32(Rm);
|
||||||
address ← ZeroExtend32(disp + op2);
|
address ← ZeroExtend32(disp + op2);
|
||||||
op3 ← SignExtend32(ReadMemory32(address));
|
op3 ← SignExtend32(ReadMemory32(address));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
11000010dddddddd
|
11000010dddddddd
|
||||||
gbr ← SignExtend32(GBR);
|
gbr ← SignExtend32(GBR);
|
||||||
r0 ← SignExtend32(R0);
|
r0 ← SignExtend32(R0);
|
||||||
disp ← ZeroExtend8(i) << 2;
|
disp ← ZeroExtend8(d) << 2;
|
||||||
address ← ZeroExtend32(disp + gbr);
|
address ← ZeroExtend32(disp + gbr);
|
||||||
WriteMemory32(address, r0);
|
WriteMemory32(address, r0);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
0001nnnnmmmmdddd
|
0001nnnnmmmmdddd
|
||||||
op1 ← SignExtend32(Rm);
|
op1 ← SignExtend32(Rm);
|
||||||
disp ← ZeroExtend4(i) << 2;
|
disp ← ZeroExtend4(d) << 2;
|
||||||
op3 ← SignExtend32(Rn);
|
op3 ← SignExtend32(Rn);
|
||||||
address ← ZeroExtend32(disp + op3);
|
address ← ZeroExtend32(disp + op3);
|
||||||
WriteMemory32(address, op1);
|
WriteMemory32(address, op1);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
11000101dddddddd
|
11000101dddddddd
|
||||||
gbr ← SignExtend32(GBR);
|
gbr ← SignExtend32(GBR);
|
||||||
disp ← ZeroExtend8(i) << 1;
|
disp ← ZeroExtend8(d) << 1;
|
||||||
address ← ZeroExtend32(disp + gbr);
|
address ← ZeroExtend32(disp + gbr);
|
||||||
r0 ← SignExtend16(ReadMemory16(address));
|
r0 ← SignExtend16(ReadMemory16(address));
|
||||||
R0 ← Register(r0);
|
R0 ← Register(r0);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
1001nnnndddddddd
|
1001nnnndddddddd
|
||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
disp ← ZeroExtend8(i) << 1;
|
disp ← ZeroExtend8(d) << 1;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
address ← ZeroExtend32(disp + (pc + 4));
|
address ← ZeroExtend32(disp + (pc + 4));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
10000101mmmmdddd
|
10000101mmmmdddd
|
||||||
disp ← ZeroExtend4(i) << 1;
|
disp ← ZeroExtend4(d) << 1;
|
||||||
op2 ← SignExtend32(Rm);
|
op2 ← SignExtend32(Rm);
|
||||||
address ← ZeroExtend32(disp + op2);
|
address ← ZeroExtend32(disp + op2);
|
||||||
r0 ← SignExtend16(ReadMemory16(address));
|
r0 ← SignExtend16(ReadMemory16(address));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
11000001dddddddd
|
11000001dddddddd
|
||||||
gbr ← SignExtend32(GBR);
|
gbr ← SignExtend32(GBR);
|
||||||
r0 ← SignExtend32(R0);
|
r0 ← SignExtend32(R0);
|
||||||
disp ← ZeroExtend8(i) << 1;
|
disp ← ZeroExtend8(d) << 1;
|
||||||
address ← ZeroExtend32(disp + gbr);
|
address ← ZeroExtend32(disp + gbr);
|
||||||
WriteMemory16(address, r0);
|
WriteMemory16(address, r0);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
10000001nnnndddd
|
10000001nnnndddd
|
||||||
r0 ← SignExtend32(R0);
|
r0 ← SignExtend32(R0);
|
||||||
disp ← ZeroExtend4(i) << 1;
|
disp ← ZeroExtend4(d) << 1;
|
||||||
op2 ← SignExtend32(Rn);
|
op2 ← SignExtend32(Rn);
|
||||||
address ← ZeroExtend32(disp + op2);
|
address ← ZeroExtend32(disp + op2);
|
||||||
WriteMemory16(address, r0);
|
WriteMemory16(address, r0);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
11000111dddddddd
|
11000111dddddddd
|
||||||
pc ← SignExtend32(PC);
|
pc ← SignExtend32(PC);
|
||||||
disp ← ZeroExtend8(i) << 2;
|
disp ← ZeroExtend8(d) << 2;
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
r0 ← disp + ((pc + 4) ∧ (~ 0x3));
|
r0 ← disp + ((pc + 4) ∧ (~ 0x3));
|
||||||
|
@ -8,7 +8,7 @@ THROW WTLBMISS, op1;
|
|||||||
IF (MMU() AND WriteProhibited(op1))
|
IF (MMU() AND WriteProhibited(op1))
|
||||||
THROW WRITEPROT, op1;
|
THROW WRITEPROT, op1;
|
||||||
IF (MMU() AND NOT DirtyBit(op1))
|
IF (MMU() AND NOT DirtyBit(op1))
|
||||||
THROW FIRSTWRITE, op1
|
THROW FIRSTWRITE, op1;
|
||||||
ALLOCO(op1);
|
ALLOCO(op1);
|
||||||
address ← ZeroExtend32(op1);
|
address ← ZeroExtend32(op1);
|
||||||
WriteMemory32(op1, r0);
|
WriteMemory32(op1, r0);
|
||||||
|
@ -7,5 +7,5 @@ THROW WTLBMISS, op1;
|
|||||||
IF (MMU() AND WriteProhibited(op1))
|
IF (MMU() AND WriteProhibited(op1))
|
||||||
THROW WRITEPROT, op1;
|
THROW WRITEPROT, op1;
|
||||||
IF (MMU() AND NOT DirtyBit(op1))
|
IF (MMU() AND NOT DirtyBit(op1))
|
||||||
THROW FIRSTWRITE, op1
|
THROW FIRSTWRITE, op1;
|
||||||
OCBI(op1);
|
OCBI(op1);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
0000nnnn10000011
|
0000nnnn10000011
|
||||||
op1 ← SignExtend32(Rn);
|
op1 ← SignExtend32(Rn);
|
||||||
IF (AddressUnavailable(op1))
|
IF (AddressUnavailable(op1))
|
||||||
THROW RADDERR, op1
|
THROW RADDERR, op1;
|
||||||
IF (NOT (MMU() AND DataAccessMiss(op1)))
|
IF (NOT (MMU() AND DataAccessMiss(op1)))
|
||||||
IF (NOT (MMU() AND ReadProhibited(op1)))
|
IF (NOT (MMU() AND ReadProhibited(op1)))
|
||||||
PREF(op1);
|
PREF(op1);
|
||||||
|
3
sh4/RTE
3
sh4/RTE
@ -3,9 +3,10 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
ssr ← SignExtend32(SSR);
|
ssr ← SignExtend32(SSR);
|
||||||
pc ← SignExtend32(PC)
|
pc ← SignExtend32(PC);
|
||||||
IF (IsDelaySlot())
|
IF (IsDelaySlot())
|
||||||
THROW ILLSLOT;
|
THROW ILLSLOT;
|
||||||
target ← pc;
|
target ← pc;
|
||||||
delayedpc ← target ∧ (~ 0x1);
|
delayedpc ← target ∧ (~ 0x1);
|
||||||
PC’’ ← Register(delayedpc);
|
PC’’ ← Register(delayedpc);
|
||||||
|
SR ← Register(ssr);
|
@ -2,4 +2,4 @@
|
|||||||
md ← ZeroExtend1(MD);
|
md ← ZeroExtend1(MD);
|
||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
SLEEP()
|
SLEEP();
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
dbr ← SignExtend32(DBR);
|
dbr ← SignExtend32(DBR);
|
||||||
op1 ← dbr
|
op1 ← dbr;
|
||||||
Rn ← Register(op1);
|
Rn ← Register(op1);
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
sgr ← SignExtend32(SGR);
|
sgr ← SignExtend32(SGR);
|
||||||
op1 ← sgr
|
op1 ← sgr;
|
||||||
Rn ← Register(op1);
|
Rn ← Register(op1);
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
spc ← SignExtend32(SPC);
|
spc ← SignExtend32(SPC);
|
||||||
op1 ← spc
|
op1 ← spc;
|
||||||
Rn ← Register(op1);
|
Rn ← Register(op1);
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
sr ← SignExtend32(SR);
|
sr ← SignExtend32(SR);
|
||||||
op1 ← sr
|
op1 ← sr;
|
||||||
Rn ← Register(op1);
|
Rn ← Register(op1);
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
ssr ← SignExtend32(SSR);
|
ssr ← SignExtend32(SSR);
|
||||||
op1 ← ssr
|
op1 ← ssr;
|
||||||
Rn ← Register(op1);
|
Rn ← Register(op1);
|
||||||
|
@ -3,5 +3,5 @@ md ← ZeroExtend1(MD);
|
|||||||
IF (md = 0)
|
IF (md = 0)
|
||||||
THROW RESINST;
|
THROW RESINST;
|
||||||
vbr ← SignExtend32(VBR);
|
vbr ← SignExtend32(VBR);
|
||||||
op1 ← vbr
|
op1 ← vbr;
|
||||||
Rn ← Register(op1);
|
Rn ← Register(op1);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
0100nnnn00011011
|
0100nnnn00011011
|
||||||
op1 ← SignExtend32(Rn);
|
op1 ← SignExtend32(Rn);
|
||||||
address ← ZeroExtend32(op1);
|
address ← ZeroExtend32(op1);
|
||||||
OCBP(address)
|
OCBP(address);
|
||||||
value ← ZeroExtend8(ReadMemory8(address));
|
value ← ZeroExtend8(ReadMemory8(address));
|
||||||
t ← INT (value = 0);
|
t ← INT (value = 0);
|
||||||
value ← value ∨ (1 << 7);
|
value ← value ∨ (1 << 7);
|
||||||
|
137
syntax.txt
Normal file
137
syntax.txt
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
identifier:
|
||||||
|
identifier-start
|
||||||
|
identifier identifier-continue
|
||||||
|
|
||||||
|
identifier-start:
|
||||||
|
nondigit
|
||||||
|
|
||||||
|
identifier-contine:
|
||||||
|
digit
|
||||||
|
nondigit
|
||||||
|
|
||||||
|
primary-expression:
|
||||||
|
identifier
|
||||||
|
constant
|
||||||
|
"(" expression ")"
|
||||||
|
|
||||||
|
postfix-expression:
|
||||||
|
primary-expression
|
||||||
|
postfix-expression "[" expression "]"
|
||||||
|
postfix-expression "(" argument-expression-list? ")"
|
||||||
|
postfix-expression "<" for-expression ">"
|
||||||
|
postfix-expression "." identifier
|
||||||
|
|
||||||
|
for-expression:
|
||||||
|
primary-expression
|
||||||
|
primary-expression "FOR" primary-expression
|
||||||
|
|
||||||
|
argument-expression-list:
|
||||||
|
assignment-expression
|
||||||
|
argument-expression-list "," assignment-expression
|
||||||
|
|
||||||
|
unary-expression:
|
||||||
|
postfix-expression
|
||||||
|
"NOT" unary-expression
|
||||||
|
"INT" unary-expression
|
||||||
|
"~" unary-expression # bitwise complement
|
||||||
|
"-" unary-expression # integer negation
|
||||||
|
"|" unary-expression "|" # integer absolute value
|
||||||
|
|
||||||
|
multiplicative-expression:
|
||||||
|
unary-expression
|
||||||
|
multiplicative-expression "×" unary-expression
|
||||||
|
multiplicative-expression "/" unary-expression
|
||||||
|
|
||||||
|
additive-expression:
|
||||||
|
multiplicative-expression
|
||||||
|
additive-expression "+" multiplicative-expression
|
||||||
|
additive-expression "-" multiplicative-expression
|
||||||
|
|
||||||
|
shift-expression:
|
||||||
|
additive-expression
|
||||||
|
shift-expression "<<" additive-expression
|
||||||
|
shift-expression ">>" additive-expression
|
||||||
|
|
||||||
|
relational-expression:
|
||||||
|
shift-expression
|
||||||
|
relational-expression "<" shift-expression
|
||||||
|
relational-expression ">" shift-expression
|
||||||
|
relational-expression "≤" shift-expression
|
||||||
|
relational-expression "≥" shift-expression
|
||||||
|
|
||||||
|
equality-expression:
|
||||||
|
relational-expression
|
||||||
|
equality-expression "=" relational-expression
|
||||||
|
equality-expression "≠" relational-expression
|
||||||
|
|
||||||
|
bitwise-AND-expression:
|
||||||
|
equality-expression
|
||||||
|
bitwise-AND-expression "∧" equality-expression
|
||||||
|
|
||||||
|
bitwise-XOR-expression:
|
||||||
|
bitwise-AND-expression
|
||||||
|
bitwise-XOR-expression "⊕" bitwise-AND-expression
|
||||||
|
|
||||||
|
bitwise-OR-expression:
|
||||||
|
bitwise-XOR-expression
|
||||||
|
bitwise-OR-expression "∨" bitwise-XOR-expression
|
||||||
|
|
||||||
|
logical-AND-expression:
|
||||||
|
bitwise-OR-expression
|
||||||
|
logical-AND-expression "AND" bitwise-OR-expression
|
||||||
|
|
||||||
|
logical-XOR-expression:
|
||||||
|
logical-AND-expression
|
||||||
|
logical-XOR-expression "XOR" logical-AND-expression
|
||||||
|
|
||||||
|
logical-OR-expression:
|
||||||
|
logical-XOR-expression
|
||||||
|
logical-OR-expression "OR" logical-XOR-expression
|
||||||
|
|
||||||
|
assignment-list:
|
||||||
|
unary-expression
|
||||||
|
assignment-lhs "," unary-expression
|
||||||
|
|
||||||
|
assignment-expression:
|
||||||
|
logical-OR-expression
|
||||||
|
assignment-list "←" assignment-expression
|
||||||
|
|
||||||
|
expression:
|
||||||
|
assignment-expression
|
||||||
|
|
||||||
|
# statement
|
||||||
|
|
||||||
|
statement:
|
||||||
|
unlabeled-statement
|
||||||
|
|
||||||
|
unlabeled-statement:
|
||||||
|
expression-statement
|
||||||
|
primary-block
|
||||||
|
|
||||||
|
primary-block:
|
||||||
|
compound-statement
|
||||||
|
selection-statement
|
||||||
|
throw-statement
|
||||||
|
|
||||||
|
secondary-block:
|
||||||
|
statement
|
||||||
|
|
||||||
|
compound-statement:
|
||||||
|
"{" block-item-list? "}"
|
||||||
|
|
||||||
|
block-item-list:
|
||||||
|
block-item
|
||||||
|
block-item-list block-item
|
||||||
|
|
||||||
|
block-item:
|
||||||
|
unlabeled-statement
|
||||||
|
|
||||||
|
expression-statement:
|
||||||
|
expression ";"
|
||||||
|
|
||||||
|
selection-statement:
|
||||||
|
"IF" "(" expression ")" secondary-block
|
||||||
|
"IF" "(" expression ")" secondary-block "ELSE" secondary-block
|
||||||
|
|
||||||
|
throw-statement:
|
||||||
|
"THROW" secondary-block
|
40
test_lexer.py
Normal file
40
test_lexer.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from lexer import Lexer, IntegerConstant, Punctuator, Identifier
|
||||||
|
|
||||||
|
def is_instruction_descriptor(s):
|
||||||
|
return all(c in {'0', '1', 'n', 'm', 'i', 'd'} for c in s)
|
||||||
|
|
||||||
|
def parse_file(path):
|
||||||
|
with open(path) as f:
|
||||||
|
buf = f.read()
|
||||||
|
|
||||||
|
lines = buf.split('\n', maxsplit=2)
|
||||||
|
assert len(lines[0]) == 16 and is_instruction_descriptor(lines[0]), lines[0]
|
||||||
|
|
||||||
|
if lines[1].startswith('Available only when'):
|
||||||
|
buf = lines[2]
|
||||||
|
else:
|
||||||
|
if len(lines) >= 3:
|
||||||
|
buf = '\n'.join([lines[1], lines[2]])
|
||||||
|
else:
|
||||||
|
buf = lines[1]
|
||||||
|
|
||||||
|
lexer = Lexer(buf)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
token = lexer.next_token()
|
||||||
|
except IndexError:
|
||||||
|
break
|
||||||
|
yield token
|
||||||
|
|
||||||
|
files = os.listdir('sh4')
|
||||||
|
for filename in files:
|
||||||
|
if filename.startswith('F'):
|
||||||
|
continue
|
||||||
|
path = os.path.join('sh4', filename)
|
||||||
|
for token in parse_file(path):
|
||||||
|
if type(token) is Identifier:
|
||||||
|
print(token.token)
|
42
test_parser.py
Normal file
42
test_parser.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
from lexer import Lexer
|
||||||
|
from parser import Parser
|
||||||
|
from ast_to_c_source import generate
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
"op1 ← FloatValue64(DR2n);",
|
||||||
|
"UTLB[MMUCR.URC].ASID ← PTEH.ASID;",
|
||||||
|
|
||||||
|
"IF (n_field = m_field)"
|
||||||
|
"{"
|
||||||
|
"m_address ← m_address + 4;"
|
||||||
|
"n_address ← n_address + 4;"
|
||||||
|
"}",
|
||||||
|
|
||||||
|
"""
|
||||||
|
IF (op1 ≥ 0)
|
||||||
|
op2 ← op2 << shift_amount;
|
||||||
|
ELSE IF (shift_amount ≠ 0)
|
||||||
|
op2 ← op2 >> (32 - shift_amount);
|
||||||
|
"""
|
||||||
|
]
|
||||||
|
|
||||||
|
def all_tokens(lexer):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
token = lexer.next_token()
|
||||||
|
except IndexError:
|
||||||
|
break
|
||||||
|
yield token
|
||||||
|
|
||||||
|
def dump(source):
|
||||||
|
lexer = Lexer(source)
|
||||||
|
tokens = list(all_tokens(lexer))
|
||||||
|
parser = Parser(tokens)
|
||||||
|
root = parser.statement()
|
||||||
|
pprint(root)
|
||||||
|
|
||||||
|
source = "c ← foobar(b, c, d);"
|
||||||
|
|
||||||
|
dump(source);
|
Loading…
x
Reference in New Issue
Block a user