📄 21060_prom.asm
字号:
/***************************************************************************
060_prom.asm
Copyright (c) 1994 Analog Devices Inc. All rights reserved.
***************************************************************************/
/*
This file is the PROM based boot loader of the ADSP21060 processor.
Gordon A. Sterling (617) 461 - 3076
Systems Software Engineering
Analog Devices, Inc.
Created on 1/4/94
*/
/* Define the addresses of various IOP registers */
#define SYSCON 0x00
#define SYSTAT 0x03
#define II6 0x40
#define IM6 0x41
#define C6 0x42
#define EI6 0x45
#define EM6 0x46
#define EC6 0x47
#define DMAC6 0x1c
.SEGMENT/PM seg_ldr;
/* The loader begins with the interrupts up to and including the low */
/* priority timer interrupt. */
NOP;NOP;NOP;NOP; /* Reserved interrupt */
___lib_RSTI: IDLE; /* Implicit IDLE instruction */
JUMP Start_Loader (DB); /* Begin loader */
NOP; /* Pad to next interrupt */
NOP; /* Pad to next interrupt */
NOP;NOP;NOP;NOP; /* Reserved interrupt */
/* Vector for status stack/loop stack overflow or PC stack full: */
___lib_SOVFI: RTI;
RTI;
RTI;
RTI;
/* Vector for high priority timer interrupt: */
___lib_TMZHI: RTI;
RTI;
RTI;
RTI;
/* Vectors for external interrupts: */
___lib_VIRPTI: RTI;
RTI;
RTI;
RTI;
___lib_IRQ2I: RTI;
RTI;
RTI;
RTI;
___lib_IRQ1I: RTI;
RTI;
RTI;
RTI;
___lib_IRQ0I: RTI;
RTI;
RTI;
RTI;
NOP;NOP;NOP;NOP; /* Reserved interrupt */
/* Vectors for Serial port DMA channels: */
___lib_SPR0I: RTI;
RTI;
RTI;
RTI;
___lib_SPR1I: RTI;
RTI;
RTI;
RTI;
___lib_SPT0I: RTI;
RTI;
RTI;
RTI;
___lib_SPT1I: RTI;
RTI;
RTI;
RTI;
/* Vectors for link port DMA channels: */
___lib_LP2I: RTI;
RTI;
RTI;
RTI;
___lib_LP3I: RTI;
RTI;
RTI;
RTI;
/* Vectors for External port DMA channels: */
___lib_EP0I: R2=DM(DMAC6); /* Get DMAC Control setting */
RTI (DB);
R6=0;
DM(DMAC6)=R6; /* zeroed between uses. */
___lib_EP1I: RTI;
RTI;
RTI;
RTI;
___lib_EP2I: RTI;
RTI;
RTI;
RTI;
___lib_EP3I: RTI;
RTI;
RTI;
RTI;
/* Vector for Link service request */
___lib_LSRQ: RTI;
RTI;
RTI;
RTI;
/* Vector for DAG1 buffer 7 circular buffer overflow */
___lib_CB7I: RTI;
RTI;
RTI;
RTI;
/* Vector for DAG2 buffer 15 circular buffer overflow */
___lib_CB15I: RTI;
RTI;
RTI;
RTI;
/* Vector for lower priority timer interrupt */
___lib_TMZLI: RTI;
RTI;
RTI;
RTI;
Start_Loader: L0=0; /* Zero out L-registers so they */
L4=0; /* can be used without wrap */
L7=0;
L8=0;
L12=0;
L15=0;
M5=0; /* Setup M-registers to use for */
M6=1; /* for various memory transfers*/
M13=0;
M14=1;
R10=DM(SYSCON); /* Read current SYSCON setting */
R12=PASS R10; /* Hold Initial SYSCON setting */
R11=BSET R10 BY 1; /* Set BSO bit for reading ROM */
R10=BCLR R10 BY 1; /* Clear BSO bit for ext write */
DM(SYSCON)=R10; /* Clear BSO bit for writing RAM*/
BIT SET IMASK 0x10000; /* Enable EP0 interrupt */
BIT SET MODE1 0x1800; /* Enable interrupts and nesting*/
R14=0x0221; /* Remove for universal loader */
/* R14=PASS R2; Use this for universal loader */
R15=3; /* EC to load one 48-bit word */
R0=DM(SYSTAT); /* Load the Host ID for use with*/
R0=FEXT R0 BY 8:3; /* the PROM loader. */
BTST R14 BY 9; /* Is this a PROM load? */
IF SZ R11=PASS R10, R0=M5;/* No, don't change BSO bit */
IF NOT SZ R15=R15+R15; /* Yes, set to 6 bytes/48-bit */
BTST R14 BY 0; /* Is this a LINK load? */
IF SZ R11=PASS R10, R0=M5;/* Yes, don't change BSO bit */
IF SZ R15=ASHIFT R15 BY 2;/* Yes, set to 12 nibs/48-bit */
DM(IM6)=M13; /* Setup the DMA registers for */
DM(EM6)=M14;
I4 = 0x400600; /* Address of boot rom */
I7 = SYSCON; /* Address of SYSCON */
I12 = SYSCON; /* Address of SYSCON */
I15 = 0x20004;
R0=PASS R0; /* Test for HostID == 0 */
IF EQ JUMP read_boot_info; /* Skip over multi-boot */
get_addr: CALL read_PROM_word (DB);
NOP;
NOP;
COMP(R0, R2);
IF NE JUMP get_addr (DB);
NOP;
NOP;
DM(EI6)=R3; /* Point to address in PROM */
read_boot_info: CALL read_PROM_word (DB);
NOP;
NOP;
R0=PASS R2;
CALL read_PROM_word (DB);
NOP;
NOP;
load_memory: R0=PASS R0;
IF NE JUMP (PC, test_dm16_zero);
/* After the IDLE completes, the following sequence of instructions will*/
/* be executed: (Remember these are in a loop) */
/* R0=R0-R0, DM(I4,M5)=R9, PM(I12,M13)=R11 */
/* This instructions sets the EQ flag to terminate the loop, writes */
/* the original value to SYSCON, and writes a *new* instruction over */
/* itself. The new instruction is: */
/* PM(0, I8)=PX; */
/* This instruction resets the DMA6 vector to whatever it should be. */
/* The loop will terminate, because of the previous set EQ. Instruction*/
/* flow will continue with 0x20005, just like nothing happened! */
final_init: R9=0xb1db0000; /* Load instruction PM(0,I8)=PX;*/
R11=BSET R11 BY 8; /* Set IDW to 1 for inst write */
DM(SYSCON)=R11; /* Setup to read PROM, inst wrt */
R1=0x020000; /* Point to destination */
R2=0x100; /* Load length of last init */
R4=R2*R15 (SSI); /* Compute external length */
DM(IM6)=M14; /* Set to increment internal ptr*/
I4=0x020004; /* Point to 0x020004 for patch */
I8=0x020040; /* Point to DMA6 vector to patch*/
R4=PASS R4, R11=R12; /* Clear AZ, hold initial SYSCON*/
DO ___lib_RSTI UNTIL EQ;/* Setup dummy loop */
R0=PCSTK; /* Clean off old top-of-loop */
R0=0x20004; /* and replace with new */
PCSTK=R0; /* top-of-loop value */
DM(II6)=R1; /* Setup DMA to load over ldr */
DM(C6)=R2; /* Load internal count */
DM(EC6)=R4; /* Load external count */
JUMP 0x20004 (DB); /* Jump to start */
DM(DMAC6)=R14; /* Start DMA transfer */
IDLE; /* After IDLE, patch then start */
test_dm16_zero: R0=R0-1;
IF EQ JUMP (PC, dm16_zero);
R0=R0-1;
IF NE JUMP (PC, test_dm40_zero);
dm32_zero:
dm16_zero: R0=R0-R0, I0=R3;
LCNTR=R2, DO dm16_zero_loop UNTIL LCE;
NOP;
dm16_zero_loop: DM(I0,M6)=R0;
JUMP read_boot_info;
test_dm40_zero: R0=R0-1;
IF NE JUMP (PC, test_dm16_init);
dm40_zero: PX1=0;
PX2=0;
R0=R0-R0, I0=R3;
LCNTR=R2, DO dm40_zero_loop UNTIL LCE;
NOP;
dm40_zero_loop: DM(I0,M6)=PX;
JUMP read_boot_info;
test_dm16_init: R0=R0-1;
IF NE JUMP (PC, test_dm32_init);
dm16_init: I0=R3;
LCNTR=R2, DO dm16_init_loop UNTIL LCE;
CALL read_PROM_word (DB);
NOP;
NOP;
dm16_init_loop: DM(I0,M6)=R3;
JUMP read_boot_info;
test_dm32_init: R0=R0-1;
IF NE JUMP (PC, test_dm40_init);
dm32_init: I0=R3;
LCNTR=R2, DO dm32_init_loop UNTIL LCE;
CALL read_PROM_word (DB);
NOP;
NOP;
dm32_init_loop: DM(I0,M6)=R3;
JUMP read_boot_info;
test_dm40_init: R0=R0-1;
IF NE JUMP (PC, test_pm16_zero);
dm40_init: I0=R3;
LCNTR=R2, DO dm40_init_loop UNTIL LCE;
CALL read_PROM_word (DB);
NOP;
NOP;
dm40_init_loop: DM(I0,M6)=PX;
JUMP read_boot_info;
test_pm16_zero: R0=R0-1;
IF EQ JUMP (PC, dm16_zero);
R0=R0-1;
IF EQ JUMP (PC, dm32_zero);
test_pm40_zero: R0=R0-1;
IF EQ JUMP (PC, dm40_zero);
R0=R0-1;
IF NE JUMP (PC, test_pm16_init);
pm48_zero: PX1=0;
PX2=0;
R0=R0-R0, I8=R3;
LCNTR=R2, DO pm40_zero_loop UNTIL LCE;
NOP;
pm40_zero_loop: PM(I8,M14)=PX;
JUMP read_boot_info;
test_pm16_init: R0=R0-1;
IF EQ JUMP (PC, dm16_init);
test_pm32_init: R0=R0-1;
IF EQ JUMP (PC, dm32_init);
test_pm40_init: R0=R0-1;
IF EQ JUMP (PC, dm40_init);
test_pm48_init: R0=R0-1;
IF NE JUMP read_boot_info;
pm48_init: I8=R3;
LCNTR=R2, DO pm48_init_loop UNTIL LCE;
CALL read_PROM_word (DB);
NOP;
NOP;
pm48_init_loop: PM(I8,M14)=PX;
JUMP read_boot_info;
read_PROM_word: R13=DM(SYSCON); /* Save old value of SYSCON */
DM(SYSCON)=R11; /* Set BSO bit for ROM read */
DM(II6)=I15; /* Setup DMA destination address*/
DM(C6)=M14; /* Setup DMA internal length */
DM(EC6)=R15; /* Setup DMA external count */
DM(DMAC6)=R14; /* Start DMA */
IDLE; /* Wait for DMA to complete */
PX=PM(0x020004); /* Read word from scratch */
DM(SYSCON)=R13; /* Reset SYSCON to previous */
RTS (DB);
R2=PX1; /* Copy PX values into DREGS */
R2=PASS R2, R3=PX2; /* Test the length */
.ENDSEG;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -