OpenRisc-67-OR的汇编

引言

之前我们写过OR的裸机程序,写过基于OR的linux设备驱动程序,也反汇编过OR的机器码。

本小节,我们将通过一个简单的实验,对OR的汇编(指令集)做一个简单的梳理和測试。

1,基本思想

要想了解OR的指令集,事实上仅仅要查查OpenRISC architecture manual就能够了,可是不是最好的熟悉方式,也没有必要将其全部指令集记下来。我觉得,通过一个实际的project或者样例,从中了解OR的指令集是比較好的一种方式。

那么,通过什么样例呢?

一般RISC的指令集包含,运算指令,分支指令,和訪存指令,三类。所以我们这个实验最好能用到这三类指令,碰巧,我近期在測试DDR控制器,所以我们以下将通过一个读写内存的样例来熟悉OR的指令集。

2,实验步骤

2.1实验准备

在開始编码之前,我们首先须要考虑例如以下几个问题:

a,怎样对汇编源程序(.S文件)进行编译,生成机器码。

b,怎样载入机器码使OR的指令总线能读到。

c,怎样查看机器码的执行过程和结果。

依据前面,我们积累下来的经验,可知,利用bootrom进行RTL仿真,能够非常好的解决上面三个问题。而且都是自己主动化的。

2.2 实验步骤

在了解并攻克了上面几个问题之后,剩下的就是详细的操作了。

a,改动soc-design/orpsocv2/sw/bootrom文件夹下的board.h

#ifndef _BOARD_H_
#define _BOARD_H_

//#define IN_CLK  	      50000000 // Hz
#define IN_CLK  	      66666667 // Hz
#define PRELOAD_RAM
#define BOOTROM_MEM_TEST
//
// ROM bootloader
//
// Uncomment the appropriate bootloader define. This will effect the bootrom.S
// file, which is compiled and converted into Verilog for inclusion at
// synthesis time. See bootloader/bootloader.S for details on each option.
#ifndef PRELOAD_RAM
#define BOOTROM_SPI_FLASH
//#define BOOTROM_GOTO_RESET
//#define BOOTROM_LOOP_AT_ZERO
//#define BOOTROM_LOOP_IN_ROM
#else
	#ifdef BOOTROM_MEM_TEST
		#define BOOTROM_MEM_TEST1
	#else
		#define BOOTROM_GOTO_RESET
	#endif
#endif

// Address bootloader should start from in FLASH
// Last 256KB of 2MB flash - offset 0x1c0000 (2MB-256KB)
#define BOOTROM_ADDR_BYTE2 0x1c
#define BOOTROM_ADDR_BYTE1 0x00
#define BOOTROM_ADDR_BYTE0 0x00
// Causes SPI bootloader to loop if SPI didn‘t give correct size of image
#define SPI_RETRY_IF_INSANE_SIZEWORD

//
// Defines for each core (memory map base, OR1200 interrupt line number, etc.)
//
#define SDRAM_BASE                 0x0

#define GPIO_0_BASE         0x91000000

#define UART0_BASE  	    0x90000000
#define UART0_IRQ                    2
#define UART0_BAUD_RATE 	115200

#define SPI0_BASE           0xb0000000
#define SPI0_IRQ                     6

#define I2C_0_BASE          0xa0000000
#define I2C_0_IRQ                   10

#define I2C_1_BASE          0xa1000000
#define I2C_1_IRQ                   11

#define ETH0_BASE            0x92000000
#define ETH0_IRQ                      4

#define ETH_MACADDR0	           0x00
#define ETH_MACADDR1	           0x12
#define ETH_MACADDR2  	           0x34
#define ETH_MACADDR3	           0x56
#define ETH_MACADDR4  	           0x78
#define ETH_MACADDR5	           0x9a

//
// OR1200 tick timer period define
//
#define TICKS_PER_SEC   100

//
// CFI flash controller base
//
#define CFI_CTRL_BASE 0xf0000000

//
// UART driver configuration
//
#define UART_NUM_CORES 1
#define UART_BASE_ADDRESSES_CSV	UART0_BASE
#define UART_BAUD_RATES_CSV UART0_BAUD_RATE

//
// i2c_master_slave core driver configuration
//

#define I2C_MASTER_SLAVE_NUM_CORES 2

#define I2C_MASTER_SLAVE_BASE_ADDRESSES_CSV			I2C_0_BASE, I2C_1_BASE

#endif

b,改动soc-design/orpsocv2/sw/bootrom文件夹下的bootrom.S

这个文件,是须要我们自己手动编写OR的汇编了。

须要注意的有几点。

首先,怎样让仿真自己主动退出:使用“l.nop 1”这条指令,详细原因可參考or1200_monitor.v文件里的相关内容。

其次,怎样推断读写内存的成功与失败,分别使用“l.nop 4”和“l.nop 3”。

最后,这些汇编,都非常easy理解,唯一须要注意的是OR支持延迟槽。

以下是详细代码清单:

//////////////////////////////////////////////////////////////////////
///                                                               ////
/// bootrom      Rill 2014-04-28                                  ////
///                                                               ////
/// Assembly programs to be embedded inside system to aid boot    ////
///                                                               ////
///                                                               ////
//////////////////////////////////////////////////////////////////////

// Defines for which bootrom app to use are in board.h - TODO: use the
// processed orspoc-defines.v file for this define. It makes more sense
// as this software ends up as gates.

#include "board.h"

#ifdef BOOTROM_MEM_TEST1

#define RAM_LOAD_BASE 0x100000
#define RESET_ADDR 0x100
#define RAM_LOAD_VALUE 0x5555
#define RAM_LOAD_SIZE 0xc

boot_init:
	l.movhi r0, 0  /*0*/
	l.movhi r1, RAM_LOAD_BASE /*1*/

mem_write:
	l.movhi r6, 0 /*2*/ /* counter*/
	l.ori r7, r0, RAM_LOAD_SIZE /*3*/
	//l.movhi	r7, RAM_LOAD_SIZE
	l.movhi r8, 0 /*4*/ /* load addr index*/
write:
	l.ori	r3,r0, RAM_LOAD_VALUE    /*5*/    /* Read a byte into r3 */
	l.add	r8, r1, r6    /*6*/   /* Calculate store address */
	l.sw	0(r8), r3     /*7*/   /* Write byte to memory */
	l.addi	r6, r6, 4     /*8*/   /* Increment counter */
	l.sfeq 	r6, r7 		/*9*/  /* Check if we‘ve finished loading the words */
	l.bnf 	write       /*10*/  /* Continue copying if not last word */
	l.nop			/*11*/

mem_read:
	l.movhi r6, 0
	l.ori r7, r0, RAM_LOAD_SIZE
	l.movhi r8, 0
read:
	l.add	r8, r1, r6
	l.lwz	r3, 0(r8)
	l.j	check
	l.nop
read2:
	l.addi	r6, r6, 4
	l.sfeq 	r6, r7
	l.bnf 	read
	l.nop
	l.j	success
	l.nop

check:
	l.ori	r5,r0, RAM_LOAD_VALUE
	l.sfeq 	r3, r5
	l.bnf 	error
	l.nop
	l.j	read2
	l.nop

error:
	l.nop 	3
	l.j error
	l.nop	1

success:
	l.nop	4
	l.j	success
	l.nop	1

#endif

c,创建C语言裸机測试文件夹和程序

因为我们想利用ORPSoC现成的測试环境,所以我们还须要编写一个假的,仅仅是为了满足原有的測试环境的文件夹和文件。

在soc-design/orpsocv2/board/xilinx/ml501/sw/tests文件夹下创建文件夹和文件:

mkdir mem
cd mem
touch mem.c
cp ../../Makefile .

编辑mem.c:

/*
* Rill
* april/28/2014
*/

int main()
{
	while(1);//we run instructions in bootrom ONLY.
	return 0;
}

因为我们仅仅执行bootrom.S中的指令,所以mem.c里面写什么语句不重要。

d,測试与验证

完毕编码之后,我们就能够执行我们刚才写的汇编程序了,方法我们之前已经介绍过多次了,这里反复例如以下:

在 soc-design/orpsocv2/board/xilinx/ml501/sim/run文件夹下执行例如以下:

make rtl-test TEST=mem VCD=1

非常快,我们就能够仿真结束,然后,我们就能够查看仿真日志文件和仿真波形。

从中能够看出,对内存的读写都是正确的。

or1200_monitor输出的日志文件:mem-general.log

58598000.0 ps: l.nop 4 putc (U)
58718000.0 ps: l.nop exit (00005555)

vcd波形文件:

3,小结

对于cpu来说,对全部外设(uart,i2c,vga......)的控制都能够通过load/store来完毕,和读写内存的实质是全然同样的,所以,通过上面的汇编,我们仅仅要改变一下读写地址改动成相应外设的地址,我们就能够实现对该设备的控制了。

当然,编写出优秀的汇编程序也不是一件太easy的事情,这就须要详细阅读OR的架构手冊,掌握GPR和SPR的用法。甚至,我们还要查看or32-elf-asm来了解更准确的OR的指令集。

OpenRisc-67-OR的汇编,布布扣,bubuko.com

时间: 2024-10-11 11:24:26

OpenRisc-67-OR的汇编的相关文章

汇编--常用汇编指令与标志位关系

加法指令 ADD (addition) 指令对标志位的影响: CF=1   最高有效位向高位有进位 CF=0   最高有效位向高位无进位 OF=1   两个同符号数相加(正数+正数 或 负数+负数),结果符号与其相反. OF=0   两个不同符号数相加,或同符号数相加,结果符号与其相同. 带进位加法指令 ADC (add with carry) 指令对标志位的影响: CF=1   最高有效位向高位有进位 CF=0   最低有效位相高位无进位 OF=1   两个同符号数相加,结果符号与其相反, O

01 start.s汇编代码注解(RTEMS)

start.s 文件中汇编代码的注解(RTEMS) 作者:zhousm    2016年01月01日 处理器:S3C2440  ARM9 操作系统:RTEMS-4.10.2 源文件路径:rtems-4.10.2/c/src/lib/libbsp/arm/gp32/start/start.S 当处理器跳转到指定的地址开始执行时,即从该文件开始执行: 1 /* Some standard definitions...*/ 2 .equ PSR_MODE_USR, 0x10 3 .equ PSR_MO

《Intel汇编第5版》 汇编调用子过程

一.Call和Ret指令 二.在子过程中需要自己保存可能会修改掉的寄存器值,这里可以使用USES伪指令来生成 三.一个数组求和的汇编例子 1 TITLE Call a Proc Demo 2 INCLUDE Irvine32.inc 3 includelib Irvine32.lib 4 includelib kernel32.lib 5 includelib user32.lib 6 7 8 .data 9 array DWORD 1000h,2000h,3000h,4000h 10 11 .

汇编小程序

相关图例: MY_CAL 1 TITLE MY_CAL PROGRRAM TO RUN THE CALCULATION 2 PAGE 60, 132 3 ;--------------------------------- 4 .MODEL SMALL 5 .STACK 64 6 PUBLIC MY_CAL 7 ;--------------------------------- 8 .DATA 9 CAL_MSG1 DB 'Please enter the expression(Q for l

汇编画圆

汇编画圆-->效果如下图 代码如下: 1 dseg segment 2 center_x dw 150 ;原点坐标_x 3 center_y dw 90 ;原点坐标_y 4 radius dw 50 ;半径_r 5 label_x dw ? ;外接正方形右边界 6 label_y dw ? ;外接正方形下边界 7 distance dw ? 8 dseg ends 9 cseg segment 10 assume cs:cseg , ds:dseg 11 start: 12 mov ax , d

[汇编] 大小写转换

1 data segment 2 ;定义字符串缓冲区 3 ;MAXLEN 表示允许输入的最大字符数量 4 ;ACTLEN 表示实际输入的数量 5 ;STR 用于存储输入的字符串 6 ;以下面为例,允许最大输入5个字符,如果STR后面的长度也定义为5,则实际输入的字符数量仅为4, 7 ;因为最后一个字符会用于存储0Dh(回车符号) 8 ;例如:输入"1234",然后回车,此时内存的情况为: 05 00 31 32 33 34 0D 9 ;因此,为了满足实际的最大数量,通常将MAXLEN定

8086汇编写冒泡排序并基于子程序设计输出结果

写在前面:也是万年没更新博客了……大二一年快过去了回首一下发现大二完全就不更新博客……原因很多吧,其一是感觉整理博客虽然能够加深理解对学习帮助很大但是还是很花时间的,效益比较低,也是不如多看看书多刷刷题:其二也可以说是最主要的原因,大二一年比较功利,做事学习也是很侧重性价比,想绩点各方面刷好然后杠一个国家奖学金,因此很少更新博客.这次更新记录我们最后一次汇编实验,很基础但是完全自学然后强行撸掉之后,内心感觉还是很快乐的.就感觉这是我在大一的状态,全身心的攻克一个比较困难的题,怼上一整天的时间,最

【转载】汇编跳转指令集

1汇编指令:  JO.JNO.JB.JNB.JE.JNE.JBE.JA.JS.JNS.JP.JNP.JL      2名称或内存 功能  操作数  操作码 模数 寄存器1 寄存器2 位移量 立即数 符号 方向 芯片型号 16位  32位  3JO   溢出跳转         短        $70    无  无  无  无  10  无  无  8086  无  无  4JNO  不溢出跳转       短        $71    无  无  无  无  10  无  无  8086 

一个卓有成效的汇编优化范例--使用SSE2指令优化进制转化

我的一个感兴趣的编程方向是大数计算,因此用汇编语言写了很多大数计算方面的小程序,上周突然想出一个使用SSE2指令将整数转为16进制字符串的好主意,遂付诸实现.原以为至多可提速500%,那知测试后发现,相对于最初的C语言版本,速度竟提高20倍以上,兴奋之余,遂有了这篇博客文章. 这个程序主要示范将64bit一个整数转化为16进制字符串的功能,功能和算法都比较简单.我相信许多人都写过类似的程序,但不知有没有人尝试去你优化它.这个示范程序包括3个C语言版和1个使用SSE2指令的汇编语言版.下面我们给出