Hardware 为LLVM/CLANG选择CPU体系结构 我正在设计TTL串行计算机,我在选择更适合LLVM编译器后端的体系结构方面很困难(我想在那里运行任何C++软件)。没有MMU,没有乘法/除法,没有硬件堆栈,没有中断

Hardware 为LLVM/CLANG选择CPU体系结构 我正在设计TTL串行计算机,我在选择更适合LLVM编译器后端的体系结构方面很困难(我想在那里运行任何C++软件)。没有MMU,没有乘法/除法,没有硬件堆栈,没有中断,hardware,cpu,llvm,clang,Hardware,Cpu,Llvm,Clang,我有两个主要选择: 1) 8位内存、8位ALU、8位寄存器(~12-16)。内存地址宽度为24位。所以我需要使用3个寄存器作为IP,3个寄存器用于任何内存位置 不用说,在编译器中实现任何地址计算都是一件痛苦的事情 2) 24位内存、24位ALU、24位寄存器(~6-8)。平坦的内存,很好。缺点是,由于设计的串行性,每个操作将需要3个时钟,即使我们在一些布尔运算。24位内存数据宽度非常昂贵。而且一般来说,在硬件中实现起来比较困难 问题是:你认为在这个8位、基于栈的硬件上实现所有的C++特性是可能

我有两个主要选择:

1) 8位内存、8位ALU、8位寄存器(~12-16)。内存地址宽度为24位。所以我需要使用3个寄存器作为IP,3个寄存器用于任何内存位置

不用说,在编译器中实现任何地址计算都是一件痛苦的事情

2) 24位内存、24位ALU、24位寄存器(~6-8)。平坦的内存,很好。缺点是,由于设计的串行性,每个操作将需要3个时钟,即使我们在一些布尔运算。24位内存数据宽度非常昂贵。而且一般来说,在硬件中实现起来比较困难



问题是:你认为在这个8位、基于栈的硬件上实现所有的C++特性是可能的,或者我需要更复杂的硬件来生成合理的质量和速度的代码?

< P>。我认为,无栈硬件已经不适合C和C++代码。如果您有嵌套函数调用,那么无论如何都需要在软件中模拟堆栈,这当然要慢得多

当采用无堆栈路径时,您可能会将大部分变量分配为“静态”,并且没有可重入函数。在这种情况下,6502样式的寻址模式是有效的。例如,您可以使用以下寻址模式:

  • 立即地址(24位)作为操作码的一部分
  • 立即地址(24位)加索引寄存器(8位)
  • 间接访问:内存的即时24位地址,包含实际地址
  • 间接访问:24位内存地址,8位索引寄存器添加到内存值
  • 上述地址模式将允许高效访问以恒定地址分配的数组、结构和对象(静态分配)。对于动态和堆栈分配的对象,它们的效率较低(但仍然可用)

    您还可以从串行设计中获得一些好处:通常24位+8位加法不需要24个周期,但当进位为0时,您可以将加法短路

    与直接将IP映射为寄存器不同,您可以只允许通过goto/branch指令,使用与上面相同的地址模式对其进行更改。跳转到动态计算的地址非常罕见,因此直接在操作码中给出整个24位地址更有意义


    我认为如果你仔细设计CPU,你可以非常有效地使用许多C++特性。但是,不要期望任何一个随机的C++代码在这样一个有限的CPU上运行得很快。

    < P>实现是可能的,但是我怀疑它是可用的(在C++代码中)。正如已经指出的,第一个问题是缺少堆栈。其次,C++的一部分依赖于动态内存分配,C++内部结构也相当大。 因此,在我看来,如果你:

  • 去掉C++的要求(或者至少限制你自己的一些子集)
  • 全部使用24位,而不是8位(同样适用于寄存器)
  • 添加硬件堆栈

  • 嗯,这对于c编译器来说是可能的。不过,对于C++,我不确定。 LLVM/CLang可能是8位计算机的艰难选择

    相反,先试试,然后再试试llvm/etc,HTH

    Bill Buzbee成功地为他的Magic-1(称为)重新定位lcc编译器

    虽然Magic-1的硬件设计和构建通常最受关注,但项目的最大部分(到目前为止)是开发/移植软件。为此,我不得不从头开始编写汇编程序和链接器,重新定位C编译器,编写并移植标准C库,编写简化的操作系统,然后移植更复杂的操作系统。这是一个挑战,但很有趣。我想我有点扭曲,但我碰巧喜欢调试困难的问题。而且,当您试图追踪的错误可能涉及一个或多个:硬件设计缺陷、松动或断开的电线、松动或坏的TTL芯片、汇编程序错误、链接器错误、编译器错误、C运行时库错误,或者最后是相关程序中的一个错误时,会有很多有趣的机会。哦,而且我也没有把臭虫怪罪于其他人的奢侈


    我一直很惊讶这该死的东西居然能跑,更不用说跑得那么好了。

    我赞成使用LCC的建议。我在这个自制的16位RISC项目中使用了它:

    我认为,无论是构建8位变体并使用3个带进位的加法来增加IP,还是构建24位变体并在硬件中完成全部工作,都不会有太大区别。您可以在汇编程序中隐藏差异

    如果你看看我上面的文章,或者这里更简单的CPU:你会发现你真的不需要那么多的操作符/指令来覆盖整数C重复。事实上,有一个lcc实用程序(ops)可以打印给定机器的最小操作员集

    有关更多信息,请参阅我的文章“将lcc移植到新机器上”:

    一旦我移植了lcc,我就编写了一个汇编程序,它从基本指令合成了更多的指令。例如,我的机器的加载字节没有签名,但没有加载字节签名,因此我发出以下序列:

    lbs rd,imm(rs) ->
      lbu rd,imm(rs)
      lea r1,0x80
      xor rd,r1
      sub rd,r1
    
    因此,我认为你可以通过这本运营手册:

      registers
      load register with constant
      load rd = *rs
      store *rs1 = rs2
      + - (w/ w/o carry)    // actually can to + with - and ^
      >> 1                  // << 1 is just +
      & ^                   // (synthesize ~ from ^, | from & and ^)
      jump-and-link rd,rs   // rd = pc, pc = rs
      skip-z/nz/n/nn rs     // skip next insn on rs==0, !=0, <0, >=0
    
    寄存器
    带常数的加载寄存器
    加载rd=*rs
    存储*rs1=rs2
    +-(带/不带进位)//实际上可以通过-和^
    
    > 1//p>你不能在那里运行“任何”C++代码。例如fork()、system()等。例如,任何明显依赖于中断的东西。当然,你可以走很长的路。 你指的是那些可以/已经被执行的程序吗