?? ts101_prom.asm
字號(hào):
/***********************************************************************************************
TigerSHARC eprom boot loader
TS101_prom.asm
This code is written unoptimized one instruction per line for clarity.
Revision history:
11/12/01 Boris Lerner Version 1.0.0
3/25/2002 Boris Lerner Version 1.0.1 Added (NP) to all jumps
Algorithm description:
1. This boot loader resides in the eprom/flash memory 0x0000 - 0x03ff. It gets loaded
by DMA0 of the TigerSharc initially into memory 0x00000000 - 0x000000ff. After the
boot loader is loaded, the DMA0 interrupt wakes the TigerSharc up and starts the
execution of the loader at location 0x00000000. At this stage, the TigerSharc is at
interrupt level of DMA0 and, thus, further DMA0 and global (PMASK[60]) interrupts
are disabled.
2. The loader sets the NMOD bit in SQCTL register to insure supervisor mode. Then,
RDS reduces interrupt to subroutine level. Now, DMA0 and global interrupts are
enabled again.
3. DMA0 interrupt vector is set to dma_int. DMA0 is setup to move data from boot
prom starting at 0x0400 (0x0000-0x03ff was the boot loader) to internal memory
starting at 0x00000000. The DMA routine will start the DMA by programming the TCBs,
advance the prom pointer and sit in IDLE until the DMA interrupt wakes it up and
sends to dma_int. There RTI returns to DMA routine, which, in turn, returns to
loader execution.
4. Since this is not a link port boot, all link port controls are reset and link port
DMAs are disabled.
5. Processor ID is computed and stored in xR10.
6. Now, the loader parses the blocks of data from the prom. Two words are moved to
locations 0x00000000 and 0x00000001. These are the tag words of the block to follow.
In the first word, bits 31:30 are block TYPE (0=final init, 1=non-zero init, 2=zero init),
bits 29:27 are the processor ID, bits 26:16 are reserved and bits 15:0 are the block
COUNT. The second tag word is pointer to DESTINATION.
7. ID of the block is compared to the ID stored in xR10. If IDs are not the same, the
prom block is skept.
8. If IDs are the same, the type is examined.
9. If type is 1, the COUNT number of words are moved one word at a time via location
0x00000000 to the DESTINATION. Once finished, the steps starting with 5 are repeated.
10. If type is 2, the COUNT number of zeros are moved to the DESTINATION. Once finished,
the steps starting with 5 are repeated.
11.If type is 0, the loader performs the final init, i.e. it overwrites itself with
the user code. A DMA of 256 words into 0x00000000-0x000000ff with wake up from IDLE
would do this, but would start user code execution at interrupt level of DMA0. To
avoid this, the following algorithm is used:
a. First four instrucions of user code (destined to locations 0x00000000-0x00000003)
are DMAed from the prom and stored in the registers xR11:8.
b. The following code is written into locations 0x00000000-0x00000003:
RETI = 0;;
NOP;;
RTI (NP); Q[j31+=0] = xR11:8;;
c. The DMA0 interrupt vector is set to 0x00000000.
d. yR0 is preset to 0x80000000. This will be the new value for IMASKH to disable
all interrupts except emulation.
e. Branch Target Buffer is invalidated (BTBINV) to clear cached branches.
f. The DMA is setup to transfer 252 words of user code destined to
0x00000004-0x000000ff.
g. DMA is started by writing to the TCBs and then processor goes IDLE.
h. When the DMA is finished, interrupt wakes the TigerSharc up and jumps
execution to code inserted at 0x00000000 in step b.
i. This code executes IMASKH = yR0;; which disables all global interrupts, then
RTI (NP); Q[j31+=0]=xR11:8;;, which reduces the interrupt level to none, puts user
code into locations 0x00000000-0x00000003 and jumps execution to 0x00000000 (since
RETI is set to 0x00000000). The user code starts cleanly at 0x00000000, with no
interrupt level. Note that (NP) option is necessary so that RTI does not cache into
BTB.
***********************************************************************************************/
/**********************************************************************************************/
.section seg_ldr;
/************************************** Start of code *****************************************/
_main:
xr0 = 0x00000201;; // set NMOD and BTB enable (1/24/00) bits in sequencer control register
SQCTLST = xr0;; // mnemonic changed to SQCTLST (12/19/00)
rds;; // reduce interrupt to subroutine level
// INSERT CUSTOM INITS HERE - DRAM REGISTERS ETC...
jL0 = 0;;
jL1 = 0;;
j0 = _dma_int;; // set DMA interrupt vector
IVDMA0 = j0;; // global and DMA0 ints are already enabled
yr0 = 0;; // will be used for zero init and ints disable in patch
LCTL0 = yr0;; // Links disable and clear
LCTL1 = yr0;;
LCTL2 = yr0;;
LCTL3 = yr0;;
xr1 = 0x00040004;; // count = 4, modify = 4
xr3 = 0x00000000;; // disable DMA, int mem,prio=norm,2D=no,word=quad,int=yes,RQ=enbl,chain=no
DC4 = xr3:0;; // disable DMA
DC5 = xr3:0;; // disable DMA
DC6 = xr3:0;; // disable DMA
DC7 = xr3:0;; // disable DMA
DC8 = xr3:0;; // disable DMA
DC9 = xr3:0;; // disable DMA
DC10 = xr3:0;; // disable DMA
DC11 = xr3:0;; // disable DMA
xr0 = 0x400;; // xr0 = source index
xr3 = 0xc3000000;; // boot rom,prio=norm,2D=no,word=norm,int=yes,RQ=dsbl,chain=no
xr4 = 0;; // xr4 = destination index
xr7 = 0x43000000;; // int mem,prio=norm,2D=no,word=norm,int=yes,RQ=dsbl,chain=no
xr8 = 1;;
xr10 = SYSTAT;;
xr1 = 0x00000007;;
xr10 = r1 and r10;; // xr10 = processor ID
/**********************************************************************************************/
_boot_loop:
xr1 = 0x00020004;; // source count = 2, modify = 4
xr5 = 0x00020001;; // dest count = 2, modify = 1
xr9 = 8;; // prom pointer modifier
call _do_dma (NP);; // do DMA transfer
xr2 = [j31+=0];; // read ID, type and count
j0 = [j31+1];; // read destination
xr1 = 0x0000FFFF;;
xr9 = r1 and r2;; // mask count
xr6 = 0x00001B03;;
xr6 = fext r2 by r6;; // extract processor ID
xcomp(r6,r10);; // if not same...
if nxaeq, jump _wrong_id (NP);; // ...skip the block...
xr6 = 0x00001E02;;
xr6 = fext r2 by r6;; // ...else, extract type
if xseq, jump _final_init (NP);; // if zero - final init...(xseq - 1/24/00)
xr6 = r6 - r8;; // ...else if 1...
if xaeq, jump _init_data (NP);; // ...non-zero data init...
/***********************************************************************************************/
_zero_init: // ...else zero-data init
LC0 = xr9;; // put count into counter
_zero_init_loop:
[j0+=1] = yr0;; // init with 0's
if NLC0E, jump _zero_init_loop (NP);;
jump _boot_loop (NP);; // check next block
/***********************************************************************************************/
_init_data:
LC0 = xr9;; // put count into loop counter
xr1 = 0x00010004;; // source count = 1, modify = 4
xr5 = 0x00010001;; // dest count = 1, modify = 1
xr9 = 4;; // prom pointer modifier
_init_data_1:
call _do_dma (NP);; // do DMA transfer
xr6 = [j31 += 0];; // read word
[j0 += 1] = xr6;; // write word
if NLC0E, jump _init_data_1 (NP);;
jump _boot_loop (NP);; // check next block
/***********************************************************************************************/
_wrong_id:
xr6 = 0x000001E02;;
xr6 = fext r2 by r6;; // extract type
if xseq, jump _skip_255 (NP);; // if zero - final init, skip 255... seq replaced by xseq (3/29/00)
xr9 = lshift r9 by 2;; // ...else, quadrupple the count...
xr6 = r6 - r8;; // ...if 1...
if xaeq, jump _skip_block (NP);; // ...skip block as is...
xr9 = 0;; // ...else zero init, skip none
jump _skip_block (NP);;
_skip_255:
xr9 = 0x3FC;; // prom pointer modifier = 255*4
_skip_block:
xr0 = r0 + r9;; // advance prom pointer
jump _boot_loop (NP);; // check next block
/**************************************************************************************************
This routine transfers data via DMA0
Input: xr3:0 = source TCB setup, xr7:4 = destination TCB setup, xr9 = prom pointer modifier
***************************************************************************************************/
_do_dma:
DCS0 = xr3:0;; // start DMA
DCD0 = xr7:4;;
idle;; // wait till DMA interrupt
xr0 = r0 + r9;; // advance prom pointer
cjmp (NP)(ABS);; // and return
/*************************************************************************************************
DMA0 ISR
*************************************************************************************************/
_dma_int:
nop;; // Note: RTI can not be the first instruction of an ISR!
rti (ABS)(NP);;
/*************************************************************************************************
Final Init
*************************************************************************************************/
_final_init:
xr9 = 4;; // since final init has only one tag,...
xr0 = r0 - r9;; // ...backup one word (4 bytes)
xr1 = 0x00040004;; // source count = 4, modify = 4
xr5 = 0x00040001;; // dest count = 4, modify = 1
xr9 = 16;;
call _do_dma (NP);; // do DMA transfer
xr11:8 = Q[j31 += 0];; // put first four user instrucions into xr11:8
j0 = _last_patch_code;; // move patch into locations 0x00000000-0x00000003
j1 = 0;;
LC0 = 4;;
_patch_loop:
xr6 = [j0 += 1];;
[j1 += 1] = xr6;;
if NLC0E, jump _patch_loop (NP);;
j1 = 0;; // set DMA0 int vector to 0x00000000
IVDMA0 = j1;;
yr0 = 0x80000000;; // IMASKH value - disable all ints except emulation
xr1 = 0x00FC0004;; // count = 0xFC, modifier = 4
xr4 = 4;; // start at location 0x4, patch is at loc 0x0-0x3
xr5 = 0x00FC0001;; // count = 0xFC, modifier = 1
btbinv;; // invalidate cache
DCS0 = xr3:0;; // start DMA
DCD0 = xr7:4;;
idle;; // wait till dma is done...
// ...by which time DMA0 interrupt takes over,...
// ...and jumps execution to 0x0 to the last patch
/*********************************** Last Patch *************************************************/
_last_patch_code:
RETI = 0;; // set RETI to 0x0 for patch
IMASKH = yr0;; // disable interrupts
rti (ABS)(NP); Q[j31+=0] = xr11:8;; // reduce interrupt and patch
nop;;
nop;;
nop;;
nop;;
nop;;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -