Skip to content

Commit

Permalink
Merge pull request #83 from craigthomas/multi-fdb-declaration
Browse files Browse the repository at this point in the history
Allow for multi-word declarations
  • Loading branch information
craigthomas committed Oct 9, 2022
2 parents 9fb0757 + f17539a commit 6f58550
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ as well as the number of cycles used to execute each operation.
|-----------|----------------------------------------------------------------------------|-----------------------|
| `FCB` | Defines a byte constant value. Separate multiple bytes with `,`. | `FCB $1C,$AA` |
| `FCC` | Defines a string constant value enclosed in a matching pair of delimiters. | `FCC "hello"` |
| `FDB` | Defines a two byte constant value. | `FDB $2000` |
| `FDB` | Defines a word constant value. Separate multiple word with `,`. | `FDB $2000,$CAFE` |
| `END` | Defines the end of the program. | `END` |
| `EQU` | Defines a symbol with a set value. | `SCRMEM EQU $1000` |
| `INCLUDE` | Includes another assembly source file at this location. | `INCLUDE globals.asm` |
Expand Down
3 changes: 2 additions & 1 deletion cocoasm/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class Instruction(NamedTuple):
is_16_bit: bool = False
is_lea: bool = False
is_multi_byte: bool = False
is_multi_word: bool = False


INSTRUCTIONS = [
Expand Down Expand Up @@ -236,7 +237,7 @@ class Instruction(NamedTuple):
Instruction(mnemonic="SET", is_pseudo=True),
Instruction(mnemonic="RMB", is_pseudo=True),
Instruction(mnemonic="FCB", is_pseudo=True, is_multi_byte=True),
Instruction(mnemonic="FDB", is_pseudo=True),
Instruction(mnemonic="FDB", is_pseudo=True, is_multi_word=True),
Instruction(mnemonic="FCC", is_pseudo=True, is_string_define=True),
Instruction(mnemonic="SETDP", is_pseudo=True),
Instruction(mnemonic="INCLUDE", is_pseudo=True, is_include=True),
Expand Down
15 changes: 13 additions & 2 deletions cocoasm/operands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

from abc import ABC, abstractmethod

from cocoasm.values import NoneValue, Value, NumericValue, DirectNumericValue, ExtendedNumericValue, MultiByteValue
from cocoasm.values import NoneValue, Value, NumericValue, DirectNumericValue, ExtendedNumericValue, MultiByteValue, \
MultiWordValue
from cocoasm.instruction import CodePackage
from cocoasm.operand_type import OperandType
from cocoasm.exceptions import OperandTypeError, ValueTypeError
Expand Down Expand Up @@ -190,6 +191,8 @@ def __init__(self, operand_string, instruction):
raise OperandTypeError("[{}] is not a pseudo instruction".format(instruction.mnemonic))
if instruction.is_multi_byte:
self.value = MultiByteValue(operand_string) if "," in operand_string else Value.create_from_str(operand_string, instruction)
elif instruction.is_multi_word:
self.value = MultiWordValue(operand_string) if "," in operand_string else Value.create_from_str(operand_string, instruction)
else:
self.value = NoneValue() if instruction.is_include else Value.create_from_str(operand_string, instruction)

Expand All @@ -215,7 +218,15 @@ def translate(self):
)

if self.instruction.mnemonic == "FDB":
return CodePackage(additional=NumericValue(self.value.int, size_hint=4), size=2, max_size=2)
return CodePackage(
additional=self.value,
size=self.value.byte_len(),
max_size=self.value.byte_len()
) if self.value.is_multi_word() else CodePackage(
additional=NumericValue(self.value.int, size_hint=4),
size=2,
max_size=2
)

if self.instruction.mnemonic == "RMB":
return CodePackage(
Expand Down
27 changes: 27 additions & 0 deletions cocoasm/values.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class ValueType(Enum):
LEFT_RIGHT = 7
ADDRESS_EXPRESSION = 8
MULTI_BYTE = 9
MULTI_WORD = 10


class Value(ABC):
Expand Down Expand Up @@ -174,6 +175,9 @@ def is_negative(self):
def is_multi_byte(self):
return self.type == ValueType.MULTI_BYTE

def is_multi_word(self):
return self.type == ValueType.MULTI_WORD

def resolve(self, symbol_table):
"""
Attempts to resolve the proper value of the object given the supplied symbol table
Expand Down Expand Up @@ -334,6 +338,29 @@ def is_16_bit(self):
return False


class MultiWordValue(Value):
def __init__(self, value):
super().__init__(value)
self.hex_array = []
self.type = ValueType.MULTI_WORD
if "," not in value:
raise ValueTypeError("multi-word declarations must have a comma in them")
values = value.split(",")
self.hex_array = [NumericValue(x).hex(size=4) for x in values if x != ""]

def hex(self, size=0):
return "".join(self.hex_array)

def hex_len(self):
return len(self.hex())

def is_8_bit(self):
return False

def is_16_bit(self):
return False


class StringValue(Value):
"""
Represents a numeric value that can be retrieved as an integer or hex value
Expand Down
10 changes: 10 additions & 0 deletions test/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,16 @@ def test_multi_byte_declaration(self):
program.translate_statements()
self.assertEqual([0x55, 0x44, 0x11, 0xAA], program.get_binary_array())

def test_multi_word_declaration(self):
statements = [
Statement(" FDB $DEAD,$BEEF"),
Statement(" FDB $CAFE"),
]
program = Program()
program.statements = statements
program.translate_statements()
self.assertEqual([0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE], program.get_binary_array())

# M A I N #####################################################################


Expand Down
43 changes: 41 additions & 2 deletions test/test_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from cocoasm.values import NumericValue, StringValue, NoneValue, SymbolValue, \
AddressValue, Value, ExpressionValue, ExplicitAddressingMode, LeftRightValue, \
MultiByteValue
MultiByteValue, MultiWordValue
from cocoasm.instruction import Instruction, Mode
from cocoasm.exceptions import ValueTypeError

Expand Down Expand Up @@ -280,7 +280,7 @@ def test_numeric_negative_int_value_get_negative_correct_16_bit(self):

class TestMultiByteValue(unittest.TestCase):
"""
A test class for the StringValue class.
A test class for the MultiByteValue class.
"""
def setUp(self):
"""
Expand Down Expand Up @@ -317,6 +317,45 @@ def test_multi_byte_16_bit_correct(self):
self.assertFalse(result.is_16_bit())


class TestMultiWordValue(unittest.TestCase):
"""
A test class for the StringValue class.
"""
def setUp(self):
"""
Common setup routines needed for all unit tests.
"""
pass

def test_multi_word_raises_on_no_delimiter(self):
with self.assertRaises(ValueTypeError) as context:
MultiWordValue('$DEAD')
self.assertEqual("multi-word declarations must have a comma in them", str(context.exception))

def test_multi_word_no_values_correct(self):
result = MultiWordValue(",")
self.assertEqual("", result.hex())
self.assertEqual(0, result.hex_len())

def test_multi_word_single_value_correct(self):
result = MultiWordValue("$DEAD,")
self.assertEqual("DEAD", result.hex())
self.assertEqual(4, result.hex_len())

def test_multi_word_many_values_correct(self):
result = MultiWordValue("$DEAD,$BEEF")
self.assertEqual("DEADBEEF", result.hex())
self.assertEqual(8, result.hex_len())

def test_multi_byte_8_bit_correct(self):
result = MultiWordValue("$DEAD,$BEEF")
self.assertFalse(result.is_8_bit())

def test_multi_byte_16_bit_correct(self):
result = MultiWordValue("$DEAD,$BEEF")
self.assertFalse(result.is_16_bit())


class TestStringValue(unittest.TestCase):
"""
A test class for the StringValue class.
Expand Down

0 comments on commit 6f58550

Please sign in to comment.