aboutsummaryrefslogtreecommitdiff
path: root/assembler/assemble.s
blob: ef3893ddbad86c328978e8bf4e11e5552cff647d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
.syntax unified
.cpu cortex-m0plus
.thumb

.type assemble, %function
.global assemble

// TODO:
// - implement opcode parser
// - test each instruction (do this later -- much easier)
// - test 4-bit reg instructions
// - test BEQ overlaps
// - decide on additional push or pops

assemble:
  // LDR R3, [SP, 20]
  MOVS R6, 0
  LDR R7, =0x00C8E893
  // LDR R7, =0xE0E3A588
  MOVS R0, ' 
  MOV R8, R0
main_loop:
  LSRS R0, R7, 8    // just peek
  BNE skip          // if more stuff then skip
  MOVS R0, '\r
  MOV R8, R0        //set end char to carriage return
skip:
  // MOVS R0, 0xFF     // lsb mask
  // ANDS R0, R7       // store in R0
  UXTB R0, R7       // store lsb in R0
  LSRS R1, R0, 4    // upper nibble
  CMP R1, 0xC       // if 0xxxxxxx or 10xxxxxx
  BLO opcode
  CMP R1, 0xE       // if 110xyyyy
  BLO handle_imm
handle_reg:         // if 111xyyyy
  MOVS R1, (1<<4)   // bit 4 mask
  ANDS R0, R1       // get bit 4
  ADDS R0, 3        // add 3 to it (now 3 or 4)
  BL register       // result is put in R4
  MOVS R0, 0x0F     // lower nibble mask
  ANDS R0, R7       // store shift amount in R0
  LSLS R4, R0       // shift the result by the shift amount
  ORRS R6, R4       // OR the register code into the word under construction
  B done_stuff
opcode:
  MOVS R2, 9        // shift amount for 7-bit opcode
  MOVS R1, (1<<7)   // bit 7 mask
  TST R0, R1        // check bit 7
  BEQ fin           // if zero done
  BICS R0, R1       // clear bit 7
  MOVS R2, 11       // shift amount for 5-bit opcode high
  MOVS R1, (1<<5)   // bit 5 mask
  TST R0, R1        // check bit 5
  BEQ fin           // if zero done
  BICS R0, R1       // clear bit 5
  MOVS R2, 6        // shift amount for 5-bit opcode low
fin:
  LSLS R0, R2
  ORRS R6, R0
  B here
handle_imm:
  MOVS R1, 0x0F  // lower nibble mask
  ANDS R0, R1    // store immediate width in R0
  BL octal       // result is put in R4
  LSLS R0, R7, 27
  LSRS R0, 31
  MOVS R2, 6
  MULS R0, R2    // R0 has shift amount (0 or 6)
  LSLS R4, R0    // shift the result by the shift amount
  ORRS R6, R4    // OR the immediate into the word under construction
done_stuff:
  MOV R0, R8     // copy the end_char into R0
  BL uart_send   // echo the space (or carriage return)
here:
  LSRS R7, 0x8   // get next parse instruction
  BNE main_loop  // if it's nonzero there are more things to parse
done:
  MOVS R0, '\n  // send newline
  BL uart_send
  MOVS R0, R6
  BL send_hex
  B assemble

.type get_char, %function
.global get_char

// R8: end_char
get_char:
  PUSH {LR}
  BL uart_recv
  CMP R0, 025 // ^U (NAK)
  BEQ redo_line
  // CMP R0, 004 // ^D (EOT)
  // BEQ done_for_real
  CMP R0, R8
  POP {PC}
redo_line:
  POP {R0}
  B done