Landin library reference source

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