请教ARM中的预取命令PLD的使用

sno_guo 2012-11-24 09:27:32
我现在在看android2.3.3提供的关于ARM平台的memcmp这个函数的实现代码,它是用汇编编写的,如下:
   .text

.global __memcmp16
.type __memcmp16, %function
.align 4

/*
* Optimized memcmp16() for ARM9.
* This would not be optimal on XScale or ARM11, where more prefetching
* and use of PLD will be needed.
* The 2 major optimzations here are
* (1) The main loop compares 16 bytes at a time
* (2) The loads are scheduled in a way they won't stall
*/

__memcmp16:
.fnstart
PLD (r0, #0)
PLD (r1, #0)

/* take of the case where length is nul or the buffers are the same */
cmp r0, r1
cmpne r2, #0
moveq r0, #0
bxeq lr

/* since r0 hold the result, move the first source
* pointer somewhere else
*/

mov r3, r0

/* make sure we have at least 12 words, this simplify things below
* and avoid some overhead for small blocks
*/

cmp r2, #12
bpl 0f

/* small blocks (less then 12 words) */
PLD (r0, #32)
PLD (r1, #32)

1: ldrh r0, [r3], #2
ldrh ip, [r1], #2
subs r0, r0, ip
bxne lr
subs r2, r2, #1
bne 1b
bx lr


.save {r4, lr}
/* save registers */
0: stmfd sp!, {r4, lr}

/* align first pointer to word boundary */
tst r3, #2
beq 0f

ldrh r0, [r3], #2
ldrh ip, [r1], #2
sub r2, r2, #1
subs r0, r0, ip
/* restore registers and return */
ldmnefd sp!, {r4, lr}
bxne lr
.fnend



0: /* here the first pointer is aligned, and we have at least 3 words
* to process.
*/

/* see if the pointers are congruent */
eor r0, r3, r1
ands r0, r0, #2
bne 5f

/* congruent case, 16 half-words per iteration
* We need to make sure there are at least 16+2 words left
* because we effectively read ahead one long word, and we could
* read past the buffer (and segfault) if we're not careful.
*/

ldr ip, [r1]
subs r2, r2, #(16 + 2)
bmi 1f

0: ///PLD是宏定义,意思是ARM指令集支持pld命令,就用pld,否则为空
///我不明白的是:这里为什么要把r3+64的地址中的数据取出来,这里好像也没有用到r3+64这个地址中的数据啊????? 请各位忙吧分析下,谢谢了,
PLD (r3, #64)
PLD (r1, #64) ///这里为什么要加64?????
ldr r0, [r3], #4
ldr lr, [r1, #4]!
eors r0, r0, ip
ldreq r0, [r3], #4
ldreq ip, [r1, #4]!
eoreqs r0, r0, lr
ldreq r0, [r3], #4
ldreq lr, [r1, #4]!
eoreqs r0, r0, ip
ldreq r0, [r3], #4
ldreq ip, [r1, #4]!
eoreqs r0, r0, lr
ldreq r0, [r3], #4
ldreq lr, [r1, #4]!
eoreqs r0, r0, ip
ldreq r0, [r3], #4
ldreq ip, [r1, #4]!
eoreqs r0, r0, lr
ldreq r0, [r3], #4
ldreq lr, [r1, #4]!
eoreqs r0, r0, ip
ldreq r0, [r3], #4
ldreq ip, [r1, #4]!
eoreqs r0, r0, lr
bne 2f
subs r2, r2, #16
bhs 0b

/* do we have at least 2 words left? */
1: adds r2, r2, #(16 - 2 + 2)
bmi 4f

/* finish off 2 words at a time */
3: ldr r0, [r3], #4
ldr ip, [r1], #4
eors r0, r0, ip
bne 2f
subs r2, r2, #2
bhs 3b

/* are we done? */
4: adds r2, r2, #2
bne 8f
/* restore registers and return */
mov r0, #0
ldmfd sp!, {r4, lr}
bx lr

2: /* the last 2 words are different, restart them */
ldrh r0, [r3, #-4]
ldrh ip, [r1, #-4]
subs r0, r0, ip
ldreqh r0, [r3, #-2]
ldreqh ip, [r1, #-2]
subeqs r0, r0, ip
/* restore registers and return */
ldmfd sp!, {r4, lr}
bx lr

/* process the last few words */
8: ldrh r0, [r3], #2
ldrh ip, [r1], #2
subs r0, r0, ip
bne 9f
subs r2, r2, #1
bne 8b

9: /* restore registers and return */
ldmfd sp!, {r4, lr}
bx lr


5: /*************** non-congruent case ***************/

/* align the unaligned pointer */
bic r1, r1, #3
ldr lr, [r1], #4
sub r2, r2, #8

6:
PLD (r3, #64)
PLD (r1, #64)
mov ip, lr, lsr #16
ldr lr, [r1], #4
ldr r0, [r3], #4
orr ip, ip, lr, lsl #16
eors r0, r0, ip
moveq ip, lr, lsr #16
ldreq lr, [r1], #4
ldreq r0, [r3], #4
orreq ip, ip, lr, lsl #16
eoreqs r0, r0, ip
moveq ip, lr, lsr #16
ldreq lr, [r1], #4
ldreq r0, [r3], #4
orreq ip, ip, lr, lsl #16
eoreqs r0, r0, ip
moveq ip, lr, lsr #16
ldreq lr, [r1], #4
ldreq r0, [r3], #4
orreq ip, ip, lr, lsl #16
eoreqs r0, r0, ip
bne 7f
subs r2, r2, #8
bhs 6b
sub r1, r1, #2
/* are we done? */
adds r2, r2, #8
moveq r0, #0
beq 9b
/* finish off the remaining bytes */
b 8b

7: /* fix up the 2 pointers and fallthrough... */
sub r1, r1, #2
b 2b
...全文
665 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
sno_guo 2013-01-06
  • 打赏
  • 举报
回复
哦,谢谢,这个我在arm网站上的论坛里问过,大概功能明白了。 可是还有点不明白的是pld 命令只是说明了从哪里地址来预取数据,可是没有说一次性取多少个数据,怎么知道一次预取多少个数据呢。
求佛_ce123 2013-01-06
  • 打赏
  • 举报
回复
http://blog.csdn.net/ce123/article/details/8471614 可以看看这篇博客,希望对你有帮助
求佛_ce123 2013-01-06
  • 打赏
  • 举报
回复
Cache块的大小需要看一下arm内核的数据手册
求佛_ce123 2013-01-06
  • 打赏
  • 举报
回复
Cache未命中时的分配策略:读操作分配策略、读/写策略分配策略。 a). 读操作分配策略,当Cache未命中时,只有进行存储器读操作时,才分配Cache行。如果被替换的Cache行包含有效数据,那么在该行被新的数据填充之前,要先把原理的内容写入到主存中去。采用读操作分配策略时,存储器写操作不会更新Cache行,除非相关的Cache行恰好是前一个主存读操作刚分配的。 b). 采用读/写分配策略,无论存储器读还是写操作,在Cache未命中时,都将分配Cache行。对于存储器写操作,如果Cache未命中,将分配一个 Cache行。如果被替换的Cache行中包含有效数据,控制器会先将该行数据写入主存,再用从主存读取的数据将改行Cache覆盖,最后把内核数据写入该Cache行中。如果采用Cache直写策略,内核数据将会同时被写入到主存中。 因此:一次性取多少数据取决于Cache行的大小,也就是Cache块的大小,但我有一个疑问,数据已经在寄存器中了,为什么还要预读取?
求佛_ce123 2013-01-06
  • 打赏
  • 举报
回复
欢迎到我博客上进行交流
sno_guo 2012-11-28
  • 打赏
  • 举报
回复
自己顶下,希望高手能帮忙回答下。谢谢了
sno_guo 2012-11-24
  • 打赏
  • 举报
回复
我的疑问已经在代码中了,各位帮忙看下,谢谢了
Node.js 是一个开源与跨平台的 JavaScript 运行时环境。 它是一个可用于几乎任何项目的流行工具!   Node.js 在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核)。 这使 Node.js 表现得非常出色。   Node.js 应用程序运行于单个进程,无需为每个请求创建新的线程。 Node.js 在其标准库提供了一组异步的 I/O 原生功能(用以防止 JavaScript 代码被阻塞),并且 Node.js 的库通常是使用非阻塞的范式编写的(从而使阻塞行为成为例外而不是规范)。   当 Node.js 执行 I/O 操作时(例如从网络读取、访问数据库或文件系统),Node.js 会在响应返回时恢复操作,而不是阻塞线程并浪费 CPU 循环等待。   这使 Node.js 可以在一台服务器上处理数千个并发连接,而无需引入管理线程并发的负担(这可能是重大 bug 的来源)。   Node.js 具有独特的优势,因为为浏览器编写 JavaScript 的数百万前端开发者现在除了客户端代码之外还可以编写服务器端代码,而无需学习完全不同的语言。   在 Node.js ,可以毫无问题地使用新的 ECMAScript 标准,因为不必等待所有用户更新其浏览器,你可以通过更改 Node.js 版本来决定要使用的 ECMAScript 版本,并且还可以通过运行带有标志的 Node.js 来启用特定的实验的特性。   大量的库 npm 的简单结构有助于 Node.js 生态系统的激增,现在 npm 仓库托管了超过 1,000,000 个可以自由使用的开源库包。   Node.js 应用程序的示例 Node.js zui常见的 Hello World 示例是 Web 服务器:   const http = require('http')const hostname = '127.0.0.1'const port = 3000const server = http.createServer((req, res) => )server.listen(port, hostname, () => ) 此代码首先引入了 Node.js http 模块。   Node.js 具有出色的标准库,包括对网络的一.流支持。   http 的 createServer() 方法会创建新的 HTTP 服务器并返回它。   服务器被设置为监听指定的端口和主机名。 当服务器就绪后,回调函数会被调用,在此示例会通知我们服务器正在运行。   每当接收到新的请求时,request 事件会被调用,并提供两个对象:一个请求(http.IncomingMessage 对象)和一个响应(http.ServerResponse 对象)。   这两个对象对于处理 HTTP 调用至关重要。   第一个对象提供了请求的详细信息。 在这个简单的示例没有使用它,但是你可以访问请求头和请求数据。   第二个对象用于返回数据给调用方。   在此示例:   res.statusCode = 200 设置 statusCode 属性为 200,以表明响应成功。   设置 Content-Type 响应头:   res.setHeader('Content-Type', 'text/plain') 关闭响应,添加内容作为 end() 的参数:   res.end('你好世界n') Node.js 框架和工具 Node.js 是一个底层的平台。 为了使开发者做事变得容易又来劲,社区在 Node.js 上构建了数千个库。   久而久之,其许多已成为受欢迎的选择。 以下是一些值得学习的清单:   AdonisJs: 一个全栈框架,高度专注于开发者的效率、稳定和信任。 Adonis 是zui快的 Node.js Web 框架之一。   Express: 提供了创建 Web 服务器的zui简单但功能zui强大的方法之一。 它的极简主义方法,专注于服务器的核心功能,是其成功的关键。   Fastify: 一个 Web 框架,高度专注于提供zui佳的开发者体验(以zui少的开销和强大的插件架构)。 Fastify 是zui快的 Node.js Web 框架之一。   Gatsby: 一个基于 React、由 GraphQL 驱动的静态网站生成器,具有非常丰富的插件和启动器生态系统。   hapi: 一个富框架,用于构建应用程序和服务,使开发者可以专注于编写可重用的应用程序逻辑,而不必花费时间来搭建基础架构。   koa: 由 Express 背后的同一个团队构建,旨在变得更简单更轻巧。 新项目的诞生是为了满足创建不兼容的更改而又不破坏现有社区。   Loopback.io: 使构建需要复杂集成的现代应用程序变得容易。   Meteor: 一个强大的全栈框架,以同构的方式使用 JavaScript 构建应用(在客户端和服务器上共享代码)。 曾经是提供所有功能的现成工具,现在可以与前端库 React,Vue 和 Angular 集成。 也可以用于创建移动应用。   Micro: 提供了一个非常轻量级的服务器,用于创建异步的 HTTP 微服务。   NestJS: 一个基于 TypeScript 的渐进式 Node.js 框架,用于构建企业级的高效、可靠和可扩展的服务器端应用程序。   Next.js: 一个 React 框架,可为你提供生产所需的所有功能的zui佳开发者体验:混合静态和服务器渲染、TypeScript 支持、智能捆绑、路由预取等。   Nx: 使用 NestJS、Express、React、Angular 等进行全栈开发的工具包! Nx 有助于将开发工作从一个团队(构建一个应用程序)扩展到多个团队(在多个应用程序上进行协作)!   Sapper: Sapper 是一个用于构建各种规模的 Web 应用程序的框架,具有出色的开发体验和灵活的基于文件系统的路由。还提供 S.S.R等!   Socket.io: 一个实时通信引擎,用于构建网络应用程序。   Strapi: Strapi 是一个灵活的开源 Headless CMS,可使开发者可以自由选择自己喜欢的工具和框架,同时还允许编辑人员轻松地管理和分发其内容。 通过使管理面板和 API 可以通过插件系统进行扩展,Strapi 使全球zui大的公司能够加速内容交付,同时构建优美的数字体验。

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧