Hi, I have read some sources that contains in the same file, asm, C and linker instruction. But when I compile a source file containing pre-processor instruction like #define and linker instruction like entry(_start) with arm-elf-as I've an error. Is it really possible to mix asm, C and linker instruction and how? thanks in advance for your help, Best regards,
I've never seen such a source file. pre-processor instructions mixed with assembler code, yes - this are the *.S files, but mixed with linker instructions... no. Can you give an example? Stefan
Stefan wrote: > I've never seen such a source file. pre-processor instructions mixed > with assembler code, yes - this are the *.S files, but mixed with linker > instructions... no. Can you give an example? > > Stefan Here it is : there are linker instruction in this source file whereas usually I've seen them in a linker script. thanks for your help. /* * linux/arch/arm/kernel/head-armv.S * * Copyright (C) 1994-1999 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 32-bit kernel startup code for all architectures * * added S3C4510 code by Mac Wang * added S3C4530 code by Arcturus Networks Inc. * added S3C2500 code by Arcturus Networks Inc. * added TI TMS320DM270 code by Chee Tim Loh <cheetim_loh@innomedia.com.sg>. * */ #include <linux/config.h> #include <linux/linkage.h> #include <asm/assembler.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #define K(a,b,c) ((a) << 24 | (b) << 12 | (c)) /* * We place the page tables 16K below TEXTADDR. Therefore, we must make sure * that TEXTADDR is correctly set. Currently, we expect the least significant * "short" to be 0x8000, but we could probably relax this restriction to * TEXTADDR > PAGE_OFFSET + 0x4000 * * Note that swapper_pg_dir is the virtual address of the page tables, and * pgtbl gives us a position-independent reference to these tables. We can * do this because stext == TEXTADDR * * swapper_pg_dir, pgtbl and krnladr are all closely related. */ /* * Kernel startup entry point. * * The rules are: * r0 - should be 0 * r1 - unique architecture number * MMU - off * I-cache - on or off * D-cache - off * * See linux/arch/arm/tools/mach-types for the complete list of numbers * for r1. */ .section ".text.init",#alloc,#execinstr .type stext, #function ENTRY(stext) mov r12, r0 /* * NOTE! Any code which is placed here should be done for one of * the following reasons: * * 1. Compatability with old production boot firmware (ie, users * actually have and are booting the kernel with the old firmware) * and therefore will be eventually removed. * 2. Cover the case when there is no boot firmware. This is not * ideal, but in this case, it should ONLY set r0 and r1 to the * appropriate value. */ #if defined(CONFIG_ARCH_L7200) /* * FIXME - No bootloader, so manually set 'r1' with our architecture number. */ mov r1, #MACH_TYPE_L7200 #elif defined(CONFIG_ARCH_INTEGRATOR) mov r1, #MACH_TYPE_INTEGRATOR #elif defined(CONFIG_ARCH_P52) mov r1, #MACH_TYPE_P52 #elif defined(CONFIG_ARCH_CX821XX) mov r1, #MACH_TYPE_CX821XX #elif defined(CONFIG_ARCH_SWARM) mov r1, #MACH_TYPE_SWARM #elif defined(CONFIG_BOARD_SNDS100) mov r1, #MACH_TYPE_SNDS100 #elif defined (CONFIG_BOARD_SMDK40100) mov r1, #MACH_TYPE_S3C3410 #elif defined (CONFIG_BOARD_MBA44) mov r1, #MACH_TYPE_S3C44B0X #elif defined(CONFIG_BOARD_SMDK2500) mov r1, #MACH_TYPE_SMDK2500 #elif defined(CONFIG_BOARD_S3C2500REFRGP) mov r1, #MACH_TYPE_S3C2500REFRGP #elif defined(CONFIG_ARCH_LPC) mov r1, #MACH_TYPE_LPC22XX & 0xff orr r1, r1, #MACH_TYPE_LPC22XX & 0xff00 #endif mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode msr cpsr_c, r0 @ and all irqs disabled #if defined(CONFIG_ARCH_ATMEL) adr r5, LC0 ldmia r5, {r5, r6, r8, r9, sp} @ Setup stack /* Copy data sections to their new home. */ /* Clear BSS */ mov r4, #0 1: cmp r5, r8 strcc r4, [r5],#4 bcc 1b /* FIXME */ #if 0 /* Put initial values into stack. This would normally be done by sched_init() in kernel/sched.c, but that would overwrite the stack we're already using. That would be bad. */ mov r5, sp sub r5, r5, #0x2000 ldr r4, L_STACK_MAGIC str r4, [r5], #4 ldr r4, L_STACK_UNTOUCHED_MAGIC 1: cmp r5, sp strcc r4, [r5], #4 bcc 1b #endif /* Pretend we know what our processor code is (for arm_id) */ @@@ ldr r2, =0x41000000 @@@ orr r2, r2, #0x7000 @ FIXME --> 0x41007000 ldr r2, L_AT91_SF_CIDR ldr r2, [r2] @ read processor id str r2, [r6] mov r2, #MACH_TYPE_ATMEL str r2, [r9] mov fp, #0 b start_kernel LC0: .long __bss_start .long processor_id .long _end .long __machine_arch_type .long init_task_union+8192 #endif adr lr, __ret @ return address add pc, r10, #12 @ initialise processor @ (return control reg) __switch_data: .long __mmap_switched .long SYMBOL_NAME(compat) .long SYMBOL_NAME(__bss_start) .long SYMBOL_NAME(_end) .long SYMBOL_NAME(processor_id) .long SYMBOL_NAME(__machine_arch_type) .long SYMBOL_NAME(cr_alignment) .long SYMBOL_NAME(init_task_union)+8192 __ret: ldr lr, __switch_data mov pc, lr /* * This code follows on after the page * table switch and jump above. * * r0 = processor control register * r1 = machine ID * r9 = processor ID */ .align 5 __mmap_switched: adr r3, __switch_data + 4 ldmia r3, {r2, r4, r5, r6, r7, r8, sp}@ r2 = compat @ sp = stack pointer str r12, [r2] #ifdef CONFIG_RAM_ATTACHED_ROMFS # ifdef CONFIG_ARCH_DM270 /* * Move ROM filesystem above bss :-) */ ldr r3, L_DM270_ROMFS @ Get end of data ldr r10, [r3, #8] @ Get size of ROMFS (big-endian) #ifndef CONFIG_CPU_BIG_ENDIAN mov r2, #0 @ Convert to little-endian and fp, r10, #0x000000ff orr r2, r2, fp, lsl #24 and fp, r10, #0x0000ff00 orr r2, r2, fp, lsl #8 and fp, r10, #0x00ff0000 orr r2, r2, fp, lsr #8 and fp, r10, #0xff000000 orr r2, r2, fp, lsr #24 mov r10, r2 #endif add r10, r10, #8 @ Allow for rounding bic r10, r10, #3 @ Whole words ldr fp, L_DM270_ROMFS + 4 @ Set up destination mov r2, r3 @ Copy of _edata add r3, r3, r10 @ Copy from end add fp, fp, r10 ldr r10, L_DM270_RAMSTART str fp, [r10] _copy_romfs: ldr r10, [r3, #-4]! @ Copy dword str r10, [fp, #-4]! cmp r3, r2 @ Check if at end bne _copy_romfs # endif #endif mov fp, #0 @ Clear BSS (and zero fp) 1: cmp r4, r5 strcc fp, [r4],#4 bcc 1b str r9, [r6] @ Save processor ID str r1, [r7] @ Save machine type #ifdef CONFIG_ALIGNMENT_TRAP orr r0, r0, #2 @ ...........A. #endif bic r2, r0, #2 @ Clear 'A' bit stmia r8, {r0, r2} @ Save control register values b SYMBOL_NAME(start_kernel) /* * Exception handling. Something went wrong and we can't * proceed. We ought to tell the user, but since we * don't have any guarantee that we're even running on * the right architecture, we do virtually nothing. * r0 = ascii error character: * a = invalid architecture * p = invalid processor * i = invalid calling convention * * Generally, only serious errors cause this. */ __error: #ifdef CONFIG_DEBUG_LL mov r8, r0 @ preserve r0 adr r0, err_str bl printascii mov r0, r8 bl printch #endif #ifdef CONFIG_ARCH_RPC /* * Turn the screen red on a error - RiscPC only. */ mov r0, #0x02000000 mov r3, #0x11 orr r3, r3, r3, lsl #8 orr r3, r3, r3, lsl #16 str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 #endif 1: mov r0, r0 b 1b #ifdef CONFIG_DEBUG_LL err_str: .asciz "\nError: " .align #endif /* * Read processor ID register (CP#15, CR0), and look up in the linker-built * supported processor list. Note that we can't use the absolute addresses * for the __proc_info lists since we aren't running with the MMU on * (and therefore, we are not in the correct address space). We have to * calculate the offset. * * Returns: * r5, r6, r7 corrupted * r8 = page table flags * r9 = processor ID * r10 = pointer to processor structure */ __lookup_processor_type: adr r5, 2f ldmia r5, {r7, r9, r10} sub r5, r5, r10 @ convert addresses add r7, r7, r5 @ to our address space add r10, r9, r5 #ifdef CONFIG_CPU_WITH_MCR_INSTRUCTION mrc p15, 0, r9, c0, c0 @ get processor id #else # warning "FIXME: Get Processor ID without MCR Instruction" @ A possible code @ldr r9, PROCESSOR_ID_MEM_LOCATION @ldr r9, [r9] #ifdef CONFIG_ARCH_DM270 ldr r9, L_DM270_PID #endif #endif 1: ldmia r10, {r5, r6, r8} @ value, mask, mmuflags and r6, r6, r9 @ mask wanted bits teq r5, r6 moveq pc, lr add r10, r10, #36 @ sizeof(proc_info_list) cmp r10, r7 blt 1b mov r10, #0 @ unknown processor mov pc, lr /* * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for * more information about the __proc_info and __arch_info structures. */ 2: .long __proc_info_end .long __proc_info_begin .long 2b .long __arch_info_begin .long __arch_info_end /* * Lookup machine architecture in the linker-build list of architectures. * Note that we can't use the absolute addresses for the __arch_info * lists since we aren't running with the MMU on (and therefore, we are * not in the correct address space). We have to calculate the offset. * * r1 = machine architecture number * Returns: * r2, r3, r4 corrupted * r5 = physical start address of RAM * r6 = physical address of IO * r7 = byte offset into page tables for IO */ __lookup_architecture_type: adr r4, 2b ldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3 sub r5, r4, r5 @ convert addresses add r4, r6, r5 @ to our address space add r7, r7, r5 1: ldr r5, [r4] @ get machine type teq r5, r1 beq 2f add r4, r4, #SIZEOF_MACHINE_DESC cmp r4, r7 blt 1b mov r7, #0 @ unknown architecture mov pc, lr 2: ldmib r4, {r5, r6, r7} @ found, get results mov r7, r7, lsr #18 @ pagetable byte offset mov pc, lr L_AT91_SF_CIDR: .long 0xfff00000 #ifdef CONFIG_ARCH_DM270 L_DM270_PID: .long 0xd2700000 # ifdef CONFIG_RAM_ATTACHED_ROMFS .global _ramstart _ramstart: .long 0 L_DM270_ROMFS: .long _edata .long _ebss L_DM270_RAMSTART: .long _ramstart # endif #endif
It looks like a "usual" asm with preprocessor-code. Maybe the instructions which "look like" linker-options are preprocessor-macros defined in the inlcuded files. Martin Thomas
Same opinion like Martin. I think ENTRY is a macro e.g. in linkage.h. Maybe something like this #define ENTRY(X) \ .global X##; \ X##: which gives for ENTRY(stext): .global stext; stext: (from http://www.ussg.iu.edu/hypermail/linux/kernel/0302.1/0128.html)
You are right. in the fiel linkage.h, there is the following lines : #define ENTRY(name) \ .globl SYMBOL_NAME(name); \ ALIGN; \ SYMBOL_NAME_LABEL(name) and #define SYMBOL_NAME_LABEL(X) X##: #define ALIGN __ALIGN and #if defined(_i386_) && defined(CONFIG_X86_ALIGNMENT_16) #define __ALIGN .align 16,0x90 #define __ALIGN_STR ".align 16,0x90" #else #define __ALIGN .align 4,0x90 #define __ALIGN_STR ".align 4,0x90" #endif so all is clear, it's asm with pre-processor code. The aim of such a pre-processor code seems to use ENTRY(stext) in the linker script. isn't it ? because if I understand the precedent lines, .globl SYMBOL_NAME(name); \ ALIGN; \ SYMBOL_NAME_LABEL(name) doesn't define an entry point, there still need an ENTRY command in the linker script.
armand iostrym wrote: > The aim of such a pre-processor code seems to use ENTRY(stext) in the > linker script. isn't it ? Not at all. The linker script is not generated from these lines. The linker script doesn't get output from the pre-processor. You (or someone else) write the linker script with the definition of the one and only entry point. Therefor you have to prepare your sources so that this entry point is available. In order to do this you define a symbol stext, start, _start or my_ugly_entry_point in your sourcecode. Some people even use several names to be sure ;-) > because if I understand the precedent lines, > > .globl SYMBOL_NAME(name); \ > ALIGN; \ > SYMBOL_NAME_LABEL(name) > > doesn't define an entry point, Yes. These lines define a label 'name:' for the assembler and make this label a global symbol '.globl name' so the linker knows this symbol when other object files want to use this symbol. > there still need an ENTRY command in the > linker script. You can define several global symbols with ENTRY(name...) in the assembler source files. But you need only one ENTRY in the linker script (or use one of the default methods http://linux.web.cern.ch/linux/slc4/docs/rhel-ld-en-4/simple-commands.html) - what you put with ENTRY() in the linker script will be the address of the first instruction of your application.
Thanks, it confirms waht I thought. Things are getting clearer now. It's really nice to all of you to help me like that.
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.