.global _start _start: mova stack_top,r0 mov r0,r15 /* part1 */ mova _part1,r0 mov r0,r14 mova solve,r0 jsr @r0 nop /* move part1 answer to GBR */ ldc r13,gbr /* part2 */ mova _part2,r0 mov r0,r14 mova solve,r0 jsr @r0 nop /* move part2 answer to VBR */ ldc r13,vbr trapa #0 /* return number of valid passwords in r13 */ .balign 4 solve: sts.l pr,@-r15 mov.l start,r8 mov.l end,r9 /* password is from r1 to r8, excluding r8; next line is at r8 */ mov #0,r13 line_loop: mova _parse_line,r0 jsr @r0 nop jsr @r14 nop cmp/eq r8,r9 bf/s line_loop add r1,r13 lds.l @r15+,pr rts nop /* return: valid as `1` in r1 */ /* r10: test position 1 */ /* r11: test position 2 */ /* r12: test character */ .balign 4 _part2: add #-1,r1 /* offset for 1-based indexing */ mov r10,r0 mov.b @(r0,r1),r3 /* r3: character */ cmp/eq r3,r12 movt r2 mov r11,r0 mov.b @(r0,r1),r3 /* r3: character */ cmp/eq r3,r12 movt r1 rts xor r2,r1 /* return: valid as `1` in r1 */ /* r10: count >= lower bound */ /* r11: count <= upper bound */ /* r12: test character */ .balign 4 _part1: mov #0,r2 /* r2: count */ part1_loop: cmp/eq r1,r8 bt part1_break mov.b @r1+,r3 /* r3: character */ cmp/eq r3,r12 movt r0 bra part1_loop add r0,r2 part1_break: /* lower bound */ cmp/hs r10,r2 /* Rn ≥ Rm (unsigned) ; r2 >= r10 */ movt r0 cmp/hs r2,r11 /* Rn ≥ Rm (unsigned) ; r11 >= r2 */ movt r1 rts and r0,r1 .balign 4 _parse_line: /* save PR */ sts.l pr,@-r15 mov.l parse_base10_ptr,r0 jsr @r0 nop mov r1,r10 /* r10: first number */ mov.l parse_base10_ptr,r0 jsr @r0 nop mov r1,r11 /* r11: second number */ mov.b @r8+,r12 /* r12: character */ /* skip colon character ; skip space character */ add #2,r8 /* advance until newline */ mov r8,r1 newline_loop: mov.b @r8+,r0 cmp/eq #0xa,r0 bf newline_loop /* restore PR */ lds.l @r15+,pr rts nop .balign 4 parse_base10_ptr: /* r8 = pointer to text ; r1 = returned number */ .long _parse_base10 .balign 4 start: .long _binary_2020_day2_input_txt_start end: .long _binary_2020_day2_input_txt_end .balign 4 stack_bot: .rept 16 .long 0 .endr stack_top: