#ifndef _HPCBOOT_SH_ARCH_H_
#define _HPCBOOT_SH_ARCH_H_
#include <arch.h>
#include <memory.h>
#include <console.h>
#include <sh3/dev/sh_dev.h>
#include <sh3/cpu/sh3.h>
#include <sh3/cpu/sh4.h>
class SHArchitecture : public Architecture {
protected:
typedef void(*boot_func_t)(struct BootArgs *, struct PageTag *);
SHdev *_dev;
private:
typedef Architecture super;
boot_func_t _boot_func;
protected:
SHArchitecture(Console *&cons, MemoryManager *&mem, boot_func_t bootfunc)
: _boot_func(bootfunc), Architecture(cons, mem) {
}
virtual ~SHArchitecture(void) { }
virtual void cache_flush(void) = 0;
public:
virtual BOOL init(void);
virtual BOOL setupLoader(void);
virtual void systemInfo(void);
virtual void jump(kaddr_t info, kaddr_t pvec);
static int cpu_type(void);
};
#define SH_(x) \
class SH ## x : public SHArchitecture { \
private: \
typedef SHArchitecture super; \
public: \
SH ## x(Console *&cons, MemoryManager *&mem, boot_func_t bootfunc)\
: SHArchitecture(cons, mem, bootfunc) { \
DPRINTF((TEXT("CPU: SH") TEXT(#x) TEXT("\n"))); \
_dev = new SH3dev; \
} \
~SH ## x(void) { \
delete _dev; \
} \
\
virtual BOOL init(void) { \
int sz; \
\
if (!super::init()) \
return FALSE; \
\
sz = SH_AREA_SIZE / 2; \
_mem->loadBank(SH_AREA3_START, sz); \
_mem->loadBank(SH_AREA3_START + sz , sz); \
return TRUE; \
} \
\
virtual void cache_flush(void) { \
SH ## x ## _CACHE_FLUSH(); \
} \
\
static void boot_func(struct BootArgs *, struct PageTag *); \
}
SH_(7709);
SH_(7709A);
SH_(7707);
class SH7750 : public SHArchitecture {
private:
typedef SHArchitecture super;
public:
SH7750(Console *&cons, MemoryManager *&mem, boot_func_t bootfunc)
: SHArchitecture(cons, mem, bootfunc) {
DPRINTF((TEXT("CPU: SH7750\n")));
_dev = new SH4dev;
}
~SH7750(void) {
delete _dev;
}
virtual BOOL init(void) {
if (!super::init())
return FALSE;
_mem->loadBank(SH_AREA3_START, SH_AREA_SIZE);
return TRUE;
}
virtual void cache_flush(void) {
CacheSync(CACHE_D_WBINV);
CacheSync(CACHE_I_INV);
}
virtual BOOL setupLoader(void) {
if (super::setupLoader()) {
(uint32_t)_loader_addr |= 0x20000000;
DPRINTF
((TEXT("loader address moved to P2-area 0x%08x\n"),
(unsigned)_loader_addr));
return TRUE;
}
return FALSE;
}
static void boot_func(struct BootArgs *, struct PageTag *);
};
#define SH_BOOT_FUNC_(x) \
void \
SH##x##::boot_func(struct BootArgs *bi, struct PageTag *p) \
{ \
\
int tmp; \
__asm("stc sr, r5\n" \
"or r4, r5\n" \
"ldc r5, sr\n", 0x500000f0, tmp); \
\
\
SH ## x ## _MMU_DISABLE(); \
do { \
uint32_t *dst =(uint32_t *)p->dst; \
uint32_t *src =(uint32_t *)p->src; \
uint32_t sz = p->sz / sizeof (int); \
if (p->src == ~0) \
while (sz--) \
*dst++ = 0; \
else \
while (sz--) \
*dst++ = *src++; \
} while ((p =(struct PageTag *)p->next) != ~0); \
\
SH ## x ## _CACHE_FLUSH(); \
\
\
__asm("jmp @r7\n" \
"nop\n", bi->argc, bi->argv, \
bi->bootinfo, bi->kernel_entry); \
}
__BEGIN_DECLS
uint32_t suspendIntr(void);
void resumeIntr(uint32_t);
__END_DECLS
#endif