OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 197 to Rev 198
    Reverse comparison

Rev 197 → Rev 198

/trunk/or1ksim/testbench/uos/int.h
0,0 → 1,16
 
/* Number of interrupt handlers */
#define MAX_INT_HANDLERS 32
 
/* High - low priority */
#define INT_HIGH_PRI 1
#define INT_LOW_PRI 0
 
/* Interrupt vectors */
#define V_TICK 3
 
/* Handler entry */
struct ihnd {
void (*handler)(void *);
void *arg;
};
/trunk/or1ksim/testbench/uos/ipc.h
0,0 → 1,27
/* This file is part of test microkernel for OpenRISC 1000. */
/* (C) 2000 Damjan Lampret, lampret@opencores.org */
 
/* Operation completed sucessfully. */
#define IPC_NOERR 0
 
/* Can't send any messages due to lack of free MCBs. */
#define IPC_EOUTOFMCBS 1
 
/* Sending message: No such destination task.
Receiving message: No such origin task. */
#define IPC_ENOTASK 2
 
/* Message to big to be sent or receive buffer is to small for
receiving message. If receiving then try again with bigger buffer. */
#define IPC_ETOOBIG 3
 
/* No messages waiting to be received. */
#define IPC_ENOMSGS 4
 
/* Send message in buffer buf of size len to task desttask. */
int uos_msgsnd(tid_t desttask, char *buf, int len);
 
/* Receive message of max size len from task origintask and put it
into buffer buf. If origintask is zero then get the first message
from the message queue. */
int uos_msgrcv(tid_t origintask, char *buf, int len);
/trunk/or1ksim/testbench/uos/task.c
0,0 → 1,52
/* This file is part of test microkernel for OpenRISC 1000. */
/* (C) 2000 Damjan Lampret, lampret@opencores.org */
 
#include "uos.h"
#include "ipc.h"
 
extern struct tcb tasks[MAX_TASKS+1];
 
int task(int id)
{
int rc;
struct _msg {
char id;
unsigned long count;
} msg;
 
printf("Task %d started\n", id);
if(id == 1) {
msg.id = 1;
msg.count = 0;
uos_msgsnd(2, (char *)&msg, sizeof(msg));
}
for(;;) {
rc = uos_msgrcv(0, (char *)&msg, sizeof(msg));
 
if(rc != 0) {
printf("Task %d: Waiting for massage\n", id);
} else {
printf("Task %d: Got massage from task %d: 0x%.8x. Sending message to task %d: 0x%.8x \n", id, msg.id, msg.count, (id == 3 ? 1 : (id + 1)), (msg.count + 1));
msg.id = id;
 
if((id == 1) && (msg.count > 15)) {
report(msg.count + 0xdeadde9c);
exit(0);
}
 
msg.count += 1;
uos_msgsnd((id == 3 ? 1 : (id + 1)), (char *)&msg, sizeof(msg));
}
}
}
 
/* Called by kernel_init to collect all tasks entries. */
void tasks_entries()
{
tasks[1].regs.pc = (unsigned long)task;
tasks[2].regs.pc = (unsigned long)task;
tasks[3].regs.pc = (unsigned long)task;
}
 
/trunk/or1ksim/testbench/uos/uos.c
0,0 → 1,354
/* This file is part of test microkernel for OpenRISC 1000. */
/* (C) 2000 Damjan Lampret, lampret@opencores.org */
 
#include <stdarg.h>
#include "spr_defs.h"
#include "uos.h"
#include "ipc.h"
#include "int.h"
 
/* External functions prototypes */
int tick_init(unsigned long period, void (* inf)(void));
 
/* Pointers to contexts used by except_or32.S routines */
unsigned long *task_context;
unsigned long *kernel_context;
 
/* TCBs for all tasks in the system */
struct tcb tasks[MAX_TASKS+1];
 
/* Stacks for the tasks (stacks[0] is kernel stack) */
unsigned char stacks[MAX_TASKS+1][STACK_SIZE];
 
/* MCBs for IPC messages */
struct mcb msgs[MAX_MSGS];
 
/* Pointer to linked list of free MCBs. */
struct mcb *free_mcbs;
 
/* TID of the current user task */
tid_t curtask = 0;
 
/* Statistics */
int kernel_sched_cnt = 0;
int kernel_syscall_cnt = 0;
 
void exit(int x)
{
asm("l.sys 203");
}
void report(unsigned long value)
{
unsigned long spr = 0x1234;
asm("l.mtspr\t\t%0,%1,0x0" : : "r" (spr), "r" (value));
return;
}
 
/* Outputs via or1ksim. */
void printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
asm("l.addi\tr3,%0,0": :"r" (fmt));
asm("l.addi\tr4,%0,0": :"r" (args));
asm("l.sys 202");
}
 
/* Timestamp via or1ksim (CPU cycle number). */
unsigned long timestamp()
{
register unsigned long cycles asm("r3");
asm("l.sys 201");
return cycles;
}
 
/* Standard function for filling memory with a constant byte. */
void *memset(void *dst, int c, int size)
{
char *tmp = dst;
for(;tmp && (tmp < (char *)dst + size); tmp++)
*(char *)tmp = (char)c;
return dst;
}
 
/* Standard function for copying memory area. */
void *memcpy(void *dst, void *src, int n)
{
char *tmp = dst;
for(;dst && (n-- > 0);)
*(char *)dst++ = *(char *)src++;
return tmp;
}
/* For writing into SPR. */
void mtspr(unsigned long spr, unsigned long value)
{
asm("l.mtspr\t\t%0,%1,0": : "r" (spr), "r" (value));
}
 
/* For reading SPR. */
unsigned long mfspr(unsigned long spr)
{
unsigned long value;
asm("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr));
return value;
}
 
/* Traverse linked list of MCBs and show individual messages. */
void kernel_show_mcbs(struct mcb *mcb)
{
for(;mcb; mcb = mcb->next) {
printf("MCB len=%u origintask=%u ", mcb->length, mcb->origin);
printf("msg:%s\n", mcb->msg);
}
}
 
/* Show all contexts. */
void kernel_show_contexts()
{
int i;
tid_t t;
for(t = 1; t <= MAX_TASKS; t++) {
printf("\ntask TID=%d: PC=0x%x ", t, tasks[t].regs.pc & ~0x3);
printf("SP(r1)=0x%x ", tasks[t].regs.sp);
printf("SR[EXR]=%d ", (tasks[t].regs.pc & SPR_SR_EXR) >> 1);
printf("SR[SUPV]=%d\n", tasks[t].regs.pc & SPR_SR_SUPV);
for(i = 1; i < GPRS; i++) {
if (i % 4 == 0)
printf("\n");
printf("r%d=0x%.8x ", i, tasks[t].regs.gprs[i]);
}
printf("\n");
kernel_show_mcbs(tasks[t].waiting_msgs);
}
printf("\n");
}
 
/* Simple round-robin scheduler that directly calls dispatcher. It is
called by low level external interrupt exception handler or by
kernel_syscall if KERNEL_SYSCALL_SCHED is defined. */
void kernel_sched()
{
if ((++curtask > MAX_TASKS) || !(tasks[curtask].regs.pc & ~0x3))
curtask = 1;
task_context = (unsigned long *)&tasks[curtask].regs;
 
#if KERNEL_OUTPUT
printf("kernel_sched(): entry number %d, ", ++kernel_sched_cnt);
printf("dispatching task TID=%d, time %u cycles", curtask, timestamp());
 
kernel_show_contexts();
#endif
dispatch();
}
 
/* System call uos_msgsnd. */
int uos_msgsnd(tid_t desttask, char *buf, int len)
{
asm("l.sys 1");
asm("l.nop");
}
 
/* System call uos_msgrcv. */
int uos_msgrcv(tid_t origintask, char *buf, int len)
{
asm("l.sys 2");
asm("l.nop");
}
 
/* Handles system call uos_msgsnd. */
void kernel_msgsnd(tid_t tid)
{
struct mcb *mcb;
struct mcb **dstmq;
struct tcb *task;
task = &tasks[tid];
/* Sanity checks. */
/* Does destination task exist? */
if (!task->regs.gprs[1] || (task->regs.gprs[1] > MAX_TASKS)) {
task->regs.gprs[9] = IPC_ENOTASK;
return;
}
 
/* Are there any free MCBs? */
if (!free_mcbs) {
task->regs.gprs[9] = IPC_EOUTOFMCBS;
return;
}
 
/* Is message too big to fit into MCB's message buffer? */
if (task->regs.gprs[3] > MAX_MSGLEN) {
task->regs.gprs[9] = IPC_ETOOBIG;
return;
}
/* OK, send the message. */
/* First, allocate MCB. */
mcb = free_mcbs;
free_mcbs = mcb->next;
/* Second, copy message to the MCB. */
memcpy(mcb->msg, (void *)task->regs.gprs[2], task->regs.gprs[3]);
mcb->origin = tid;
mcb->length = task->regs.gprs[3];
mcb->next = NULL;
/* Insert MCB into destination task's message queue at
the end. */
dstmq = &tasks[task->regs.gprs[1]].waiting_msgs;
for(;*dstmq;)
dstmq = &((*dstmq)->next);
*dstmq = mcb;
task->regs.gprs[9] = IPC_NOERR;
return;
}
 
/* Handles system call uos_msgrcv. */
void kernel_msgrcv(tid_t tid)
{
struct mcb *mcb;
struct mcb *curmsg, **linkp;
struct tcb *task;
task = &tasks[tid];
/* Sanity checks. */
/* Does origin task exist? */
if (task->regs.gprs[1] > MAX_TASKS) {
task->regs.gprs[9] = IPC_ENOTASK;
return;
}
 
/* Are there any messages waiting for reception? */
if (!task->waiting_msgs) {
task->regs.gprs[9] = IPC_ENOMSGS;
return;
}
 
/* OK, receive the message. */
/* Search waiting messages for one coming from origintask. If
origintask is zero then grab the first message. */
curmsg = task->waiting_msgs;
linkp = &task->waiting_msgs;
for(;task->regs.gprs[1] && curmsg->next && curmsg->origin != task->regs.gprs[1];) {
linkp = &curmsg->next;
curmsg = curmsg->next;
}
 
/* Is receive buffer too small for receiving message? */
if (task->regs.gprs[3] < curmsg->length) {
task->regs.gprs[9] = IPC_ETOOBIG;
return;
}
 
/* Now copy the message from the MCB. */
memcpy((void *)task->regs.gprs[2], curmsg->msg, task->regs.gprs[3]);
/* Remove MCB from task's waiting queue and place it
back into free MCBs queue. */
*linkp = curmsg->next;
curmsg->next = free_mcbs;
free_mcbs = curmsg;
task->regs.gprs[9] = IPC_NOERR;
return;
}
 
/* Handles all uOS system calls. It is called by low level system call
exception handler. */
void kernel_syscall()
{
unsigned short syscall_num;
 
#if KERNEL_OUTPUT
printf("kernel_syscall(): entry number %d, ", ++kernel_syscall_cnt);
printf("current TID=%d, time %u cycles", curtask, timestamp());
kernel_show_contexts();
#endif
syscall_num = *(unsigned short *)((tasks[curtask].regs.pc & ~0x3) - 6);
switch(syscall_num) {
case IPC_MSGSND:
kernel_msgsnd(curtask);
break;
case IPC_MSGRCV:
kernel_msgrcv(curtask);
break;
default:
printf("kernel_syscall(): unknown syscall (%u)\n", syscall_num);
}
 
#if KERNEL_SYSCALL_SCHED
kernel_sched();
#endif
dispatch();
}
 
/* Called by reset exception handler to initialize the kernel and start
rolling first task. */
int kernel_init()
{
tid_t t;
int i;
printf("Initializing kernel:\n");
 
printf(" Clearing kernel structures...\n");
memset(tasks, 0, sizeof(tasks));
memset(stacks, 0, sizeof(stacks));
memset(msgs, 0, sizeof(msgs));
printf(" Initializing MCBs... %d MCB(s)\n", MAX_MSGS);
for(i = 0; i < (MAX_MSGS - 1); i++)
msgs[i].next = &msgs[i+1];
free_mcbs = &msgs[0];
printf(" Initializing TCBs... %d user task(s)\n", MAX_TASKS);
 
tasks_entries();
 
for(t = 0; t <= MAX_TASKS; t++) {
tasks[t].regs.sp = (unsigned long)stacks[t] + STACK_SIZE - 4;
/* Disable EXR for kernel context */
tasks[t].regs.sr |= (t == 0 ? SPR_SR_SUPV : SPR_SR_EXR | SPR_SR_EIR);
tasks[t].regs.gprs[1] = t;
}
 
/* First task runs in seprvisor mode */
tasks[1].regs.sr |= SPR_SR_SUPV;
 
/* TID=0 is reserved for kernel use */
kernel_context = (unsigned long *)&tasks[0].regs;
 
/* First task to be scheduled is task TID=1 */
task_context = (unsigned long *)&tasks[1].regs;
 
/* Initialize initrrupt controller */
int_init();
 
printf(" Exceptions will be enabled when first task is dispatched.\n");
printf("Kernel initalized. Starting first user task.\n");
 
#if KERNEL_SYSCALL_SCHED
kernel_sched(); /* Lets schedule and dispatch our first task */
#else
tick_init(TICK_PERIOD, kernel_sched);
kernel_sched(); /* Lets schedule and dispatch our first task */
#endif
/* ... */ /* We never get here */
}
/trunk/or1ksim/testbench/uos/int.c
0,0 → 1,80
/* This file is part of test microkernel for OpenRISC 1000. */
/* (C) 2001 Simon Srot, srot@opencores.org */
 
#include "spr_defs.h"
#include "int.h"
 
/* Interrupt handlers table */
struct ihnd int_handlers[MAX_INT_HANDLERS];
 
/* Initialize routine */
int int_init(void)
{
int i;
 
for(i = 0; i < MAX_INT_HANDLERS; i++) {
int_handlers[i].handler = 0;
int_handlers[i].arg = 0;
}
return 0;
}
 
/* Add interrupt handler */
int int_add(unsigned long vect, void (* handler)(void *), void *arg/*, int hilo*/)
{
if(vect >= MAX_INT_HANDLERS)
return -1;
 
int_handlers[vect].handler = handler;
int_handlers[vect].arg = arg;
 
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << vect));
/*if(hilo == INT_HIGH_PRI)*/
if(1)
mtspr(SPR_PICPR, mfspr(SPR_PICPR) | (0x00000001L << vect));
else
mtspr(SPR_PICPR, mfspr(SPR_PICPR) & ~(0x00000001L << vect));
return 0;
}
 
/* Disable interrupt */
int int_disable(unsigned long vect)
{
if(vect >= MAX_INT_HANDLERS)
return -1;
 
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(0x00000001L << vect));
return 0;
}
 
/* Enable interrupt */
int int_enable(unsigned long vect)
{
if(vect >= MAX_INT_HANDLERS)
return -1;
 
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << vect));
return 0;
}
 
/* Main interrupt handler */
void int_main(void)
{
unsigned long picsr = mfspr(SPR_PICSR);
unsigned long i = 0;
 
mtspr(SPR_PICSR, 0);
 
while(i < 32) {
if((picsr & (0x01L << i)) && (int_handlers[i].handler != 0)) {
(*int_handlers[i].handler)(int_handlers[i].arg);
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(0x00000001L << i));
}
i++;
}
}
/trunk/or1ksim/testbench/uos/spr_defs.h
0,0 → 1,391
/* spr_defs.h -- Defines OR1K architecture specific special-purpose registers
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
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 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.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* This file is also used by microkernel test bench. Among
others it is also used in assembly file(s). */
 
/* Definition of special-purpose registers (SPRs) */
 
#define MAX_GRPS (32)
#define MAX_SPRS_PER_GRP_BITS (11)
#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS)
#define MAX_SPRS (0x10000)
 
/* Base addresses for the groups */
#define SPRGROUP_SYS (0<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_DMMU (1<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_IMMU (2<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_DC (3<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_IC (4<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_MAC (5<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_D (6<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_PC (7<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_PM (8<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_PIC (9<< MAX_SPRS_PER_GRP_BITS)
#define SPRGROUP_TT (10<< MAX_SPRS_PER_GRP_BITS)
 
/* System control and status group */
#define SPR_VR (SPRGROUP_SYS + 0)
#define SPR_UPR (SPRGROUP_SYS + 1)
#define SPR_PC (SPRGROUP_SYS + 16) /* CZ 21/06/01 */
#define SPR_SR (SPRGROUP_SYS + 17) /* CZ 21/06/01 */
#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) /* CZ 21/06/01 */
#define SPR_EPCR_LAST (SPRGROUP_SYS + 47) /* CZ 21/06/01 */
#define SPR_EEAR_BASE (SPRGROUP_SYS + 48)
#define SPR_EEAR_LAST (SPRGROUP_SYS + 63)
#define SPR_ESR_BASE (SPRGROUP_SYS + 64)
#define SPR_ESR_LAST (SPRGROUP_SYS + 79)
 
/* Data MMU group */
#define SPR_DMMUCR (SPRGROUP_DMMU + 0)
#define SPR_DTLBMR_BASE(WAY) (SPRGROUP_DMMU + 0x200 + (WAY) * 0x200)
#define SPR_DTLBMR_LAST(WAY) (SPRGROUP_DMMU + 0x2ff + (WAY) * 0x200)
#define SPR_DTLBTR_BASE(WAY) (SPRGROUP_DMMU + 0x300 + (WAY) * 0x200)
#define SPR_DTLBTR_LAST(WAY) (SPRGROUP_DMMU + 0x3ff + (WAY) * 0x200)
 
/* Instruction MMU group */
#define SPR_IMMUCR (SPRGROUP_IMMU + 0)
#define SPR_ITLBMR_BASE(WAY) (SPRGROUP_IMMU + 0x200 + (WAY) * 0x200)
#define SPR_ITLBMR_LAST(WAY) (SPRGROUP_IMMU + 0x2ff + (WAY) * 0x200)
#define SPR_ITLBTR_BASE(WAY) (SPRGROUP_IMMU + 0x300 + (WAY) * 0x200)
#define SPR_ITLBTR_LAST(WAY) (SPRGROUP_IMMU + 0x3ff + (WAY) * 0x200)
 
/* Data cache group */
#define SPR_DCCR (SPRGROUP_DC + 0)
#define SPR_DCBPR (SPRGROUP_DC + 1)
#define SPR_DCBFR (SPRGROUP_DC + 2)
#define SPR_DCBIR (SPRGROUP_DC + 3)
#define SPR_DCBWR (SPRGROUP_DC + 4)
#define SPR_DCBLR (SPRGROUP_DC + 5)
#define SPR_DCR_BASE(WAY) (SPRGROUP_DC + 0x200 + (WAY) * 0x200)
#define SPR_DCR_LAST(WAY) (SPRGROUP_DC + 0x3ff + (WAY) * 0x200)
 
/* Instruction cache group */
#define SPR_ICCR (SPRGROUP_IC + 0)
#define SPR_ICBPR (SPRGROUP_IC + 1)
#define SPR_ICBIR (SPRGROUP_IC + 2)
#define SPR_ICBLR (SPRGROUP_IC + 3)
#define SPR_ICR_BASE(WAY) (SPRGROUP_IC + 0x200 + (WAY) * 0x200)
#define SPR_ICR_LAST(WAY) (SPRGROUP_IC + 0x3ff + (WAY) * 0x200)
 
/* MAC group */
#define SPR_MACLO (SPRGROUP_MAC + 1)
#define SPR_MACHI (SPRGROUP_MAC + 2)
 
/* Debug group */
#define SPR_DVR(N) (SPRGROUP_D + (N))
#define SPR_DCR(N) (SPRGROUP_D + 8 + (N))
#define SPR_DMR1 (SPRGROUP_D + 16)
#define SPR_DMR2 (SPRGROUP_D + 17)
#define SPR_DWCR0 (SPRGROUP_D + 18)
#define SPR_DWCR1 (SPRGROUP_D + 19)
#define SPR_DSR (SPRGROUP_D + 20)
#define SPR_DRR (SPRGROUP_D + 21)
#define SPR_DIR (SPRGROUP_D + 22)
 
/* Performance counters group */
#define SPR_PCCR(N) (SPRGROUP_PC + (N))
#define SPR_PCMR(N) (SPRGROUP_PC + 8 + (N))
 
/* Power management group */
#define SPR_PMR (SPRGROUP_PM + 0)
 
/* PIC group */
#define SPR_PICMR (SPRGROUP_PIC + 0)
#define SPR_PICPR (SPRGROUP_PIC + 1)
#define SPR_PICSR (SPRGROUP_PIC + 2)
 
/* Tick Timer group */
#define SPR_TTMR (SPRGROUP_TT + 0)
#define SPR_TTCR (SPRGROUP_TT + 1)
 
/*
* Bit definitions for the Version Register
*
*/
#define SPR_VR_VER 0xffff0000 /* Processor version */
#define SPR_VR_REV 0x0000003f /* Processor revision */
 
/*
* Bit definitions for the Unit Present Register
*
*/
#define SPR_UPR_UP 0x00000001 /* UPR present */
#define SPR_UPR_DCP 0x00000002 /* Data cache present */
#define SPR_UPR_ICP 0x00000004 /* Instruction cache present */
#define SPR_UPR_DMP 0x00000008 /* Data MMU present */
#define SPR_UPR_IMP 0x00000010 /* Instruction MMU present */
#define SPR_UPR_OB32P 0x00000020 /* ORBIS32 present */
#define SPR_UPR_OB64P 0x00000040 /* ORBIS64 present */
#define SPR_UPR_OF32P 0x00000080 /* ORFPX32 present */
#define SPR_UPR_OF64P 0x00000100 /* ORFPX64 present */
#define SPR_UPR_OV32P 0x00000200 /* ORVDX32 present */
#define SPR_UPR_OV64P 0x00000400 /* ORVDX64 present */
#define SPR_UPR_DUP 0x00000800 /* Debug unit present */
#define SPR_UPR_PCUP 0x00001000 /* Performance counters unit present */
#define SPR_UPR_PMP 0x00002000 /* Power management present */
#define SPR_UPR_PICP 0x00004000 /* PIC present */
#define SPR_UPR_TTP 0x00008000 /* Tick timer present */
#define SPR_UPR_SRP 0x00010000 /* Shadow registers present */
#define SPR_UPR_RES 0x00fe0000 /* ORVDX32 present */
#define SPR_UPR_CUST 0xff000000 /* Custom units */
 
/*
* Bit definitions for the Supervision Register
*
*/
#define SPR_SR_CID 0xf0000000 /* Context ID */
#define SPR_SR_PXR 0x00008000 /* Partial exception recognition */
#define SPR_SR_EP 0x00004000 /* Exception Prefix */
#define SPR_SR_DSX 0x00002000 /* Delay Slot Exception */
#define SPR_SR_OVE 0x00001000 /* Overflow flag Exception */
#define SPR_SR_OV 0x00000800 /* Overflow flag */
#define SPR_SR_CY 0x00000400 /* Carry flag */
#define SPR_SR_F 0x00000200 /* Condition Flag */
#define SPR_SR_CE 0x00000100 /* CID Enable */
#define SPR_SR_LEE 0x00000080 /* Little Endian Enable */
#define SPR_SR_IME 0x00000040 /* Instruction MMU Enable */
#define SPR_SR_DME 0x00000020 /* Data MMU Enable */
#define SPR_SR_ICE 0x00000010 /* Instruction Cache Enable */
#define SPR_SR_DCE 0x00000008 /* Data Cache Enable */
#define SPR_SR_EIR 0x00000004 /* External Interrupt Recognition */
#define SPR_SR_EXR 0x00000002 /* Exception Recognition */
#define SPR_SR_SUPV 0x00000001 /* Supervisor mode */
 
/*
* Bit definitions for the Data MMU Control Register
*
*/
#define SPR_DMMUCR_P2S 0x0000003e /* Level 2 Page Size */
#define SPR_DMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
#define SPR_DMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
#define SPR_DMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
 
/*
* Bit definitions for the Instruction MMU Control Register
*
*/
#define SPR_IMMUCR_P2S 0x0000003e /* Level 2 Page Size */
#define SPR_IMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
#define SPR_IMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
#define SPR_IMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
 
/*
* Bit definitions for the Data TLB Match Register
*
*/
#define SPR_DTLBMR_V 0x00000001 /* Valid */
#define SPR_DTLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
#define SPR_DTLBMR_CID 0x0000003c /* Context ID */
#define SPR_DTLBMR_LRU 0x000000c0 /* Least Recently Used */
#define SPR_DTLBMR_VPN 0xfffff000 /* Virtual Page Number */
 
/*
* Bit definitions for the Data TLB Translate Register
*
*/
#define SPR_DTLBTR_CC 0x00000001 /* Cache Coherency */
#define SPR_DTLBTR_CI 0x00000002 /* Cache Inhibit */
#define SPR_DTLBTR_WBC 0x00000004 /* Write-Back Cache */
#define SPR_DTLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
#define SPR_DTLBTR_A 0x00000010 /* Accessed */
#define SPR_DTLBTR_D 0x00000020 /* Dirty */
#define SPR_DTLBTR_URE 0x00000040 /* User Read Enable */
#define SPR_DTLBTR_UWE 0x00000080 /* User Write Enable */
#define SPR_DTLBTR_SRE 0x00000100 /* Supervisor Read Enable */
#define SPR_DTLBTR_SWE 0x00000200 /* Supervisor Write Enable */
#define SPR_DTLBTR_PPN 0xfffff000 /* Physical Page Number */
 
/*
* Bit definitions for the Instruction TLB Match Register
*
*/
#define SPR_ITLBMR_V 0x00000001 /* Valid */
#define SPR_ITLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
#define SPR_ITLBMR_CID 0x0000003c /* Context ID */
#define SPR_ITLBMR_LRU 0x000000c0 /* Least Recently Used */
#define SPR_ITLBMR_VPN 0xfffff000 /* Virtual Page Number */
 
/*
* Bit definitions for the Instruction TLB Translate Register
*
*/
#define SPR_ITLBTR_CC 0x00000001 /* Cache Coherency */
#define SPR_ITLBTR_CI 0x00000002 /* Cache Inhibit */
#define SPR_ITLBTR_WBC 0x00000004 /* Write-Back Cache */
#define SPR_ITLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
#define SPR_ITLBTR_A 0x00000010 /* Accessed */
#define SPR_ITLBTR_D 0x00000020 /* Dirty */
#define SPR_ITLBTR_URE 0x00000040 /* User Read Enable */
#define SPR_ITLBTR_UWE 0x00000080 /* User Write Enable */
#define SPR_ITLBTR_SRE 0x00000100 /* Supervisor Read Enable */
#define SPR_ITLBTR_SWE 0x00000200 /* Supervisor Write Enable (not used actually) */
#define SPR_ITLBTR_PPN 0xfffff000 /* Physical Page Number */
 
/*
* Bit definitions for Data Cache Control register
*
*/
#define SPR_DCCR_EW 0x000000ff /* Enable ways */
 
/*
* Bit definitions for Insn Cache Control register
*
*/
#define SPR_ICCR_EW 0x000000ff /* Enable ways */
 
/*
* Bit definitions for Debug Control registers
*
*/
#define SPR_DCR_DP 0x00000001 /* DVR/DCR present */
#define SPR_DCR_CC 0x0000000e /* Compare condition */
#define SPR_DCR_SC 0x00000010 /* Signed compare */
#define SPR_DCR_CT 0x000000e0 /* Compare to */
 
/*
* Bit definitions for Debug Mode 1 register
*
*/
#define SPR_DMR1_CW0 0x00000003 /* Chain watchpoint 0 */
#define SPR_DMR1_CW1 0x0000000c /* Chain watchpoint 1 */
#define SPR_DMR1_CW2 0x00000030 /* Chain watchpoint 2 */
#define SPR_DMR1_CW3 0x000000c0 /* Chain watchpoint 3 */
#define SPR_DMR1_CW4 0x00000300 /* Chain watchpoint 4 */
#define SPR_DMR1_CW5 0x00000c00 /* Chain watchpoint 5 */
#define SPR_DMR1_CW6 0x00003000 /* Chain watchpoint 6 */
#define SPR_DMR1_CW7 0x0000c000 /* Chain watchpoint 7 */
#define SPR_DMR1_CW8 0x00030000 /* Chain watchpoint 8 */
#define SPR_DMR1_CW9 0x000c0000 /* Chain watchpoint 9 */
#define SPR_DMR1_CW10 0x00300000 /* Chain watchpoint 10 */
#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/
#define SPR_DMR1_BT 0x00800000 /* Branch trace */
#define SPR_DMR1_DXFW 0x01000000 /* Disable external force watchpoint */
 
/*
* Bit definitions for Debug Mode 2 register
*
*/
#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter 0 enable */
#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter 0 enable */
#define SPR_DMR2_AWTC 0x00001ffc /* Assign watchpoints to counters */
#define SPR_DMR2_WGB 0x00ffe000 /* Watchpoints generating breakpoint */
 
/*
* Bit definitions for Debug watchpoint counter registers
*
*/
#define SPR_DWCR_COUNT 0x0000ffff /* Count */
#define SPR_DWCR_MATCH 0xffff0000 /* Match */
 
/*
* Bit definitions for Debug stop register
*
*/
#define SPR_DSR_RSTE 0x00000001 /* Reset exception */
#define SPR_DSR_BUSEE 0x00000002 /* Bus error exception */
#define SPR_DSR_DPFE 0x00000004 /* Data Page Fault exception */
#define SPR_DSR_IPFE 0x00000008 /* Insn Page Fault exception */
#define SPR_DSR_LPINTE 0x00000010 /* Low priority interrupt exception */
#define SPR_DSR_AE 0x00000020 /* Alignment exception */
#define SPR_DSR_IIE 0x00000040 /* Illegal Instruction exception */
#define SPR_DSR_HPINTE 0x00000080 /* High priority interrupt exception */
#define SPR_DSR_DME 0x00000100 /* DTLB miss exception */
#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */
#define SPR_DSR_RE 0x00000400 /* Range exception */
#define SPR_DSR_SCE 0x00000800 /* System call exception */
#define SPR_DSR_BE 0x00001000 /* Breakpoint exception */
 
/*
* Bit definitions for Debug reason register
*
*/
#define SPR_DRR_RSTE 0x00000001 /* Reset exception */
#define SPR_DRR_BUSEE 0x00000002 /* Bus error exception */
#define SPR_DRR_DPFE 0x00000004 /* Data Page Fault exception */
#define SPR_DRR_IPFE 0x00000008 /* Insn Page Fault exception */
#define SPR_DRR_LPINTE 0x00000010 /* Low priority interrupt exception */
#define SPR_DRR_AE 0x00000020 /* Alignment exception */
#define SPR_DRR_IIE 0x00000040 /* Illegal Instruction exception */
#define SPR_DRR_HPINTE 0x00000080 /* High priority interrupt exception */
#define SPR_DRR_DME 0x00000100 /* DTLB miss exception */
#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */
#define SPR_DRR_RE 0x00000400 /* Range exception */
#define SPR_DRR_SCE 0x00000800 /* System call exception */
#define SPR_DRR_BE 0x00001000 /* Breakpoint exception */
 
/*
* Bit definitions for Performance counters mode registers
*
*/
#define SPR_PCMR_CP 0x00000001 /* Counter present */
#define SPR_PCMR_UMRA 0x00000002 /* User mode read access */
#define SPR_PCMR_CISM 0x00000004 /* Count in supervisor mode */
#define SPR_PCMR_CIUM 0x00000008 /* Count in user mode */
#define SPR_PCMR_LA 0x00000010 /* Load access event */
#define SPR_PCMR_SA 0x00000020 /* Store access event */
#define SPR_PCMR_IF 0x00000040 /* Instruction fetch event*/
#define SPR_PCMR_DCM 0x00000080 /* Data cache miss event */
#define SPR_PCMR_ICM 0x00000100 /* Insn cache miss event */
#define SPR_PCMR_IFS 0x00000200 /* Insn fetch stall event */
#define SPR_PCMR_LSUS 0x00000400 /* LSU stall event */
#define SPR_PCMR_BS 0x00000800 /* Branch stall event */
#define SPR_PCMR_DTLBM 0x00001000 /* DTLB miss event */
#define SPR_PCMR_ITLBM 0x00002000 /* ITLB miss event */
#define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */
#define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */
 
/*
* Bit definitions for the Power management register
*
*/
#define SPR_PMR_SDF 0x00000001 /* Slow down factor */
#define SPR_PMR_DME 0x00000002 /* Doze mode enable */
#define SPR_PMR_SME 0x00000004 /* Sleep mode enable */
#define SPR_PMR_DCGE 0x00000008 /* Dynamic clock gating enable */
#define SPR_PMR_SUME 0x00000010 /* Suspend mode enable */
 
/*
* Bit definitions for PICMR
*
*/
#define SPR_PICMR_IUM 0xfffffffc /* Interrupt unmask */
 
/*
* Bit definitions for PICPR
*
*/
#define SPR_PICPR_IPRIO 0xfffffffc /* Interrupt priority */
 
/*
* Bit definitions for PICSR
*
*/
#define SPR_PICSR_IS 0xffffffff /* Interrupt status */
 
/*
* Bit definitions for Tick Timer Control Register
*
*/
#define SPR_TTCR_PERIOD 0x0fffffff /* Time Period */
#define SPR_TTMR_PERIOD SPR_TTCR_PERIOD
#define SPR_TTMR_IP 0x10000000 /* Interrupt Pending */
#define SPR_TTMR_IE 0x20000000 /* Interrupt Enable */
#define SPR_TTMR_CR 0x40000000 /* Continuous Run */
#define SPR_TTMR_TTE 0x80000000 /* Tick Timer Enable */
trunk/or1ksim/testbench/uos/spr_defs.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/or1ksim/testbench/uos/tick.c =================================================================== --- trunk/or1ksim/testbench/uos/tick.c (nonexistent) +++ trunk/or1ksim/testbench/uos/tick.c (revision 198) @@ -0,0 +1,41 @@ +/* This file is part of test microkernel for OpenRISC 1000. */ +/* (C) 2001 Simon Srot, srot@opencores.org */ + +#include "spr_defs.h" +#include "int.h" + +/* Tick timer period */ +unsigned long tick_period; + +/* Inform of tick interrupt */ +void (*tick_inf)(void); + +/* Tick interrupt routine */ +void tick_int(void) +{ + unsigned long period; + + /* Call inf routine */ + (*tick_inf)(); + + /* Set new counter period iand clear inet pending bit */ +/* mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_SR | (period & SPR_TTMR_PERIOD)); +*/ +} + +/* Initialize routine */ +int tick_init(unsigned long period, void (* inf)(void)) +{ + /* Save tick timer period and inform routine */ + tick_period = period; + tick_inf = inf; + + /* Add interrupt handler */ + int_add(V_TICK, tick_int, 0/*, INT_HIGH_PRI*/); + + /* Set counter period, enable timer and interrupt */ + mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_CR | (period & SPR_TTMR_PERIOD)); + + return 0; +} + Index: trunk/or1ksim/testbench/uos/uos.h =================================================================== --- trunk/or1ksim/testbench/uos/uos.h (nonexistent) +++ trunk/or1ksim/testbench/uos/uos.h (revision 198) @@ -0,0 +1,60 @@ +/* This file is part of test microkernel for OpenRISC 1000. */ +/* (C) 2000 Damjan Lampret, lampret@opencores.org */ + +/* Length of the IPC message's useful data. */ +#define MAX_MSGLEN 100 + +/* Number of user tasks in the system. */ +#define MAX_TASKS 8 + +/* Number of IPC messages in the system. */ +#define MAX_MSGS 16 + +/* Number of general purpose registers (not counting r0 and r1). */ +#define GPRS 30 + +/* Size of kernel and user task stacks. Size for individual task. */ +#define STACK_SIZE 2048 + +/* Define this if you want kernel debug output. Note that you must + assemble except_or32.S with KERNEL_OUTPUT defined in Makefile. This + definition is only for main uos.c. */ +#define KERNEL_OUTPUT 0 + +/* Define this if you want task switch at every system call. */ +#define KERNEL_SYSCALL_SCHED 0 + +/* System tick timer period */ +#define TICK_PERIOD 0x500 + +/* Task ID type (if we would have processes then we would call it PID) */ +typedef int tid_t; + +/* NULL */ +#define NULL 0 + +/* System call numbers */ +#define IPC_MSGSND 1 +#define IPC_MSGRCV 2 + +/* Message Control Block structure */ +struct mcb { + char msg[MAX_MSGLEN]; /* Message's data */ + int length; /* Message's length */ + tid_t origin; /* TID of message's origin task */ + struct mcb *next; /* Next message in linked list */ +}; + +/* Task Control Block structure */ +struct tcb { + struct regs { + unsigned long pc; /* Task's PC */ + unsigned long sp; /* Task's stack (r1)*/ + unsigned long gprs[GPRS]; /* Task's GPRs r2-r15 */ + unsigned long sr; /* Task's supervision register */ + } regs; + struct mcb *waiting_msgs; /* Waiting messages */ +}; + +extern void printf(const char *fmt, ...); + Index: trunk/or1ksim/testbench/uos/Makefile =================================================================== --- trunk/or1ksim/testbench/uos/Makefile (nonexistent) +++ trunk/or1ksim/testbench/uos/Makefile (revision 198) @@ -0,0 +1,60 @@ +# Makefile -- Makefile for the Micro OS +# Copyright (C) 2000 Damjan Lampret, lampret@opencores.org +# +# This file is part of OpenRISC 1000 Architectural Simulator. +# +# 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 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +## + +# SEARCHDIR = /home/simons/or1k/lib/gcc-lib/or32-rtems/2.95.2/ +SEARCHDIR = /home/simons/or1k-elf-test/lib/gcc-lib/or32-elf/2.95.2/ + +# CC = or32-elf-gcc +# LD = or32-elf-ld +CC = or32-rtems-gcc +LD = or32-rtems-ld + +CFLAGS = -O2 +# CFLAGS = -O2 -DOR32 +# LDFLAGS = -nostdlib + +LDFLAGS = -L/home/simons/or1k/lib/gcc-lib/or32-rtems/2.95.2/ -lgcc +# LDFLAGS = -L/home/simons/or1k/lib/gcc-lib/or32-elf/2.95.2/ -lgcc + +UOS_OBJECTS = except_or32.o \ + uos.o \ + task.o \ + int.o \ + tick.o + +## + +uos.or32: $(UOS_OBJECTS) Makefile + $(LD) -o $@ $(UOS_OBJECTS) $(LDFLAGS) + +uos.o: uos.c spr_defs.h uos.h ipc.h Makefile + $(CC) $(CFLAGS) -c -o $@ $< + +except_or32.o: except_or32.S spr_defs.h Makefile + $(CC) $(CFLAGS) -c -o $@ $< + +task.o: task.c uos.h Makefile + $(CC) $(CFLAGS) -c -o $@ $< + +tick.o: tick.c uos.h Makefile + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -rf *.o *.s *.i uos.or32 Index: trunk/or1ksim/testbench/uos/README =================================================================== --- trunk/or1ksim/testbench/uos/README (nonexistent) +++ trunk/or1ksim/testbench/uos/README (revision 198) @@ -0,0 +1,18 @@ + +This is the Micro OS (uOS) for testing operating system features of +OpenRISC 1000 architecture. Specifically non reentrant, preemptive +multitasking microkernel. Purpose of this code is not to be a true +operating system but merely a testbench for testing the architecture, +or1ksim and software development tools (GCC, Binutils, ...). + +This test OS has all necessary exception handlers to handle exceptions. There +are two tasks: one task generates data and passes that data via IPC to the +second task. Second task outputs the data via or1ksim syscall to the simulator. + +Currently only OR32 is supported (exception handlers are written in +assembly). Tools required to compile sources are the latest +or32-coff-gcc, or32-coff-as and or32-coff-ld. Also make sure you undefine +VIRTUAL_MACHINE_ONLY when compiling or1ksim. + +-- +10/Jun/2000, Damjan Lampret, lampret@opencores.org Index: trunk/or1ksim/testbench/uos/except_or32.S =================================================================== --- trunk/or1ksim/testbench/uos/except_or32.S (nonexistent) +++ trunk/or1ksim/testbench/uos/except_or32.S (revision 198) @@ -0,0 +1,259 @@ +/* This file is part of test microkernel for OpenRISC 1000. */ +/* (C) 2000 Damjan Lampret, lampret@opencores.org */ + +#include "spr_defs.h" + +/* + * Context is saved to area pointed by pointer in R3. Original + * R3 is at memory location 0 and task's PC is at memory location 4. + */ +#define SAVEREGS \ + l.lwz r3,0(r3); \ + l.sw 4(r3),r1; \ + l.sw 8(r3),r2; \ + l.lwz r2,0(r0); /* saving original r3*/ \ + l.sw 12(r3),r2; \ + l.sw 16(r3),r4; \ + l.sw 20(r3),r5; \ + l.sw 24(r3),r6; \ + l.sw 28(r3),r7; \ + l.sw 32(r3),r8; \ + l.sw 36(r3),r9; \ + l.sw 40(r3),r10; \ + l.sw 44(r3),r11; \ + l.sw 48(r3),r12; \ + l.sw 52(r3),r13; \ + l.sw 56(r3),r14; \ + l.sw 60(r3),r15; \ + l.sw 64(r3),r16; \ + l.sw 68(r3),r17; \ + l.sw 72(r3),r18; \ + l.sw 76(r3),r19; \ + l.sw 80(r3),r20; \ + l.sw 84(r3),r21; \ + l.sw 88(r3),r22; \ + l.sw 92(r3),r23; \ + l.sw 96(r3),r24; \ + l.sw 100(r3),r25; \ + l.sw 104(r3),r26; \ + l.sw 108(r3),r27; \ + l.sw 112(r3),r28; \ + l.sw 116(r3),r29; \ + l.sw 120(r3),r30; \ + l.sw 124(r3),r31; \ + l.lwz r2,4(r0); /* saving original PC*/ \ + l.sw 0(r3),r2; \ + \ + l.mfspr r2,r0,SPR_ESR_BASE; \ + l.sw 128(r3),r2 /* saving SR */ + +/* + * Pointer to context is in R3. All registers are loaded and execution is + * transfered to the loaded context's task + */ +#define LOADREGS_N_GO \ + l.lwz r3,0(r3); \ + l.lwz r2,0(r3); /* prepare PC*/ \ + l.mtspr r0,r2,SPR_EPCR_BASE; \ + \ + l.lwz r2,128(r3); /* prepare SR*/ \ + l.mtspr r0,r2,SPR_ESR_BASE; \ + \ + l.lwz r1,4(r3); \ + l.lwz r2,8(r3); \ + l.lwz r4,16(r3); \ + l.lwz r5,20(r3); \ + l.lwz r6,24(r3); \ + l.lwz r7,28(r3); \ + l.lwz r8,32(r3); \ + l.lwz r9,36(r3); \ + l.lwz r10,40(r3); \ + l.lwz r11,44(r3); \ + l.lwz r12,48(r3); \ + l.lwz r13,52(r3); \ + l.lwz r14,56(r3); \ + l.lwz r15,60(r3); \ + l.lwz r16,64(r3); \ + l.lwz r17,68(r3); \ + l.lwz r18,72(r3); \ + l.lwz r19,76(r3); \ + l.lwz r20,80(r3); \ + l.lwz r21,84(r3); \ + l.lwz r22,88(r3); \ + l.lwz r23,92(r3); \ + l.lwz r24,96(r3); \ + l.lwz r25,100(r3); \ + l.lwz r26,104(r3); \ + l.lwz r27,108(r3); \ + l.lwz r28,112(r3); \ + l.lwz r29,116(r3); \ + l.lwz r30,120(r3); \ + l.lwz r31,124(r3); \ + \ + l.lwz r3,12(r3); /* prepare r3*/ \ + \ + l.rfe; /* Call task */ \ + l.nop + +/* + * All registers are loaded from save area. + */ +#define LOADREGS \ + l.lwz r3,0(r3); \ + l.lwz r2,0(r3); /* prepare PC*/ \ + l.mtspr r0,r2,SPR_EPCR_BASE; \ + \ + l.lwz r2,128(r3); /* prepare SR*/ \ + l.mtspr r0,r2,SPR_ESR_BASE; \ + \ + l.lwz r1,4(r3); \ + l.lwz r2,8(r3); \ + l.lwz r4,16(r3); \ + l.lwz r5,20(r3); \ + l.lwz r6,24(r3); \ + l.lwz r7,28(r3); \ + l.lwz r8,32(r3); \ + l.lwz r9,36(r3); \ + l.lwz r10,40(r3); \ + l.lwz r11,44(r3); \ + l.lwz r12,48(r3); \ + l.lwz r13,52(r3); \ + l.lwz r14,56(r3); \ + l.lwz r15,60(r3); \ + l.lwz r16,64(r3); \ + l.lwz r17,68(r3); \ + l.lwz r18,72(r3); \ + l.lwz r19,76(r3); \ + l.lwz r20,80(r3); \ + l.lwz r21,84(r3); \ + l.lwz r22,88(r3); \ + l.lwz r23,92(r3); \ + l.lwz r24,96(r3); \ + l.lwz r25,100(r3); \ + l.lwz r26,104(r3); \ + l.lwz r27,108(r3); \ + l.lwz r28,112(r3); \ + l.lwz r29,116(r3); \ + l.lwz r30,120(r3); \ + l.lwz r31,124(r3); \ + \ + l.lwz r3,12(r3); /* prepare r3*/ + +/* + * Set new PC in saved context + */ +#define SET_CONTEXTPC(AREA,SUBROUTINE,TMPREG) \ + l.lwz AREA,0(AREA); \ + l.movhi TMPREG,hi(SUBROUTINE); \ + l.addi TMPREG,r0,lo(SUBROUTINE); \ + l.sw 0(AREA),TMPREG; + +/* + * Printf via or1ksim hook + */ +#if KERNEL_OUTPUT +#define PRINTF(REG,STR) \ + l.movhi REG,hi(STR); \ + l.addi REG,r0,lo(STR); \ + l.sys 202 +#else +#define PRINTF(REG,STR) +#endif + +/* + * Reset Exception handler + */ +.org 0x100 +_reset: + l.nop + l.j _kernel_init + l.nop + +/* + * Bus Error Exception handler + */ +.org 0x0200 +_buserr: + l.nop + l.sw 0(r0),r3 /* Save r3 */ + PRINTF(r3, _buserr_str) +_hang: + l.j _hang + l.nop + +_buserr_str: + .ascii "Bus error exception.\n\000" + +/* + * External Interrupt Exception handler + */ +.org 0x800 +_extint: + l.nop + l.sw 0(r0),r3 /* Save r3 */ + PRINTF(r3,_extint_str) + l.mfspr r3,r0,SPR_EPCR_BASE /* Get EPCR */ +/* l.addi r3,r3,4 /* increment because EPCR instruction was already executed */ + l.sw 4(r0),r3 /* and save it */ + + /* now save user task context */ + l.movhi r3,hi(_task_context) + l.addi r3,r0,lo(_task_context) + SAVEREGS + + /* set kernel context's PC to kernel's scheduler */ + l.movhi r3,hi(_kernel_context) + l.addi r3,r0,lo(_kernel_context) + SET_CONTEXTPC(r3,_int_main,r4) + + /* load kernel context */ + l.movhi r3,hi(_kernel_context) + l.addi r3,r0,lo(_kernel_context) + LOADREGS + l.j _int_main + l.nop + +_extint_str: + .ascii "External interrupt exception.\n\000" + +/* + * System Call Exception handler + */ +.org 0x0c00 +_syscall: + l.nop + l.sw 0(r0),r3 /* Save r3 */ + PRINTF(r3,_syscall_str) + l.mfspr r3,r0,SPR_EPCR_BASE /* Get EPCR */ + l.addi r3,r3,4 /* increment because EPCR instruction was already executed */ + l.sw 4(r0),r3 /* and save it */ + + /* now save user task context */ + l.movhi r3,hi(_task_context) + l.addi r3,r0,lo(_task_context) + SAVEREGS + + /* set kernel context's PC to kernel's syscall entry */ + l.movhi r3,hi(_kernel_context) + l.addi r3,r0,lo(_kernel_context) + SET_CONTEXTPC(r3,_kernel_syscall,r4) + + /* load kernel context */ + l.movhi r3,hi(_kernel_context) + l.addi r3,r0,lo(_kernel_context) + LOADREGS_N_GO + +_syscall_str: + .ascii "System call exception.\n\000" + +/* + * Switch to a new context pointed by _task_context + */ +.global _dispatch +.align 4 +_dispatch: + /* load user task GPRs and PC */ + l.movhi r3,hi(_task_context) + l.addi r3,r0,lo(_task_context) + LOADREGS_N_GO +

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.