diff --git a/sim/aviron/src/lib/Cpu.zig b/sim/aviron/src/lib/Cpu.zig index 9525f46eb..36ff7175a 100644 --- a/sim/aviron/src/lib/Cpu.zig +++ b/sim/aviron/src/lib/Cpu.zig @@ -755,7 +755,7 @@ const instructions = struct { cpu.sreg.z = (res == 0); cpu.sreg.n = ((res & 0x8000) != 0); cpu.sreg.c = ((src & 0x8000) == 0) and ((res & 0x8000) != 0); - cpu.sreg.v = cpu.sreg.c; + cpu.sreg.v = ((src & 0x8000) != 0) and ((res & 0x8000) == 0); cpu.sreg.s = (cpu.sreg.n != cpu.sreg.v); } diff --git a/sim/aviron/src/testrunner.zig b/sim/aviron/src/testrunner.zig index a39bc2899..d38adcb77 100644 --- a/sim/aviron/src/testrunner.zig +++ b/sim/aviron/src/testrunner.zig @@ -172,8 +172,8 @@ fn run_test( }; // Check if it was a system exit (via IO) - const exit_mode: ExitMode = if (io.exit_requested) - .{ .system_exit = io.exit_code.? } + const exit_mode: ExitMode = if (io.exit_code) |code| + .{ .system_exit = code } else switch (result) { .breakpoint => .breakpoint, .enter_sleep_mode => .enter_sleep_mode, @@ -310,7 +310,6 @@ const IO = struct { // Exit status tracking exit_code: ?u8 = null, - exit_requested: bool = false, const DataBusType = aviron.Bus(.{ .address_type = u24 }); const IOBusType = aviron.IOBus; @@ -433,7 +432,6 @@ const IO = struct { switch (reg) { .exit => { io.exit_code = value & mask; - io.exit_requested = true; }, .stdio => io.stdout.append(value & mask) catch @panic("out of memory"), @@ -497,7 +495,9 @@ const IO = struct { fn dev_check_exit(ctx: *anyopaque) ?u8 { const io: *IO = @ptrCast(@alignCast(ctx)); - if (io.exit_requested) return io.exit_code; + if (io.exit_code) |code| { + return code; + } return null; } }; diff --git a/sim/aviron/testsuite.avr-gcc/instructions/sbiw.S b/sim/aviron/testsuite.avr-gcc/instructions/sbiw.S new file mode 100644 index 000000000..fd8ea790a --- /dev/null +++ b/sim/aviron/testsuite.avr-gcc/instructions/sbiw.S @@ -0,0 +1,56 @@ +//! { +//! "exit": "breakpoint", +//! "cpus": ["atmega2560", "atmega328p"], +//! "precondition": { +//! "r24": 0, +//! "r25": 0, +//! "r26": 0, +//! "r27": 128, +//! "r28": 8, +//! "r29": 0, +//! "r30": 255, +//! "r31": 255 }, +//! "postcondition": { +//! "r16": 21, +//! "r17": 24, +//! "r18": 2, +//! "r19": 20, +//! "r24": 248, +//! "r25": 255, +//! "r26": 255, +//! "r27": 127, +//! "r28": 0, +//! "r29": 0, +//! "r30": 192, +//! "r31": 255 } +//! } + + ; Test case 1: 0x0000 - 0x08 = 0xFFF8 + ; Precondition: r25:r24 = 0x0000 + ; Expected: r25:r24 = 0xFFF8, C=1, N=1, V=0, S=1, Z=0 + ; SREG should be 0x15 (C=1, Z=0, N=1, V=0, S=1) + sbiw r24, 0x8 + in r16, 0x3F ; Save SREG to r16 + + ; Test case 2: 0x8000 - 0x01 = 0x7FFF (overflow) + ; Precondition: r27:r26 = 0x8000 + ; Expected: r27:r26 = 0x7FFF, C=0, N=0, V=1, S=1, Z=0 + ; SREG should be 0x18 (C=0, Z=0, N=0, V=1, S=1) + sbiw r26, 0x1 + in r17, 0x3F ; Save SREG to r17 + + ; Test case 3: 0x0008 - 0x08 = 0x0000 (zero result) + ; Precondition: r29:r28 = 0x0008 + ; Expected: r29:r28 = 0x0000, C=0, N=0, V=0, S=0, Z=1 + ; SREG should be 0x02 (C=0, Z=1, N=0, V=0, S=0) + sbiw r28, 0x8 + in r18, 0x3F ; Save SREG to r18 + + ; Test case 4: 0xFFFF - 0x3F = 0xFFC0 + ; Precondition: r31:r30 = 0xFFFF + ; Expected: r31:r30 = 0xFFC0, C=0, N=1, V=0, S=1, Z=0 + ; SREG should be 0x14 (C=0, Z=0, N=1, V=0, S=1) + sbiw r30, 0x3F + in r19, 0x3F ; Save SREG to r19 + + break diff --git a/sim/aviron/testsuite/instructions/sbiw-atmega2560.elf b/sim/aviron/testsuite/instructions/sbiw-atmega2560.elf new file mode 100755 index 000000000..3b8fd2a0f Binary files /dev/null and b/sim/aviron/testsuite/instructions/sbiw-atmega2560.elf differ diff --git a/sim/aviron/testsuite/instructions/sbiw-atmega2560.elf.json b/sim/aviron/testsuite/instructions/sbiw-atmega2560.elf.json new file mode 100644 index 000000000..6086d1019 --- /dev/null +++ b/sim/aviron/testsuite/instructions/sbiw-atmega2560.elf.json @@ -0,0 +1,106 @@ +{ + "exit": "breakpoint", + "exit_code": 0, + "stdout": "", + "stderr": "", + "stdin": "", + "precondition": { + "sreg": { + "c": null, + "z": null, + "n": null, + "v": null, + "s": null, + "h": null, + "t": null, + "i": null + }, + "r0": null, + "r1": null, + "r2": null, + "r3": null, + "r4": null, + "r5": null, + "r6": null, + "r7": null, + "r8": null, + "r9": null, + "r10": null, + "r11": null, + "r12": null, + "r13": null, + "r14": null, + "r15": null, + "r16": null, + "r17": null, + "r18": null, + "r19": null, + "r20": null, + "r21": null, + "r22": null, + "r23": null, + "r24": 0, + "r25": 0, + "r26": 0, + "r27": 128, + "r28": 8, + "r29": 0, + "r30": 255, + "r31": 255 + }, + "postcondition": { + "sreg": { + "c": null, + "z": null, + "n": null, + "v": null, + "s": null, + "h": null, + "t": null, + "i": null + }, + "r0": null, + "r1": null, + "r2": null, + "r3": null, + "r4": null, + "r5": null, + "r6": null, + "r7": null, + "r8": null, + "r9": null, + "r10": null, + "r11": null, + "r12": null, + "r13": null, + "r14": null, + "r15": null, + "r16": 21, + "r17": 24, + "r18": 2, + "r19": 20, + "r20": null, + "r21": null, + "r22": null, + "r23": null, + "r24": 248, + "r25": 255, + "r26": 255, + "r27": 127, + "r28": 0, + "r29": 0, + "r30": 192, + "r31": 255 + }, + "mileage": 0, + "cpu": "atmega2560", + "cpus": null, + "optimize": "ReleaseSmall", + "gcc_flags": [ + "-g", + "-O2", + "-nostdlib", + "-nostdinc", + "-ffreestanding" + ] +} \ No newline at end of file diff --git a/sim/aviron/testsuite/instructions/sbiw-atmega328p.elf b/sim/aviron/testsuite/instructions/sbiw-atmega328p.elf new file mode 100755 index 000000000..1b87a09f2 Binary files /dev/null and b/sim/aviron/testsuite/instructions/sbiw-atmega328p.elf differ diff --git a/sim/aviron/testsuite/instructions/sbiw-atmega328p.elf.json b/sim/aviron/testsuite/instructions/sbiw-atmega328p.elf.json new file mode 100644 index 000000000..2a3da12aa --- /dev/null +++ b/sim/aviron/testsuite/instructions/sbiw-atmega328p.elf.json @@ -0,0 +1,106 @@ +{ + "exit": "breakpoint", + "exit_code": 0, + "stdout": "", + "stderr": "", + "stdin": "", + "precondition": { + "sreg": { + "c": null, + "z": null, + "n": null, + "v": null, + "s": null, + "h": null, + "t": null, + "i": null + }, + "r0": null, + "r1": null, + "r2": null, + "r3": null, + "r4": null, + "r5": null, + "r6": null, + "r7": null, + "r8": null, + "r9": null, + "r10": null, + "r11": null, + "r12": null, + "r13": null, + "r14": null, + "r15": null, + "r16": null, + "r17": null, + "r18": null, + "r19": null, + "r20": null, + "r21": null, + "r22": null, + "r23": null, + "r24": 0, + "r25": 0, + "r26": 0, + "r27": 128, + "r28": 8, + "r29": 0, + "r30": 255, + "r31": 255 + }, + "postcondition": { + "sreg": { + "c": null, + "z": null, + "n": null, + "v": null, + "s": null, + "h": null, + "t": null, + "i": null + }, + "r0": null, + "r1": null, + "r2": null, + "r3": null, + "r4": null, + "r5": null, + "r6": null, + "r7": null, + "r8": null, + "r9": null, + "r10": null, + "r11": null, + "r12": null, + "r13": null, + "r14": null, + "r15": null, + "r16": 21, + "r17": 24, + "r18": 2, + "r19": 20, + "r20": null, + "r21": null, + "r22": null, + "r23": null, + "r24": 248, + "r25": 255, + "r26": 255, + "r27": 127, + "r28": 0, + "r29": 0, + "r30": 192, + "r31": 255 + }, + "mileage": 0, + "cpu": "atmega328p", + "cpus": null, + "optimize": "ReleaseSmall", + "gcc_flags": [ + "-g", + "-O2", + "-nostdlib", + "-nostdinc", + "-ffreestanding" + ] +} \ No newline at end of file