r6502 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,213 @@
1
+ module R6502
2
+ class Cpu
3
+ def instr_mode(opcode)
4
+ #adc
5
+ { 0x69 => [:adc, :imm],
6
+ 0x65 => [:adc, :zp],
7
+ 0x75 => [:adc, :zpx],
8
+ 0x6d => [:adc, :abs],
9
+ 0x7d => [:adc, :absx],
10
+ 0x79 => [:adc, :absy],
11
+ 0x61 => [:adc, :indx],
12
+ 0x71 => [:adc, :indy],
13
+ #and
14
+ 0x29 => [:and, :imm],
15
+ 0x25 => [:and, :zp],
16
+ 0x35 => [:and, :zpx],
17
+ 0x2d => [:and, :abs],
18
+ 0x3d => [:and, :absx],
19
+ 0x39 => [:and, :absy],
20
+ 0x21 => [:and, :indx],
21
+ 0x31 => [:and, :indy],
22
+ #asl
23
+ 0x0a => [:asl, :acc],
24
+ 0x06 => [:asl, :zp],
25
+ 0x16 => [:asl, :zpx],
26
+ 0x0e => [:asl, :abs],
27
+ 0x1e => [:asl, :absx],
28
+ #bit
29
+ 0x24 => [:bit, :zp],
30
+ 0x2c => [:bit, :abs],
31
+ #bpl
32
+ 0x10 => [:bpl, :rel],
33
+ #bmi
34
+ 0x30 => [:bmi, :rel],
35
+ #bvc
36
+ 0x50 => [:bvc, :rel],
37
+ #bvs
38
+ 0x70 => [:bvs, :rel],
39
+ #bcc
40
+ 0x90 => [:bcc, :rel],
41
+ #bcs
42
+ 0xb0 => [:bcs, :rel],
43
+ #bne
44
+ 0xd0 => [:bne, :rel],
45
+ #beq
46
+ 0xf0 => [:beq, :rel],
47
+ #brk
48
+ 0x00 => [:brk, :imp],
49
+ #cmp
50
+ 0xc9 => [:cmp, :imm],
51
+ 0xc5 => [:cmp, :zp],
52
+ 0xd5 => [:cmp, :zpx],
53
+ 0xcd => [:cmp, :abs],
54
+ 0xdd => [:cmp, :absx],
55
+ 0xd9 => [:cmp, :absy],
56
+ 0xc1 => [:cmp, :indx],
57
+ 0xd1 => [:cmp, :indy],
58
+ #cpx
59
+ 0xe0 => [:cpx, :imm],
60
+ 0xe4 => [:cpx, :zp],
61
+ 0xec => [:cpx, :abs],
62
+ #cpy
63
+ 0xc0 => [:cpy, :imm],
64
+ 0xc4 => [:cpy, :zp],
65
+ 0xcc => [:cpy, :abs],
66
+ #dec
67
+ 0xc6 => [:dec, :zp],
68
+ 0xd6 => [:dec, :zpx],
69
+ 0xce => [:dec, :abs],
70
+ 0xde => [:dec, :absx],
71
+ #eor
72
+ 0x49 => [:eor, :imm],
73
+ 0x45 => [:eor, :zp],
74
+ 0x55 => [:eor, :zpx],
75
+ 0x4d => [:eor, :abs],
76
+ 0x5d => [:eor, :absx],
77
+ 0x59 => [:eor, :absy],
78
+ 0x41 => [:eor, :indx],
79
+ 0x51 => [:eor, :indy],
80
+ #clc
81
+ 0x18 => [:clc, :imp],
82
+ #sec
83
+ 0x38 => [:sec, :imp],
84
+ #cli
85
+ 0x58 => [:cli, :imp],
86
+ #sei
87
+ 0x78 => [:sei, :imp],
88
+ #clv
89
+ 0xb8 => [:clv, :imp],
90
+ #cld
91
+ 0xd8 => [:cld, :imp],
92
+ #sed
93
+ 0xf8 => [:sed, :imp],
94
+ #inc
95
+ 0xe6 => [:inc, :zp],
96
+ 0xf6 => [:inc, :zpx],
97
+ 0xee => [:inc, :abs],
98
+ 0xfe => [:inc, :absx],
99
+ #jmp,
100
+ 0x4c => [:jmp, :abs],
101
+ 0x6c => [:jmp, :ind],
102
+ #jsr,
103
+ 0x20 => [:jsr, :abs],
104
+ #lda,
105
+ 0xa9 => [:lda, :imm],
106
+ 0xa5 => [:lda, :zp],
107
+ 0xb5 => [:lda, :zpx],
108
+ 0xad => [:lda, :abs],
109
+ 0xbd => [:lda, :absx],
110
+ 0xb9 => [:lda, :absy],
111
+ 0xa1 => [:lda, :indx],
112
+ 0xb1 => [:lda, :indy],
113
+ #ldx,
114
+ 0xa2 => [:ldx, :imm],
115
+ 0xa6 => [:ldx, :zp],
116
+ 0xb6 => [:ldx, :zpy],
117
+ 0xae => [:ldx, :abs],
118
+ 0xbe => [:ldx, :absy],
119
+ #ldy,
120
+ 0xa0 => [:ldy, :imm],
121
+ 0xa4 => [:ldy, :zp],
122
+ 0xb4 => [:ldy, :zpx],
123
+ 0xac => [:ldy, :abs],
124
+ 0xbc => [:ldy, :absx],
125
+ #lsr,
126
+ 0x4a => [:lsr, :imp],
127
+ 0x46 => [:lsr, :zp],
128
+ 0x56 => [:lsr, :zpx],
129
+ 0x4e => [:lsr, :abs],
130
+ 0x5e => [:lsr, :absx],
131
+ #nop,
132
+ 0xea => [:nop, :imp],
133
+ #ora,
134
+ 0x09 => [:ora, :imm],
135
+ 0x05 => [:ora, :zp],
136
+ 0x15 => [:ora, :zpx],
137
+ 0x0d => [:ora, :abs],
138
+ 0x1d => [:ora, :absx],
139
+ 0x19 => [:ora, :absy],
140
+ 0x01 => [:ora, :indx],
141
+ 0x11 => [:ora, :indy],
142
+ #tax,
143
+ 0xaa => [:tax, :imp],
144
+ #txa,
145
+ 0x8a => [:txa, :imp],
146
+ #dex,
147
+ 0xca => [:dex, :imp],
148
+ #inx,
149
+ 0xe8 => [:inx, :imp],
150
+ #tay,
151
+ 0xa8 => [:tay, :imp],
152
+ #tya,
153
+ 0x98 => [:tya, :imp],
154
+ #dey,
155
+ 0x88 => [:dey, :imp],
156
+ #iny,
157
+ 0xc8 => [:iny, :imp],
158
+ #rol,
159
+ 0x2a => [:rol, :imp],
160
+ 0x26 => [:rol, :zp],
161
+ 0x36 => [:rol, :zpx],
162
+ 0x2e => [:rol, :abs],
163
+ 0x3e => [:rol, :absx],
164
+ #ror,
165
+ 0x6a => [:ror, :imp],
166
+ 0x66 => [:ror, :zp],
167
+ 0x76 => [:ror, :zpx],
168
+ 0x6e => [:ror, :abs],
169
+ 0x7e => [:ror, :absx],
170
+ #rti,
171
+ 0x40 => [:rti, :imp],
172
+ #rts,
173
+ 0x60 => [:rts, :imp],
174
+ #sbc,
175
+ 0xe9 => [:sbc, :imm],
176
+ 0xe5 => [:sbc, :zp],
177
+ 0xf5 => [:sbc, :zpx],
178
+ 0xed => [:sbc, :abs],
179
+ 0xfd => [:sbc, :absx],
180
+ 0xf9 => [:sbc, :absy],
181
+ 0xe1 => [:sbc, :indx],
182
+ 0xf1 => [:sbc, :indy],
183
+ #sta,
184
+ 0x85 => [:sta, :zp],
185
+ 0x95 => [:sta, :zpx],
186
+ 0x8d => [:sta, :abs],
187
+ 0x9d => [:sta, :absx],
188
+ 0x99 => [:sta, :absy],
189
+ 0x81 => [:sta, :indx],
190
+ 0x91 => [:sta, :indy],
191
+ #txs,
192
+ 0x9a => [:txs, :imp],
193
+ #tsx,
194
+ 0xba => [:tsx, :imp],
195
+ #pha,
196
+ 0x48 => [:pha, :imp],
197
+ #pla,
198
+ 0x68 => [:pla, :imp],
199
+ #php,
200
+ 0x08 => [:php, :imp],
201
+ #plp,
202
+ 0x28 => [:plp, :imp],
203
+ #stx,
204
+ 0x86 => [:stx, :zp],
205
+ 0x96 => [:stx, :zpy],
206
+ 0x8e => [:stx, :abs],
207
+ #sty,
208
+ 0x84 => [:sty, :zp],
209
+ 0x94 => [:sty, :zpx],
210
+ 0x8c => [:sty, :abs] }[opcode]
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,21 @@
1
+ module R6502
2
+ class Memory
3
+ def initialize
4
+ @mem_array = []
5
+ end
6
+ def set( addr, val )
7
+ @mem_array[addr] = val & 0xff
8
+ end
9
+ def get( addr )
10
+ @mem_array[addr] || 0
11
+ end
12
+ def get_word( addr )
13
+ get(addr) + ( get(addr + 1) << 8 )
14
+ end
15
+ def get_range( top, bot )
16
+ bytes = []
17
+ (top..bot).each { |i| bytes << get(i) }
18
+ bytes
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ module R6502
2
+ class Assembler
3
+ def opcode(instr, mode)
4
+ { :adc => {:imm => 0x69, :zp => 0x65, :zpx => 0x75, :zpy => nil, :abs => 0x6d, :absx => 0x7d, :absy => 0x79, :ind => nil, :indx => 0x61, :indy => 0x71, :imp => nil, :rel => nil },
5
+ :and => {:imm => 0x29, :zp => 0x25, :zpx => 0x35, :zpy => nil, :abs => 0x2d, :absx => 0x3d, :absy => 0x39, :ind => nil, :indx => 0x21, :indy => 0x31, :imp => nil, :rel => nil },
6
+ :asl => {:imm => nil, :zp => 0x06, :zpx => 0x16, :zpy => nil, :abs => 0x0e, :absx => 0x1e, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x0a, :rel => nil },
7
+ :bit => {:imm => nil, :zp => 0x24, :zpx => nil, :zpy => nil, :abs => 0x2c, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
8
+ :bpl => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0x10},
9
+ :bmi => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0x30},
10
+ :bvc => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0x50},
11
+ :bvs => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0x70},
12
+ :bcc => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0x90},
13
+ :bcs => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0xb0},
14
+ :bne => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0xd0},
15
+ :beq => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => 0xf0},
16
+ :brk => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x00, :rel => nil },
17
+ :cmp => {:imm => 0xc9, :zp => 0xc5, :zpx => 0xd5, :zpy => nil, :abs => 0xcd, :absx => 0xdd, :absy => 0xd9, :ind => nil, :indx => 0xc1, :indy => 0xd1, :imp => nil, :rel => nil },
18
+ :cpx => {:imm => 0xe0, :zp => 0xe4, :zpx => nil, :zpy => nil, :abs => 0xec, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
19
+ :cpy => {:imm => 0xc0, :zp => 0xc4, :zpx => nil, :zpy => nil, :abs => 0xcc, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
20
+ :dec => {:imm => nil, :zp => 0xc6, :zpx => 0xd6, :zpy => nil, :abs => 0xce, :absx => 0xde, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
21
+ :eor => {:imm => 0x49, :zp => 0x45, :zpx => 0x55, :zpy => nil, :abs => 0x4d, :absx => 0x5d, :absy => 0x59, :ind => nil, :indx => 0x41, :indy => 0x51, :imp => nil, :rel => nil },
22
+ :clc => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x18, :rel => nil },
23
+ :sec => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x38, :rel => nil },
24
+ :cli => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x58, :rel => nil },
25
+ :sei => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x78, :rel => nil },
26
+ :clv => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xb8, :rel => nil },
27
+ :cld => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xd8, :rel => nil },
28
+ :sed => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xf8, :rel => nil },
29
+ :inc => {:imm => nil, :zp => 0xe6, :zpx => 0xf6, :zpy => nil, :abs => 0xee, :absx => 0xfe, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
30
+ :jmp => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => 0x4c, :absx => nil, :absy => nil, :ind => 0x6c, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
31
+ :jsr => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => 0x20, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
32
+ :lda => {:imm => 0xa9, :zp => 0xa5, :zpx => 0xb5, :zpy => nil, :abs => 0xad, :absx => 0xbd, :absy => 0xb9, :ind => nil, :indx => 0xa1, :indy => 0xb1, :imp => nil, :rel => nil },
33
+ :ldx => {:imm => 0xa2, :zp => 0xa6, :zpx => nil, :zpy => 0xb6, :abs => 0xae, :absx => nil, :absy => 0xbe, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
34
+ :ldy => {:imm => 0xa0, :zp => 0xa4, :zpx => 0xb4, :zpy => nil, :abs => 0xac, :absx => 0xbc, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
35
+ :lsr => {:imm => nil, :zp => 0x46, :zpx => 0x56, :zpy => nil, :abs => 0x4e, :absx => 0x5e, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x4a, :rel => nil },
36
+ :nop => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xea, :rel => nil },
37
+ :ora => {:imm => 0x09, :zp => 0x05, :zpx => 0x15, :zpy => nil, :abs => 0x0d, :absx => 0x1d, :absy => 0x19, :ind => nil, :indx => 0x01, :indy => 0x11, :imp => nil, :rel => nil },
38
+ :tax => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xaa, :rel => nil },
39
+ :txa => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x8a, :rel => nil },
40
+ :dex => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xca, :rel => nil },
41
+ :inx => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xe8, :rel => nil },
42
+ :tay => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xa8, :rel => nil },
43
+ :tya => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x98, :rel => nil },
44
+ :dey => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x88, :rel => nil },
45
+ :iny => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xc8, :rel => nil },
46
+ :ror => {:imm => nil, :zp => 0x66, :zpx => 0x76, :zpy => nil, :abs => 0x6e, :absx => 0x7e, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x6a, :rel => nil },
47
+ :rol => {:imm => nil, :zp => 0x26, :zpx => 0x36, :zpy => nil, :abs => 0x2e, :absx => 0x3e, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x2a, :rel => nil },
48
+ :rti => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x40, :rel => nil },
49
+ :rts => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x60, :rel => nil },
50
+ :sbc => {:imm => 0xe9, :zp => 0xe5, :zpx => 0xf5, :zpy => nil, :abs => 0xed, :absx => 0xfd, :absy => 0xf9, :ind => nil, :indx => 0xe1, :indy => 0xf1, :imp => nil, :rel => nil },
51
+ :sta => {:imm => nil, :zp => 0x85, :zpx => 0x95, :zpy => nil, :abs => 0x8d, :absx => 0x9d, :absy => 0x99, :ind => nil, :indx => 0x81, :indy => 0x91, :imp => nil, :rel => nil },
52
+ :txs => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x9a, :rel => nil },
53
+ :tsx => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0xba, :rel => nil },
54
+ :pha => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x48, :rel => nil },
55
+ :pla => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x68, :rel => nil },
56
+ :php => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x08, :rel => nil },
57
+ :plp => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => 0x28, :rel => nil },
58
+ :stx => {:imm => nil, :zp => 0x86, :zpx => nil, :zpy => 0x96, :abs => 0x8e, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
59
+ :sty => {:imm => nil, :zp => 0x84, :zpx => 0x94, :zpy => nil, :abs => 0x8c, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil },
60
+ :nil => {:imm => nil, :zp => nil, :zpx => nil, :zpy => nil, :abs => nil, :absx => nil, :absy => nil, :ind => nil, :indx => nil, :indy => nil, :imp => nil, :rel => nil }
61
+ }[instr][mode]
62
+ end
63
+ end
64
+ end
data/r6502.gemspec ADDED
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'r6502'
3
+ s.version = '0.0.1'
4
+ s.date = '2014-04-09'
5
+ s.summary = "6502 simulator and assembler"
6
+ s.description = "6502 simulator and assembler, work-in-progress, not cycle-accurate, etc."
7
+ s.author = "Joe Landers"
8
+ s.email = 'joe@joelanders.net'
9
+ s.files = Dir['**/*']
10
+ s.homepage =
11
+ 'https://github.com/joelanders/r6502'
12
+ s.license = 'MIT'
13
+ end
@@ -0,0 +1,226 @@
1
+ require 'spec_helper'
2
+
3
+ module R6502
4
+ describe Assembler do
5
+ before(:each) do
6
+ @mem = Memory.new
7
+ @asm = Assembler.new(@mem)
8
+ end
9
+
10
+ describe "Assembler" do
11
+ it "Assembles a file and places machine code in memory." do
12
+ @asm.process_file("lda $2000 ;cmt\nloop nop\njmp loop\n")
13
+ @mem.get_range(0x600, 0x602).should == [0xad, 0x00, 0x20]
14
+ @mem.get_range(0x603, 0x606).should == [0xea, 0x4c, 0x03, 0x06]
15
+ end
16
+ it "handles relative addressing correctly (negative)" do
17
+ @asm.process_file("ldx \#$04\nloop dex\nbne loop")
18
+ @mem.get_range(0x600, 0x604).should == [0xa2, 0x04, 0xca, 0xd0, 0xfd]
19
+ end
20
+ it "handles relative addressing correctly (positive)" do
21
+ @asm.process_file("ldx \#$04\nbne finish\nnop\nnop\nfinish")
22
+ @mem.get_range(0x600, 0x605).should == [0xa2, 0x04, 0xd0, 0x02, 0xea, 0xea]
23
+ end
24
+ describe "assembles a line of assembly" do
25
+ describe "reads a line of assembly" do
26
+ describe "parses the pieces of a line of assembly" do
27
+ it "removes label from an assembly instr" do
28
+ @asm.delabel('loop: brk').should == 'brk'
29
+ @asm.delabel('scoop:').should == ''
30
+ @asm.delabel('').should == ''
31
+ @asm.delabel(' ').should == ''
32
+ @asm.delabel(' lda $2000').should == 'lda $2000'
33
+ @asm.delabel('doop lda $2000').should == 'lda $2000'
34
+ end
35
+ it "removes comment and trailing whitespace" do
36
+ @asm.uncomment('nop ; comment here').should == 'nop'
37
+ @asm.uncomment('lda #$ff; com').should == 'lda #$ff'
38
+ end
39
+ it "extracts command part of line" do
40
+ @asm.extract_command('nop').should == :nop
41
+ @asm.extract_command(' nop').should == :nop
42
+ @asm.extract_command('adc \($44\),y').should == :adc
43
+ @asm.extract_command('asl $0100').should == :asl
44
+ end
45
+ it "extracts parameter part of line" do
46
+ @asm.extract_param('and $abcd,x').should == '$abcd,x'
47
+ @asm.extract_param('cmd \($bb,x\)').should == '\($bb,x\)'
48
+ @asm.extract_param('nop').should == ''
49
+ end
50
+ end # end of "parses the pieces of a line of assembly"
51
+
52
+ # under "reads a line of assembly"
53
+ describe "determines addressing mode" do
54
+ it "immediate" do
55
+ @asm.addr_mode('#$10').should == :imm
56
+ @asm.addr_mode('#$4').should == :imm
57
+ end
58
+ it "zero page" do
59
+ @asm.addr_mode('$20').should == :zp
60
+ @asm.addr_mode('$2').should == :zp
61
+ end
62
+ it "zero page, x" do
63
+ @asm.addr_mode('$30,x').should == :zpx
64
+ @asm.addr_mode('$3,x').should == :zpx
65
+ end
66
+ it "zero page, y" do
67
+ @asm.addr_mode('$40,y').should == :zpy
68
+ @asm.addr_mode('$4,y').should == :zpy
69
+ end
70
+ it "absolute" do
71
+ @asm.addr_mode('$ffff').should == :abs
72
+ @asm.addr_mode('$eee').should == :abs
73
+ @asm.addr_mode('loop').should == :abs
74
+ end
75
+ it "absolute, x" do
76
+ @asm.addr_mode('$1000,x').should == :absx
77
+ @asm.addr_mode('$800,x').should == :absx
78
+ end
79
+ it "absolute, y" do
80
+ @asm.addr_mode('$4000,y').should == :absy
81
+ @asm.addr_mode('$f00,y').should == :absy
82
+ end
83
+ it "indirect" do
84
+ @asm.addr_mode('($deca)').should == :ind
85
+ @asm.addr_mode('($dec)').should == :ind
86
+ end
87
+ it "indirect, x" do
88
+ @asm.addr_mode('($de,x)').should == :indx
89
+ @asm.addr_mode('($b,x)').should == :indx
90
+ end
91
+ it "indirect, y" do
92
+ @asm.addr_mode('($ed),y').should == :indy
93
+ @asm.addr_mode('($e),y').should == :indy
94
+ end
95
+ it "implied" do
96
+ @asm.addr_mode('').should == :imp
97
+ end
98
+ end
99
+
100
+ # under "reads a line of assembly"
101
+ it "figures out the opcode" do
102
+ @asm.opcode(:lda, :imm).should == 0xa9
103
+ @asm.opcode(:lda, :zp).should == 0xa5
104
+ @asm.opcode(:nop, :imp).should == 0xea
105
+ end
106
+ # under "reads a line of assembly"
107
+ it "records the label and its address" do
108
+ @asm.delabel('loop: nop').should == 'nop'
109
+ @asm.labels.should == {'loop' => 0x600}
110
+ @asm.label_get('loop').should == 0x600
111
+ end
112
+ end # end of "reads a line of assembly"
113
+
114
+ # under "assembles a line of assembly"
115
+ it "records mem. bytes whose values we don't know yet" do
116
+ @asm.defer_value(0x601, 'main')
117
+ @asm.deferred.should == {0x601 => 'main'}
118
+ @asm.asm_instr('jmp main').should == [0x4c, 0xff, 0xff]
119
+ end
120
+ it "implied" do
121
+ @asm.asm_instr('nop').should == [0xea]
122
+ @asm.asm_instr('asl').should == [0x0a]
123
+ end
124
+ it "absolute" do
125
+ @asm.asm_instr('lda $dcba').should == [0xad, 0xba, 0xdc]
126
+ end
127
+ it "absolute, x" do
128
+ @asm.asm_instr('adc $cbad,x').should == [0x7d, 0xad, 0xcb]
129
+ end
130
+ it "absolute y" do
131
+ @asm.asm_instr('and $badc,y').should == [0x39, 0xdc, 0xba]
132
+ end
133
+ it "immediate" do
134
+ @asm.asm_instr('lda #$aa').should == [0xa9, 0xaa]
135
+ end
136
+ it "zero page" do
137
+ @asm.asm_instr('asl $10').should == [0x06, 0x10]
138
+ end
139
+ it "zero page, x" do
140
+ @asm.asm_instr('cmp $36,x').should == [0xd5, 0x36]
141
+ end
142
+ it "zero page, y" do
143
+ @asm.asm_instr('ldx $63,y').should == [0xb6, 0x63]
144
+ end
145
+ it "indirect" do
146
+ @asm.asm_instr('jmp ($fffe)').should == [0x6c, 0xfe, 0xff]
147
+ end
148
+ it "indirect, x" do
149
+ @asm.asm_instr('eor ($10,x)').should == [0x41, 0x10]
150
+ end
151
+ it "indirect, y" do
152
+ @asm.asm_instr('ora ($20),y').should == [0x11, 0x20]
153
+ end
154
+ it "relative" do
155
+ @asm.asm_instr('bne $12').should == [0xd0, 0x12]
156
+ end
157
+ end # end of "assembles a line of assembly"
158
+
159
+ # under "describe Assembler"
160
+ describe "puts machine code in memory" do
161
+ it "starts with pc = 0x600" do
162
+ @asm.pc.should == 0x600
163
+ end
164
+ it "places multiple bytes in memory, tracks pc" do
165
+ @asm.pc.should == 0x600
166
+ [0xa1, 0xb2, 0xc3, 0xd4].each {|b| @asm.write_byte(b) }
167
+ @mem.get_range(0x600, 0x603).should == [0xa1, 0xb2, 0xc3, 0xd4]
168
+ @asm.pc.should == 0x604
169
+ end
170
+ end
171
+
172
+ # under "describe Assembler"
173
+ describe "assembles and places (multiple) lines" do
174
+ it "processes a 1-byte instruction" do
175
+ @asm.process_line('nop ; comment')
176
+ @asm.pc.should == 0x601
177
+ @mem.get(0x600).should == 0xea
178
+ end
179
+ it "processes a mixed-case 1-byte instruction" do
180
+ @asm.process_line('NOp ; comment')
181
+ @asm.pc.should == 0x601
182
+ @mem.get(0x600).should == 0xea
183
+ end
184
+ it "processes a 2-byte instruction" do
185
+ @asm.process_line('lda #$6c')
186
+ @asm.pc.should == 0x602
187
+ @mem.get_range(0x600, 0x601).should == [0xa9, 0x6c]
188
+ end
189
+ it "processes a 3-byte instruction" do
190
+ @asm.process_line('inc $2001')
191
+ @asm.pc.should == 0x603
192
+ @mem.get_range(0x600, 0x602).should == [0xee, 0x01, 0x20]
193
+ end
194
+ it "processes a few instructions" do
195
+ @asm.process_line('nop')
196
+ @asm.process_line('asl')
197
+ @asm.process_line('ldx $55')
198
+ @asm.pc.should == 0x604
199
+ @mem.get_range(0x600, 0x603).should == [0xea, 0x0a, 0xa6, 0x55]
200
+ end
201
+ it "processes instructions with leading labels" do
202
+ @asm.process_line('top: nop')
203
+ @asm.process_line('second: asl')
204
+ @asm.process_line('third ldx $55')
205
+ @asm.process_line('fourth')
206
+ @asm.pc.should == 0x604
207
+ @mem.get_range(0x600, 0x603).should == [0xea, 0x0a, 0xa6, 0x55]
208
+ @asm.label_get('top').should == 0x600
209
+ @asm.label_get('second').should == 0x601
210
+ @asm.label_get('third').should == 0x602
211
+ @asm.label_get('fourth').should == 0x604
212
+ end
213
+ it "processes instructions with referenced-to labels" do
214
+ @asm.process_line('jmp cleanup')
215
+ @mem.get_range(0x600, 0x602).should == [0x4c, 0xff, 0xff]
216
+ @asm.deferred.should == {0x601 => 'cleanup'}
217
+ @asm.pc.should == 0x603
218
+ end
219
+ it "processes relative-addressing labels" do
220
+ @asm.process_line('beq loop')
221
+ @mem.get_range(0x600, 0x602).should == [0xf0, 0xff, 0x00]
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end