Skip to content

Commit 6f58550

Browse files
authored
Merge pull request #83 from craigthomas/multi-fdb-declaration
Allow for multi-word declarations
2 parents 9fb0757 + f17539a commit 6f58550

File tree

6 files changed

+94
-6
lines changed

6 files changed

+94
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ as well as the number of cycles used to execute each operation.
474474
|-----------|----------------------------------------------------------------------------|-----------------------|
475475
| `FCB` | Defines a byte constant value. Separate multiple bytes with `,`. | `FCB $1C,$AA` |
476476
| `FCC` | Defines a string constant value enclosed in a matching pair of delimiters. | `FCC "hello"` |
477-
| `FDB` | Defines a two byte constant value. | `FDB $2000` |
477+
| `FDB` | Defines a word constant value. Separate multiple word with `,`. | `FDB $2000,$CAFE` |
478478
| `END` | Defines the end of the program. | `END` |
479479
| `EQU` | Defines a symbol with a set value. | `SCRMEM EQU $1000` |
480480
| `INCLUDE` | Includes another assembly source file at this location. | `INCLUDE globals.asm` |

cocoasm/instruction.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class Instruction(NamedTuple):
8080
is_16_bit: bool = False
8181
is_lea: bool = False
8282
is_multi_byte: bool = False
83+
is_multi_word: bool = False
8384

8485

8586
INSTRUCTIONS = [
@@ -236,7 +237,7 @@ class Instruction(NamedTuple):
236237
Instruction(mnemonic="SET", is_pseudo=True),
237238
Instruction(mnemonic="RMB", is_pseudo=True),
238239
Instruction(mnemonic="FCB", is_pseudo=True, is_multi_byte=True),
239-
Instruction(mnemonic="FDB", is_pseudo=True),
240+
Instruction(mnemonic="FDB", is_pseudo=True, is_multi_word=True),
240241
Instruction(mnemonic="FCC", is_pseudo=True, is_string_define=True),
241242
Instruction(mnemonic="SETDP", is_pseudo=True),
242243
Instruction(mnemonic="INCLUDE", is_pseudo=True, is_include=True),

cocoasm/operands.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
from abc import ABC, abstractmethod
1212

13-
from cocoasm.values import NoneValue, Value, NumericValue, DirectNumericValue, ExtendedNumericValue, MultiByteValue
13+
from cocoasm.values import NoneValue, Value, NumericValue, DirectNumericValue, ExtendedNumericValue, MultiByteValue, \
14+
MultiWordValue
1415
from cocoasm.instruction import CodePackage
1516
from cocoasm.operand_type import OperandType
1617
from cocoasm.exceptions import OperandTypeError, ValueTypeError
@@ -190,6 +191,8 @@ def __init__(self, operand_string, instruction):
190191
raise OperandTypeError("[{}] is not a pseudo instruction".format(instruction.mnemonic))
191192
if instruction.is_multi_byte:
192193
self.value = MultiByteValue(operand_string) if "," in operand_string else Value.create_from_str(operand_string, instruction)
194+
elif instruction.is_multi_word:
195+
self.value = MultiWordValue(operand_string) if "," in operand_string else Value.create_from_str(operand_string, instruction)
193196
else:
194197
self.value = NoneValue() if instruction.is_include else Value.create_from_str(operand_string, instruction)
195198

@@ -215,7 +218,15 @@ def translate(self):
215218
)
216219

217220
if self.instruction.mnemonic == "FDB":
218-
return CodePackage(additional=NumericValue(self.value.int, size_hint=4), size=2, max_size=2)
221+
return CodePackage(
222+
additional=self.value,
223+
size=self.value.byte_len(),
224+
max_size=self.value.byte_len()
225+
) if self.value.is_multi_word() else CodePackage(
226+
additional=NumericValue(self.value.int, size_hint=4),
227+
size=2,
228+
max_size=2
229+
)
219230

220231
if self.instruction.mnemonic == "RMB":
221232
return CodePackage(

cocoasm/values.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class ValueType(Enum):
7979
LEFT_RIGHT = 7
8080
ADDRESS_EXPRESSION = 8
8181
MULTI_BYTE = 9
82+
MULTI_WORD = 10
8283

8384

8485
class Value(ABC):
@@ -174,6 +175,9 @@ def is_negative(self):
174175
def is_multi_byte(self):
175176
return self.type == ValueType.MULTI_BYTE
176177

178+
def is_multi_word(self):
179+
return self.type == ValueType.MULTI_WORD
180+
177181
def resolve(self, symbol_table):
178182
"""
179183
Attempts to resolve the proper value of the object given the supplied symbol table
@@ -334,6 +338,29 @@ def is_16_bit(self):
334338
return False
335339

336340

341+
class MultiWordValue(Value):
342+
def __init__(self, value):
343+
super().__init__(value)
344+
self.hex_array = []
345+
self.type = ValueType.MULTI_WORD
346+
if "," not in value:
347+
raise ValueTypeError("multi-word declarations must have a comma in them")
348+
values = value.split(",")
349+
self.hex_array = [NumericValue(x).hex(size=4) for x in values if x != ""]
350+
351+
def hex(self, size=0):
352+
return "".join(self.hex_array)
353+
354+
def hex_len(self):
355+
return len(self.hex())
356+
357+
def is_8_bit(self):
358+
return False
359+
360+
def is_16_bit(self):
361+
return False
362+
363+
337364
class StringValue(Value):
338365
"""
339366
Represents a numeric value that can be retrieved as an integer or hex value

test/test_integration.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,16 @@ def test_multi_byte_declaration(self):
854854
program.translate_statements()
855855
self.assertEqual([0x55, 0x44, 0x11, 0xAA], program.get_binary_array())
856856

857+
def test_multi_word_declaration(self):
858+
statements = [
859+
Statement(" FDB $DEAD,$BEEF"),
860+
Statement(" FDB $CAFE"),
861+
]
862+
program = Program()
863+
program.statements = statements
864+
program.translate_statements()
865+
self.assertEqual([0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE], program.get_binary_array())
866+
857867
# M A I N #####################################################################
858868

859869

test/test_values.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from cocoasm.values import NumericValue, StringValue, NoneValue, SymbolValue, \
1212
AddressValue, Value, ExpressionValue, ExplicitAddressingMode, LeftRightValue, \
13-
MultiByteValue
13+
MultiByteValue, MultiWordValue
1414
from cocoasm.instruction import Instruction, Mode
1515
from cocoasm.exceptions import ValueTypeError
1616

@@ -280,7 +280,7 @@ def test_numeric_negative_int_value_get_negative_correct_16_bit(self):
280280

281281
class TestMultiByteValue(unittest.TestCase):
282282
"""
283-
A test class for the StringValue class.
283+
A test class for the MultiByteValue class.
284284
"""
285285
def setUp(self):
286286
"""
@@ -317,6 +317,45 @@ def test_multi_byte_16_bit_correct(self):
317317
self.assertFalse(result.is_16_bit())
318318

319319

320+
class TestMultiWordValue(unittest.TestCase):
321+
"""
322+
A test class for the StringValue class.
323+
"""
324+
def setUp(self):
325+
"""
326+
Common setup routines needed for all unit tests.
327+
"""
328+
pass
329+
330+
def test_multi_word_raises_on_no_delimiter(self):
331+
with self.assertRaises(ValueTypeError) as context:
332+
MultiWordValue('$DEAD')
333+
self.assertEqual("multi-word declarations must have a comma in them", str(context.exception))
334+
335+
def test_multi_word_no_values_correct(self):
336+
result = MultiWordValue(",")
337+
self.assertEqual("", result.hex())
338+
self.assertEqual(0, result.hex_len())
339+
340+
def test_multi_word_single_value_correct(self):
341+
result = MultiWordValue("$DEAD,")
342+
self.assertEqual("DEAD", result.hex())
343+
self.assertEqual(4, result.hex_len())
344+
345+
def test_multi_word_many_values_correct(self):
346+
result = MultiWordValue("$DEAD,$BEEF")
347+
self.assertEqual("DEADBEEF", result.hex())
348+
self.assertEqual(8, result.hex_len())
349+
350+
def test_multi_byte_8_bit_correct(self):
351+
result = MultiWordValue("$DEAD,$BEEF")
352+
self.assertFalse(result.is_8_bit())
353+
354+
def test_multi_byte_16_bit_correct(self):
355+
result = MultiWordValue("$DEAD,$BEEF")
356+
self.assertFalse(result.is_16_bit())
357+
358+
320359
class TestStringValue(unittest.TestCase):
321360
"""
322361
A test class for the StringValue class.

0 commit comments

Comments
 (0)