原文在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,=0x0c700000ldr r0,=WTCON @ disable watch dog
ldr r1,=0x0str r1, [r0]
ldr r0,=INTCON @ non-vector mode, disable irq, disable fiq
ldr r1,=0x7str r1, [r0]
ldr r0,=LOCKTIME
ldrb r1,=800strb r1, [r0]
ldr r0,=PLLCON
ldr r1,=0x34031str r1,[r0]
ldr r0,=CLKCON
ldr r1,=0x7ff8str r1, [r0]
@ UART0ldr r0,=UFCON0
mov r1,#0x0str r1,[r0]
ldr r0,=ULCON0
mov r1,#0x03str r1,[r0]
ldr r0,=UCON0
mov r1,#0x05str r1,[r0]
ldr r0,=UBRDIV0
mov r1,#32str r1,[r0]
ldr r0,=UTXH0 @ print 'C'mov r1,#'C'str r1,[r0]
@ sp_svc
ldr sp,=0x0c700000ldr 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, #0x1swi #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, getswi instruction code
bic r4,r4,#0xff000000 @ get#x
cmp r4,#1 @ 1 --add(a,b)
bne next
bl add @ c function use r0,r1as parameter, and returnresult 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,intb){return a +b;
}int sub(int a,intb){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 forS3C44B0X
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# uart0uart: mod=stdio