sorted sources per functionality in different subdirs

This commit is contained in:
Markus Fröschle
2013-12-19 13:02:39 +00:00
parent b7d4c4e91a
commit 72eb1494b0
47 changed files with 48 additions and 148 deletions

347
sys/BaS.c Normal file
View File

@@ -0,0 +1,347 @@
/*
* BaS
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*/
#include <stdint.h>
#include <stdbool.h>
#include "MCF5475.h"
#include "MCF5475_SLT.h"
#include "startcf.h"
#include "sysinit.h"
#include "cache.h"
#include "bas_printf.h"
#include "bas_string.h"
#include "bas_types.h"
#include "sd_card.h"
#include "wait.h"
#include "diskio.h"
#include "ff.h"
#include "s19reader.h"
#include "dma.h"
/* imported routines */
extern int mmu_init();
extern int vec_init();
/* Symbols from the linker script */
extern uint8_t _STRAM_END[];
#define STRAM_END ((uint32_t)_STRAM_END)
extern uint8_t _TOS[];
#define TOS ((uint32_t)_TOS) /* final TOS location */
extern uint8_t _FASTRAM_END[];
#define FASTRAM_END ((uint32_t)_FASTRAM_END)
extern uint8_t _EMUTOS[];
#define EMUTOS ((uint32_t)_EMUTOS) /* where EmuTOS is stored in flash */
extern uint8_t _EMUTOS_SIZE[];
#define EMUTOS_SIZE ((uint32_t)_EMUTOS_SIZE) /* size of EmuTOS, in bytes */
#define NOP() __asm__ __volatile__("nop\n\t" : : : "memory") /* need this to force pipeline sync after MMUCR write */
/*
* check if it is possible to transfer data to PIC
*/
static inline bool pic_txready(void)
{
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_TXRDY)
return true;
return false;
}
/*
* check if it is possible to receive data from PIC
*/
static inline bool pic_rxready(void)
{
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_RXRDY)
return true;
return false;
}
void write_pic_byte(uint8_t value)
{
/* Wait until the transmitter is ready or 1000us are passed */
waitfor(1000, pic_txready);
/* Transmit the byte */
*(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT) = value; // Really 8-bit
}
uint8_t read_pic_byte(void)
{
/* Wait until a byte has been received or 1000us are passed */
waitfor(1000, pic_rxready);
/* Return the received byte */
return *(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT); // Really 8-bit
}
void pic_init(void)
{
char answer[4] = "OLD";
xprintf("initialize the PIC: ");
/* Send the PIC initialization string */
write_pic_byte('A');
write_pic_byte('C');
write_pic_byte('P');
write_pic_byte('F');
/* Read the 3-char answer string. Should be "OK!". */
answer[0] = read_pic_byte();
answer[1] = read_pic_byte();
answer[2] = read_pic_byte();
answer[3] = '\0';
if (answer[0] != 'O' || answer[1] != 'K' || answer[2] != '!')
{
xprintf("PIC initialization failed. Already initialized?\r\n");
}
else
{
xprintf("%s\r\n", answer);
}
}
void nvram_init(void)
{
int i;
xprintf("Restore the NVRAM data: ");
/* Request for NVRAM backup data */
write_pic_byte(0x01);
/* Check answer type */
if (read_pic_byte() != 0x81)
{
// FIXME: PIC protocol error
xprintf("FAILED\r\n");
return;
}
/* Restore the NVRAM backup to the FPGA */
for (i = 0; i < 64; i++)
{
uint8_t data = read_pic_byte();
*(volatile uint8_t*)0xffff8961 = i;
*(volatile uint8_t*)0xffff8963 = data;
}
xprintf("finished\r\n");
}
#define KBD_ACIA_CONTROL ((uint8_t *) 0xfffffc00)
#define MIDI_ACIA_CONTROL ((uint8_t *) 0xfffffc04)
#define MFP_INTR_IN_SERVICE_A ((uint8_t *) 0xfffffa0f)
#define MFP_INTR_IN_SERVICE_B ((uint8_t *) 0xfffffa11)
void acia_init()
{
xprintf("init ACIA: ");
/* init ACIA */
* KBD_ACIA_CONTROL = 3; /* master reset */
NOP();
* MIDI_ACIA_CONTROL = 3; /* master reset */
NOP();
* KBD_ACIA_CONTROL = 0x96; /* clock div = 64, 8N1, RTS low, TX int disable, RX int enable */
NOP();
* MFP_INTR_IN_SERVICE_A = -1;
NOP();
* MFP_INTR_IN_SERVICE_B = -1;
NOP();
xprintf("finished\r\n");
}
/* ACP interrupt controller */
#define FPGA_INTR_CONTRL (volatile uint32_t *) 0xf0010000
#define FPGA_INTR_ENABLE (volatile uint8_t *) 0xf0010004
#define FPGA_INTR_PENDIN (volatile uint32_t *) 0xf0010008
void enable_coldfire_interrupts()
{
xprintf("enable interrupts: ");
#if MACHINE_FIREBEE
*FPGA_INTR_CONTRL = 0L; /* disable all interrupts */
#endif /* MACHINE_FIREBEE */
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
#if MACHINE_FIREBEE
/*
* TIN0 on the Coldfire is connected to the FPGA. TIN0 triggers every write
* access to 0xff8201 (vbasehi), i.e. everytime the video base address is written
*/
MCF_GPT0_GMS = MCF_GPT_GMS_ICT(1) | /* timer 0 on, video change capture on rising edge */
MCF_GPT_GMS_IEN |
MCF_GPT_GMS_TMS(1);
/* route GPT0 interrupt on interrupt controller */
MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */
*FPGA_INTR_ENABLE = 0xfe; /* enable int 1-7 */
#endif /* MACHINE_FIREBEE */
MCF_EPORT_EPIER = 0xfe; /* int 1-7 on */
MCF_EPORT_EPFR = 0xff; /* clear all pending interrupts */
MCF_INTC_IMRL = 0xffffff00; /* int 1-7 on */
MCF_INTC_IMRH = 0xbffffffe; /* psc3 and timer 0 int on */
xprintf("finished\r\n");
}
void disable_coldfire_interrupts()
{
*FPGA_INTR_ENABLE = 0; /* disable all interrupts */
MCF_EPORT_EPIER = 0x0;
MCF_EPORT_EPFR = 0x0;
MCF_INTC_IMRL = 0xfffffffe;
MCF_INTC_IMRH = 0xffffffff;
}
void BaS(void)
{
uint8_t *src;
uint8_t *dst = (uint8_t *) TOS;
#if MACHINE_FIREBEE /* LITE board has no pic and (currently) no nvram */
pic_init();
nvram_init();
#endif /* MACHINE_FIREBEE */
xprintf("copy EmuTOS: ");
/* copy EMUTOS */
src = (uint8_t *) EMUTOS;
memcpy(dst, src, EMUTOS_SIZE);
xprintf("finished\r\n");
xprintf("initialize MMU: ");
mmu_init();
xprintf("finished\r\n");
xprintf("initialize exception vector table: ");
vec_init();
xprintf("finished\r\n");
xprintf("flush caches: ");
flush_and_invalidate_caches();
xprintf("finished\r\n");
xprintf("enable MMU: ");
MCF_MMU_MMUCR = MCF_MMU_MMUCR_EN; /* MMU on */
NOP(); /* force pipeline sync */
xprintf("finished\r\n");
#ifdef MACHINE_FIREBEE
xprintf("IDE reset: ");
/* IDE reset */
* (volatile uint8_t *) (0xffff8802 - 2) = 14;
* (volatile uint8_t *) (0xffff8802 - 0) = 0x80;
wait(1);
* (volatile uint8_t *) (0xffff8802 - 0) = 0;
xprintf("finished\r\n");
xprintf("enable video: ");
/*
* video setup (25MHz)
*/
* (volatile uint32_t *) (0xf0000410 + 0) = 0x032002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020c020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x0190015d; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x020C020A; /* vertical 320x230 */
#ifdef _NOT_USED_
// 32MHz
* (volatile uint32_t *) (0xf0000410 + 0) = 0x037002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020d020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x02a001e0; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x05a00160; /* vertical 320x230 */
#endif /* _NOT_USED_ */
/* fifo on, refresh on, ddrcs and cke on, video dac on */
* (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
xprintf("finished\r\n");
#endif /* MACHINE_FIREBEE */
sd_card_init();
/*
* memory setup
*/
memset((void *) 0x400, 0, 0x400);
#ifdef MACHINE_FIREBEE
/* set Falcon bus control register */
/* sets bit 3 and 6. Both are undefined on an original Falcon? */
* (volatile uint8_t *) 0xffff8007 = 0x48;
#endif /* MACHINE_FIREBEE */
/* ST RAM */
* (uint32_t *) 0x42e = STRAM_END; /* phystop TOS system variable */
* (uint32_t *) 0x420 = 0x752019f3; /* memvalid TOS system variable */
* (uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */
* (uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */
/* TT-RAM */
* (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */
* (uint32_t *) 0x5a4 = 0x1d000000;
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
#ifdef MACHINE_FIREBEE /* m5484lite has no ACIA and no dip switch... */
acia_init();
/* Test for pseudo-supervisor mode: DIP switch #6 down */
if (DIP_SWITCH & (1 << 7)) {
/* In this mode, the OS actually runs in user mode
* and all the supervisor instructions are emulated. */
__asm__ __volatile__("move.w #0x0700,sr \n\t" : : : "memory");
}
#endif /* MACHINE_FIREBEE */
srec_execute("BASFLASH.S19");
/* Jump into the OS */
typedef void void_func(void);
typedef struct {
void *initial_sp;
void_func *initial_pc;
} ROM_HEADER;
xprintf("BaS initialization finished, enable interrupts\r\n");
enable_coldfire_interrupts();
xprintf("call EmuTOS\r\n");
ROM_HEADER* os_header = (ROM_HEADER*)TOS;
os_header->initial_pc();
}

145
sys/cache.c Normal file
View File

@@ -0,0 +1,145 @@
/*
* cache handling
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*
*/
#include "cache.h"
void cacr_set(uint32_t value)
{
extern uint32_t rt_cacr;
rt_cacr = value;
__asm__ __volatile__("movec %0, cacr\n\t"
: /* output */
: "r" (rt_cacr)
: /* clobbers */);
}
uint32_t cacr_get(void)
{
extern uint32_t rt_cacr;
return rt_cacr;
}
void flush_and_invalidate_caches(void)
{
__asm__ (
" clr.l d0\n\t"
" clr.l d1\n\t"
" move.l d0,a0\n\t"
"cfa_setloop:\n\t"
" cpushl bc,(a0) | flush\n\t"
" lea 0x10(a0),a0 | index+1\n\t"
" addq.l #1,d1 | index+1\n\t"
" cmpi.w #512,d1 | all sets?\n\t"
" bne.s cfa_setloop | no->\n\t"
" clr.l d1\n\t"
" addq.l #1,d0\n\t"
" move.l d0,a0\n\t"
" cmpi.w #4,d0 | all ways?\n\t"
" bne.s cfa_setloop | no->\n\t"
/* input */ :
/* output */ :
/* clobber */ : "d0", "d1", "a0"
);
}
/*
* flush and invalidate a specific memory region from the instruction cache
*/
void flush_icache_range(void *address, size_t size)
{
uint32_t set;
uint32_t start_set;
uint32_t end_set;
void *endaddr = address + size;
start_set = (uint32_t) address & _ICACHE_SET_MASK;
end_set = (uint32_t) endaddr & _ICACHE_SET_MASK;
if (start_set > end_set) {
/* from the begining to the lowest address */
for (set = 0; set <= end_set; set += (0x10 - 3)) {
asm volatile("cpushl ic,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl ic,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl ic,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl ic,(%0)" : "=a" (set) : "a" (set));
}
/* next loop will finish the cache ie pass the hole */
end_set = LAST_ICACHE_ADDR;
}
for (set = start_set; set <= end_set; set += (0x10 - 3)) {
asm volatile("cpushl ic,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl ic,(%0)\n\t"
"addq%.l #1,%0\n\t"
"cpushl ic,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl ic,(%0)" : "=a" (set) : "a" (set));
}
}
/*
* flush and invalidate a specific region from the data cache
*/
void flush_dcache_range(void *address, size_t size)
{
unsigned long set;
unsigned long start_set;
unsigned long end_set;
void *endaddr;
endaddr = address + size;
start_set = (uint32_t) address & _DCACHE_SET_MASK;
end_set = (uint32_t) endaddr & _DCACHE_SET_MASK;
if (start_set > end_set) {
/* from the begining to the lowest address */
for (set = 0; set <= end_set; set += (0x10 - 3)) {
asm volatile("cpushl dc,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl dc,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl dc,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl dc,(%0)" : "=a" (set) : "a" (set));
}
/* next loop will finish the cache ie pass the hole */
end_set = LAST_DCACHE_ADDR;
}
for (set = start_set; set <= end_set; set += (0x10 - 3)) {
asm volatile("cpushl dc,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl dc,(%0)\n\t"
"addq%.l #1,%0\n\t"
"cpushl dc,(%0)\n\t"
"addq.l #1,%0\n\t"
"cpushl dc,(%0)" : "=a" (set) : "a" (set));
}
}

1148
sys/exceptions.S Normal file

File diff suppressed because it is too large Load Diff

198
sys/fault_vectors.c Normal file
View File

@@ -0,0 +1,198 @@
/*
* This file is part of BaS_gcc.
*
* BaS_gcc 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 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* provide an early exception vector branch table to catch exceptions _before_ VBR has been setup eventually
* (to RAMBAR0, in exceptions.S)
*/
#include "MCF5475.h"
#include "bas_types.h"
#include "bas_printf.h"
typedef void (*exception_handler)(void);
extern exception_handler SDRAM_VECTOR_TABLE[];
/*
* decipher Coldfire exception stack frame and print it out in cleartext
*/
void fault_handler(uint32_t pc, uint32_t format_status)
{
int format;
int fault_status;
int vector;
int sr;
xprintf("\007\007exception! Processor halted.\r\n");
xprintf("format_status: %lx\r\n", format_status);
xprintf("pc: %lx\r\n", pc);
/*
* extract info from format-/status word
*/
format = (format_status & 0b11110000000000000000000000000000) >> 28;
fault_status = ((format_status & 0b00001100000000000000000000000000) >> 26) |
((format_status & 0b00000000000000110000000000000000) >> 16);
vector = (format_status & 0b00000011111111000000000000000000) >> 18;
sr = (format_status & 0b00000000000000001111111111111111);
xprintf("format: %x\r\n", format);
xprintf("fault_status: %x (", fault_status);
switch (fault_status)
{
case 0:
xprintf("not an access or address error nor an interrupted debug service routine");
break;
case 1:
case 3:
case 11:
xprintf("reserved");
break;
case 2:
xprintf("interrupt during a debug service routine for faults other than access errors");
break;
case 4:
xprintf("error (for example, protection fault) on instruction fetch");
break;
case 5:
xprintf("TLB miss on opword or instruction fetch");
break;
case 6:
xprintf("TLB miss on extension word of instruction fetch");
break;
case 7:
xprintf("IFP access error while executing in emulator mode");
break;
case 8:
xprintf("error on data write");
break;
case 9:
xprintf("error on attempted write to write-protected space");
break;
case 10:
xprintf("TLB miss on data write");
break;
case 12:
xprintf("error on data read");
break;
case 13:
xprintf("attempted read, read-modify-write of protected space");
break;
case 14:
xprintf("TLB miss on data read or read-modify-write");
break;
case 15:
xprintf("OEP access error while executing in emulator mode");
}
xprintf(")\r\n");
xprintf("vector = %02x (", vector);
switch (vector)
{
case 2:
xprintf("access error");
break;
case 3:
xprintf("address error");
break;
case 4:
xprintf("illegal instruction");
break;
case 5:
xprintf("divide by zero");
break;
case 8:
xprintf("privilege violation");
break;
case 9:
xprintf("trace");
break;
case 10:
xprintf("unimplemented line-a opcode");
break;
case 11:
xprintf("unimplemented line-f opcode");
break;
case 12:
xprintf("non-PC breakpoint debug interrupt");
break;
case 13:
xprintf("PC breakpoint debug interrupt");
break;
case 14:
xprintf("format error");
break;
case 24:
xprintf("spurious interrupt");
break;
default:
if ( ((fault_status >= 6) && (fault_status <= 7)) ||
((fault_status >= 16) && (fault_status <= 23)))
{
xprintf("reserved");
}
else if ((fault_status >= 25) && (fault_status <= 31))
{
xprintf("level %d autovectored interrupt", fault_status - 24);
}
else if ((fault_status >= 32) && (fault_status <= 47))
{
xprintf("trap #%d", fault_status - 32);
}
else
{
xprintf("unknown fault status");
}
}
xprintf(")\r\n");
xprintf("sr=%4x\r\n", sr);
}
void __attribute__((interrupt)) handler(void)
{
/*
* Prepare exception stack contents so it can be handled by a C routine.
*
* For standard routines, we'd have to save registers here.
* Since we do not intend to return anyway, we just ignore that requirement.
*/
__asm__ __volatile__("move.l (sp),-(sp)\n\t"\
"move.l 8(sp),-(sp)\n\t"\
"bsr _fault_handler\n\t"\
"halt\n\t"\
: : : "memory");
}
void setup_vectors(void)
{
int i;
xprintf("\r\ninstall early exception vector table:");
for (i = 8; i < 256; i++)
{
SDRAM_VECTOR_TABLE[i] = &handler;
}
/*
* make sure VBR points to our table
*/
__asm__ __volatile__("clr.l d0\n\t"\
"movec.l d0,VBR\n\t"\
"nop\n\t"\
"move.l d0,_rt_vbr" ::: "d0", "memory");
xprintf("finished.\r\n");
}

42
sys/illegal_instruction.S Normal file
View File

@@ -0,0 +1,42 @@
/*
* illegal_instruction.S
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*/
.global _illegal_instruction
.global _illegal_table_make
#include "startcf.h"
.extern _ii_shift_vec
.extern ewf
/*******************************************************/
.text
ii_error:
nop
halt
nop
nop
_illegal_instruction:
_illegal_table_make:
rts

170
sys/init_fpga.c Normal file
View File

@@ -0,0 +1,170 @@
/*
* init_fpga.c
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*
*/
#include "MCF5475.h"
#include "sysinit.h"
#include "bas_printf.h"
#include "wait.h"
#define FPGA_STATUS (1 << 0)
#define FPGA_CLOCK (1 << 1)
#define FPGA_CONFIG (1 << 2)
#define FPGA_DATA0 (1 << 3)
#define FPGA_CONF_DONE (1 << 5)
extern uint8_t _FPGA_FLASH_DATA[];
#define FPGA_FLASH_DATA &_FPGA_FLASH_DATA[0]
extern uint8_t _FPGA_FLASH_DATA_SIZE[];
#define FPGA_FLASH_DATA_SIZE ((uint32_t) &_FPGA_FLASH_DATA_SIZE[0])
void test_longword(void)
{
uint32_t *fpga_data = (uint32_t *) FPGA_FLASH_DATA;
const uint32_t *fpga_flash_data_end = (uint32_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
do
{
uint32_t value = *fpga_data++;
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value);
} while (fpga_data < fpga_flash_data_end);
xprintf("finished. \r\n");
}
void test_word(void)
{
uint16_t *fpga_data = (uint16_t *) FPGA_FLASH_DATA;
const uint16_t *fpga_flash_data_end = (uint16_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
do
{
uint16_t value = *fpga_data++;
xprintf("WORDS: addr=%p, value=%04x\r", fpga_data, value);
} while (fpga_data < fpga_flash_data_end);
xprintf("finished. \r\n");
}
void test_byte(void)
{
uint8_t *fpga_data = (uint8_t *) FPGA_FLASH_DATA;
const uint8_t *fpga_flash_data_end = (uint8_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
do
{
uint8_t value = *fpga_data++;
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value);
} while (fpga_data < fpga_flash_data_end);
xprintf("finished. \r\n");
}
/*
* load FPGA
*/
void init_fpga(void)
{
uint8_t *fpga_data;
int i;
/*
xprintf("MCF_FBCS0_CSAR: %08x\r\n", MCF_FBCS0_CSAR);
xprintf("MCF_FBCS0_CSCR: %08x\r\n", MCF_FBCS0_CSCR);
xprintf("MCF_FBCS0_CSMR: %08x\r\n", MCF_FBCS0_CSMR);
*/
xprintf("FPGA load config... ");
//test_longword();
//test_word();
//test_byte();
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
/* pulling FPGA_CONFIG to low resets the FPGA */
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */
wait(10); /* give it some time to do its reset stuff */
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE));
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS)); /* wait until status becomes high */
/*
* excerpt from an Altera configuration manual:
*
* The low-to-high transition of nCONFIG on the FPGA begins the configuration cycle. The
* configuration cycle consists of 3 stages<65>reset, configuration, and initialization.
* While nCONFIG is low, the device is in reset. When the device comes out of reset,
* nCONFIG must be at a logic high level in order for the device to release the open-drain
* nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA
* is ready to receive configuration data. Before and during configuration, all user I/O pins
* are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors
* on the I/O pins which are on, before and during configuration.
*
* To begin configuration, nCONFIG and nSTATUS must be at a logic high level. You can delay
* configuration by holding the nCONFIG low. The device receives configuration data on its
* DATA0 pins. Configuration data is latched into the FPGA on the rising edge of DCLK. After
* the FPGA has received all configuration data successfully, it releases the CONF_DONE pin,
* which is pulled high by a pull-up resistor. A low to high transition on CONF_DONE indicates
* configuration is complete and initialization of the device can begin.
*/
const uint8_t *fpga_flash_data_end = FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
fpga_data = (uint8_t *) FPGA_FLASH_DATA;
do
{
uint8_t value = *fpga_data++;
for (i = 0; i < 8; i++, value >>= 1)
{
if (value & 1)
{
/* bit set -> toggle DATA0 to high */
MCF_GPIO_PODR_FEC1L |= FPGA_DATA0;
}
else
{
/* bit is cleared -> toggle DATA0 to low */
MCF_GPIO_PODR_FEC1L &= ~FPGA_DATA0;
}
/* toggle DCLK -> FPGA reads the bit */
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
}
} while ((!(MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)) && (fpga_data < fpga_flash_data_end));
if (fpga_data < fpga_flash_data_end)
{
while (fpga_data++ < fpga_flash_data_end)
{
/* toggle a little more since it's fun ;) */
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
}
xprintf("finished\r\n");
}
else
{
xprintf("FAILED!\r\n");
}
}

81
sys/interrupts.c Normal file
View File

@@ -0,0 +1,81 @@
/*
* Interrupts
*
* Handle interrupts, the levels.
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Created on: 26.02.2013
* Author: Markus Fröschle
*/
#include <stdint.h>
#include "MCF5475.h"
#include "bas_utils.h"
#include "bas_printf.h"
#include "exceptions.h"
#include "interrupts.h"
#include "bas_printf.h"
extern void (*rt_vbr[])(void);
#define VBR rt_vbr
/*
* register an interrupt handler at the Coldfire interrupt controller and add the handler to
* the interrupt vector table
*/
int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void))
{
int ipl;
int i;
volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1;
uint8_t lp;
source &= 63;
priority &= 7;
if (source < 1 || source > 63)
{
xprintf("%s: interrupt source %d not defined\r\n", __FUNCTION__, source);
return -1;
}
lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority);
/* check if this combination is already set somewhere */
for (i = 1; i < 64; i++)
{
if (ICR[i] == lp)
{
xprintf("%s: level %d and priority %d already used for interrupt source %d!\r\n", __FUNCTION__,
level, priority, i);
return -1;
}
}
/* disable interrupts */
ipl = set_ipl(7);
VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
/* set level and priority in interrupt controller */
ICR[source] = lp;
/* set interrupt mask to where it was before */
set_ipl(ipl);
return 0;
}

406
sys/mmu.c Normal file
View File

@@ -0,0 +1,406 @@
#include "mmu.h"
#include "acia.h"
/*
* mmu.c
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* derived from original assembler sources:
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2013 M. Froeschle
*/
#define ACR_BA(x) ((x) & 0xffff0000)
#define ACR_ADMSK(x) (((x) & 0xffff) << 16)
#define ACR_E(x) (((x) & 1) << 15)
#define ACR_S(x) (((x) & 3) << 13)
#define ACR_S_USERMODE 0
#define ACR_S_SUPERVISOR_MODE 1
#define ACR_S_ALL 2
#define ACR_AMM(x) (((x) & 1) << 10)
#define ACR_CM(x) (((x) & 3) << 5)
#define ACR_CM_CACHEABLE_WT 0x0
#define ACR_CM_CACHEABLE_CB 0x1
#define ACR_CM_CACHE_INH_PRECISE 0x2
#define ACR_CM_CACHE_INH_IMPRECISE 0x3
#define ACR_SP(x) (((x) & 1) << 3)
#define ACR_W(x) (((x) & 1) << 2)
#include <stdint.h>
#include "bas_printf.h"
#include "bas_types.h"
#include "MCF5475.h"
#include "pci.h"
#include "cache.h"
#if MACHINE_FIREBEE
#include "firebee.h"
#elif MACHINE_M5484LITE
#include "m5484l.h"
#endif /* MACHINE_FIREBEE */
#define DEBUG_MMU
#ifdef DEBUG_MMU
#define dbg_mmu(format, arg...) do { xprintf("DEBUG: " format "\r\n", ##arg);} while(0)
#else
#define dbg_mmu(format, arg...) do {;} while (0)
#endif /* DEBUG_MMU */
/*
* set ASID register
* saves new value to rt_asid and returns former value
*/
inline uint32_t set_asid(uint32_t value)
{
extern long rt_asid;
uint32_t ret = rt_asid;
__asm__ __volatile__(
"movec %[value],ASID\n\t"
: /* no output */
: [value] "r" (value)
:
);
rt_asid = value;
return ret;
}
/*
* set ACRx register
* saves new value to rt_acrx and returns former value
*/
inline uint32_t set_acr0(uint32_t value)
{
extern uint32_t rt_acr0;
uint32_t ret = rt_acr0;
__asm__ __volatile__(
"movec %[value],ACR0\n\t"
: /* not output */
: [value] "r" (value)
:
);
rt_acr0 = value;
return ret;
}
/*
* set ACRx register
* saves new value to rt_acrx and returns former value
*/
inline uint32_t set_acr1(uint32_t value)
{
extern uint32_t rt_acr1;
uint32_t ret = rt_acr1;
__asm__ __volatile__(
"movec %[value],ACR1\n\t"
: /* not output */
: [value] "r" (value)
:
);
rt_acr1 = value;
return ret;
}
/*
* set ACRx register
* saves new value to rt_acrx and returns former value
*/
inline uint32_t set_acr2(uint32_t value)
{
extern uint32_t rt_acr2;
uint32_t ret = rt_acr2;
__asm__ __volatile__(
"movec %[value],ACR2\n\t"
: /* not output */
: [value] "r" (value)
:
);
rt_acr2 = value;
return ret;
}
/*
* set ACRx register
* saves new value to rt_acrx and returns former value
*/
inline uint32_t set_acr3(uint32_t value)
{
extern uint32_t rt_acr3;
uint32_t ret = rt_acr3;
__asm__ __volatile__(
"movec %[value],ACR3\n\t"
: /* not output */
: [value] "r" (value)
:
);
rt_acr3 = value;
return ret;
}
inline uint32_t set_mmubar(uint32_t value)
{
extern uint32_t rt_mmubar;
uint32_t ret = rt_mmubar;
__asm__ __volatile__(
"movec %[value],MMUBAR\n\t"
: /* no output */
: [value] "r" (value)
: /* no clobber */
);
rt_mmubar = value;
return ret;
}
void mmu_init(void)
{
extern uint8_t _MMUBAR[];
uint32_t MMUBAR = (uint32_t) &_MMUBAR[0];
extern uint8_t _TOS[];
uint32_t TOS = (uint32_t) &_TOS[0];
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */
/* set data access attributes in ACR0 and ACR1 */
set_acr0(ACR_W(0) | /* read and write accesses permitted */
ACR_SP(0) | /* supervisor and user mode access permitted */
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */
ACR_AMM(0) | /* control region > 16 MB */
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */
ACR_E(1) | /* enable ACR */
#if MACHINE_FIREBEE
ACR_ADMSK(0x3f) | /* cover 1GB area from 0xc0000000 to 0xffffffff */
ACR_BA(0xc0000000)); /* (equals area from 3 to 4 GB */
#elif MACHINE_M5484LITE
ACR_ADMSK(0xff) | /* cover 2 GB area from 0x80000000 to 0xffffffff */
ACR_BA(0x80000000));
#endif /* MACHINE_FIREBEE */
// set_acr1(0x601fc000);
set_acr1(ACR_W(0) |
ACR_SP(0) |
ACR_CM(0) |
#if MACHINE_FIREBEE
ACR_CM(ACR_CM_CACHEABLE_WT) | /* video RAM on the Firebee */
#elif MACHINE_M5484LITE
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */
#endif /* MACHINE_FIREBEE */
ACR_AMM(0) |
ACR_S(ACR_S_ALL) |
ACR_E(1) |
ACR_ADMSK(0x1f) |
ACR_BA(0x60000000));
/* set instruction access attributes in ACR2 and ACR3 */
//set_acr2(0xe007c400);
set_acr2(ACR_W(0) |
ACR_SP(0) |
ACR_CM(0) |
ACR_CM(ACR_CM_CACHEABLE_WT) |
ACR_AMM(1) |
ACR_S(ACR_S_ALL) |
ACR_E(1) |
ACR_ADMSK(0x7) |
ACR_BA(0xe0000000));
/* disable ACR3 */
set_acr3(0x0);
set_mmubar(MMUBAR | 1); /* set and enable MMUBAR */
/* clear all MMU TLB entries */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA;
/* create locked TLB entries */
/*
* 0x0000'0000 - 0x000F'FFFF (first MB of physical memory) locked virtual = physical
*/
MCF_MMU_MMUTR = 0x0 | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = 0x0 | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x1) | /* cacheable, copyback */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
#if MACHINE_FIREBEE /* map FPGA video memory for FireBee only */
/*
* 0x00d0'0000 - 0x00df'ffff (last megabyte of ST RAM = Falcon video memory) locked ID = 6
* mapped to physical address 0x60d0'0000 (FPGA video memory)
* video RAM: read write execute normal write true
*/
MCF_MMU_MMUTR = 0x00d00000 | /* virtual address */
MCF_MMU_MMUTR_ID(SCA_PAGE_ID) |
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = 0x60d00000 | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x0) | /* cachable writethrough */
MCF_MMU_MMUDR_SP | /* supervisor protect */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
video_tlb = 0x2000; /* set page as video page */
video_sbt = 0x0; /* clear time */
#endif /* MACHINE_FIREBEE */
/*
* Make the TOS (in SDRAM) read-only
* This maps virtual 0x00e0'0000 - 0x00ef'ffff to the same virtual address
*/
MCF_MMU_MMUTR = TOS | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = TOS | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x1) | /* cachable copyback */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable (FIXME: for now) */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
#if MACHINE_FIREBEE
/*
* Map FireBee I/O area (0xfff0'0000 - 0xffff'ffff physical) to the Falcon-compatible I/O
* area (0x00f0'0000 - 0x00ff'ffff virtual) for the FireBee
*/
MCF_MMU_MMUTR = 0x00f00000 | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = 0xfff00000 | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x2) | /* nocache precise */
MCF_MMU_MMUDR_SP | /* supervisor protect */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
#endif /* MACHINE_FIREBEE */
/*
* Map (locked) the last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same
* virtual address. This is also used when BaS is in RAM
*/
MCF_MMU_MMUTR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x0) | /* cacheable writethrough */
MCF_MMU_MMUDR_SP | /* supervisor protect */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
}
void mmutr_miss(void)
{
register uint32_t address asm("d0");
dbg_mmu("MMU TLB MISS at 0x%08x\r\n", address);
flush_and_invalidate_caches();
switch (address)
{
case keyctl:
case keybd:
/* do something to emulate the IKBD access */
dbg_mmu("IKBD access\r\n");
break;
case midictl:
case midi:
/* do something to emulate MIDI access */
dbg_mmu("MIDI ACIA access\r\n");
break;
default:
/* add missed page to TLB */
MCF_MMU_MMUTR = (address & 0xfff00000) | /* virtual aligned to 1M */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (address & 0xfff00000) | /* physical aligned to 1M */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x1) | /* cacheable copyback */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X; /* execute access enable */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
}
}

65
sys/startcf.S Normal file
View File

@@ -0,0 +1,65 @@
/*
* This object file must be the first to be linked,
* so it will be placed at the very beginning of the ROM.
*/
.equ MCF_MMU_MMUCR, __MMUBAR + 0
.global _rom_header
.global _rom_entry
.extern _initialize_hardware
.extern _rt_mbar
/* ROM header */
_rom_header:
/* The first long is supposed to be the initial SP.
* We replace it by bra.s to allow running the ROM from the first byte.
* Then we add a fake jmp instruction for pretty disassembly.
*/
bra.s _rom_entry // Short jump to the real entry point
.short 0x4ef9 // Fake jmp instruction
/* The second long is the initial PC */
.long _rom_entry // Real entry point
/* ROM entry point */
_rom_entry:
/* disable interrupts */
move.w #0x2700,SR
/* Initialize MBAR */
move.l #__MBAR,d0
movec d0,MBAR
move.l d0,_rt_mbar
/* mmu off */
move.l #__MMUBAR+1,d0
movec d0,MMUBAR
clr.l d0
move.l d0,MCF_MMU_MMUCR
/* Initialize RAMBARs: locate SRAM and validate it */
move.l #__RAMBAR0 + 0x7,d0 /* supervisor only */
movec d0,RAMBAR0
move.l #__RAMBAR1 + 0x1,d0
movec d0,RAMBAR1
/* set stack pointer to end of SRAM */
lea __SUP_SP,a7
move.l #0,(sp)
/* Initialize the processor caches.
* The instruction cache is fully enabled.
* The data cache is enabled, but cache-inhibited by default.
* Later, the MMU will fully activate the data cache for specific areas.
* It is important to enable both caches now, otherwise cpushl would hang.
*/
move.l #0xa50c8120,d0
movec d0,cacr
andi.l #0xfefbfeff,d0 // Clear invalidate bits
move.l d0,_rt_cacr
/* initialize any hardware specific issues */
bra _initialize_hardware

565
sys/supervisor.S Normal file
View File

@@ -0,0 +1,565 @@
/*
* user/supervisor handler
*/
#include "startcf.h"
#define cf_stack
.extern _rt_cacr;
.extern _rt_mod;
.extern _rt_ssp;
.extern _rt_usp;
.extern ___MMUBAR
.extern _flush_and_invalidate_caches
/* Register read/write macros */
#define MCF_MMU_MMUCR __MMUBAR
#define MCF_MMU_MMUOR __MMUBAR+0x04
#define MCF_MMU_MMUSR __MMUBAR+0x08
#define MCF_MMU_MMUAR __MMUBAR+0x10
#define MCF_MMU_MMUTR __MMUBAR+0x14
#define MCF_MMU_MMUDR __MMUBAR+0x18
.global _privileg_violation
.global cpusha
.text
_privileg_violation:
move.w #0x2700,sr
lea -12(a7),a7
movem.l d0/a0/a5,(a7)
#ifndef cf_stack
lea 0x52f0,a0
move.l #0x20,(a0) // set auf 68030
#endif
lea _rt_mod,a0 // zugriff setzen
tst.b (a0) // vom rt_supervisormodus?
bne pv_work // ja->
// tats<EFBFBD>chlich privileg violation
mov3q.l #-1,(a0) // sr_mod setzen
move.l usp,a5 // usp holen
move.l a5,8(a0) // sichern
move.l 4(a0),a5 // rt_ssp holen
#ifdef cf_stack
move.l 16(a7),-(a5) // pc verschieben
move.l 12(a7),-(a5) // sr verschieben
bset #5,2(a5) // auf super setzen
#else
move.w 12(a7),-(a5) // vector nr.
move.l 16(a7),-(a5) // pc verschieben
move.w 14(a7),-(a5) // sr verschieben
bset #5,(a5) // auf super
#endif
move.l a5,usp
move.l 12(a0),a5 // rt_vbr
lea 0x18(a5),a5 // vector
move.l (a5),16(a7) // vector privileg violation
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// privileg violation
pv_work:
move.l 16(a7),a5 // fault pc
move.b (a5),d0 // fault code
cmp.b #0x4e,d0 // 1.byt 0x4e
beq pv_4e // ja->
cmp.b #0x46,d0 // 1.byt 0x46
beq pv_46 // ja->
cmp.b #0x40,d0 // 1.byt 0x40
beq pv_40 // ja->
cmp.b #0xf4,d0 // 0xf4?
beq pv_f4
cmp.b #0xf3,d0 // 0xf3?
beq pv_f3
// hierher sollt man nicht kommen
nop
halt
nop
// code 0x4exx ********************************************
pv_4e:
move.b 1(a5),d0
cmp.b #0x73,d0 //rte?
beq pv_rte //ja->
cmp.b #0x72,d0 //stop?
beq pv_stop //ja->
cmp.b #0x7B,d0 //movec?
beq pv_movec //ja->
// move usp
btst #3,d0 // to or from
bne pv_usp_to_ax // usp -> ax
// move ax->usp
cmp.b #0x60,d0 //movec?
beq pv_a0_usp //ja->
cmp.b #0x61,d0 //movec?
beq pv_a1_usp //ja->
cmp.b #0x62,d0 //movec?
beq pv_a2_usp //ja->
cmp.b #0x63,d0 //movec?
beq pv_a3_usp //ja->
cmp.b #0x64,d0 //movec?
beq pv_a4_usp //ja->
cmp.b #0x65,d0 //movec?
beq pv_a5_usp //ja->
cmp.b #0x66,d0 //movec?
beq pv_a6_usp //ja->
halt
bra pv_a7_usp //ja->
// move usp->ax
pv_usp_to_ax:
move.l 8(a0),a5 //rt_usp holen
cmp.b #0x68,d0 //movec?
beq pv_usp_a0 //ja->
cmp.b #0x69,d0 //movec?
beq pv_usp_a1 //ja->
cmp.b #0x6a,d0 //movec?
beq pv_usp_a2 //ja->
cmp.b #0x6b,d0 //movec?
beq pv_usp_a3 //ja->
cmp.b #0x6c,d0 //movec?
beq pv_usp_a4 //ja->
cmp.b #0x6d,d0 //movec?
beq pv_usp_a5 //ja->
cmp.b #0x6e,d0 //movec?
beq pv_usp_a6 //ja->
// usp->a7
move.l a5,4(a0) // rt usp -> rt ssp
move.l a5,usp // und setzen
bra pv_usp_ax
// a0->usp
pv_a0_usp: move.l 4(a7),a5
bra pv_ax_usp
// a1->usp
pv_a1_usp: move.l a1,a5
bra pv_ax_usp
// a2->usp
pv_a2_usp: move.l a2,a5
bra pv_ax_usp
// a3->usp
pv_a3_usp: move.l a3,a5
bra pv_ax_usp
// a4->usp
pv_a4_usp: move.l a4,a5
bra pv_ax_usp
// a5->usp
pv_a5_usp: move.l 8(a7),a5
bra pv_ax_usp
// a6->usp
pv_a6_usp: move.l a6,a5
bra pv_ax_usp
// a7->usp
pv_a7_usp: move.l 4(a0),a5 // rt_ssp -> a5
pv_ax_usp:
move.l a5,8(a0) // usp -> rt_usp
addq.l #2,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// usp->a0
pv_usp_a0:
move.l a5,4(a7)
bra pv_usp_ax
pv_usp_a1:
move.l a5,a1
bra pv_usp_ax
pv_usp_a2:
move.l a5,a2
bra pv_usp_ax
pv_usp_a3:
move.l a5,a3
bra pv_usp_ax
pv_usp_a4:
move.l a5,a4
bra pv_usp_ax
pv_usp_a5:
move.l a5,8(a7)
bra pv_usp_ax
pv_usp_a6:
move.l a5,a6
pv_usp_ax:
addq.l #2,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// rte
pv_rte:
move.l usp,a5
#ifdef cf_stack
move.l (a5)+,12(a7) // sr verschieben
move.l (a5)+,16(a7) // pc verschieben
#else
move.w (a5)+,14(a7) // sr verschieben
move.l (a5)+,16(a7) // pc verschieben
move.w (a5)+,12(a7) // vector
#endif
bclr #5,14(a7) // war es von super?
bne pv_rte_sup // ja->
clr.l (a0) // rt_mod auf user
move.l a5,4(a0) // rt_ssp sichern
move.l 8(a0),a5 // rt_usp holen
pv_rte_sup:
move.l a5,usp // usp setzen
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// stop
pv_stop:
move.b 2(a5),d0 // sr wert
and.l #0x0700,d0 // int mask
cmp.w #0x700,d0
beq stop7
cmp.w #0x600,d0
beq stop6
cmp.w #0x500,d0
beq stop5
cmp.w #0x400,d0
beq stop4
cmp.w #0x300,d0
beq stop3
cmp.w #0x200,d0
beq stop2
cmp.w #0x100,d0
beq stop1
stop #0x2000
bra stop_weiter
stop1:
stop #0x2100
bra stop_weiter
stop2:
stop #0x2200
bra stop_weiter
stop3:
stop #0x2300
bra stop_weiter
stop4:
stop #0x2400
bra stop_weiter
stop5:
stop #0x2500
bra stop_weiter
stop6:
stop #0x2600
bra stop_weiter
stop7:
stop #0x2700
stop_weiter:
addq.l #4,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// movec ???????
pv_movec:
move.w 2(a5),d0 // 2.word holen
and.l #0xf000,d0
btst #15,d0 // addressregister?
bne pv_movec_ax // ja->
tst.w d0 // d0?
bne pvm_d1 // nein->
move.l (a7),-(a7) // d0 holen und sichern
bra pvm_me
pvm_d1:
cmp.w #0x1000,d0 // d1?
bne pvm_d2 // nein->
move.l d1,-(a7) // d1 holen und sichern
bra pvm_me // fertig machen
pvm_d2:
cmp.w #0x2000,d0 // d1?
bne pvm_d3 // nein->
move.l d2,-(a7) // d2 holen und sichern
bra pvm_me // fertig machen
pvm_d3:
cmp.w #0x3000,d0 // d1?
bne pvm_d4 // nein->
move.l d3,-(a7) // d3 holen und sichern
bra pvm_me // fertig machen
pvm_d4:
cmp.w #0x4000,d0 // d1?
bne pvm_d5 // nein->
move.l d4,-(a7) // d4 holen und sichern
bra pvm_me // fertig machen
pvm_d5:
cmp.w #0x5000,d0 // d1?
bne pvm_d6 // nein->
move.l d5,-(a7) // d5 holen und sichern
bra pvm_me // fertig machen
pvm_d6:
cmp.w #0x6000,d0 // d1?
bne pvm_d7 // nein->
move.l d6,-(a7) // d6 holen und sichern
bra pvm_me // fertig machen
pvm_d7:
move.l d7,-(a7) // d7 holen und sichern
bra pvm_me // fertig machen
pv_movec_ax:
cmp.w #0x8000,d0 // a0?
bne pvm_a1 // nein->
move.l 4(a7),-(a7) // a0 holen und sichern
bra pvm_me // fertig machen
pvm_a1:
cmp.w #0x9000,d0 // a0?
bne pvm_a2 // nein->
move.l a1,-(a7) // a1 holen und sichern
bra pvm_me // fertig machen
pvm_a2:
cmp.w #0xa000,d0 // a0?
bne pvm_a3 // nein->
move.l a2,-(a7) // a2 holen und sichern
bra pvm_me // fertig machen
pvm_a3:
cmp.w #0xb000,d0 // a0?
bne pvm_a4 // nein->
move.l a3,-(a7) // a3 holen und sichern
bra pvm_me // fertig machen
pvm_a4:
cmp.w #0xc000,d0 // a0?
bne pvm_a5 // nein->
move.l a4,-(a7) // a4 holen und sichern
bra pvm_me // fertig machen
pvm_a5:
cmp.w #0xd000,d0 // a0?
bne pvm_a6 // nein->
move.l 8(a7),-(a7) // a5 holen und sichern
bra pvm_me // fertig machen
pvm_a6:
cmp.w #0xe000,d0 // a0?
bne pvm_a7 // nein->
move.l a6,-(a7) // a6 holen und sichern
bra pvm_me // fertig machen
pvm_a7:
move.l 4(a7),-(a7) // a7 holen und sichern
pvm_me:
move.w 2(a5),d0 // 2.word holen
andi.l #0xf,d0 // nur letzte 4 bits
move.l (a7)+,8(a0,d0*4) // start bei +8, *4 weil long
jsr cpusha // gesammten cache flushen
rte
// code 0x46xx *****************************************
pv_46:
move.b 1(a5),d0
cmp.b #0xfc,d0 //#d16->sr
beq im_sr //ja->
//move dx->sr (sr und rt_mod ist supervisor sonst w<EFBFBD>re es privileg violation
cmp.b #0xc0,d0 //d0->sr?
bne d1_sr //nein->
move.w 2(a7),d0 //hier ist d0 gesichert
bra d0_sr
d1_sr:
cmp.b #0xc1,d0 //d1->sr?
bne d2_sr //nein->
move.w d1,d0
bra d0_sr
d2_sr:
cmp.b #0xc2,d0 //d2->sr?
bne d3_sr
move.w d2,d0
bra d0_sr
d3_sr:
cmp.b #0xc3,d0 //d3->sr?
bne d4_sr
move.w d3,d0
bra d0_sr
d4_sr:
cmp.b #0xc4,d0 //d4->sr?
bne d5_sr
move.w d4,d0
bra d0_sr
d5_sr:
cmp.b #0xc5,d0 //d5->sr?
bne d6_sr
move.w d5,d0
bra d0_sr
d6_sr:
cmp.b #0xc6,d0 //d6->sr?
bne d7_sr
move.w d6,d0
bra d0_sr
d7_sr:
move.w d7,d0 // sonst d7->sr
d0_sr:
addq.l #2,16(a7) // next
bra pv_set_sr_end // fertig machen
// move #xxxx,sr
im_sr:
addq.l #4,16(a7) // next
move.w 2(a5),d0 // data
pv_set_sr_end:
bclr #13,d0 // war super?
bne pv_sre2 // ja ->
clr.l (a0)
move.l usp,a5 // usp
move.l a5,4(a0) // rt_ssp speichern
move.l 8(a0),a5 // rt_usp holen
move.l a5,usp // setzen
pv_sre2:
move.w d0,14(a7) // sr setzen
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// code 0x40xx *****************************************
pv_40:
move.b 1(a5),d0 // 2.byt
cmp.b #0xe7,d0
beq pv_strldsr
// move sr->dx
move.l 12(a7),a5 // sr holen
tst.b (a0) // super?
beq pv_40_user // nein?
lea 0x2000(a5),a5 // super zuaddieren
pv_40_user:
cmp.b #0xc0,d0
bne nsr_d1
move.w a5,2(a7)
bra sr_dx_end
nsr_d1:
cmp.b #0xc1,d0
bne nsr_d2
move.w a5,d1
bra sr_dx_end
nsr_d2:
cmp.b #0xc2,d0
bne nsr_d3
move.w a5,d2
bra sr_dx_end
nsr_d3:
cmp.b #0xc3,d0
bne nsr_d4
move.w a5,d3
bra sr_dx_end
nsr_d4:
cmp.b #0xc4,d0
bne nsr_d5
move.w a5,d4
bra sr_dx_end
nsr_d5:
cmp.b #0xc5,d0
bne nsr_d6
move.w a5,d5
bra sr_dx_end
nsr_d6:
cmp.b #0xc6,d0
bne nsr_d7
move.w a5,d6
bra sr_dx_end
nsr_d7:
move.w a5,d7
halt
sr_dx_end:
addq.l #2,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// strldsr
pv_strldsr:
nop
halt
nop
// code 0xf4xx ***********************************
pv_f4:
addq.l #2,16(a7) // next instr
move.b 1(a5),d0 // 2.byt
bsr pv_ax_a0 // richtiges register
move.b 1(a5),d0 // 2.byt
cmp.b #0x30,d0 // >0xf430
blo pv_intouch
// cpushl
cpushl bc,(a0)
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
pv_intouch:
intouch a0
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
// subroutine register ax->a0
pv_ax_a0:
and.l #0x7,d0 // nur register nummer
subq.l #1,d0
bmi pv_a0_a0
subq.l #1,d0
bmi pv_a1_a0
subq.l #1,d0
bmi pv_a2_a0
subq.l #1,d0
bmi pv_a3_a0
subq.l #1,d0
bmi pv_a4_a0
subq.l #1,d0
bmi pv_a5_a0
subq.l #1,d0
bmi pv_a6_a0
move.l a7,a0
rts
pv_a0_a0:
move.l 8(a7),a0
rts
pv_a1_a0:
move.l a1,a0
rts
pv_a2_a0:
move.l a2,a0
rts
pv_a3_a0:
move.l a3,a0
rts
pv_a4_a0:
move.l a4,a0
rts
pv_a5_a0:
move.l 12(a7),a0
rts
pv_a6_a0:
move.l a6,a0
rts
// code 0xf4xx ***********************************
pv_f3:
addq.l #2,16(a7) // next instr
move.b 1(a5),d0 // 2. byt
cmp.b #0x40,d0
bgt pv_frestore
//fsave (ax) oder d16(ax)
jsr pv_ax_a0 // richtiges register holen
move.b 1(a5),d0
cmp.b #0x20,d0
// +d16
blt pv_f3_ax
addq.l #2,16(a7) // next instr
clr.l d0
move.w 2(a0),d0 // d16
add.l d0,a0
pv_f3_ax:
fsave (a0)
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
pv_frestore:
cmp.b #0x7a,d0
beq pv_f_d16pc
// frestore (ax) oder d16(ax)
jsr pv_ax_a0 // richtiges register holen
move.b 1(a5),d0
cmp.b #0x60,d0
blt pv_frestore_ax
pv_fend:
addq.l #2,16(a7) // next instr
clr.l d0
move.w 2(a0),d0 // d16
add.l d0,a0
pv_frestore_ax:
frestore (a0)
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
// frestore d16(pc)
pv_f_d16pc:
move.l 16(a7),a0 // pc holen
bra pv_fend
//*****************************************************
cpusha:
lea -16(a7),a7
movem.l d0-d1/a0-a1,(a7) // backup C trash registers
jsr _flush_and_invalidate_caches
movem.l (a7),d0-d1/a0-a1 // restore C trash registers
lea 16(a7),a7
rts
//*******************************************************33

1122
sys/sysinit.c Normal file

File diff suppressed because it is too large Load Diff