1

我需要在 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)

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

4

1 回答 1

2

你的程序是错误的。它在技术上这样做

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

它实际上会切换最高位,如果该值设置了最高位,则不会为您提供正确的值。事实上,如果设置了最高位,它会陷入困境,因为这是dadd而不是daddu

您应该阅读有关按位运算的更多信息:清除一点,请使用and; 用于设置切换or_ _xor

在 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)
于 2014-06-15T04:13:37.697 回答