1use crate::{
4 builder::pass1::BuildResultPass1,
5 context::{CommonContext, Context},
6 directive::GetData,
7 expr::Expr,
8 instruction::{process, register::Reg8},
9 parser::{DataDefine, Item, Segment, SegmentType},
10};
11
12use std::str::FromStr;
13
14use failure::{bail, Error};
15
16#[derive(Clone, PartialEq, Eq, Debug)]
17pub struct BuildResultPass2 {
18 pub code_start_address: u32,
19 pub code: Vec<u8>,
20 pub eeprom_start_address: u32,
21 pub eeprom: Vec<u8>,
22 pub ram_filling: u32,
23 pub messages: Vec<String>,
24}
25
26pub fn build_pass_2(
27 pass1: BuildResultPass1,
28 common_context: &CommonContext,
29) -> Result<BuildResultPass2, Error> {
30 let mut code = vec![];
31 let code_start_address = 0x0;
32 let mut eeprom = vec![];
33 let eeprom_start_address = 0x0;
34
35 for segment in pass1.segments {
36 match segment.t {
38 SegmentType::Code => {
39 for _ in (code_start_address as i32)..segment.address as i32 - code.len() as i32 / 2
41 {
42 code.extend(vec![0x00, 0x00]);
44 }
45 }
46 SegmentType::Eeprom => {
47 for _ in (eeprom_start_address as i32)..segment.address as i32 - eeprom.len() as i32
49 {
50 eeprom.extend(vec![0x00]);
52 }
53 }
54 SegmentType::Data => {}
56 }
57
58 let fragment = pass_2_internal(&segment, common_context)?;
59
60 match segment.t {
61 SegmentType::Code => {
62 code.extend(fragment);
63 }
64 SegmentType::Eeprom => {
65 eeprom.extend(fragment);
66 }
67 SegmentType::Data => {}
69 }
70 }
71
72 Ok(BuildResultPass2 {
73 code_start_address,
74 code,
75 eeprom_start_address,
76 eeprom,
77 ram_filling: pass1.ram_filling,
78 messages: pass1.messages,
79 })
80}
81
82fn pass_2_internal(segment: &Segment, common_context: &CommonContext) -> Result<Vec<u8>, Error> {
83 let mut code_fragment = vec![];
84
85 let mut cur_address = segment.address;
86
87 for (line, item) in segment.items.iter() {
88 common_context.set_special("pc".to_string(), Expr::Const(cur_address as i64));
89 match item {
90 Item::Instruction(op, op_args) => {
91 if common_context.get_device().check_operation(op) {
92 let complete_op = match process(&op, &op_args, cur_address, common_context) {
93 Ok(ok) => ok,
94 Err(e) => bail!("{}, {}", e, line),
95 };
96 cur_address += complete_op.len() as u32 / 2;
97 code_fragment.extend(complete_op);
98 } else {
99 bail!(
100 "instruction {} is not allowed for current device, {}",
101 op,
102 line
103 )
104 }
105 }
106 Item::Data(item_type, items) => {
107 let data = match item_type {
108 DataDefine::Db => items.get_bytes(common_context),
109 DataDefine::Dw => items.get_words(common_context),
110 DataDefine::Dd => items.get_double_words(common_context),
111 DataDefine::Dq => items.get_quad_words(common_context),
112 }?;
113 cur_address += if let SegmentType::Code = segment.t {
114 data.len() as u32 / 2
115 } else {
116 data.len() as u32
117 };
118 code_fragment.extend(data);
119 }
120 Item::ReserveData(size) => {
121 cur_address += *size as u32;
122 for _ in 0..*size {
123 code_fragment.push(0x0);
124 }
125 }
126 Item::Def(alias, Expr::Ident(register)) => {
127 if let Some(_) = common_context.set_def(
128 alias.to_lowercase(),
129 Reg8::from_str(register.to_lowercase().as_str()).unwrap(),
130 ) {
131 bail!("Identifier {} is used twice, {}", alias, line);
133 }
134 }
135 Item::Undef(alias) => {
136 if let None = common_context.defs.borrow_mut().remove(alias) {
137 bail!("Identifier {} isn't defined, {}", alias, line);
138 }
139 }
140 Item::Set(name, expr) => {
141 let value = expr.run(common_context)?;
142 if common_context.exist(name) {
143 let mut sets = common_context.sets.borrow_mut();
144 if let Some(_) = sets.get(name) {
145 sets.insert(name.clone(), Expr::Const(value));
146 } else {
147 bail!("Identifier {} is used twice, {}", name, line);
149 }
150 } else {
151 common_context
152 .sets
153 .borrow_mut()
154 .insert(name.clone(), Expr::Const(value));
155 }
156 }
157 _ => {}
158 }
159 }
160
161 Ok(code_fragment)
162}
163
164#[cfg(test)]
165mod builder_tests {
166 use super::*;
167 use crate::{
168 builder::{
169 pass0::{build_pass_0, BuildResultPass0},
170 pass1::build_pass_1,
171 },
172 parser::parse_str,
173 };
174
175 #[test]
176 fn check_empty() {
177 let common_context = CommonContext::new();
178 let build_result = build_pass_2(
179 build_pass_1(BuildResultPass0::new(), &common_context).unwrap(),
180 &common_context,
181 );
182 assert_eq!(
183 build_result.unwrap(),
184 BuildResultPass2 {
185 code_start_address: 0x0,
186 code: vec![],
187 eeprom_start_address: 0x0,
188 eeprom: vec![],
189 ram_filling: 0,
190 messages: vec![],
191 }
192 );
193 }
194
195 #[test]
196 fn check_no_args() {
197 let common_context = CommonContext::new();
198 let parse_result = parse_str(
199 "
200 nop
201 ret
202 seh
203 clh
204 ",
205 &common_context,
206 );
207 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
208
209 let build_result = build_pass_2(
210 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
211 &common_context,
212 );
213 assert_eq!(
214 build_result.unwrap(),
215 BuildResultPass2 {
216 code_start_address: 0x0,
217 code: vec![0x00, 0x00, 0x08, 0x95, 0x58, 0x94, 0xd8, 0x94],
218 eeprom_start_address: 0x0,
219 eeprom: vec![],
220 ram_filling: 0,
221 messages: vec![],
222 }
223 );
224 }
225
226 #[test]
227 fn check_one_arg() {
228 let common_context = CommonContext::new();
229 let parse_result = parse_str(
230 "
231 push r0
232 lsl r0
233 swap r0
234 pop r1
235 ",
236 &common_context,
237 );
238 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
239
240 let build_result = build_pass_2(
241 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
242 &common_context,
243 );
244 assert_eq!(
245 build_result.unwrap(),
246 BuildResultPass2 {
247 code_start_address: 0x0,
248 code: vec![0xf, 0x92, 0x0, 0xc, 0x2, 0x94, 0x1f, 0x90],
249 eeprom_start_address: 0x0,
250 eeprom: vec![],
251 ram_filling: 0,
252 messages: vec![],
253 }
254 );
255
256 let common_context = CommonContext::new();
257 let parse_result = parse_str(
258 "
259 tst r1
260error:
261 brpl exit
262exit:
263 rjmp error
264 ",
265 &common_context,
266 );
267 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
268
269 let build_result = build_pass_2(
270 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
271 &common_context,
272 );
273 assert_eq!(
274 build_result.unwrap(),
275 BuildResultPass2 {
276 code_start_address: 0x0,
277 code: vec![0x11, 0x20, 0x2, 0xf4, 0xfe, 0xcf],
278 eeprom_start_address: 0x0,
279 eeprom: vec![],
280 ram_filling: 0,
281 messages: vec![],
282 }
283 );
284 }
285
286 #[test]
287 fn check_two_args() {
288 let common_context = CommonContext::new();
289 let parse_result = parse_str(
290 "
291 ldi r16, 1 << 2 | 1 << 1
292 mov r0, r16
293 subi r16, (-1)
294 sts data, r16
295data:
296 ",
297 &common_context,
298 );
299 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
300
301 let build_result = build_pass_2(
302 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
303 &common_context,
304 );
305 assert_eq!(
306 build_result.unwrap(),
307 BuildResultPass2 {
308 code_start_address: 0x0,
309 code: vec![0x6, 0xe0, 0x0, 0x2e, 0xf, 0x5f, 0x0, 0x93, 0x5, 0x0],
310 eeprom_start_address: 0x0,
311 eeprom: vec![],
312 ram_filling: 0,
313 messages: vec![],
314 }
315 );
316
317 let common_context = CommonContext::new();
318 let parse_result = parse_str(
319 "
320 ld r17, X
321 ld r18, Y+
322 ld r19, -Z
323 st X+, r19
324 ",
325 &common_context,
326 );
327 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
328
329 let build_result = build_pass_2(
330 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
331 &common_context,
332 );
333 assert_eq!(
334 build_result.unwrap(),
335 BuildResultPass2 {
336 code_start_address: 0x0,
337 code: vec![0x1c, 0x91, 0x29, 0x91, 0x32, 0x91, 0x3d, 0x93],
338 eeprom_start_address: 0x0,
339 eeprom: vec![],
340 ram_filling: 0,
341 messages: vec![],
342 }
343 );
344
345 let common_context = CommonContext::new();
346 let parse_result = parse_str(
347 "
348 ldd r25, Z+2
349 std Z+6, r24
350 ",
351 &common_context,
352 );
353 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
354
355 let build_result = build_pass_2(
356 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
357 &common_context,
358 );
359 assert_eq!(
360 build_result.unwrap(),
361 BuildResultPass2 {
362 code_start_address: 0x0,
363 code: vec![0x92, 0x81, 0x86, 0x83],
364 eeprom_start_address: 0x0,
365 eeprom: vec![],
366 ram_filling: 0,
367 messages: vec![],
368 }
369 );
370 }
371
372 #[test]
373 fn check_db_dw_dd_dq() {
374 let common_context = CommonContext::new();
375 let parse_result = parse_str(
376 "
377 .equ end = 0
378 ldi r16, data
379data: .db 15, 26, \"Hello, World\", end
380 ",
381 &common_context,
382 );
383 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
384
385 let build_result = build_pass_2(
386 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
387 &common_context,
388 );
389 assert_eq!(
390 build_result.unwrap(),
391 BuildResultPass2 {
392 code_start_address: 0x0,
393 code: vec![
394 0x1, 0xe0, 0xf, 0x1a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f,
395 0x72, 0x6c, 0x64, 0x0, 0x0
396 ],
397 eeprom_start_address: 0x0,
398 eeprom: vec![],
399 ram_filling: 0,
400 messages: vec![],
401 }
402 );
403
404 let common_context = CommonContext::new();
405 let parse_result = parse_str(
406 "
407 .equ end = 0
408 ldi r18, data_w
409data_w:
410 .dw 0xff44, end, 0xda4e
411 ",
412 &common_context,
413 );
414 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
415
416 let build_result = build_pass_2(
417 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
418 &common_context,
419 );
420 assert_eq!(
421 build_result.unwrap(),
422 BuildResultPass2 {
423 code_start_address: 0x0,
424 code: vec![0x21, 0xe0, 0x44, 0xff, 0x0, 0x0, 0x4e, 0xda],
425 eeprom_start_address: 0x0,
426 eeprom: vec![],
427 ram_filling: 0,
428 messages: vec![],
429 }
430 );
431
432 let common_context = CommonContext::new();
433 let parse_result = parse_str(
434 "
435 ldi r18, data_d
436data_d:
437 .dd 0x12345678, 0x9abcdef0
438 ",
439 &common_context,
440 );
441 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
442
443 let build_result = build_pass_2(
444 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
445 &common_context,
446 );
447 assert_eq!(
448 build_result.unwrap(),
449 BuildResultPass2 {
450 code_start_address: 0x0,
451 code: vec![0x21, 0xe0, 0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a],
452 eeprom_start_address: 0x0,
453 eeprom: vec![],
454 ram_filling: 0,
455 messages: vec![],
456 }
457 );
458
459 let common_context = CommonContext::new();
460 let parse_result = parse_str(
461 "
462 ldi r18, data_q
463data_q:
464 .dq 0x1, 0x1000000000011000
465 ",
466 &common_context,
467 );
468 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
469
470 let build_result = build_pass_2(
471 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
472 &common_context,
473 );
474 assert_eq!(
475 build_result.unwrap(),
476 BuildResultPass2 {
477 code_start_address: 0x0,
478 code: vec![
479 0x21, 0xe0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1, 0x0, 0x0,
480 0x0, 0x0, 0x10
481 ],
482 eeprom_start_address: 0x0,
483 eeprom: vec![],
484 ram_filling: 0,
485 messages: vec![],
486 }
487 );
488 }
489
490 #[test]
491 fn check_cseg_org() {
492 let common_context = CommonContext::new();
493 let parse_result = parse_str(
494 "
495 nop
496 .org 0x2
497 seh
498 .cseg
499 .org 0x5
500 clh
501 ",
502 &common_context,
503 );
504 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
505
506 let build_result = build_pass_2(
507 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
508 &common_context,
509 );
510 assert_eq!(
511 build_result.unwrap(),
512 BuildResultPass2 {
513 code_start_address: 0x0,
514 code: vec![0x00, 0x00, 0x00, 0x00, 0x58, 0x94, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x94],
515 eeprom_start_address: 0x0,
516 eeprom: vec![],
517 ram_filling: 0,
518 messages: vec![],
519 }
520 );
521 }
522
523 #[test]
524 fn check_eseg() {
525 let common_context = CommonContext::new();
526 let parse_result = parse_str(
527 "
528 .equ end = 0
529 ldi r18, data_w
530 .eseg
531data_w:
532 .dw 0xff44, end, 0xda4e
533 ",
534 &common_context,
535 );
536 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
537
538 let build_result = build_pass_2(
539 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
540 &common_context,
541 );
542 assert_eq!(
543 build_result.unwrap(),
544 BuildResultPass2 {
545 code_start_address: 0x0,
546 code: vec![0x20, 0xe0],
547 eeprom_start_address: 0x0,
548 eeprom: vec![0x44, 0xff, 0x0, 0x0, 0x4e, 0xda],
549 ram_filling: 0,
550 messages: vec![],
551 }
552 );
553 }
554
555 #[test]
556 fn check_dseg() {
557 let common_context = CommonContext::new();
558 let parse_result = parse_str(
559 "
560.dseg
561data: .byte 1
562counter:
563 .byte 2
564 .cseg
565 lds r18, data
566 lds r16, counter
567 lds r17, counter+1
568 ",
569 &common_context,
570 );
571 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
572
573 let build_result = build_pass_2(
574 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
575 &common_context,
576 );
577 assert_eq!(
578 build_result.unwrap(),
579 BuildResultPass2 {
580 code_start_address: 0x0,
581 code: vec![0x20, 0x91, 0x60, 0x0, 0x0, 0x91, 0x61, 0x0, 0x10, 0x91, 0x62, 0x0],
582 eeprom_start_address: 0x0,
583 eeprom: vec![],
584 ram_filling: 3,
585 messages: vec![],
586 }
587 );
588 }
589
590 #[test]
591 fn relatives_branch() {
592 let common_context = CommonContext::new();
593 let parse_result = parse_str(
594 "
595 subi r16, 1
596 breq pc-1
597 rjmp pc
598 ",
599 &common_context,
600 );
601 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
602
603 let build_result = build_pass_2(
604 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
605 &common_context,
606 );
607 assert_eq!(
608 build_result.unwrap(),
609 BuildResultPass2 {
610 code_start_address: 0x0,
611 code: vec![0x1, 0x50, 0xf1, 0xf3, 0xff, 0xcf],
612 eeprom_start_address: 0x0,
613 eeprom: vec![],
614 ram_filling: 0,
615 messages: vec![],
616 }
617 );
618 }
619
620 #[test]
621 fn avr8l_lds_sts() {
622 let common_context = CommonContext::new();
623 let parse_result = parse_str(
624 "
625 .device ATtiny20
626 .dseg
627counter: .byte 1
628 .cseg
629 lds r18, counter
630 inc r18
631 sts counter, r18
632 ",
633 &common_context,
634 );
635 let post_parse_result = build_pass_0(parse_result.unwrap(), &common_context);
636
637 let build_result = build_pass_2(
638 build_pass_1(post_parse_result.unwrap(), &common_context).unwrap(),
639 &common_context,
640 );
641 assert_eq!(
642 build_result.unwrap(),
643 BuildResultPass2 {
644 code_start_address: 0x0,
645 code: vec![0x20, 0xa1, 0x23, 0x95, 0x20, 0xa9],
646 eeprom_start_address: 0x0,
647 eeprom: vec![],
648 ram_filling: 1,
649 messages: vec![],
650 }
651 );
652 }
653}