From 112cab89fca082b1d77b0682f2bd41794370b3e1 Mon Sep 17 00:00:00 2001 From: Test_User Date: Fri, 9 Jun 2023 20:16:53 -0400 Subject: Start making an assembler for this; using python for the intial version --- assembler/hasm.py | 43 +++++++++++++++++++++++++++++++++++++++++++ assembler/syntax.txt | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100755 assembler/hasm.py create mode 100644 assembler/syntax.txt diff --git a/assembler/hasm.py b/assembler/hasm.py new file mode 100755 index 0000000..2eb5fc7 --- /dev/null +++ b/assembler/hasm.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +import os +import sys +import glob + +datadir = os.path.abspath(os.path.dirname(__file__)+"/../cpu") + +paths = glob.glob(datadir+"/instructions/*/*") + +paths.sort() + +instructions = {} + +num_instructions = 0 +for file in paths: + if os.path.isfile(file) and not os.path.basename(file).endswith("notes.txt"): + name = os.path.splitext(os.path.basename(file))[0] + try: + _ = instructions[name] + raise Exception("Instruction name conflict") + except KeyError: + pass + instructions[name] = {"path": file, "id": num_instructions} + num_instructions += 1 + +for ins in instructions: + info = instructions[ins] + f = open(info["path"], "r") + line = f.readline() + f.close() + + header, num = line.rsplit(maxsplit=1) + if header != "Number of parameters:": + print("Unable to read file "+info["path"]+": does not look like an instruction. ignoring...") + + if type(int(num)) != int: + raise Exception("Invalid number: "+num) + + info["params"] = int(num) + +print(instructions) +print(num_instructions) diff --git a/assembler/syntax.txt b/assembler/syntax.txt new file mode 100644 index 0000000..a3bfc9a --- /dev/null +++ b/assembler/syntax.txt @@ -0,0 +1,36 @@ +TODO: possibly simplify this to make it less of a pain to write + +Leading and trailing whitespace is ignored +Comments start with ; and must not be inside "", '', or `` +\ is used for escaping; only applies to ", ', `, and itself when outside of quotations + +Data-at-address is indicated by [value], where value is anything valid to be used as an indirect reference + +Size of operand is specified by a {number} preceeding its reference, and number is to be specified as the size in bytes + +Format for each instruction is , ... + Whitespace here can be any amount of either spaces or tabs + Commas seperating parameters is optional + +Instruction queues are surrounded by { and }: +{ + add a, b, c + add b, a, c +} + +{ and } must be on their own in the line (aside for whitespace and comments) + +Labels are any combination of non-whitespace from the start of the line to a ':', and not followed by any non-comment non-whitespace +Labels must not be declared inside instruction queues +If a label includes { or }, it must start with {, then a number, then }, to be used as its default size; all other uses of these characters are invalid + +Using the value of the label in a parameter will be ':' as the operand, like so: + add a, my_data:, b + jmp {8}[my_data:] + +Constants will have a default size of the minimum amount required to represent it in full, as will labels without a default size explicitly set + +The "declare" keyword is to be used like an instruction, but not within an instruction queue + It will place the following constant's or label's data into the binary output, for an unlimited number of parameters + You may use "" to place the literal value of its contents in the output; \ will only apply to " and itself when within these quotes + You may use `` to place an evaluated string into the output; for example \n will be translated into a newline -- cgit v1.2.3