/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See the file COPYING * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Copyright (C) 2010 Frank van Maarseveen */ /* * sei(), cli() and accessing SREG directly is fscked up by gcc by reordering across it. * Note that sei() never interrupts the instruction following it. Since saveicli() issues * at least one instruction before cli() it is possible to restore interrupt state * temporarily without do_nop() in between by: * * restorei(sreg); * saveicli(sreg); * */ #define saveicli(x) do { x = SREG; __asm__ __volatile__ ("cli" ::: "memory"); } while (0) #define restorei(x) do { __asm__ __volatile__ ("" ::: "memory"); SREG = x; } while (0) #define do_sei() do { __asm__ __volatile__ ("sei" ::: "memory"); } while (0) #define do_wdr() do { __asm__ __volatile__ ("wdr" ::: "memory"); } while (0) #define do_nop() do { __asm__ __volatile__ ("nop" ::: "memory"); } while (0) #define do_sleep() do { __asm__ __volatile__ ("sleep" ::: "memory"); } while (0) #define barrier() do { __asm__ __volatile__ ("" ::: "memory"); } while (0) /* * Newer gccs have this builtin for telling the compiler code cannot be reached. * Useful for suppressing a "'noreturn' function does return" warning. */ __attribute__((always_inline,noreturn)) static inline void __builtin_unreachable(void) { while (1) ; } #define ARRAYSIZE(x) (sizeof (x) / sizeof ((x)[0]))