991ae1e395
This dir is suitable for stuff that doesn't fit the target tree, e.g. because it also builds on hosted or otherwise. It also has a generic subfolder for fallback C implementations so that not all archs need to provide asm files. SOURCES should only contain "foo.c" where foo.c includes the specific <arch>/foo.c files from the subdirs using the preprocessor. This way automatic selection of asm versions or generic C verion is possible. For the start, the thread support files are moved, since ASM threads can be used on hosted platforms as well. Since core_sleep() remains platform specific it's moved to the corresponding system.h headers. Change-Id: Iebff272f3407a6eaafeb7656ceb0ae9eca3f7cb9
154 lines
4.6 KiB
C
154 lines
4.6 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2007 by Jens Arnold
|
|
* Based on the work of Alan Korr and others
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
#ifndef SYSTEM_TARGET_H
|
|
#define SYSTEM_TARGET_H
|
|
|
|
#define or_b(mask, address) \
|
|
asm \
|
|
("or.b %0,@(r0,gbr)" \
|
|
: \
|
|
: /* %0 */ I_CONSTRAINT((char)(mask)), \
|
|
/* %1 */ "z"(address-GBR))
|
|
|
|
#define and_b(mask, address) \
|
|
asm \
|
|
("and.b %0,@(r0,gbr)" \
|
|
: \
|
|
: /* %0 */ I_CONSTRAINT((char)(mask)), \
|
|
/* %1 */ "z"(address-GBR))
|
|
|
|
#define xor_b(mask, address) \
|
|
asm \
|
|
("xor.b %0,@(r0,gbr)" \
|
|
: \
|
|
: /* %0 */ I_CONSTRAINT((char)(mask)), \
|
|
/* %1 */ "z"(address-GBR))
|
|
|
|
|
|
/****************************************************************************
|
|
* Interrupt level setting
|
|
* The level is left shifted 4 bits
|
|
****************************************************************************/
|
|
#define HIGHEST_IRQ_LEVEL (15<<4)
|
|
|
|
static inline int set_irq_level(int level)
|
|
{
|
|
int i;
|
|
/* Read the old level and set the new one */
|
|
|
|
/* Not volatile - will be optimized away if the return value isn't used */
|
|
asm ("stc sr, %0" : "=r" (i));
|
|
asm volatile ("ldc %0, sr" : : "r" (level));
|
|
return i;
|
|
}
|
|
|
|
static inline void enable_irq(void)
|
|
{
|
|
int i;
|
|
asm volatile ("mov %1, %0 \n" /* Save a constant load from RAM */
|
|
"ldc %0, sr \n" : "=&r"(i) : "i"(0));
|
|
}
|
|
|
|
#define disable_irq() \
|
|
((void)set_irq_level(HIGHEST_IRQ_LEVEL))
|
|
|
|
#define disable_irq_save() \
|
|
set_irq_level(HIGHEST_IRQ_LEVEL)
|
|
|
|
#define restore_irq(i) \
|
|
((void)set_irq_level(i))
|
|
|
|
static inline uint16_t swap16_hw(uint16_t value)
|
|
/*
|
|
result[15..8] = value[ 7..0];
|
|
result[ 7..0] = value[15..8];
|
|
*/
|
|
{
|
|
uint16_t result;
|
|
asm ("swap.b\t%1,%0" : "=r"(result) : "r"(value));
|
|
return result;
|
|
}
|
|
|
|
static inline uint32_t swaw32_hw(uint32_t value)
|
|
/*
|
|
result[31..16] = value[15.. 0];
|
|
result[15.. 0] = value[31..16];
|
|
*/
|
|
{
|
|
uint32_t result;
|
|
asm ("swap.w\t%1,%0" : "=r"(result) : "r"(value));
|
|
return result;
|
|
}
|
|
|
|
static inline uint32_t swap32_hw(uint32_t value)
|
|
/*
|
|
result[31..24] = value[ 7.. 0];
|
|
result[23..16] = value[15.. 8];
|
|
result[15.. 8] = value[23..16];
|
|
result[ 7.. 0] = value[31..24];
|
|
*/
|
|
{
|
|
asm ("swap.b\t%0,%0\n"
|
|
"swap.w\t%0,%0\n"
|
|
"swap.b\t%0,%0\n" : "+r"(value));
|
|
return value;
|
|
}
|
|
|
|
static inline uint32_t swap_odd_even32_hw(uint32_t value)
|
|
{
|
|
/*
|
|
result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
|
|
result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
|
|
*/
|
|
asm ("swap.b\t%0,%0\n"
|
|
"swap.w\t%0,%0\n"
|
|
"swap.b\t%0,%0\n"
|
|
"swap.w\t%0,%0\n" : "+r"(value));
|
|
return value;
|
|
}
|
|
|
|
extern const unsigned bit_n_table[32];
|
|
#define BIT_N(n) ( \
|
|
__builtin_constant_p(n) \
|
|
? (1U << (n)) \
|
|
: bit_n_table[n] \
|
|
)
|
|
|
|
static inline void commit_dcache(void) {}
|
|
static inline void commit_discard_dcache(void) {}
|
|
static inline void commit_discard_idcache(void) {}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Put core in a power-saving state.
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
static inline void core_sleep(void)
|
|
{
|
|
asm volatile (
|
|
"and.b #0x7f, @(r0, gbr) \n" /* Clear SBY (bit 7) in SBYCR */
|
|
"mov #0, r1 \n" /* Enable interrupts */
|
|
"ldc r1, sr \n" /* Following instruction cannot be interrupted */
|
|
"sleep \n" /* Execute standby */
|
|
: : "z"(&SBYCR-GBR) : "r1");
|
|
}
|
|
|
|
#endif /* SYSTEM_TARGET_H */
|