git @ Cat's Eye Technologies SixtyPical / 5b429ad
6502 opcodes are Emittables. Can compile simple programs now! Chris Pressey 6 years ago
4 changed file(s) with 296 addition(s) and 130 deletion(s). Raw diff Collapse all Expand all
3232 optparser.add_option("--compile",
3333 action="store_true", dest="compile", default=False,
3434 help="")
35 optparser.add_option("--debug",
36 action="store_true", dest="debug", default=False,
37 help="")
3538 optparser.add_option("--traceback",
3639 action="store_true", dest="traceback", default=False,
3740 help="")
6063 if options.compile:
6164 emitter = Emitter(41952)
6265 compile_program(program, emitter)
63 emitter.serialize(sys.stdout)
66 if options.debug:
67 print repr(emitter.accum)
68 else:
69 emitter.serialize(sys.stdout)
6470
6571 if options.execute:
6672 context = eval_program(program)
44 ConstantRef, LocationRef,
55 REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
66 )
7 from sixtypical.gen6502 import Generator
7 from sixtypical.emitter import Byte
8 from sixtypical.gen6502 import (
9 Immediate, Absolute,
10 LDA, LDX, LDY, STA, STX, STY, CLC, SEC, ADC, RTS
11 )
12
13
14 class UnsupportedOpcodeError(KeyError):
15 pass
816
917
1018 def compile_program(program, emitter):
1119 assert isinstance(program, Program)
12 generator = Generator(emitter)
1320 routines = {r.name: r for r in program.routines}
1421 for routine in program.routines:
15 compile_routine(routine, generator, routines)
22 compile_routine(routine, emitter, routines)
1623
1724
18 def compile_routine(routine, generator, routines):
25 def compile_routine(routine, emitter, routines):
1926 assert isinstance(routine, Routine)
20 label = generator.emitter.make_label(routine.name)
21 compile_block(routine.block, generator, routines)
27 label = emitter.make_label(routine.name)
28 compile_block(routine.block, emitter, routines)
29 emitter.emit(RTS())
2230 return label
2331
2432
25 def compile_block(block, generator, routines):
33 def compile_block(block, emitter, routines):
2634 assert isinstance(block, Block)
27 label = generator.emitter.make_label()
35 label = emitter.make_label()
2836 for instr in block.instrs:
29 compile_instr(instr, generator, routines)
37 compile_instr(instr, emitter, routines)
3038 return label
3139
3240
33 def compile_instr(instr, generator, routines):
41 def compile_instr(instr, emitter, routines):
3442 assert isinstance(instr, Instr)
3543 opcode = instr.opcode
3644 dest = instr.dest
3947 if opcode == 'ld':
4048 if dest == REG_A:
4149 if isinstance(src, ConstantRef):
42 # LDA #...
43 pass
50 emitter.emit(LDA(Immediate(Byte(src.value))))
4451 else:
45 # LDA abs
46 pass
52 emitter.emit(LDA(Absolute(src.label)))
4753 elif dest == REG_X:
4854 pass
4955 elif dest == REG_Y:
5056 pass
5157 else:
52 raise KeyError
58 raise UnsupportedOpcodeError(instr)
5359 elif opcode == 'st':
54 if src == REG_A:
55 # assert isinstance(dest, MemoryRef)
56 # generate STA
57 pass
60 if dest == FLAG_C and src == ConstantRef(0):
61 emitter.emit(CLC())
62 elif dest == FLAG_C and src == ConstantRef(1):
63 emitter.emit(SEC())
64 elif src == REG_A:
65 emitter.emit(STA(Absolute(dest.label)))
66 elif src == REG_X:
67 emitter.emit(STX(Absolute(dest.label)))
68 elif src == REG_Y:
69 emitter.emit(STY(Absolute(dest.label)))
5870 else:
59 raise KeyError
71 raise UnsupportedOpcodeError(instr)
6072 elif opcode == 'add':
61 raise NotImplementedError
73 if dest == REG_A:
74 if isinstance(src, ConstantRef):
75 emitter.emit(ADC(Immediate(Byte(src.value))))
76 else:
77 emitter.emit(ADC(Absolute(src.label)))
78 else:
79 raise UnsupportedOpcodeError(instr)
6280 elif opcode == 'sub':
6381 raise NotImplementedError
6482 elif opcode == 'inc':
0 class Word(object):
0 class Emittable(object):
1 def size(self):
2 """Default implementation may not be very efficient."""
3 return len(self.serialize())
4
5 def serialize(self):
6 raise NotImplementedError
7
8
9 class Byte(Emittable):
110 def __init__(self, value):
11 if value < -127 or value > 255:
12 raise IndexError(thing)
13 if value < 0:
14 value += 256
15 self.value = value
16
17 def size(self):
18 return 1
19
20 def serialize(self):
21 return chr(self.value)
22
23 def __repr__(self):
24 return "%s(%r)" % (self.__class__.__name__, self.value)
25
26
27 class Word(Emittable):
28 def __init__(self, value):
29 # TODO: range-checking
230 self.value = value
331
432 def size(self):
1038 high = (word >> 8) & 255
1139 return chr(low) + chr(high)
1240
41 def __repr__(self):
42 return "%s(%r)" % (self.__class__.__name__, self.value)
1343
14 class Label(object):
44
45 class Label(Emittable):
1546 def __init__(self, name, addr=None):
1647 self.name = name
1748 self.addr = addr
2354 return 2
2455
2556 def serialize(self):
26 if self.addr is None:
27 raise ValueError(self.addr)
57 assert self.addr is not None, "unresolved label: %s" % self.name
2858 return Word(self.addr).serialize()
2959
3060
3464 self.addr = addr
3565 self.name_counter = 0
3666
37 def gen(self, *things):
67 def emit(self, *things):
3868 for thing in things:
3969 if isinstance(thing, int):
40 if thing < -127 or thing > 255:
41 raise ValueError(thing)
42 if thing < 0:
43 thing += 256
44 self.accum.append(thing)
45 self.addr += 1
46 else:
47 self.accum.append(thing)
48 self.addr += thing.size()
70 thing = Byte(thing)
71 self.accum.append(thing)
72 self.addr += thing.size()
4973
5074 def serialize(self, stream):
51 for thing in self.accum:
52 if isintance(thing, int):
53 stream.write(chr(thing))
54 else:
55 stream.write(thing.serialize())
75 for emittable in self.accum:
76 stream.write(emittable.serialize())
5677
5778 def make_label(self, name=None):
5879 if name is None:
00 """This is just a sketch for now."""
11
2 from sixtypical.emitter import Emitter, Word, Label
3
4
5 class Generator(object):
6 def __init__(self, emitter):
7 self.emitter = emitter
8
9 ### ld ###
10
11 def gen_lda_imm(self, b):
12 self.emitter.emit(0xa9, b)
13
14 def gen_lda_abs(self, addr):
15 self.emitter.emit(0xad, addr)
16
17 def gen_ldx_imm(self, b):
18 self.emitter.emit(0xa2, b)
19
20 def gen_ldx_abs(self, addr):
21 self.emitter.emit(0xae, addr)
22
23 def gen_tax(self):
24 self.emitter.emit(0xaa)
25
26 def gen_tay(self):
27 self.emitter.emit(0xa8)
28
29 def gen_txa(self):
30 self.emitter.emit(0x8a)
31
32 def gen_tya(self):
33 self.emitter.emit(0x98)
34
35 ### st ###
36
37 def gen_sta_abs(self, addr):
38 self.emitter.emit(0x8d, addr)
39
40 def gen_stx_abs(self, addr):
41 self.emitter.emit(0x8e, addr)
42
43 def gen_sty_abs(self, addr):
44 self.emitter.emit(0x8c, addr)
45
46 ### add ###
47
48 def gen_adc_imm(self, b):
49 self.emitter.emit(0x69, b)
50
51 def gen_adc_abs(self, addr):
52 self.emitter.emit(0x6d, addr)
53
54 ### sub ###
55
56 def gen_sbc_imm(self, b):
57 self.emitter.emit(0xe9, b)
58
59 def gen_sbc_abs(self, addr):
60 self.emitter.emit(0xed, addr)
61
62 ### inc ###
63
64 def gen_inc_abs(self, addr):
65 self.emitter.emit(0xee, addr)
66
67 def gen_inx(self):
68 self.emitter.emit(0xe8)
69
70 def gen_iny(self):
71 self.emitter.emit(0xc8)
72
73 ### dec ###
74
75 def gen_dec_abs(self, addr):
76 self.emitter.emit(0xce, addr)
77
78 def gen_dex(self):
79 self.emitter.emit(0xca)
80
81 def gen_dey(self):
82 self.emitter.emit(0x88)
83
84 ### and ###
85
86 def gen_and_imm(self, b):
87 self.emitter.emit(0x29, b)
88
89 def gen_and_abs(self, addr):
90 self.emitter.emit(0x2d, addr)
2 from sixtypical.emitter import Emittable, Byte, Word, Label
3
4
5 class AddressingMode(object):
6 def size(self):
7 """Size of the operand for the mode (not including the opcode)"""
8 raise NotImplementedError
9
10
11 class Implied(AddressingMode):
12 def size(self):
13 return 0
14
15 def serialize(self):
16 return ''
17
18 def __repr__(self):
19 return "%s()" % (self.__class__.__name__)
20
21
22 class Immediate(AddressingMode):
23 def __init__(self, value):
24 assert isinstance(value, Byte)
25 self.value = value
26
27 def size(self):
28 return 1
29
30 def serialize(self):
31 return self.value.serialize()
32
33 def __repr__(self):
34 return "%s(%r)" % (self.__class__.__name__, self.value)
35
36
37 class Absolute(AddressingMode):
38 def __init__(self, value):
39 assert isinstance(value, (Word, Label))
40 self.value = value
41
42 def size(self):
43 return 2
44
45 def serialize(self):
46 return self.value.serialize()
47
48 def __repr__(self):
49 return "%s(%r)" % (self.__class__.__name__, self.value)
50
51
52 class Opcode(Emittable):
53 def __init__(self, operand=None):
54 self.operand = operand or Implied()
55
56 def size(self):
57 return 1 + self.operand.size() if self.operand else 0
58
59 def serialize(self):
60 return (
61 chr(self.opcodes[self.operand.__class__]) +
62 self.operand.serialize()
63 )
64
65 def __repr__(self):
66 return "%s(%r)" % (self.__class__.__name__, self.operand)
67
68
69 class ADC(Opcode):
70 opcodes = {
71 Immediate: 0x69,
72 Absolute: 0x6d,
73 }
74
75
76 class ADD(Opcode):
77 opcodes = {
78 Immediate: 0x29,
79 Absolute: 0x2d,
80 }
81
82
83 class CLC(Opcode):
84 opcodes = {
85 Implied: 0x18
86 }
87
88
89 class DEC(Opcode):
90 opcodes = {
91 Absolute: 0xce,
92 }
93
94
95 class DEX(Opcode):
96 opcodes = {
97 Implied: 0xca,
98 }
99
100
101 class DEY(Opcode):
102 opcodes = {
103 Implied: 0x88,
104 }
105
106
107 class INC(Opcode):
108 opcodes = {
109 Absolute: 0xee,
110 }
111
112
113 class INX(Opcode):
114 opcodes = {
115 Implied: 0xe8,
116 }
117
118
119 class INY(Opcode):
120 opcodes = {
121 Implied: 0xc8,
122 }
123
124
125 class LDA(Opcode):
126 opcodes = {
127 Immediate: 0xa9,
128 Absolute: 0xad,
129 }
130
131
132 class LDX(Opcode):
133 opcodes = {
134 Immediate: 0xa2,
135 Absolute: 0xae,
136 }
137
138
139 class LDY(Opcode):
140 opcodes = {
141 Immediate: 0xa0,
142 Absolute: 0xac,
143 }
144
145
146 class ORA(Opcode):
147 opcodes = {
148 Immediate: 0x09,
149 Absolute: 0x0d,
150 }
151
152
153 class RTS(Opcode):
154 opcodes = {
155 Implied: 0x60,
156 }
157
158
159 class SBC(Opcode):
160 opcodes = {
161 Immediate: 0xe9,
162 Absolute: 0xed,
163 }
164
165
166 class SEC(Opcode):
167 opcodes = {
168 Implied: 0x38,
169 }
170
171
172 class STA(Opcode):
173 opcodes = {
174 Absolute: 0x8d,
175 }
176
177
178 class STX(Opcode):
179 opcodes = {
180 Absolute: 0x8e,
181 }
182
183
184 class STY(Opcode):
185 opcodes = {
186 Absolute: 0x8c,
187 }
188
189
190 class TAX(Opcode):
191 opcodes = {
192 Implied: 0xaa,
193 }
194
195
196 class TAY(Opcode):
197 opcodes = {
198 Implied: 0xa8,
199 }
200
201
202 class TXA(Opcode):
203 opcodes = {
204 Implied: 0x8a,
205 }
206
207
208 class TYA(Opcode):
209 opcodes = {
210 Implied: 0x98,
211 }