Skip to content

Commit 2f318ce

Browse files
committedJul 30, 2017
Added JGE
1 parent 06a0a76 commit 2f318ce

File tree

10 files changed

+75
-9
lines changed

10 files changed

+75
-9
lines changed
 

‎.coveragerc

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ exclude_lines =
1111
ignore_errors = True
1212
omit =
1313
tests/*
14-
setup.py
14+
setup.py
15+
RCPU/safe_eval.py

‎RCPU/assemble.py

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ def assemble(lines):
2828
})
2929
# Insert references to resourcetable
3030
text, datasection = assembler.generate_datasection(text, resourcetable)
31+
# Replace symbolic arguments
32+
text = assembler.eval_expressions(text)
3133
# Translate instructions into machine code
3234
binary = assembler.translate_all(text)
3335
binary += datasection
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from RCPU.assembler.expanders.baseexpander import BaseExpander
2+
from .helpers import get_free_register, generate_label, fill_instructions
3+
4+
class ConditionalExpander(BaseExpander):
5+
6+
@BaseExpander.instruction
7+
def JGE(arg):
8+
'''Jump to memory address pointed at by the source register,
9+
if value in the A register is greater than or equal to to
10+
the value in destination register
11+
'''
12+
destination = arg[0]
13+
source = arg[1]
14+
free_register = get_free_register([destination, source, "A"])
15+
failure = generate_label()
16+
instructions = [
17+
"SWP A, {destination}",
18+
"PSH {free_register}",
19+
"LDV16 {free_register}, {failure}",
20+
"JLT {destination}, {free_register}",
21+
# Success, reset everything to how it was and make the jump
22+
"POP {free_register}",
23+
"SWP A, {destination}",
24+
"JMR {source}",
25+
# Failure, reset everything to how it was
26+
"{failure}",
27+
"POP {free_register}",
28+
"SWP A, {destination}"
29+
]
30+
return fill_instructions(instructions, destination=destination, source=source,
31+
free_register=free_register,failure=failure)

‎RCPU/assembler/expanders/expander.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from RCPU.architecture import instruction_mapping
22
import RCPU.assembler.parser as parser
3-
from . import arithmetic
4-
from . import utilexpander
53

6-
_all_classes = [arithmetic.ArithmeticExpander, utilexpander.UtilExpander]
4+
from .arithmetic import ArithmeticExpander
5+
from .utilexpander import UtilExpander
6+
from .conditionalexpander import ConditionalExpander
7+
8+
_all_classes = [ArithmeticExpander, UtilExpander, ConditionalExpander]
79
mapping = {}
810
for c in _all_classes:
911
mapping.update(c.get_instructions())

‎RCPU/assembler/expanders/helpers.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from RCPU.architecture import register_mapping
2+
import string
3+
import random
24

35
def get_free_register(registers_used):
46
'''Returns a register that is not in use'''
@@ -8,4 +10,8 @@ def get_free_register(registers_used):
810

911
def fill_instructions(instructions, **kwargs):
1012
'''Formats instructions with values given in **kwargs'''
11-
return [instruction.format(**kwargs) for instruction in instructions]
13+
return [instruction.format(**kwargs) for instruction in instructions]
14+
15+
def generate_label():
16+
random_name = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(64))
17+
return '{name}:'.format(name=random_name)

‎tests/assembler/expanders/test_helpers.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from RCPU.assembler.expanders.helpers import get_free_register, fill_instructions
1+
from RCPU.assembler.expanders.helpers import get_free_register, fill_instructions, generate_label
2+
from RCPU.assembler.parser import is_label
23

34
def test_get_free_register():
45
assert get_free_register(["A", "B", "C"]) == "D"
@@ -18,4 +19,8 @@ def test_fill_instructions():
1819
"ADD A, C",
1920
"PSH A"
2021
]
21-
assert fill_instructions(original, P='A', Q='B', R='C') == filled
22+
assert fill_instructions(original, P='A', Q='B', R='C') == filled
23+
24+
def test_generate_label():
25+
assert is_label(generate_label())
26+
assert generate_label() != generate_label()

‎tests/functional/expanders/__init__.py

Whitespace-only changes.

‎tests/functional/test_ath.py ‎tests/functional/expanders/test_ath.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .utils import execute_code
1+
from tests.functional.utils import execute_code
22

33
def test_ADD():
44
program = '''
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from tests.functional.utils import execute_code
2+
3+
def test_JGE():
4+
program = '''
5+
.text
6+
.global main:
7+
main:
8+
LDV A, 25
9+
LDV B, 10
10+
LDV C, positive:
11+
JGE B, C
12+
HLT
13+
positive:
14+
LDV C, 16
15+
HLT
16+
'''
17+
c = execute_code(program)
18+
for reg, val in enumerate([25, 10, 16, 0]):
19+
assert c.registers.get(reg) == val

‎tests/functional/test_utilexpander.py ‎tests/functional/expanders/test_utilexpander.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .utils import execute_code
1+
from tests.functional.utils import execute_code
22

33
def test_LDV16():
44
program = '''

0 commit comments

Comments
 (0)
Please sign in to comment.