首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

C28x寻址方式详解[转帖]

C28x寻址方式详解[转帖]


有四种基本寻址方式:


直接寻址 - 16位的寄存器DP用作,固定页指针(段指针),DP中存放当前变量所在页的首地址,指令中的6位或7位二进制数给出变量的偏移量(段偏移量)。用于访问固定地址的数据结构,如片上外设或C/C++中的全局变量和静态变量。


栈寻址-通过使用栈指针SP访问变量,在C28x中栈是从低地址向高地址增长的,SP始终指向下一个可用的空栈单元。SP值减去指令中6位二进制数给出的偏移量为变量地址,或者该偏移量给出分别在压栈(或出栈)操作时SP需要后加(或先减)的量。


间接寻址 - 32位的辅助寄存器XAR0~XAR7用作通用32位数据指针。指令可以进行直接的后加、先减/后减,或者通过三位二进制立即数给出对哪个寄存器操作,也可以用另外一个16位辅助寄存器内容给出当前用的寄存器。


寄存器寻址 - 直接对寄存器内容操作,寄存器可以是操作的源或目的地。这就使得C28x架构可以直接进行寄存器对寄存器的操作。


其它的寻址方式
数据/程序/IO空间立即寻址 - 存储器地址操作数直接嵌入在指令中。
程序空间间接寻址 - 某些指令可以使用某个间接指针来访问程序空间。因为C28x CPU中存储器之一致的,因此这种寻址模式可以完成在同一条指令中同时读两个操作数的操作。


说明:寻址模式由指令中的八位编码给出,状态寄存器ST1中的寻址模式选择位AMODE给出了编译器所使用的编码方式。
AMODE=0 - 复位时默认的寻址模式,也是C28x的C/C++编译器使用的默认模式。但某些寻址方式C2xLP器件不兼容,此时段偏移量由六位二进制数给出(C2xLP器件是七位的),因此仅支持部分C2xLP器件的间接寻址方式。
AMODE=1 - 包含了C2xLP器件全兼容的寻址模式。此时段偏移量为七位二进制数给出,支持C2xLP器件所有的寻址方式。


注意:(1)C28x器件和C2xLP器件间接寻址指令的不同在于,C28x的指令中辅助寄存器指针是隐含的,也就是指令中标明了对哪个寄存器操作。而在Cx2LP的指令中,对哪个寄存器操作是由3位的辅助寄存器指针ARP(在ST1中)给出的,并且可以同时给出下一条指令要使用辅助寄存器指针(第三个操作数);(2)在C28x的指令中,目的操作数总是在源操作数的左边。请看下例:
   
    假如要完成这样的操作,把XAR4所指的数据读出加到AL中,随后把XAR4的内容加一,C28x的指令为:ADD AL,*XAR4++;C2xLP的指令可以为:ADD AL,*++(此时ARP=4)。而C2xLP的指令ADD AL,*++,ARP5则在完成上述操作的同时,把ARP的内容更新为5,即令ARP指向ARP5。


具体的区别请参见TI的文档spru430d中第五章的表5-1。


操作符*和@的作用:*表示取后面的变量值或寄存器的内容作为地址,取该地址所指向的存储空间的内容作为操作数。@表示直接取后面的变量值或寄存器的内容作为操作数。


如何改变编译器的处理模式:
编译器总是默认为AMODE=0,通过两种方式改变编译器的处理方式,一种是命令行参数法,当使用-v28时使编译器默认为AMODE=0模式,当使用-v28 -m20时默认为AMODE=1模式。另一种是源文件中指定法,如下面的文件(假设编译器命令行参数为-v28)
              ; 文件开始
                ...
                ...
                ...
                SETC AMODE    ; AMODE位置一
                .lp_amode     ; 通知编译器检查C27x/C28x的语法,该段代码只能用AMODE=1的寻址方式
                ...
                ...
                ...
                CLRC AMODE    ; AMODE位清零
                .c28_amode    ; 通知编译器检查C28x的语法,该段代码只用AMODE=0的寻址方式
                ...
                ...
                ...
              ; 文件结束

指令实例:
直接寻址(只能寻址C28x的低4M数据地址空间):
(1)@6位二进制立即数方式,适用于AMODE=0,地址高10位为0,地址次高16位为DP的低16位,地址低6位为6位二进制立即数,可寻址DP以上的0到63字的地址范围:
; VarA和VarB在同一个长度为64字的分页中,VarC和VarD同在另外一个长度为64字的分页中
MOVW DP,#VarA ; 把变量VarA所在页的首地址载入段指针DP中
ADD AL,@VarA ; 把变量VarA的内容加到AL中
MOV @VarB,AL ; 把AL的内容写进变量VarB中

MOVW DP,#VarC ;
SUB AL,@VarC ;
MOV @VarD,AL ;
(2)@7位二进制立即数方式,适用于AMODE=1,地址高10位为0,地址次高15位为DP的低15:1位,地址低7位为7位二进制立即数,可寻址DP以上的0到127字的地址范围:
SETC AMODE
.lp_amode

MOVW DP,#VarA
ADD AL,@@VarA
MOV @@VarB,AL

MOVW DP,#VarC
SUB AL,@@VarC
MOV @@VarD,AL
栈寻址(只能寻址C28x的低64k数据地址空间):
(2) *-SP[6位二进制立即数]方式,适用于AMODE=0,高16位地址为0,低16位地址为SP-6位二进制立即数,SP不变,可寻址低于SP的0到63个字地址范围:
ADD AL,*-SP[5] ; 栈顶减5个字所指向的内容(16位)加到AL中,SP不变
MOV *-SP[8],AL ; AL的内容(16位)写到栈顶减8个字所指向的位置,SP不变

ADDL ACC,*-SP[12] ; 栈顶减12个字所指向的内容(32位)加到ACC中,SP不变
MOVL *-SP[34],ACC ; ACC的内容(32位)写到栈顶减32个字所指向的位置,SP不变

(2) *SP++方式,适用于AMODE=x,16位操作时SP=SP+1,32位操作时SP=SP+2,高16位地址为0,低16位地址为SP:
MOV *SP++,AL ; AL的内容(16位)压入栈顶
MOVL *SP++,P ; P的内容(32位)压入栈顶
(3) *--SP方式,适用于AMODE=x,16位操作时SP=SP-1,32位操作时SP=SP-2,高16位地址为0,低16位地址为SP:
ADD AL,*--SP ; 栈顶内容弹出并加到AL中(16位)
MOVL ACC,*--SP ; 栈顶内容弹出到ACC中(32位)
C28x间接寻址:
(1)*XARn++方式,适用于AMODE=x,ARP=n,32位地址为XARn,16位操作时XARn=XARn+1,32位操作时XARn=XARn+2:
MOVL XAR2,#Array1 ; 载入Array1的首地址到XAR2中
MOVL XAR3,#Array2 ; 载入Array2的首地址到XAR3中
MOV @AR0,#N-1 ; 载入循环计数N到AR0中
Loop:
MOVL ACC,*XAR2++ ; 载入XAR2指向的内容到ACC中,XAR2后加1
MOVL *XAR3++,ACC ; ACC的内容写入XAR3指向的地址,XAR3后加1
BANZ Loop,AR0-- ; 循环到AR0 == 0,AR0后加1
(2)*--XARn方式,适用于AMODE=x,ARP=n,32位地址为XARn,16位操作时XARn=XARn-1,32位操作时XARn=XARn-2:
MOVL XAR2,#Array1+N*2 ; 载入Array1的末地址到XAR2中
MOVL XAR3,#Array2+N*2 ; 载入Array1的末地址到XAR2中
MOV @AR0,#N-1 ; 载入循环计数N到AR0中
Loop:
MOVL ACC,*--XAR2 ; XAR2先减1,载入XAR2所指向的内容到ACC中
MOVL *--XAR3,ACC ; XAR3先减,ACC内容写入XAR3所指的位置
BANZ Loop,AR0-- ; 循环到 AR0 == 0, AR0后加1
(3)*+XARn[AR0或(AR1)]方式,适用于AMODE=x,ARP=n,32位地址为XARn+AR0(或AR1),XAR0(或XAR1)的低16位作为无符号数加到XARn中,忽略高16位,可能会产生到XARn高16位的溢出:
MOVW DP,#Array1Ptr ; 指向Array1Ptr的段
MOVL XAR2,@Array1Ptr ; 载入Array1的首地址到XAR2中
MOVB XAR0,#16 ; AR0 = 16, AR0H = 0
MOVB XAR1,#68 ; AR1 = 68, AR1H = 0
MOVL ACC,*+XAR2[AR0] ; 把Array1[16]和Array1[68]内容互换,首先载入Array1[16]内容到ACC
MOVL P,*+XAR2[AR1] ; 把Array1[68]内容到P
MOVL *+XAR2[AR1],ACC ; 写入ACC内容到Array1[68]
MOVL *+XAR2[AR0],P ; 写入P内容到Array1[16],完成互换
(4)*+XARn[3位二进制立即数]方式,适用于AMODE=x,ARP=n,32位地址为XARn+无符号3位二进制立即数,*XARn等价于*+XARn[0]:
MOVW DP,#Array1Ptr ; 指向Array1Ptr的段
MOVL XAR2,@Array1Ptr ; 载入Array1的首地址到XAR2
MOVL ACC,*+XAR2[2] ; 把Array1[2]和Array1[5]内容互换,首先载入Array1[2]内容到ACC
MOVL P,*+XAR2[5] ; 把Array1[5]内容到P
MOVL *+XAR2[5],ACC ; 写入ACC内容到Array1[5]
MOVL *+XAR2[2],P ; 写入P内容到Array1[2],完成互换
循环间接寻址:
寄存器寻址:
(1)32位操作,使用寄存器@ACC,@XT,@P,@XARn,当@ACC作为目的操作数时,可能会影响Z,N,V,C,OVC标志位。
(2)16位操作,使用寄存器@AL,@AH,@PL,@PH,@TH,@SP,@ARn,当@AL或@AH作为目的操作数时,可能会影响Z,N,V,C,OVC标志位。对应的高16位或低16位不受影响。

数据/程序/IO空间立即寻址:
(1) *(16位二进制立即数)方式,地址的高16位为0,低16位为16位二进制立即数。当该指令连续使用时,每次地址都会后加。只能寻址低64k数据空间。可用指令:
MOV loc16,*(0:16bit) ; [loc16] = [0:16bit]
MOV *(0:16bit),loc16 ; [loc16] = [0:16bit]
(2) *(PA)方式,地址的高16位为0,低16位为PA中的16位二进制立即数。当该指令连续使用时,每次地址都会后加。该模式寻址时,在访问IO空间时,IO选通信号被置位。用数据地址线访问IO空间。可用指令:
OUT *(PA),loc16 ; IOspace[0A] = [loc16]
UOUT *(PA),loc16 ; IOspace[0A] = [loc16] (unprotected)
IN loc16,*(PA) ; [loc16] = IOspace[0A]
(3) 0:pma方式,22位的地址高6位为0,低16位为16位二进制立即数pma,当该指令连续使用时,每次地址都会后加。只能寻址低64k程序空间。可用指令:
MAC P,loc16,0:pma ; ACC = ACC + P << PM,P = [loc16] * ProgSpace[0:pma]
(4) *(pma)方式,22位的地址高6位为0,低16位为16位二进制立即数pma,当该指令连续使用时,每次地址都会后加。只能寻址低64k程序空间。可用指令:
XPREAD loc16,*(pma) ; [loc16] = ProgSpace[0x3F:pma]
XMAC P,loc16,*(pma) ; ACC = ACC + P << PM,P = [loc16] * ProgSpace[0x3F:pma]
XMACD P,loc16,*(pma) ; ACC = ACC + P << PM,P = [loc16] * ProgSpace[0x3F:pma],[loc16+1] = [loc16]

程序空间间接寻址:
(1) *(AL)方式,22位的地址高6位为0x3F,低16位为AL,当该指令连续使用时,AL的内容被复制到一个影子寄存器中,并在每次地址后加,AL的内容不变。只能寻址低64k程序空间。可用指令:
XPREAD loc16,*AL ; [loc16] = ProgSpace[0x3F:AL]
XPWRITE *AL,loc16 ; ProgSpace[0x3F:AL] = [loc16]
(2) *XAR7方式,22位地址为XAR7,当在指令XPREAD或XPWRITE中连续使用时,XAR7的内容被复制到一个影子寄存器中,并每次地址后加,XAR7的内容不变。其它指令则不会。可用指令:
MAC P,loc16,*XAR7 ; ACC = ACC + P << PM,P = [loc16] * ProgSpace[*XAR7]
DMAC ACC,loc32,*XAR7 ; ACC = ([loc32].MSW * ProgSpace[*XAR7].MSW) >> PM,
; P = ([loc32].LSW * ProgSpace[*XAR7].MSW) >> PM
QMACL P,loc32,*XAR7 ; ACC = ACC + P >> PM,
; P = ([loc32] * ProgSpace[*XAR7]) >> 32
IMACL P,loc32,*XAR7 ; ACC = ACC + P,
; P = ([loc32] * ProgSpace[*XAR7]) << PM
PREAD loc16,*XAR7 ; [loc16] = ProgSpace[*XAR7]
PWRITE *XAR7,loc16 ; ProgSpace[*XAR7] = [loc16]
(2) *XAR7++方式,22位地址为XAR7, 16位操作时XAR7=XAR7+1,32位操作时XAR7=XAR7+2,指令重复时,地址后加。可用指令:
MAC P,loc16,*XAR7++ ; ACC = ACC + P << PM,P = [loc16] * ProgSpace[*XAR7++]
DMAC ACC,loc32,*XAR7++ ; ACC=([loc32].MSW * ProgSpace[*XAR7++].MSW)>>PM,
; P=([loc32].LSW * ProgSpace[*XAR7++].MSW)>>PM
QMACL P,loc32,*XAR7++ ; ACC = ACC + P >> PM, P = ([loc32] * ProgSpace[*XAR7++]) >> 32
IMACL P,loc32,*XAR7++ ; ACC = ACC + P, P = ([loc32] * ProgSpace[*XAR7++]) << PM
字节寻址:
*+XARn[AR0],*+XARn[AR0],*+XARn[3位二进制立即数],32位地址为XARn+偏移量(AR0/AR1/3位二进制立即数),如果偏移量为偶数值,则访问16位存储器位置的低有效位,高有效位不变;如果为奇数,则访问16位存储器位置的高有效位,低有效位不变。其它所有寻址模式,只访问访问寻址位置的低有效位,不改变高有效位。可用指令:
MOVB AX.LSB,loc16 ; if( address mode == *+XARn[AR0/AR1/3bit] )
; if( offset == even )
; AX.LSB = [loc16].LSB;
; AX.MSB = 0x00;
; if( offset == odd )
; AX.LSB = [loc16].MSB;
; AX.MSB = 0x00;
; else
; AX.LSB = [loc16].LSB;
; AX.MSB = 0x00;
MOVB AX.MSB,loc16 ; if( address mode == *+XARn[AR0/AR1/3bit] )
; if( offset == even )
; AX.LSB = untouched;
; AX.MSB = [loc16].LSB;
; if( offset == odd )
; AX.LSB = untouched;
; AX.MSB = [loc16].MSB;
; else
; AX.LSB = untouched;
; AX.MSB = [loc16].LSB;
MOVB loc16,AX.LSB ; if( address mode == *+XARn[AR0/AR1/3bit] )
; if( offset == even )
; [loc16].LSB = AX.LSB
; [loc16].MSB = untouched;
; if( offset == odd )
; [loc16].LSB = untouched;
; [loc16].MSB = AX.LSB;
; else
; [loc16].LSB = AX.LSB;
; [loc16].MSB = untouched;
MOVB loc16,AX.MSB ; if( address mode == *+XARn[AR0/AR1/3bit] )
; if( offset == even )
; [loc16].LSB = AX.MSB
; [loc16].MSB = untouched;
; if( offset == odd )
; [loc16].LSB = untouched;
; [loc16].MSB = AX.MSB;
; else
; [loc16].LSB = AX.MSB;
; [loc16].MSB = untouched;
很好的东西,不要错过哟.
返回列表