原文在CU,挪過來了。
1. 目標
本文單純驗證swi指令相關功能
2. 環境
vmware + redhat 9 + arm-elf-gcc 2.95 + skyeye-1.2.6_rc1(模擬s3c44b0x)
3. 功能詳述
1). 調用swi前,關IRQ,FIQ,INTMSK,改變CPU模式為用戶模式0x10000
2). 指令的功能號由swi指令碼的低24位傳輸,通過
ldr r4,[lr,#-4]
bic r4,r4,#0xff000000
得到它的功能號,這樣就可以根據功能號來進行相關功能的調用,
本例只使用了兩個功能號:
swi #1 1 表示兩個數的加法
swi #2 2 表示兩個數的減法
加法和減法的函數在.c文件中定義
3). 在swi的處理程序中,對於c函數int add(int a,int b)的參數傳遞是通過
r0,r1進行的, add(),sub()的結果通過r0返回給swi的處理程序
4). swi的處理流程: swi #x --> 0x00000008 --> HandlerSWI --> C函數, 僅此而已
4. 運行:
# skyeye
調試
# skyeye -d
不用再加文件名,文件寫在skyeye.conf里了, 當然還得用arm-elf-gdb.
5. 文件清單(5個文件)
swi.s
.equ INTCON, 0x01e00000 .equ INTMSK, 0x01e0000c .equ LOCKTIME, 0x01d8000c .equ PLLCON, 0x01d80000 .equ CLKCON, 0x01d80004 .equ WTCON, 0x01d30000 .equ I_ISPR, 0x01e00020 .equ I_ISPC, 0x01e00024 .equ TCFG0, 0x01d50000 .equ TCFG1, 0x01d50004 .equ TCON, 0x01d50008 .equ TCNTB5, 0X01d50048 .equ UTXH0, 0x01d00020 .equ UFCON0, 0x01d00008 .equ ULCON0, 0x01d00000 .equ UCON0, 0x01d00004 .equ UBRDIV0, 0x01d00028 .globl _start _start: b reset b . b HandlerSWI b . b . b . b . b . reset: mov r0,#0x80 | 0x40 | 0x13 @ svc, disable irq,fiq msr cpsr_c,r0 ldr sp, =0x0c700000 ldr r0,=WTCON @ disable watch dog ldr r1, =0x0 str r1, [r0] ldr r0, =INTCON @ non-vector mode, disable irq, disable fiq ldr r1, =0x7 str r1, [r0] ldr r0, =LOCKTIME ldrb r1, =800 strb r1, [r0] ldr r0, =PLLCON ldr r1, =0x34031 str r1,[r0] ldr r0, =CLKCON ldr r1, =0x7ff8 str r1, [r0] @ UART 0 ldr r0,=UFCON0 mov r1,#0x0 str r1,[r0] ldr r0,=ULCON0 mov r1,#0x03 str r1,[r0] ldr r0,=UCON0 mov r1,#0x05 str r1,[r0] ldr r0,=UBRDIV0 mov r1,#32 str r1,[r0] ldr r0,=UTXH0 @ print 'C' mov r1,#'C' str r1,[r0] @ sp_svc ldr sp,=0x0c700000 ldr r0, =INTMSK ldr r1, =0x03ffffff @ disable all irq. str r1, [r0] @ move to user mode mov r0, #0x80 | 0x40 | 0x10 @ svc, disable irq,fiq msr cpsr_c,r0 mov r0, #'A' mov r1, #0x1 swi #1 @ add('A',1), print 'B' ldr r1,=UTXH0 @ print 'A' str r0,[r1] mov r0, #'H' @ subtract mov r1, #0x1 @ swi #2 @ sub('H',1), print 'G' ldr r1,=UTXH0 @ print 'H' str r0,[r1] ldr r1,=UTXH0 @ print 'S' -- STOP mov r0,#'S' str r0,[r1] stop: b stop @ while(1); HandlerSWI: stmfd sp!,{r0-r12,lr} ldr r4,[lr,#-4] @ lr is "swi #x" address, get swi instruction code bic r4,r4,#0xff000000 @ get #x cmp r4,#1 @ 1 -- add(a,b) bne next bl add @ c function use r0,r1 as parameter, and return result with r0 ldr r1,=UTXH0 @ print 'B' str r0,[r1] next: cmp r4,#2 @ 2 -- sub(a,b) bne swi_return bl sub ldr r1,=UTXH0 @ print 'G' str r0,[r1] swi_return: ldmfd sp!, {r0-r12,pc}^
c_fun.c
int add(int a,int b){ return a + b; } int sub(int a,int b){ return a - b; }
swi.lds
OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { . = 0x00000000; .text : { swi.o (.text) } . = ALIGN(4); .data : { *(.data) } }
Makefile
all: swi swi: swi.o c_fun.o arm-elf-ld -T swi.lds -o swi swi.o c_fun.o arm-elf-objcopy -O binary -S swi swi.bin swi.o: swi.s arm-elf-as --gstabs -o swi.o swi.s c_fun.o: c_fun.c arm-elf-gcc -gstabs -c c_fun.c .PHONY: clean clean: rm -f swi.o c_fun.o swi swi.bin
skyeye.conf
#skyeye config file for S3C44B0X cpu: arm7tdmi mach: s3c44b0x # physical memory mem_bank: map=M, type=RW, addr=0x00000000, size=0x00200000, file=swi.bin mem_bank: map=M, type=RW, addr=0x0c000000, size=0x00800000 # peripherals I/O mapping area mem_bank: map=I, type=RW, addr=0x01c00000, size=0x00400000 # uart 0 uart: mod=stdio