2008-08-14 Jie Zhang <jie.zhang@analog.com>
* bfin/Makefile.in: (top_srcdir): Define. (mkinstalldirs): Define. (BOARD_SCRIPTS): Define. (BOARD_LDFLAGS): Define. (BOARD_BSP): Define. (BOARD_CRT0S): Define. (BOARD_OBJS): Define. (BOARD_TEST): Define. (BOARD_INSTALL): Define. (INCLUDES): Add -I$(srcdir)/include. (all): Add ${BOARD_CRT0S} and ${BOARD_BSP}. (.c.S): Remove target. (crt0.o): New target. (basiccrt.o): Likewise. (basiccrtb.o): Likewise. (basiccrts.o): Likewise. (basiccrt561.o, basiccrt561s.o, basiccrt561b.o): Likewise (clean mostlyclean): Remove ${BOARD_BSP}. (install): Depend on ${BOARD_INSTALL}. (install-sim): Reformat. (install-board): New target. * bfin/basiccrt.S: Remove useless __ADSPBF561_COREB__ in workaround code for 05000229. * bfin/syscalls.c (do_syscall): Use `EXCPT 0' instead of `RAISE 0' for syscall. * bfin/basiccrt.S: New file. * bfin/bf5*ld: New file. * bfin/bfin-common-mc.ld: New file. * bfin/bfin-common-sc.ld: New file. * bfin/include/blackfin.h: New file. * bfin/include/cdefBF5*.h: New file. * bfin/include/cdef_LPBlackfin.h: New file. * bfin/include/cdefblackfin.h: New file. * bfin/include/cplb.h: New file. * bfin/include/cplbtab.h: New file. * bfin/include/defBF5*.h: New files. * bfin/include/def_LPBlackfin.h: New files. * bfin/include/defblackfin.h: New file. * bfin/include/sys/_adi_platform.h: New file. * bfin/include/sys/anomaly_macros_rtl.h: New file. * bfin/include/sys/excause.h: New file. * bfin/include/sys/exception.h: New file. * bfin/include/sys/mc_typedef.h: New file. * bfin/include/sys/platform.h: New file. * bfin/include/sys/pll.h: New file. * bfin/include/sysreg.h: New file. * libnosys/configure.in (MISSING_SYSCALL_NAMES): Don't define for bfin. * libnosys/configure: Regenerate.
This commit is contained in:
586
libgloss/bfin/basiccrt.S
Normal file
586
libgloss/bfin/basiccrt.S
Normal file
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
* Basic startup code for Blackfin processor
|
||||
*
|
||||
* Copyright (C) 2008 Analog Devices, Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice is included verbatim in any distributions. No written agreement,
|
||||
* license, or royalty fee is required for any of the authorized uses.
|
||||
* Modifications to this software may be copyrighted by their authors
|
||||
* and need not follow the licensing terms described here, provided that
|
||||
* the new terms are clearly indicated on the first page of each file where
|
||||
* they apply.
|
||||
*/
|
||||
|
||||
// basic startup code which
|
||||
// - turns the cycle counter on
|
||||
// - loads up FP & SP (both supervisor and user)
|
||||
// - initialises the device drivers (FIOCRT)
|
||||
// - calls monstartup to set up the profiling routines (PROFCRT)
|
||||
// - calls the C++ startup (CPLUSCRT)
|
||||
// - initialises argc/argv (FIOCRT/normal)
|
||||
// - calls _main
|
||||
// - calls _exit (which calls monexit to dump accumulated prof data (PROFCRT))
|
||||
// - defines dummy IO routines (!FIOCRT)
|
||||
|
||||
#include <sys/platform.h>
|
||||
#include <cplb.h>
|
||||
#include <sys/anomaly_macros_rtl.h>
|
||||
|
||||
#define IVBh (EVT0 >> 16)
|
||||
#define IVBl (EVT0 & 0xFFFF)
|
||||
#define UNASSIGNED_VAL 0
|
||||
#define UNASSIGNED_FILL 0
|
||||
// just IVG15
|
||||
#define INTERRUPT_BITS 0x400
|
||||
#if defined(_ADI_THREADS) || \
|
||||
!defined(__ADSPLPBLACKFIN__) || defined(__ADSPBF561__) || defined(__ADSPBF566__)
|
||||
#define SET_CLOCK_SPEED 0
|
||||
#else
|
||||
#define SET_CLOCK_SPEED 1
|
||||
#endif
|
||||
|
||||
#if SET_CLOCK_SPEED == 1
|
||||
#include <sys/pll.h>
|
||||
#define SET_CLK_MSEL 0x16
|
||||
#define SET_CLK_DF 0
|
||||
#define SET_CLK_LOCK_COUNT 0x300
|
||||
#define SET_CLK_CSEL 0
|
||||
#define SET_CLK_SSEL 5
|
||||
|
||||
/*
|
||||
** CLKIN == 27MHz on the EZ-Kits.
|
||||
** D==0 means CLKIN is passed to PLL without dividing.
|
||||
** MSEL==0x16 means VCO==27*0x16 == 594MHz
|
||||
** CSEL==0 means CCLK==VCO == 594MHz
|
||||
** SSEL==5 means SCLK==VCO/5 == 118MHz
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
.section .b.text,"ax",@progbits
|
||||
.align 2;
|
||||
.global __coreb_start;
|
||||
.type __coreb_start, STT_FUNC;
|
||||
__coreb_start:
|
||||
#else
|
||||
.text;
|
||||
.align 2;
|
||||
.global __start;
|
||||
.type __start, STT_FUNC;
|
||||
__start:
|
||||
#endif
|
||||
#if WA_05000109
|
||||
// Avoid Anomaly ID 05000109.
|
||||
# define SYSCFG_VALUE 0x30
|
||||
R1 = SYSCFG_VALUE;
|
||||
SYSCFG = R1;
|
||||
#endif
|
||||
#if WA_05000229
|
||||
// Avoid Anomaly 05-00-0229: DMA5_CONFIG and SPI_CTL not cleared on reset.
|
||||
R1 = 0x400;
|
||||
#if defined(__ADSPBF538__) || defined(__ADSPBF539__)
|
||||
P0.L = SPI0_CTL & 0xFFFF;
|
||||
P0.H = SPI0_CTL >> 16;
|
||||
W[P0] = R1.L;
|
||||
#else
|
||||
P0.L = SPI_CTL & 0xFFFF;
|
||||
P0.H = SPI_CTL >> 16;
|
||||
W[P0] = R1.L;
|
||||
#endif
|
||||
P0.L = DMA5_CONFIG & 0xFFFF;
|
||||
P0.H = DMA5_CONFIG >> 16;
|
||||
R1 = 0;
|
||||
W[P0] = R1.L;
|
||||
#endif
|
||||
// Zap loop counters to zero, to make sure that
|
||||
// hw loops are disabled - it could be really baffling
|
||||
// if the counters and bottom regs are set, and we happen
|
||||
// to run into them.
|
||||
R7 = 0;
|
||||
LC0 = R7;
|
||||
LC1 = R7;
|
||||
|
||||
// Clear the DAG Length regs too, so that it's safe to
|
||||
// use I-regs without them wrapping around.
|
||||
L0 = R7;
|
||||
L1 = R7;
|
||||
L2 = R7;
|
||||
L3 = R7;
|
||||
|
||||
// Zero ITEST_COMMAND and DTEST_COMMAND
|
||||
// (in case they have crud in them and
|
||||
// does a write somewhere when we enable cache)
|
||||
I0.L = (ITEST_COMMAND & 0xFFFF);
|
||||
I0.H = (ITEST_COMMAND >> 16);
|
||||
I1.L = (DTEST_COMMAND & 0xFFFF);
|
||||
I1.H = (DTEST_COMMAND >> 16);
|
||||
R7 = 0;
|
||||
[I0] = R7;
|
||||
[I1] = R7;
|
||||
// It seems writing ITEST_COMMAND from SDRAM with icache enabled
|
||||
// needs SSYNC.
|
||||
#ifdef __BFIN_SDRAM
|
||||
SSYNC;
|
||||
#else
|
||||
CSYNC;
|
||||
#endif
|
||||
|
||||
// Initialise the Event Vector table.
|
||||
P0.H = IVBh;
|
||||
P0.L = IVBl;
|
||||
|
||||
// Install __unknown_exception_occurred in EVT so that
|
||||
// there is defined behaviour.
|
||||
P0 += 2*4; // Skip Emulation and Reset
|
||||
P1 = 13;
|
||||
R1.L = __unknown_exception_occurred;
|
||||
R1.H = __unknown_exception_occurred;
|
||||
LSETUP (L$ivt,L$ivt) LC0 = P1;
|
||||
L$ivt: [P0++] = R1;
|
||||
// Set IVG15's handler to be the start of the mode-change
|
||||
// code. Then, before we return from the Reset back to user
|
||||
// mode, we'll raise IVG15. This will mean we stay in supervisor
|
||||
// mode, and continue from the mode-change point., but at a
|
||||
// much lower priority.
|
||||
P1.H = L$supervisor_mode;
|
||||
P1.L = L$supervisor_mode;
|
||||
[P0] = P1;
|
||||
|
||||
// Initialise the stack.
|
||||
// Note: this points just past the end of the section.
|
||||
// First write should be with [--SP].
|
||||
#ifdef __BFIN_SDRAM
|
||||
SP.L = __end + 0x400000 - 12;
|
||||
SP.H = __end + 0x400000 - 12;
|
||||
#else
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
SP.L=__coreb_stack_end - 12;
|
||||
SP.H=__coreb_stack_end - 12;
|
||||
#else
|
||||
SP.L=__stack_end - 12;
|
||||
SP.H=__stack_end - 12;
|
||||
#endif
|
||||
#endif
|
||||
usp = sp;
|
||||
|
||||
// We're still in supervisor mode at the moment, so the FP
|
||||
// needs to point to the supervisor stack.
|
||||
FP = SP;
|
||||
|
||||
// And make space for incoming "parameters" for functions
|
||||
// we call from here:
|
||||
SP += -12;
|
||||
|
||||
// Zero out bss section
|
||||
#ifdef __BFIN_SDRAM
|
||||
R0.L = ___bss_start;
|
||||
R0.H = ___bss_start;
|
||||
R1.L = __end;
|
||||
R1.H = __end;
|
||||
#else
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
R0.L = __coreb_bss_start;
|
||||
R0.H = __coreb_bss_start;
|
||||
R1.L = __coreb_bss_end;
|
||||
R1.H = __coreb_bss_end;
|
||||
#else
|
||||
R0.L = __bss_start;
|
||||
R0.H = __bss_start;
|
||||
R1.L = __bss_end;
|
||||
R1.H = __bss_end;
|
||||
#endif
|
||||
#endif
|
||||
R2 = R1 - R0;
|
||||
R1 = 0;
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
CALL.X __coreb_memset;
|
||||
#else
|
||||
CALL.X _memset;
|
||||
#endif
|
||||
|
||||
R0 = INTERRUPT_BITS;
|
||||
R0 <<= 5; // Bits 0-4 not settable.
|
||||
// CALL.X __install_default_handlers;
|
||||
R4 = R0; // Save modified list
|
||||
|
||||
R0 = SYSCFG; // Enable the Cycle counter
|
||||
BITSET(R0,1);
|
||||
SYSCFG = R0;
|
||||
|
||||
#if WA_05000137
|
||||
// Avoid anomaly #05000137
|
||||
|
||||
// Set the port preferences of DAG0 and DAG1 to be
|
||||
// different; this gives better performance when
|
||||
// performing dual-dag operations on SDRAM.
|
||||
P0.L = DMEM_CONTROL & 0xFFFF;
|
||||
P0.H = DMEM_CONTROL >> 16;
|
||||
R0 = [P0];
|
||||
BITSET(R0, 12);
|
||||
BITCLR(R0, 13);
|
||||
[P0] = R0;
|
||||
CSYNC;
|
||||
#endif
|
||||
|
||||
// Reinitialise data areas in RAM from ROM, if MemInit's
|
||||
// been used.
|
||||
// CALL.X _mi_initialize;
|
||||
|
||||
#if defined(__ADSPLPBLACKFIN__)
|
||||
#if SET_CLOCK_SPEED == 1
|
||||
|
||||
#if 0
|
||||
// Check if this feature is enabled, i.e. ___clk_ctrl is defined to non-zero
|
||||
P0.L = ___clk_ctrl;
|
||||
P0.H = ___clk_ctrl;
|
||||
R0 = MAX_IN_STARTUP;
|
||||
R1 = [P0];
|
||||
R0 = R0 - R1;
|
||||
CC = R0;
|
||||
IF CC JUMP L$clock_is_set;
|
||||
#endif
|
||||
|
||||
// Investigate whether we are a suitable revision
|
||||
// for boosting the system clocks.
|
||||
// speed.
|
||||
P0.L = DSPID & 0xFFFF;
|
||||
P0.H = DSPID >> 16;
|
||||
R0 = [P0];
|
||||
R0 = R0.L (Z);
|
||||
CC = R0 < 2;
|
||||
IF CC JUMP L$clock_is_set;
|
||||
|
||||
// Set the internal Voltage-Controlled Oscillator (VCO)
|
||||
R0 = SET_CLK_MSEL (Z);
|
||||
R1 = SET_CLK_DF (Z);
|
||||
R2 = SET_CLK_LOCK_COUNT (Z);
|
||||
CALL.X __pll_set_system_vco;
|
||||
|
||||
// Set the Core and System clocks
|
||||
R0 = SET_CLK_CSEL (Z);
|
||||
R1 = SET_CLK_SSEL (Z);
|
||||
CALL.X __pll_set_system_clocks;
|
||||
|
||||
L$clock_is_set:
|
||||
#endif
|
||||
#endif /* ADSPLPBLACKFIN */
|
||||
|
||||
#if defined(__ADSPBF561__) || defined(__ADSPBF566__)
|
||||
// Initialise the multi-core data tables.
|
||||
// A dummy function will be called if we are not linking with
|
||||
// -multicore
|
||||
// CALL.X __mc_data_initialise;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Write the cplb exception handler to the EVT if approprate and
|
||||
// initialise the CPLBs if they're needed. couldn't do
|
||||
// this before we set up the stacks.
|
||||
P2.H = ___cplb_ctrl;
|
||||
P2.L = ___cplb_ctrl;
|
||||
R0 = CPLB_ENABLE_ANY_CPLBS;
|
||||
R6 = [P2];
|
||||
R0 = R0 & R6;
|
||||
CC = R0;
|
||||
IF !CC JUMP L$no_cplbs;
|
||||
#if !defined(_ADI_THREADS)
|
||||
P1.H = __cplb_hdr;
|
||||
P1.L = __cplb_hdr;
|
||||
P0.H = IVBh;
|
||||
P0.L = IVBl;
|
||||
[P0+12] = P1; // write exception handler
|
||||
#endif /* _ADI_THREADS */
|
||||
R0 = R6;
|
||||
CALL.X __cplb_init;
|
||||
#endif
|
||||
L$no_cplbs:
|
||||
// Enable interrupts
|
||||
STI R4; // Using the mask from default handlers
|
||||
RAISE 15;
|
||||
|
||||
// Move the processor into user mode.
|
||||
P0.L=L$still_interrupt_in_ipend;
|
||||
P0.H=L$still_interrupt_in_ipend;
|
||||
RETI=P0;
|
||||
|
||||
L$still_interrupt_in_ipend:
|
||||
rti; // keep doing 'rti' until we've 'finished' servicing all
|
||||
// interrupts of priority higher than IVG15. Normally one
|
||||
// would expect to only have the reset interrupt in IPEND
|
||||
// being serviced, but occasionally when debugging this may
|
||||
// not be the case - if restart is hit when servicing an
|
||||
// interrupt.
|
||||
//
|
||||
// When we clear all bits from IPEND, we'll enter user mode,
|
||||
// then we'll automatically jump to supervisor_mode to start
|
||||
// servicing IVG15 (which we will 'service' for the whole
|
||||
// program, so that the program is in supervisor mode.
|
||||
//
|
||||
// Need to do this to 'finish' servicing the reset interupt.
|
||||
|
||||
L$supervisor_mode:
|
||||
[--SP] = RETI; // re-enables the interrupt system
|
||||
|
||||
R0.L = UNASSIGNED_VAL;
|
||||
R0.H = UNASSIGNED_VAL;
|
||||
#if UNASSIGNED_FILL
|
||||
R2=R0;
|
||||
R3=R0;
|
||||
R4=R0;
|
||||
R5=R0;
|
||||
R6=R0;
|
||||
R7=R0;
|
||||
P0=R0;
|
||||
P1=R0;
|
||||
P2=R0;
|
||||
P3=R0;
|
||||
P4=R0;
|
||||
P5=R0;
|
||||
#endif
|
||||
// Push a RETS and Old FP onto the stack, for sanity.
|
||||
[--SP]=R0;
|
||||
[--SP]=R0;
|
||||
// Make sure the FP is sensible.
|
||||
FP = SP;
|
||||
|
||||
// And leave space for incoming "parameters"
|
||||
SP += -12;
|
||||
|
||||
#ifdef PROFCRT
|
||||
CALL.X monstartup; // initialise profiling routines
|
||||
#endif /* PROFCRT */
|
||||
|
||||
#ifndef __ADSPBF561_COREB__
|
||||
CALL.X __init;
|
||||
|
||||
R0.L = __fini;
|
||||
R0.H = __fini;
|
||||
CALL.X _atexit;
|
||||
#endif
|
||||
|
||||
#if !defined(_ADI_THREADS)
|
||||
#ifdef FIOCRT
|
||||
// FILE IO provides access to real command-line arguments.
|
||||
CALL.X __getargv;
|
||||
r1.l=__Argv;
|
||||
r1.h=__Argv;
|
||||
#else
|
||||
// Default to having no arguments and a null list.
|
||||
R0=0;
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
R1.L=L$argv_coreb;
|
||||
R1.H=L$argv_coreb;
|
||||
#else
|
||||
R1.L=L$argv;
|
||||
R1.H=L$argv;
|
||||
#endif
|
||||
#endif /* FIOCRT */
|
||||
#endif /* _ADI_THREADS */
|
||||
|
||||
// At long last, call the application program.
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
CALL.X _coreb_main;
|
||||
#else
|
||||
CALL.X _main;
|
||||
#endif
|
||||
|
||||
#if !defined(_ADI_THREADS)
|
||||
#ifndef __ADSPBF561_COREB__
|
||||
CALL.X _exit; // passing in main's return value
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
.size __coreb_start, .-__coreb_start
|
||||
#else
|
||||
.size __start, .-__start
|
||||
#endif
|
||||
|
||||
.align 2
|
||||
.type __unknown_exception_occurred, STT_FUNC;
|
||||
__unknown_exception_occurred:
|
||||
// This function is invoked by the default exception
|
||||
// handler, if it does not recognise the kind of
|
||||
// exception that has occurred. In other words, the
|
||||
// default handler only handles some of the system's
|
||||
// exception types, and it does not expect any others
|
||||
// to occur. If your application is going to be using
|
||||
// other kinds of exceptions, you must replace the
|
||||
// default handler with your own, that handles all the
|
||||
// exceptions you will use.
|
||||
//
|
||||
// Since there's nothing we can do, we just loop here
|
||||
// at what we hope is a suitably informative label.
|
||||
IDLE;
|
||||
CSYNC;
|
||||
JUMP __unknown_exception_occurred;
|
||||
RTS;
|
||||
.size __unknown_exception_occurred, .-__unknown_exception_occurred
|
||||
|
||||
#if defined(__ADSPLPBLACKFIN__)
|
||||
#if SET_CLOCK_SPEED == 1
|
||||
|
||||
/*
|
||||
** CLKIN == 27MHz on the EZ-Kits.
|
||||
** D==0 means CLKIN is passed to PLL without dividing.
|
||||
** MSEL==0x16 means VCO==27*0x16 == 594MHz
|
||||
** CSEL==0 means CCLK==VCO == 594MHz
|
||||
** SSEL==5 means SCLK==VCO/5 == 118MHz
|
||||
*/
|
||||
|
||||
// int pll_set_system_clocks(int csel, int ssel)
|
||||
// returns 0 for success, -1 for error.
|
||||
|
||||
.align 2
|
||||
.type __pll_set_system_clocks, STT_FUNC;
|
||||
__pll_set_system_clocks:
|
||||
P0.H = PLL_DIV >> 16;
|
||||
P0.L = PLL_DIV & 0xFFFF;
|
||||
R2 = W[P0] (Z);
|
||||
|
||||
// Plant CSEL and SSEL
|
||||
R0 <<= 16;
|
||||
R0.L = (4 << 8) | 2; // 2 bits, at posn 4
|
||||
R1 <<= 16;
|
||||
R1.L = 4; // 4 bits, at posn 0
|
||||
R2 = DEPOSIT(R2, R0);
|
||||
|
||||
#if defined(__WORKAROUND_DREG_COMP_LATENCY)
|
||||
// Work around anomaly 05-00-0209 which affects the DEPOSIT
|
||||
// instruction (and the EXTRACT, SIGNBITS, and EXPADJ instructions)
|
||||
// if the previous instruction created any of its operands
|
||||
NOP;
|
||||
#endif
|
||||
|
||||
R2 = DEPOSIT(R2, R1);
|
||||
|
||||
W[P0] = R2;
|
||||
SSYNC;
|
||||
RTS;
|
||||
.size __pll_set_system_clocks, .-__pll_set_system_clocks
|
||||
|
||||
// int pll_set_system_vco(int msel, int df, lockcnt)
|
||||
.align 2
|
||||
.type __pll_set_system_vco, STT_FUNC;
|
||||
__pll_set_system_vco:
|
||||
P0.H = PLL_CTL >> 16;
|
||||
P0.L = PLL_CTL & 0xFFFF;
|
||||
R3 = W[P0] (Z);
|
||||
P2 = R3; // Save copy
|
||||
R3 >>= 1; // Drop old DF
|
||||
R1 = ROT R1 BY -1; // Move DF into CC
|
||||
R3 = ROT R3 BY 1; // and into ctl space.
|
||||
R0 <<= 16; // Set up pattern reg
|
||||
R0.L = (9<<8) | 6; // (6 bits at posn 9)
|
||||
R1 = P2; // Get the old version
|
||||
R3 = DEPOSIT(R3, R0);
|
||||
CC = R1 == R3; // and if we haven't changed
|
||||
IF CC JUMP L$done; // Anything, return
|
||||
|
||||
CC = R2 == 0; // Use default lockcount if
|
||||
IF CC JUMP L$wakeup; // user one is zero.
|
||||
P2.H = PLL_LOCKCNT >> 16;
|
||||
P2.L = PLL_LOCKCNT & 0xFFFF;
|
||||
W[P2] = R2; // Set the lock counter
|
||||
L$wakeup:
|
||||
P2.H = SIC_IWR >> 16;
|
||||
P2.L = SIC_IWR & 0xFFFF;
|
||||
R2 = [P2];
|
||||
BITSET(R2, 0); // enable PLL Wakeup
|
||||
[P2] = R2;
|
||||
|
||||
W[P0] = R3; // Update PLL_CTL
|
||||
SSYNC;
|
||||
|
||||
CLI R2; // Avoid unnecessary interrupts
|
||||
IDLE; // Wait until PLL has locked
|
||||
STI R2; // Restore interrupts.
|
||||
|
||||
L$done:
|
||||
RTS;
|
||||
.size __pll_set_system_vco, .-__pll_set_system_vco
|
||||
#endif
|
||||
#endif /* ADSPLPBLACKFIN */
|
||||
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
.section .b.text,"ax",@progbits
|
||||
.type __coreb_memset, STT_FUNC
|
||||
__coreb_memset:
|
||||
P0 = R0 ; /* P0 = address */
|
||||
P2 = R2 ; /* P2 = count */
|
||||
R3 = R0 + R2; /* end */
|
||||
CC = R2 <= 7(IU);
|
||||
IF CC JUMP .Ltoo_small;
|
||||
R1 = R1.B (Z); /* R1 = fill char */
|
||||
R2 = 3;
|
||||
R2 = R0 & R2; /* addr bottom two bits */
|
||||
CC = R2 == 0; /* AZ set if zero. */
|
||||
IF !CC JUMP .Lforce_align ; /* Jump if addr not aligned. */
|
||||
|
||||
.Laligned:
|
||||
P1 = P2 >> 2; /* count = n/4 */
|
||||
R2 = R1 << 8; /* create quad filler */
|
||||
R2.L = R2.L + R1.L(NS);
|
||||
R2.H = R2.L + R1.H(NS);
|
||||
P2 = R3;
|
||||
|
||||
LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
|
||||
.Lquad_loop:
|
||||
[P0++] = R2;
|
||||
|
||||
CC = P0 == P2;
|
||||
IF !CC JUMP .Lbytes_left;
|
||||
RTS;
|
||||
|
||||
.Lbytes_left:
|
||||
R2 = R3; /* end point */
|
||||
R3 = P0; /* current position */
|
||||
R2 = R2 - R3; /* bytes left */
|
||||
P2 = R2;
|
||||
|
||||
.Ltoo_small:
|
||||
CC = P2 == 0; /* Check zero count */
|
||||
IF CC JUMP .Lfinished; /* Unusual */
|
||||
|
||||
.Lbytes:
|
||||
LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2;
|
||||
.Lbyte_loop:
|
||||
B[P0++] = R1;
|
||||
|
||||
.Lfinished:
|
||||
RTS;
|
||||
|
||||
.Lforce_align:
|
||||
CC = BITTST (R0, 0); /* odd byte */
|
||||
R0 = 4;
|
||||
R0 = R0 - R2;
|
||||
P1 = R0;
|
||||
R0 = P0; /* Recover return address */
|
||||
IF !CC JUMP .Lskip1;
|
||||
B[P0++] = R1;
|
||||
.Lskip1:
|
||||
CC = R2 <= 2; /* 2 bytes */
|
||||
P2 -= P1; /* reduce count */
|
||||
IF !CC JUMP .Laligned;
|
||||
B[P0++] = R1;
|
||||
B[P0++] = R1;
|
||||
JUMP .Laligned;
|
||||
.size __coreb_memset,.-__coreb_memset
|
||||
#endif
|
||||
|
||||
#ifdef __ADSPBF561_COREB__
|
||||
.section .b.bss,"aw",@progbits
|
||||
.align 4
|
||||
.type L$argv_coreb, @object
|
||||
.size L$argv_coreb, 4
|
||||
L$argv_coreb:
|
||||
.zero 4
|
||||
#else
|
||||
.local L$argv
|
||||
.comm L$argv,4,4
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user