原文在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