add non-FPU/UBC/MMU/cache SH4 instructions
Previously, ast transformations were performed informally as ad-hoc modifications to the generated C source code. In this commit, the same transformations are performed by rewriting the ast prior to code generation time. The most significant new transformer is transform_assignment_list. This transforms assignments such as: a, b, c = f(b, c, d) To: a = f(&b, &c, d) The former syntax is used frequently in the manual's description of FPU-related instructions.
This commit is contained in:
parent
8a300ba4c6
commit
ea3c389944
278
ast_to_c_source.py
Normal file
278
ast_to_c_source.py
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
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 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
|
74
bitfield.py
74
bitfield.py
@ -1,74 +0,0 @@
|
|||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
#define FPSCR__RM (1 << 0 ) /* Rounding mode */
|
|
||||||
#define FPSCR__FLAG_INEXACT (1 << 2 )
|
|
||||||
#define FPSCR__FLAG_UNDERFLOW (1 << 3 )
|
|
||||||
#define FPSCR__FLAG_OVERFLOW (1 << 4 )
|
|
||||||
#define FPSCR__FLAG_DIVISION_BY_ZERO (1 << 5 )
|
|
||||||
#define FPSCR__FLAG_INVALID_OPERATION (1 << 6 )
|
|
||||||
#define FPSCR__ENABLE_INEXACT (1 << 7 )
|
|
||||||
#define FPSCR__ENABLE_UNDERFLOW (1 << 8 )
|
|
||||||
#define FPSCR__ENABLE_OVERFLOW (1 << 9 )
|
|
||||||
#define FPSCR__ENABLE_DIVISION_BY_ZERO (1 << 10)
|
|
||||||
#define FPSCR__ENABLE_INVALID (1 << 11)
|
|
||||||
#define FPSCR__CAUSE_INEXACT (1 << 12)
|
|
||||||
#define FPSCR__CAUSE_UNDERFLOW (1 << 13)
|
|
||||||
#define FPSCR__CAUSE_OVERFLOW (1 << 14)
|
|
||||||
#define FPSCR__CAUSE_DIVISION_BY_ZERO (1 << 15)
|
|
||||||
#define FPSCR__CAUSE_INVALID (1 << 16)
|
|
||||||
#define FPSCR__CAUSE_FPU_ERROR (1 << 17)
|
|
||||||
#define FPSCR__DN (1 << 18) /* Denormalization mode */
|
|
||||||
#define FPSCR__PR (1 << 19) /* Precision mode */
|
|
||||||
#define FPSCR__SZ (1 << 20) /* Transfer size mode */
|
|
||||||
#define FPSCR__FR (1 << 21) /* 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 "#pragma once"
|
|
||||||
yield ""
|
|
||||||
yield "#include <stdint.h>"
|
|
||||||
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 "};"
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print('\n'.join(generate("sr_bits", sr_bits)))
|
|
4
build.sh
4
build.sh
@ -1,3 +1,3 @@
|
|||||||
PYTHONPATH=python/ python transform.py c/impl.c c/impl.h
|
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_decoder.py c/decode_execute.c c/decode_print.c
|
||||||
PYTHONPATH=python/ python bitfield.py > c/sr_bits.h
|
PYTHONPATH=python/ python generate_bits.py > c/status_bits.h
|
||||||
|
@ -321,6 +321,20 @@ enum decode_status decode_and_execute_instruction(struct architectural_state * s
|
|||||||
addv__source_and_destination_operands(state, map, m, n);
|
addv__source_and_destination_operands(state, map, m, n);
|
||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
|
case 0b0100000000001100: // SHAD Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shad__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001101: // SHLD Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
shld__source_and_destination_operands(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
case 0b0100000000001111: // MAC.W @Rm+,@Rn+
|
case 0b0100000000001111: // MAC.W @Rm+,@Rn+
|
||||||
{
|
{
|
||||||
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
@ -652,6 +666,42 @@ enum decode_status decode_and_execute_instruction(struct architectural_state * s
|
|||||||
sts__transfer_from_pr(state, map, n);
|
sts__transfer_from_pr(state, map, n);
|
||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
|
case 0b0000000000110010: // STC SSR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_ssr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000111010: // STC SGR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_sgr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001000010: // STC SPC,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_spc(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001011010: // STS FPUL,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts__transfer_from_fpul(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001101010: // STS FPSCR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts__transfer_from_fpscr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000011111010: // STC DBR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_dbr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
case 0b0100000000000000: // SHLL Rn
|
case 0b0100000000000000: // SHLL Rn
|
||||||
{
|
{
|
||||||
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
@ -880,6 +930,102 @@ enum decode_status decode_and_execute_instruction(struct architectural_state * s
|
|||||||
ldc__transfer_to_vbr(state, map, m);
|
ldc__transfer_to_vbr(state, map, m);
|
||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
|
case 0b0100000000110010: // STC.L SGR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_sgr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000110011: // STC.L SSR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_ssr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000110111: // LDC.L @Rm+,SSR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc_l__load_to_ssr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000111110: // LDC Rm,SSR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc__transfer_to_ssr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001000011: // STC.L SPC,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_spc(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001000111: // LDC.L @Rm+,SPC
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc_l__load_to_spc(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001001110: // LDC Rm,SPC
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc__transfer_to_spc(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001010010: // STS.L FPUL,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts_l__store_from_fpul(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001010110: // LDS.L @Rm+,FPUL
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds_l__load_to_fpul(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001011010: // LDS Rm,FPUL
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds__transfer_to_fpul(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001100010: // STS.L FPSCR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
sts_l__store_from_fpscr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001100110: // LDS.L @Rm+,FPSCR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds_l__load_to_fpscr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001101010: // LDS Rm,FPSCR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
lds__transfer_to_fpscr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000011110010: // STC.L DBR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_dbr(state, map, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000011110110: // LDC.L @Rm+,DBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc_l__load_to_dbr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000011111010: // LDC Rm,DBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
ldc__transfer_to_dbr(state, map, m);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (code & 0b1111111111111111) {
|
switch (code & 0b1111111111111111) {
|
||||||
case 0b0000000000001000: // CLRT
|
case 0b0000000000001000: // CLRT
|
||||||
@ -933,5 +1079,35 @@ enum decode_status decode_and_execute_instruction(struct architectural_state * s
|
|||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
switch (code & 0b1111000010001111) {
|
||||||
|
case 0b0000000010000010: // STC Rm_BANK,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc__transfer_from_rm_bank(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000010000011: // STC.L Rm_BANK,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
stc_l__store_from_rm_bank(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000010000111: // LDC.L @Rm+,Rn_BANK
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
ldc_l__load_to_rn_bank(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000010001110: // LDC Rm,Rn_BANK
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
ldc__transfer_to_rn_bank(state, map, m, n);
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
return DECODE__UNDEFINED;
|
return DECODE__UNDEFINED;
|
||||||
}
|
}
|
||||||
|
204
c/decode_print.c
204
c/decode_print.c
@ -367,6 +367,22 @@ enum decode_status decode_and_print_instruction(struct architectural_state * sta
|
|||||||
*instruction_buf = "ADDV";
|
*instruction_buf = "ADDV";
|
||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
|
case 0b0100000000001100: // SHAD Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,R%d", m, n);
|
||||||
|
*instruction_buf = "SHAD";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000001101: // SHLD Rm,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,R%d", m, n);
|
||||||
|
*instruction_buf = "SHLD";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
case 0b0100000000001111: // MAC.W @Rm+,@Rn+
|
case 0b0100000000001111: // MAC.W @Rm+,@Rn+
|
||||||
{
|
{
|
||||||
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
uint32_t m = (code >> 4) & ((1 << 4) - 1);
|
||||||
@ -749,6 +765,48 @@ enum decode_status decode_and_print_instruction(struct architectural_state * sta
|
|||||||
*instruction_buf = "STS";
|
*instruction_buf = "STS";
|
||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
|
case 0b0000000000110010: // STC SSR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "SSR,R%d", n);
|
||||||
|
*instruction_buf = "STC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000000111010: // STC SGR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "SGR,R%d", n);
|
||||||
|
*instruction_buf = "STC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001000010: // STC SPC,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "SPC,R%d", n);
|
||||||
|
*instruction_buf = "STC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001011010: // STS FPUL,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "FPUL,R%d", n);
|
||||||
|
*instruction_buf = "STS";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000001101010: // STS FPSCR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "FPSCR,R%d", n);
|
||||||
|
*instruction_buf = "STS";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0000000011111010: // STC DBR,Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "DBR,R%d", n);
|
||||||
|
*instruction_buf = "STC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
case 0b0100000000000000: // SHLL Rn
|
case 0b0100000000000000: // SHLL Rn
|
||||||
{
|
{
|
||||||
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
@ -1015,6 +1073,118 @@ enum decode_status decode_and_print_instruction(struct architectural_state * sta
|
|||||||
*instruction_buf = "LDC";
|
*instruction_buf = "LDC";
|
||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
|
case 0b0100000000110010: // STC.L SGR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "SGR,@-R%d", n);
|
||||||
|
*instruction_buf = "STC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000110011: // STC.L SSR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "SSR,@-R%d", n);
|
||||||
|
*instruction_buf = "STC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000110111: // LDC.L @Rm+,SSR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "@R%d+,SSR", m);
|
||||||
|
*instruction_buf = "LDC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000000111110: // LDC Rm,SSR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,SSR", m);
|
||||||
|
*instruction_buf = "LDC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001000011: // STC.L SPC,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "SPC,@-R%d", n);
|
||||||
|
*instruction_buf = "STC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001000111: // LDC.L @Rm+,SPC
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "@R%d+,SPC", m);
|
||||||
|
*instruction_buf = "LDC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001001110: // LDC Rm,SPC
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,SPC", m);
|
||||||
|
*instruction_buf = "LDC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001010010: // STS.L FPUL,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "FPUL,@-R%d", n);
|
||||||
|
*instruction_buf = "STS.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001010110: // LDS.L @Rm+,FPUL
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "@R%d+,FPUL", m);
|
||||||
|
*instruction_buf = "LDS.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001011010: // LDS Rm,FPUL
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,FPUL", m);
|
||||||
|
*instruction_buf = "LDS";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001100010: // STS.L FPSCR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "FPSCR,@-R%d", n);
|
||||||
|
*instruction_buf = "STS.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001100110: // LDS.L @Rm+,FPSCR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "@R%d+,FPSCR", m);
|
||||||
|
*instruction_buf = "LDS.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000001101010: // LDS Rm,FPSCR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,FPSCR", m);
|
||||||
|
*instruction_buf = "LDS";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000011110010: // STC.L DBR,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "DBR,@-R%d", n);
|
||||||
|
*instruction_buf = "STC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000011110110: // LDC.L @Rm+,DBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "@R%d+,DBR", m);
|
||||||
|
*instruction_buf = "LDC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000011111010: // LDC Rm,DBR
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,DBR", m);
|
||||||
|
*instruction_buf = "LDC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (code & 0b1111111111111111) {
|
switch (code & 0b1111111111111111) {
|
||||||
case 0b0000000000001000: // CLRT
|
case 0b0000000000001000: // CLRT
|
||||||
@ -1078,5 +1248,39 @@ enum decode_status decode_and_print_instruction(struct architectural_state * sta
|
|||||||
return DECODE__DEFINED;
|
return DECODE__DEFINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
switch (code & 0b1111000010001111) {
|
||||||
|
case 0b0000000010000010: // STC Rm_BANK,Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d_BANK,R%d", m, n);
|
||||||
|
*instruction_buf = "STC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000010000011: // STC.L Rm_BANK,@-Rn
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
uint32_t n = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d_BANK,@-R%d", m, n);
|
||||||
|
*instruction_buf = "STC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000010000111: // LDC.L @Rm+,Rn_BANK
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
snprintf(operand_buf, size, "@R%d+,R%d_BANK", m, n);
|
||||||
|
*instruction_buf = "LDC.L";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
case 0b0100000010001110: // LDC Rm,Rn_BANK
|
||||||
|
{
|
||||||
|
uint32_t m = (code >> 8) & ((1 << 4) - 1);
|
||||||
|
uint32_t n = (code >> 4) & ((1 << 3) - 1);
|
||||||
|
snprintf(operand_buf, size, "R%d,R%d_BANK", m, n);
|
||||||
|
*instruction_buf = "LDC";
|
||||||
|
return DECODE__DEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
return DECODE__UNDEFINED;
|
return DECODE__UNDEFINED;
|
||||||
}
|
}
|
||||||
|
58
c/impl.h
58
c/impl.h
@ -183,10 +183,14 @@ void rotr__destination_operand_only(struct architectural_state * state, struct m
|
|||||||
void rotcl__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void rotcl__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* ROTCR Rn */
|
/* ROTCR Rn */
|
||||||
void rotcr__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
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 */
|
/* SHAL Rn */
|
||||||
void shal__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void shal__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* SHAR Rn */
|
/* SHAR Rn */
|
||||||
void shar__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
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 */
|
/* SHLL Rn */
|
||||||
void shll__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void shll__destination_operand_only(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* SHLR Rn */
|
/* SHLR Rn */
|
||||||
@ -237,12 +241,28 @@ void ldc__transfer_to_sr(struct architectural_state * state, struct memory_map *
|
|||||||
void ldc__transfer_to_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
void ldc__transfer_to_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
/* LDC Rm,VBR */
|
/* LDC Rm,VBR */
|
||||||
void ldc__transfer_to_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
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 */
|
/* LDC.L @Rm+,SR */
|
||||||
void ldc_l__load_to_sr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
void ldc_l__load_to_sr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
/* LDC.L @Rm+,GBR */
|
/* LDC.L @Rm+,GBR */
|
||||||
void ldc_l__load_to_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
void ldc_l__load_to_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
/* LDC.L @Rm+,VBR */
|
/* LDC.L @Rm+,VBR */
|
||||||
void ldc_l__load_to_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
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 */
|
/* LDS Rm,MACH */
|
||||||
void lds__transfer_to_mach(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
void lds__transfer_to_mach(struct architectural_state * state, struct memory_map * map, const uint32_t m);
|
||||||
/* LDS Rm,MACL */
|
/* LDS Rm,MACL */
|
||||||
@ -271,12 +291,32 @@ void stc__transfer_from_sr(struct architectural_state * state, struct memory_map
|
|||||||
void stc__transfer_from_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void stc__transfer_from_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* STC VBR,Rn */
|
/* STC VBR,Rn */
|
||||||
void stc__transfer_from_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
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 */
|
/* STC.L SR,@-Rn */
|
||||||
void stc_l__store_from_sr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void stc_l__store_from_sr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* STC.L GBR,@-Rn */
|
/* STC.L GBR,@-Rn */
|
||||||
void stc_l__store_from_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void stc_l__store_from_gbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* STC.L VBR,@-Rn */
|
/* STC.L VBR,@-Rn */
|
||||||
void stc_l__store_from_vbr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
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 */
|
/* STS MACH,Rn */
|
||||||
void sts__transfer_from_mach(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void sts__transfer_from_mach(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* STS MACL,Rn */
|
/* STS MACL,Rn */
|
||||||
@ -290,4 +330,20 @@ void sts_l__store_from_macl(struct architectural_state * state, struct memory_ma
|
|||||||
/* STS.L PR,@-Rn */
|
/* STS.L PR,@-Rn */
|
||||||
void sts_l__store_from_pr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
void sts_l__store_from_pr(struct architectural_state * state, struct memory_map * map, const uint32_t n);
|
||||||
/* TRAPA #imm */
|
/* TRAPA #imm */
|
||||||
void trapa__immediate(struct architectural_state * state, struct memory_map * map, const uint32_t i);
|
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);
|
@ -64,6 +64,11 @@ static inline uint32_t zero_extend8(uint32_t x)
|
|||||||
return zero_extend(x, 8);
|
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)
|
static inline uint32_t zero_extend4(uint32_t x)
|
||||||
{
|
{
|
||||||
return zero_extend(x, 4);
|
return zero_extend(x, 4);
|
||||||
|
39
c/sr_bits.h
39
c/sr_bits.h
@ -1,39 +0,0 @@
|
|||||||
#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
|
|
||||||
};
|
|
32
c/state.h
32
c/state.h
@ -4,7 +4,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "sr_bits.h"
|
#include "status_bits.h"
|
||||||
|
|
||||||
#define SR__RB (1 << 29)
|
#define SR__RB (1 << 29)
|
||||||
#define SR__MD (1 << 30)
|
#define SR__MD (1 << 30)
|
||||||
@ -33,6 +33,29 @@ 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, 8 ) == 8 );
|
||||||
static_assert(REGN_BANK(SR__MD | SR__RB, 15) == 15);
|
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 {
|
struct architectural_state {
|
||||||
uint32_t general_register[24];
|
uint32_t general_register[24];
|
||||||
|
|
||||||
@ -41,7 +64,10 @@ struct architectural_state {
|
|||||||
uint32_t macl;
|
uint32_t macl;
|
||||||
uint32_t pr[3];
|
uint32_t pr[3];
|
||||||
uint32_t pc[3];
|
uint32_t pc[3];
|
||||||
uint32_t fpscr;
|
union {
|
||||||
|
struct fpscr_bits bits;
|
||||||
|
uint32_t value;
|
||||||
|
} fpscr;
|
||||||
uint32_t fpul;
|
uint32_t fpul;
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -58,7 +84,7 @@ struct architectural_state {
|
|||||||
uint32_t dbr;
|
uint32_t dbr;
|
||||||
//
|
//
|
||||||
|
|
||||||
uint32_t floating_point_register[32];
|
union floating_point_registers floating_point_register;
|
||||||
|
|
||||||
bool is_delay_slot;
|
bool is_delay_slot;
|
||||||
};
|
};
|
||||||
|
@ -5,12 +5,28 @@
|
|||||||
|
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
#include "status_bits.h"
|
||||||
|
|
||||||
static inline bool is_delay_slot(struct architectural_state * state)
|
static inline bool is_delay_slot(struct architectural_state * state)
|
||||||
{
|
{
|
||||||
return state->is_delay_slot;
|
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 sleep(struct architectural_state * state)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
92
c/status_bits.h
Normal file
92
c/status_bits.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#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 q : 1;
|
||||||
|
uint32_t m : 1;
|
||||||
|
uint32_t _res1 : 5;
|
||||||
|
uint32_t fd : 1;
|
||||||
|
uint32_t _res2 : 12;
|
||||||
|
uint32_t bl : 1;
|
||||||
|
uint32_t rb : 1;
|
||||||
|
uint32_t md : 1;
|
||||||
|
uint32_t _res3 : 1;
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
uint32_t _res3 : 1;
|
||||||
|
uint32_t md : 1;
|
||||||
|
uint32_t rb : 1;
|
||||||
|
uint32_t bl : 1;
|
||||||
|
uint32_t _res2 : 12;
|
||||||
|
uint32_t fd : 1;
|
||||||
|
uint32_t _res1 : 5;
|
||||||
|
uint32_t m : 1;
|
||||||
|
uint32_t q : 1;
|
||||||
|
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 : 2;
|
||||||
|
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 _res0 : 10;
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
uint32_t _res0 : 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 rm : 2;
|
||||||
|
#else
|
||||||
|
# error "unsupported endianness"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
38
disabled_instructions.py
Normal file
38
disabled_instructions.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
disabled_instructions = [
|
||||||
|
"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",
|
||||||
|
]
|
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, 2), # 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 + length
|
||||||
|
|
||||||
|
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)))
|
@ -6,6 +6,8 @@ from instruction_table import untabulate_instructions_sh2
|
|||||||
from instruction_function_name import instruction_function_name
|
from instruction_function_name import instruction_function_name
|
||||||
from generate import renderer
|
from generate import renderer
|
||||||
|
|
||||||
|
from disabled_instructions import disabled_instructions
|
||||||
|
|
||||||
def b16(n):
|
def b16(n):
|
||||||
bits = []
|
bits = []
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
@ -83,9 +85,8 @@ def main():
|
|||||||
by_mask = defaultdict(list)
|
by_mask = defaultdict(list)
|
||||||
masks = []
|
masks = []
|
||||||
|
|
||||||
sh2_instructions = set((ins.instruction, ins.operands) for ins in untabulate_instructions_sh2())
|
|
||||||
for ins in untabulate_instructions_sh4():
|
for ins in untabulate_instructions_sh4():
|
||||||
if (ins.instruction, ins.operands) not in sh2_instructions:
|
if ins.instruction in disabled_instructions:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if ins.code.mask_bits not in masks:
|
if ins.code.mask_bits not in masks:
|
||||||
|
@ -3,7 +3,8 @@ import os
|
|||||||
|
|
||||||
from lexer import Lexer
|
from lexer import Lexer
|
||||||
from parser import Parser
|
from parser import Parser
|
||||||
from generator import generate, CTX
|
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_sh4
|
||||||
from instruction_table import untabulate_instructions_sh2
|
from instruction_table import untabulate_instructions_sh2
|
||||||
@ -11,6 +12,8 @@ from instruction_function_name import instruction_function_name
|
|||||||
from instruction_file_name import instruction_file_name
|
from instruction_file_name import instruction_file_name
|
||||||
from instruction_properties import has_delay_slot
|
from instruction_properties import has_delay_slot
|
||||||
|
|
||||||
|
from disabled_instructions import disabled_instructions
|
||||||
|
|
||||||
def is_instruction_descriptor(s):
|
def is_instruction_descriptor(s):
|
||||||
return all(c in {'0', '1', 'n', 'm', 'i', 'd'} for c in s)
|
return all(c in {'0', '1', 'n', 'm', 'i', 'd'} for c in s)
|
||||||
|
|
||||||
@ -52,17 +55,20 @@ def generate_function_declaration(instruction_name, function_name, variables):
|
|||||||
yield f"void {function_name}({args})"
|
yield f"void {function_name}({args})"
|
||||||
|
|
||||||
def generate_file(instruction_name, function_name, variables, delay_slot, src_path):
|
def generate_file(instruction_name, function_name, variables, delay_slot, src_path):
|
||||||
|
print(instruction_name)
|
||||||
tokens = list(parse_file(src_path))
|
tokens = list(parse_file(src_path))
|
||||||
parser = Parser(tokens)
|
parser = Parser(tokens)
|
||||||
|
statements = []
|
||||||
|
while parser.tokens[parser.pos:]:
|
||||||
|
statements.append(parser.statement())
|
||||||
|
|
||||||
ctx = CTX(identifiers=set())
|
statements = transform_statements(statements)
|
||||||
|
|
||||||
yield from generate_function_declaration(instruction_name, function_name, variables)
|
yield from generate_function_declaration(instruction_name, function_name, variables)
|
||||||
yield "{"
|
yield "{"
|
||||||
output = []
|
output = []
|
||||||
while parser.tokens[parser.pos:]:
|
for statement in statements:
|
||||||
stmt = parser.statement()
|
src = "".join(generate(statement))
|
||||||
src = "".join(generate(ctx, stmt))
|
|
||||||
output.append(src)
|
output.append(src)
|
||||||
|
|
||||||
for line in "".join(output).rstrip().split('\n'):
|
for line in "".join(output).rstrip().split('\n'):
|
||||||
@ -90,10 +96,10 @@ def main():
|
|||||||
'',
|
'',
|
||||||
]
|
]
|
||||||
|
|
||||||
sh2_instructions = set((ins.instruction, ins.operands) for ins in untabulate_instructions_sh2())
|
|
||||||
for ins in untabulate_instructions_sh4():
|
for ins in untabulate_instructions_sh4():
|
||||||
if (ins.instruction, ins.operands) not in sh2_instructions:
|
if ins.instruction in disabled_instructions:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
_name = [ins.instruction, ins.operands] if ins.operands else [ins.instruction]
|
_name = [ins.instruction, ins.operands] if ins.operands else [ins.instruction]
|
||||||
instruction_name = " ".join(_name)
|
instruction_name = " ".join(_name)
|
||||||
function_name = instruction_function_name(ins)
|
function_name = instruction_function_name(ins)
|
301
generator.py
301
generator.py
@ -1,301 +0,0 @@
|
|||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
from parser import Tree
|
|
||||||
from lexer import Identifier, Punctuator, IntegerConstant
|
|
||||||
import identifier_substitution
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CTX:
|
|
||||||
identifiers: set
|
|
||||||
|
|
||||||
def argument_list(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ", "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def _is_new_temporary(ctx, tree):
|
|
||||||
return (
|
|
||||||
type(tree) is Identifier
|
|
||||||
and tree.token not in identifier_substitution.mapping
|
|
||||||
and tree.token not in ctx.identifiers
|
|
||||||
)
|
|
||||||
|
|
||||||
def assignment(ctx, tree):
|
|
||||||
lhs = tree.children[0]
|
|
||||||
rhs = tree.children[1]
|
|
||||||
if _is_new_temporary(ctx, lhs):
|
|
||||||
ctx.identifiers.add(lhs.token)
|
|
||||||
yield "int64_t "
|
|
||||||
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " = "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def bit_extraction(ctx, tree):
|
|
||||||
yield "bit_extract("
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ", "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
yield ")"
|
|
||||||
|
|
||||||
def bitwise_and(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " & "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def bitwise_or(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " | "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def bitwise_xor(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " ^ "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def block_item_list(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def compound_statement(ctx, tree):
|
|
||||||
yield "\n{\n"
|
|
||||||
if tree.children:
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield "}\n"
|
|
||||||
|
|
||||||
def expression_statement(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ";\n"
|
|
||||||
|
|
||||||
def for_expression(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ", "
|
|
||||||
if len(tree.children) > 1:
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
else:
|
|
||||||
yield "1"
|
|
||||||
|
|
||||||
def helper_arguments(tree):
|
|
||||||
if type(tree.children[0]) is not Identifier:
|
|
||||||
return
|
|
||||||
name = tree.children[0].token
|
|
||||||
mapping = {
|
|
||||||
"IsDelaySlot": "state",
|
|
||||||
"SLEEP": "state",
|
|
||||||
"OCBP" : "state",
|
|
||||||
"WriteMemory8" : "map",
|
|
||||||
"WriteMemory16": "map",
|
|
||||||
"WriteMemory32": "map",
|
|
||||||
"ReadMemory8" : "map",
|
|
||||||
"ReadMemory16" : "map",
|
|
||||||
"ReadMemory32" : "map",
|
|
||||||
}
|
|
||||||
return mapping.get(name, None)
|
|
||||||
|
|
||||||
def function_call(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield "("
|
|
||||||
if len(tree.children) >= 2:
|
|
||||||
if helper_arguments(tree):
|
|
||||||
yield helper_arguments(tree)
|
|
||||||
yield ", "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
else:
|
|
||||||
if helper_arguments(tree):
|
|
||||||
yield helper_arguments(tree)
|
|
||||||
yield ")"
|
|
||||||
|
|
||||||
def grouping(ctx, tree):
|
|
||||||
yield "("
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ")"
|
|
||||||
|
|
||||||
def _if(ctx, tree):
|
|
||||||
yield "if ("
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ") "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def if_else(ctx, tree):
|
|
||||||
yield "if ("
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ") "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
yield "else "
|
|
||||||
yield from generate(ctx, tree.children[2])
|
|
||||||
|
|
||||||
def logical_and(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " && "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def logical_or(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " || "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def member(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield "."
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def subscript(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield "["
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
yield "]"
|
|
||||||
|
|
||||||
def throw(ctx, tree):
|
|
||||||
yield "return "
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield "(state);\n"
|
|
||||||
|
|
||||||
def throw_arg(ctx, tree):
|
|
||||||
yield "return "
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield "(state, "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
yield ");\n"
|
|
||||||
|
|
||||||
def unary_complement(ctx, tree):
|
|
||||||
yield from "~"
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
|
|
||||||
def unary_int(ctx, tree):
|
|
||||||
yield "unary_int("
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield ")"
|
|
||||||
|
|
||||||
def unary_negation(ctx, tree):
|
|
||||||
yield "-"
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
|
|
||||||
def unary_not(ctx, tree):
|
|
||||||
yield "!"
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
|
|
||||||
#
|
|
||||||
def addition(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " + "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def division(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " / "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def equality_equal(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " == "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def equality_not_equal(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " != "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def greater_than(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " > "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def greater_than_equal(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " >= "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def left_shift(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
# hack for left shift by LHS constant
|
|
||||||
if type(tree.children[0]) is IntegerConstant:
|
|
||||||
yield "LL"
|
|
||||||
yield " << "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def less_than(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " < "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def less_than_equal(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " <= "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def multiplication(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " * "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def right_shift(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " >> "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def subtraction(ctx, tree):
|
|
||||||
yield from generate(ctx, tree.children[0])
|
|
||||||
yield " - "
|
|
||||||
yield from generate(ctx, tree.children[1])
|
|
||||||
|
|
||||||
def identifier(ctx, token):
|
|
||||||
if token.token in identifier_substitution.mapping:
|
|
||||||
yield identifier_substitution.mapping[token.token]
|
|
||||||
else:
|
|
||||||
assert token.token.lower() == token.token, token
|
|
||||||
if token.token not in {'m', 'n', 'i', 'd'}:
|
|
||||||
assert token.token in ctx.identifiers, (token, ctx.identifiers)
|
|
||||||
yield token.token
|
|
||||||
|
|
||||||
def constant(ctx, elem):
|
|
||||||
yield elem.token.lower()
|
|
||||||
|
|
||||||
def generate(ctx, elem):
|
|
||||||
mapping = {
|
|
||||||
"argument_list": argument_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,
|
|
||||||
#
|
|
||||||
}
|
|
||||||
if type(elem) is Tree:
|
|
||||||
yield from mapping[elem.operation](ctx, elem)
|
|
||||||
elif type(elem) is Identifier:
|
|
||||||
yield from identifier(ctx, elem)
|
|
||||||
elif type(elem) is IntegerConstant:
|
|
||||||
yield from constant(ctx, elem)
|
|
||||||
else:
|
|
||||||
assert False, type(elem)
|
|
@ -28,7 +28,7 @@ mapping = {
|
|||||||
"PC" : "state->pc[0]",
|
"PC" : "state->pc[0]",
|
||||||
"PC’" : "state->pc[1]",
|
"PC’" : "state->pc[1]",
|
||||||
"PC’’" : "state->pc[2]",
|
"PC’’" : "state->pc[2]",
|
||||||
"FPSCR" : "state->fpscr",
|
"FPSCR" : "state->fpscr.value",
|
||||||
"FPUL" : "state->fpul",
|
"FPUL" : "state->fpul",
|
||||||
|
|
||||||
"SR" : "state->sr.value",
|
"SR" : "state->sr.value",
|
||||||
@ -71,37 +71,111 @@ mapping = {
|
|||||||
"IsDelaySlot" : "is_delay_slot",
|
"IsDelaySlot" : "is_delay_slot",
|
||||||
"SLEEP" : "sleep",
|
"SLEEP" : "sleep",
|
||||||
"OCBP" : "ocbp",
|
"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",
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
|
||||||
ASID
|
|
||||||
VPN
|
|
||||||
PPN
|
|
||||||
SZ
|
|
||||||
SZ0
|
|
||||||
SZ1
|
|
||||||
SH
|
|
||||||
PR
|
|
||||||
WT
|
|
||||||
C
|
|
||||||
D
|
|
||||||
V
|
|
||||||
|
|
||||||
AddressUnavailable
|
|
||||||
ALLOCO
|
|
||||||
DataAccessMiss
|
|
||||||
DirtyBit
|
|
||||||
FpuIsDisabled
|
|
||||||
IsDelaySlot
|
|
||||||
MMU
|
|
||||||
MMUCR
|
|
||||||
OCBI
|
|
||||||
OCBWB
|
|
||||||
PREF
|
|
||||||
PTEH
|
|
||||||
PTEL
|
|
||||||
ReadProhibited
|
|
||||||
URC
|
|
||||||
UTLB
|
|
||||||
WriteProhibited
|
|
||||||
"""
|
|
||||||
|
15
parser.py
15
parser.py
@ -337,10 +337,23 @@ class Parser:
|
|||||||
)
|
)
|
||||||
return expr
|
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):
|
def assignment_expression(self):
|
||||||
backtrack = self.pos
|
backtrack = self.pos
|
||||||
try:
|
try:
|
||||||
left = self.unary_expression()
|
left = self.assignment_list()
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
self.pos = backtrack
|
self.pos = backtrack
|
||||||
return self.logical_or_expression()
|
return self.logical_or_expression()
|
||||||
|
@ -88,9 +88,13 @@ logical-OR-expression:
|
|||||||
logical-XOR-expression
|
logical-XOR-expression
|
||||||
logical-OR-expression "OR" logical-XOR-expression
|
logical-OR-expression "OR" logical-XOR-expression
|
||||||
|
|
||||||
|
assignment-list:
|
||||||
|
unary-expression
|
||||||
|
assignment-lhs "," unary-expression
|
||||||
|
|
||||||
assignment-expression:
|
assignment-expression:
|
||||||
logical-OR-expression
|
logical-OR-expression
|
||||||
unary-expression "←" assignment-expression
|
assignment-list "←" assignment-expression
|
||||||
|
|
||||||
expression:
|
expression:
|
||||||
assignment-expression
|
assignment-expression
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
from pprint import pprint
|
||||||
|
|
||||||
from lexer import Lexer
|
from lexer import Lexer
|
||||||
from parser import Parser
|
from parser import Parser
|
||||||
from generator import generate
|
from ast_to_c_source import generate
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
"op1 ← FloatValue64(DR2n);",
|
"op1 ← FloatValue64(DR2n);",
|
||||||
@ -28,12 +30,13 @@ def all_tokens(lexer):
|
|||||||
break
|
break
|
||||||
yield token
|
yield token
|
||||||
|
|
||||||
for source in sources:
|
def dump(source):
|
||||||
lexer = Lexer(source)
|
lexer = Lexer(source)
|
||||||
tokens = list(all_tokens(lexer))
|
tokens = list(all_tokens(lexer))
|
||||||
parser = Parser(tokens)
|
parser = Parser(tokens)
|
||||||
from pprint import pprint
|
|
||||||
root = parser.statement()
|
root = parser.statement()
|
||||||
s = "".join(generate(root))
|
pprint(root)
|
||||||
print(s, end='')
|
|
||||||
print()
|
source = "c ← foobar(b, c, d);"
|
||||||
|
|
||||||
|
dump(source);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user