在 C 中实现 SB 型 riscv 指令

2024-01-10

我遇到了一些问题,我尝试将 32 位二进制解码为 RISCV 架构集中的 SB 类型指令

我已经移动了操作码、imm、rs1、rs2 和 rd 值,但未能获得正确的 IMM 值

例如对于以下 32 位二进制

11111110000001111001101011100011

直接值是-12,但是在我的实现中

int type_sb_imm(unsigned char* p) {
    // Extract the 32-bit instruction from the byte array
    unsigned int opcode = (((unsigned int)p[0]) << 24) |
                          (((unsigned int)p[1]) << 16) |
                          (((unsigned int)p[2]) << 8) |
                          ((unsigned int)p[3]);

    // Extract the immediate value from the instruction (Type SB: branch)
    unsigned int uimm = ((opcode >> 7) & 0x1F) |            // imm[4:1]
                        ((opcode >> 20) & (0x7F << 5)) |    // imm[11:5]
                        ((opcode << 4) & (1 << 11)) |       // imm[12]
                        ((opcode << 19) & (0x1F << 12));    // imm[10:5]

    // Sign-extend the immediate value to 32 bits
    int imm = uimm;
    if (imm & 0x1000) {
        imm |= 0xFFFFE000;
    }

    return imm;
}

返回的立即值是4085,我想知道我哪里出错了?

请使用正确的移位修改我的函数,以从 32 位二进制中提取立即值。


以最高评论为序...

创建一个使用表定义位的函数(例如):

imm = bitmask(opcode,31,25,5) | bitmask(opcode,11,7,0);

这是我快速完成的一些示例代码(因为您的时间压力)。我把它运行在下面gdb and I think我拿到mask生成正确——但不保证:

#include <stdio.h>

typedef unsigned int u32;

u32
bitmask(u32 opc,u32 bhi,u32 blo,u32 shfl)
{
    u32 val = opc >> blo;
    u32 mask = 0xFFFFFFFF >> 31 - (bhi - blo);
    val &= mask;
    val <<= shfl;
    return val;
}

int
main(void)
{

    u32 opc = 0xF0FFFF0A;
    u32 imm = 0;
    imm |= bitmask(opc,31,25,5);
    imm |= bitmask(opc,11,7,0);
    printf("%8.8X/%u\n",imm,imm);

    return 0;
}

请注意,如果您使该功能inline并且仅传递常量位值和移位,编译器优化器将生成高效的代码。


UPDATE:

这会返回带有符号的立即值吗? – 超级编码器Superion

No, bitmask is 故意地无符号,因此您可以在许多安装格式上使用它来获取位字段。

您可以应用已有的代码来应用签名。

我正在做这个too快速地。这是我的尝试,但很容易出错——调整以适应:

#include <stdio.h>

typedef unsigned int u32;

u32
bitmask(u32 opc,u32 bhi,u32 blo,u32 shfl)
{
    u32 val = opc >> blo;
    u32 mask = 0xFFFFFFFF >> 31 - (bhi - blo);
    val &= mask;
    val <<= shfl;
    return val;
}

int
main(void)
{

    u32 opc = 0xF0FFFF0A;

    u32 uimm = 0;
    uimm |= bitmask(opc,31,25,5);
    uimm |= bitmask(opc,11,7,0);

    printf("uimm=%8.8X/%u\n",uimm,uimm);

    int imm;
    if (uimm & 0x1000) {
        imm = uimm & 0xFFF;
        imm = -imm;
    }
    else
        imm = uimm;
    printf("imm=%8.8X/%d\n",imm,imm);

    return 0;
}

更新#2:

我仍然不明白,如何传递包含指令本身的指令数组? – 超级编码器Superion

您已经在现有代码中获得了大部分内容。当你得到之后opcode,只需用我输入的代码替换您的位移代码main。也就是说,使用bitmask而不是你正在做的轮班。

这是您的代码的快速修改。

Note:我用了一种不同的方式来获得imm from uimm在第二个例子中。您必须尝试哪种方式(您的或我的)实际上是正确的,因为我没有时间进行太多测试。

int
type_sb_imm(unsigned char *p)
{
    // Extract the 32-bit instruction from the byte array
    unsigned int opcode = (((unsigned int) p[0]) << 24) | (((unsigned int) p[1]) << 16) | (((unsigned int) p[2]) << 8) | ((unsigned int) p[3]);

    // Extract the immediate value from the instruction (Type SB: branch)
    u32 uimm = 0;
    uimm |= bitmask(opcode,31,25,5);
    uimm |= bitmask(opcode,11,7,0);

    // Sign-extend the immediate value to 32 bits
    int imm = uimm;

    if (imm & 0x1000) {
        imm |= 0xFFFFE000;
    }

    return imm;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C 中实现 SB 型 riscv 指令 的相关文章

  • 如何以编程方式将访问键(快捷方式)添加到 WPF ContextMenu?

    我已经有以下内容 var myContextMenu new System Windows Controls ContextMenu var exitItem new MenuItem exitItem Header E xit exitI
  • 采用 std::vector 或 std::array 的模板函数

    我有一个函数 当前接受 2 个向量 其中可以包含任何普通的旧数据 template
  • 在 WCF 上重用我的 PagedList 对象

    问题 我有一个自定义集合PagedList
  • C# 异步任务比同步慢

    你知道为什么同步斐波那契方法比异步 等待更快并且比异步任务更快吗 我在每个项目方法上都使用了异步 所以主要是这是一个非常糟糕的方法 Code static int FibonacciSync int number if number 0 r
  • 头文件中实现的函数的静态与内联

    我想到的方式inline在 C 中用于链接 作用域 我把它放在同一个篮子里extern and static对于全局对象 通常 对于在头文件中实现的函数 我的首选解决方案是将其设为静态 In Foo h static void foo Do
  • 预编译头和 Visual Studio

    有没有办法设置 Visual Studio 解决方案参数 以便它只创建预编译头而不构建整个解决方案 具体来说 它是一个巨大的 C 解决方案 本身有许多项目 谢谢 仅选择 pch 创建者源文件 通常是 stdafx cpp 然后编译该文件 C
  • 如何从不同的线程访问控件?

    如何从创建控件的线程以外的线程访问控件 避免跨线程错误 这是我的示例代码 private void Form1 Load object sender EventArgs e Thread t new Thread foo t Start p
  • 选择initializer_list迭代器定义

    Why std initializer list
  • 从内存流播放视频文件

    只是好奇看看这是否可能 我有一个 Windows 应用程序 它从我的电脑上的 avi 文件读取所有字节 然后将其存储在 byte 中 现在我的内存中有 avi 文件 我想直接从内存将其加载到某种视频播放器控件中 我尝试过使用 wmplaye
  • QSpinBox 输入 NaN 作为有效值

    我正在尝试扩展 QSpinBox 以能够输入 NaN 或 nan 作为有效值 根据文档 我应该使用 textFromValue valueFromText 和 validate 函数来完成此操作 但我无法让它工作 因为它仍然不允许我输入除数
  • C# 中的抽象类和接口类有什么不同?

    C 中的抽象类和接口类有什么不同 An 接口不是类 它只是一个contract定义了public一个类的成员must实施 抽象类只是一个类 您从中可以cannot创建一个实例 通常您会使用它来定义一个基类 该基类定义了一些virtual方法
  • 检查两个函数或成员函数指针的签名是否相等

    我编写了一些代码来检查自由函数的签名是否等于成员函数的签名等 它比较提取的返回类型和函数参数 include
  • 从 C# 调用时无法识别 Powershell 命令

    这是这个的延续Question https stackoverflow com questions 66280000 powershell object returns null 66280138 noredirect 1 comment1
  • 应在堆栈上分配的最大数量

    我一直在寻找堆栈溢出有关应在堆栈上分配的最大内存量的指南 我看到了堆栈与堆分配的最佳实践 但没有关于应该在堆栈上分配多少以及应该在堆上分配多少的指南 有什么想法 数字可以作为指导吗 什么时候应该在堆栈上分配 什么时候应该在堆上分配 多少才算
  • 实体框架读取列但阻止其更新

    给定一个数据库表 其中有一列包含历史数据但不再填充 实体框架中是否有一种方法可以读取该列 但在使用相同的模型对象时防止它被更新 例如我有一个对象 public class MyObject public string CurrentData
  • 如果仅使用第一个元素,是否必须为整个结构分配内存?

    我有一个结构 其中第一个元素被测试 并且根据其值 结构的其余部分将被读取或不会被读取 在第一个元素的值指示结构的其余部分不会被读取的情况下 我是否必须为整个结构或仅第一个元素分配足够的内存 struct element int x int
  • 如何重用具有稍微不同的 ProcessStartInfo 实例的 Process 实例?

    我有以下开始的代码robocopy https technet microsoft com en us library cc733145 aspx as a Process 我还需要进行数据库查询以确定每次需要复制哪些目录robocopy被
  • 基础设施 - 同步和异步接口和实现? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在实现库 基础设施时 并且该 API 的用户希望同步和异步使用代码 我读到混合同步和异步并不是一个好主意 例如 同步实现包括等待异步实现 显然
  • 使用C标准数学库精确计算标准正态分布的CDF

    标准 C 数学库不提供计算标准正态分布 CDF 的函数 normcdf 然而 它确实提供了密切相关的函数 误差函数 erf 和互补误差函数 erfc 计算 CDF 的最快方法通常是通过误差函数 使用预定义常量 M SQRT1 2 来表示 d
  • 检查一个数是否是完全平方数?

    我认为以下代码存在精度问题 bool isPerfectSquare long long n long long squareRootN long long sqrt n 0 5 return squareRootN squareRootN

随机推荐