Hi.
I’ve dug out Arduino Nano from my stash and now I’m trying to re-implement one of my old pet project in Zig. After some lurking I wrote this:
const PORTBDATA: u8 = 0x25;
const PORTBDIR: u8 = 0x24;
inline fn cli() void {
asm volatile ("cli");
}
inline fn sei() void {
asm volatile ("sei");
}
inline fn setBit(port: *u8, n: u4) void {
port.* |= (1 << n);
}
export fn __vector_14() callconv(.Signal) void {
const x: u8 = 9;
const y: u8 = 8;
_ = x + y;
}
export fn main () void {
asm volatile ("cli");
cli();
const pbd: *u8 = @ptrFromInt(PORTBDIR);
const pb: *u8 = @ptrFromInt(PORTBDATA);
//pbd.* = 0xff;
// pbd.* |= (1 << 5); // -> sbi 4, 5
setBit(pbd, 5);
//pb.* &= ~(@as(u8, 1) << 5);
pb.* |= (1 << 5);
// yessss, same code as with avr-gcc
// pb.* ^= (1 << 5); // too long
while(true) {}
}
There is no much sense in this code, but it does not matter.
The problem is in generated code, which I obtained like this:
zig build-obj -femit-asm -O ReleaseSmall -target avr-freestanding-eabi 2.zig
avr-ld -o 2.elf 2.o
avr-objcopy -j .text -j .data -O ihex 2.elf 2.hex
Looking at disassembled code
Disassembly of section .text:
00000000 <__vector_14>:
0: 0f 92 push r0
2: 0f b6 in r0, 0x3f ; 63
4: 0f 92 push r0
6: 0f 90 pop r0
8: 0f be out 0x3f, r0 ; 63
a: 0f 90 pop r0
c: 18 95 reti
we see that it starts from that ISR and this is completely wrong.
For comparison, avr-gcc
produces the jump (interrupt vector) table in the very beginning:
00000000 <__vectors>:
0: 0c 94 3a 00 jmp 0x74 ; 0x74 <__ctors_end>
4: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
8: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
c: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
10: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
14: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
18: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
1c: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
20: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
24: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
28: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
2c: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
30: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
34: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
38: 0c 94 5c 00 jmp 0xb8 ; 0xb8 <__vector_14>
3c: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
40: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
44: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
48: 0c 94 a9 00 jmp 0x152 ; 0x152 <__vector_18>
4c: 0c 94 7e 00 jmp 0xfc ; 0xfc <__vector_19>
50: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
54: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
58: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
5c: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
60: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
64: 0c 94 57 00 jmp 0xae ; 0xae <__bad_interrupt>
Is there some way to make zig/llvm do the same?
Also, avr-gcc
generates some code for copying global variables (from flash to RAM):
00000080 <__do_copy_data>:
80: 12 e0 ldi r17, 0x02 ; 2
82: a0 e0 ldi r26, 0x00 ; 0
84: b1 e0 ldi r27, 0x01 ; 1
86: e6 eb ldi r30, 0xB6 ; 182
88: f2 e1 ldi r31, 0x12 ; 18
8a: 02 c0 rjmp .+4 ; 0x90 <__do_copy_data+0x10>
8c: 05 90 lpm r0, Z+
8e: 0d 92 st X+, r0
90: ae 30 cpi r26, 0x0E ; 14
92: b1 07 cpc r27, r17
94: d9 f7 brne .-10 ; 0x8c <__do_copy_data+0xc>
Zig doesn’t
Does this mean that currently Zig is not completely ready for AVR8?
Or maybe I do not understand something?