原文在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, =
strb r1, [r0] ldr r0, =PLLCON
ldr r1, =0x34031
str r1,[r0] ldr r0, =CLKCON
ldr r1, =0x7ff8
str r1, [r0] @ UART
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,#
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 # @ add('A',), print 'B' ldr r1,=UTXH0 @ print 'A'
str r0,[r1] mov r0, #'H' @ subtract
mov r1, #0x1 @
swi # @ sub('H',), 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(); HandlerSWI:
stmfd sp!,{r0-r12,lr} ldr r4,[lr,#-] @ lr is "swi #x" address, get swi instruction code
bic r4,r4,#0xff000000 @ get #x cmp r4,# @ -- 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,# @ -- 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();
.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
uart: mod=stdio