最优化的方法是在mips64上设置MMIO寄存器的第63位

时间:2013-09-28 12:06:40

标签: assembly mips micro-optimization mips64

我需要用MIPS汇编语言设置64位MMIO寄存器的第63位(MSB)。

目前我正在这样做

ldi $2,0x8000000000123456 #This is the address of the register which i want to set 63 rd bit 
ld $3,0($2) # read current value from the register 
dli $4,0x8000000000000000  # set 63rd bit as 1 and load in to register $4
dadd $4,$3,$4    # add mask value and current value to set 63rd bit 
sd $4,0($2)

但这是非常冗长的代码。我想以最优化的方式做到这一点。还有其他办法吗?

1 个答案:

答案 0 :(得分:2)

你的程序错了。从技术上讲,这是

uint64_t p = *((uint64_t*)0x8000000000123456ULL);
p += 0x8000000000000000ULL;

实际上切换顶部位,如果值设置了最高位,则不会给出正确的值。实际上,如果设置了最高位,它将陷入陷阱,因为它是dadd而不是daddu

您应该详细了解bitwise operationsTo clear a bit, use and; use or to set and xor to toggle a bit

在MIPS中你可以这样做

ldi  $2, 0x8000000000123456
ld   $3, 0($2)
lui  $4, 0x8000 # $4 = 0x80000000
dsll $4, $4, 32 # $4 = 0x8000000000000000
or   $4, $3, $4
sd   $3, 0($2)

lui / dsll对用于加载立即数。它可以替换为任何等效序列,将2的幂加载到低半部分,然后将其移到高部分

请注意,除非您使用的是MMIO,否则没有任何名为“注册地址”的内容。它是包含内存位置地址的寄存器。如果您正在访问实际内存或允许部分寄存器访问的MMIO设备,那么您只需加载特定的字节,半字或字并编辑它就可以获得替代解决方案,从而为您节省了几条加载64位立即数的指令

# byte
ldi $2, 0x8000000000123456 # assume big endian
lbu $3, 0($2)
ori $3, 0x80
sb  $3, 0($2)

# halfword
ldi $2, 0x8000000000123456
lhu $3, 0($2)
ori $3, 0x8000
sh  $3, 0($2)

# word
ldi $2, 0x8000000000123456
lbu $3, 0($2)
lui $4, 0x8000
or  $3, $4, $3
sd  $3, 0($2)