environments/cortex-m/probes/core-cpu.ldn
1import platform/cpu
2
3mut initialized: u32 = 0x670
4mut cleared: u32 = 0
5mut observed: u32 = 0
6mut interrupts: u32 = 0
7mut handler_mask: u32 = 99
8mut discarded: u32 = 0
9mut evaluations: u32 = 0
10
11operand: () -> (carrier: u32) =
12 evaluations = evaluations + 1
13 carrier = u32(usize(addr discarded))
14end operand
15
16skip_assembly: (early: bool) -> (result: u32) =
17 result = 41
18 _ = assembler.block("movs r1, #99\nstr r1, [r0]", begin
19 return when early
20 operand()
21 end)
22 result = 42
23end skip_assembly
24
25link(vector: 16)
26extern(interrupt) irq: () -> none =
27 previous := cpu.disable_interrupts()
28 nested := cpu.disable_interrupts()
29 cpu.restore_interrupts(nested)
30 handler_mask = previous + cpu.interrupt_mask()
31 cpu.restore_interrupts(previous)
32 interrupts = interrupts + 1
33end irq
34
35transport: (item: type, value: u32) -> (result: u32) =
36 result = assembler.block("adds r0, #7\nmovs r1, #99\nmovs r4, #88", value)
37end transport
38
39-- [1630]'s named operands: several outputs destructured, a block that
40-- holds every low register, general passing over a register the text
41-- writes, and a signed byte extended to the whole register on the way in.
42split: (value: u32) -> (low: u32, high: u32) =
43 (l, h) := assembler.block("lsrs {h}, {v}, #16\nuxth {l}, {v}",
44 out l: u32 at general, out h: u32 at general,
45 in v: u32 at general = value)
46 low = l
47 high = h
48end split
49
50every_register: (base: u32) -> (total: u32) =
51 (a, b, c, d, e, f, g, h) := assembler.block(
52 "adds r1, r0, #1\nadds r2, r0, #2\nadds r3, r0, #3\nadds r4, r0, #4\nadds r5, r0, #5\nadds r6, r0, #6\nadds r7, r0, #7",
53 inout a: u32 at r0 = base, out b: u32 at r1, out c: u32 at r2,
54 out d: u32 at r3, out e: u32 at r4, out f: u32 at r5,
55 out g: u32 at r6, out h: u32 at r7)
56 total = a + b + c + d + e + f + g + h
57end every_register
58
59avoided: (value: u32) -> (result: u32) =
60 result = assembler.block("movs r0, #0\nmovs r1, #0\nadds {r}, {r}, #1",
61 inout r: u32 at general = value)
62end avoided
63
64widened: (value: i8) -> (result: i32) =
65 result = assembler.block("mov {r}, {v}", out r: i32 at general,
66 in v: i8 at general = value)
67end widened
68
69temporary_mask: (early: bool) -> (masked: u32) =
70 previous := cpu.disable_interrupts()
71 defer cpu.restore_interrupts(previous)
72 masked = cpu.interrupt_mask()
73 return when early
74 masked = masked + cpu.interrupt_mask()
75end temporary_mask
76
77start: () -> none =
78 observed = 1
79 return when initialized <> 0x670 or cleared <> 0
80 return when cpu.interrupt_mask() <> 0
81 previous := cpu.disable_interrupts()
82 return when previous <> 0 or cpu.interrupt_mask() <> 1
83 nested := cpu.disable_interrupts()
84 return when nested <> 1
85 cpu.restore_interrupts(nested)
86 return when cpu.interrupt_mask() <> 1
87 cpu.restore_interrupts(previous)
88 return when cpu.interrupt_mask() <> 0
89 return when temporary_mask(true) <> 1 or cpu.interrupt_mask() <> 0
90 return when temporary_mask(false) <> 2 or cpu.interrupt_mask() <> 0
91 outer := cpu.disable_interrupts()
92 return when temporary_mask(true) <> 1 or cpu.interrupt_mask() <> 1
93 cpu.restore_interrupts(outer)
94
95 mut value: u32 = 35
96 answer := transport(item: u32, value: value)
97 return when answer <> 42 or value <> 35
98 before := discarded
99 _ = assembler.block("movs r1, #73\nstr r1, [r0]", operand())
100 return when before <> 0 or discarded <> 73 or evaluations <> 1
101 return when skip_assembly(true) <> 41
102 return when discarded <> 73 or evaluations <> 1
103 return when value <> 35
104 (low, high) := split(0x12345678)
105 return when low <> 0x5678 or high <> 0x1234
106 return when every_register(10) <> 108
107 return when avoided(41) <> 42
108 return when widened(-3) <> -3
109
110 saved := cpu.disable_interrupts()
111 enable: ptr mut u32 = ptr(0xe000e100)
112 pending: ptr mut u32 = ptr(0xe000e200)
113 compiler.volatile_store(enable, 1)
114 compiler.volatile_store(pending, 1)
115 cpu.completion_barrier()
116 cpu.wait_for_interrupt()
117 return when interrupts <> 0 or cpu.interrupt_mask() <> 1
118 cpu.restore_interrupts(saved)
119 while interrupts == 0 do
120 cpu.wait_for_interrupt()
121 end while
122 return when interrupts <> 1 or handler_mask <> 1
123 return when cpu.interrupt_mask() <> 0
124 cpu.device_barrier()
125 cpu.compiler_barrier()
126 observed = 0x670
127end start