# SandBox3 **Repository Path**: sandbox-lang_tree/sandbox-3 ## Basic Information - **Project Name**: SandBox3 - **Description**: “沙箱”计算机语言树相关内容,将提供长期更新和向后兼容,更多内容参见主页和readme - **Primary Language**: C++ - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: http://tech.sandbox-language.site - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2024-05-02 - **Last Updated**: 2025-04-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # “沙箱”3.x通用介绍文档 版本号规范:SandBox Label 3.a.b (a:版本号,b:类型号)
编写日期:2024.6.29 修订日期: - 2024.6.29 - 2024.7.20 - 2024.8.31 - 2024.10.10 - 2024.11.7 - 2024.11.24 *3.0.0相关定义已经转移到对应文件夹下* - 2024.12.2 - 2025.1.24 *进行了3.0.2相关指令的定义* ## 概述 “沙箱”3开始将采用统一的编号管理方法,其中第二项号码用来标记实现类型,第三项号码用来标记版本号。类型定义如下:0:处理器定义,1:汇编编译器,2:编译器IR实现,3:面向过程语言编译器,4:面向对象语言编译器,5:操作系统,6:栈结构虚拟机,16:网络协议。**“沙箱”全部版本提供向后兼容。** ## 3.0.x(标准结构处理器) 3.0.x版本对应标准结构处理器,并将在这一基础上设计汇编语言编译器和高级语言编译器。*在C++当中,处理器的功能由四类线程实现:CalcCore(计算核心)、MMU、Cache、ProcessorBus(处理器操作总线)* ### 寄存器结构定义 3.0.x版本每个处理器提供了32个64bit整型通用寄存器、32个单精度浮点寄存器和32个双精度浮点寄存器,以及一系列特殊寄存器,处理器全部寄存器设计时已启用。整型通用寄存器包含参数寄存器、返回寄存器、临时寄存器和栈指针寄存器。
整型寄存器分配为:0-7:参数寄存器,8-10:返回寄存器,11:返回地址寄存器,12:默认变址寄存器,13:默认基址寄存器,14:默认栈指针寄存器,16-31:临时寄存器。浮点寄存器分配为:0-7:参数寄存器,8-15:返回寄存器,16-31:临时寄存器。
除此之外,3.0.x特殊寄存器包含如下信息: 1. Code/ExcCode:指令指针/异常指令指针 2. Cause:异常原因 3. Status:状态寄存器 4. IE:中断使能寄存器 5. IP:中断触发寄存器 6. IDTR:中断表 7. EDTR:异常表(3.0.1及以后废弃) 8. PDTR:根页表地址 #### Status寄存器 Status寄存器包含如下信息: - 0:Zero - 1:Pos - 2:Neg - 3:OverFlow(3.0.1及以后移除) - 8:IE - 9:IT - 10:Privilege - 16:Error - 17:HALT - 18:CacheEnable - 19:TLBEnable - 20:PageEnable(3.0.1及以后) - 24:Block(3.0.2及以后) - 25:Master(3.0.2及以后) - 26:Slave(3.0.2及以后) *指令集检验在处理器中独立存放。* ### 内存结构定义 #### Cache ##### 3.0.1及以后 处理器包含两级缓存,L1分为代码和数据两个部分,L2、L3不作区分。L1、L2由物理核独占,L1指令缓存大小64KiB/Core,L1数据缓存大小128KiB/Core,L2大小256KiB/Core,L3大小4MiB。每个Cache行大小为64字节,其中L1指令Cache和L3 Cache采用直接映射,其余采用4路组相联映射,Cache集内部使用PLRU算法进行替换,Cache之间采用MESI协议保证一致性以及写标志。Cache调入时总是调入到L1,调出时逐层调出。
Cache行结构如下:*C++当中默认不实现L3 Cache* - 0-511:data - 512-515:MESI - 516-:Tag(不定长) #### 物理地址与虚拟地址*支持MMIO* 处理器支持48bit虚拟地址和48bit物理地址,其中虚拟地址分为页索引和偏移量,页大小默认4KiB。虚拟地址结构如下: - 0-11:页内偏移 - 12-20:三级页表索引 - 21-29:二级页表索引 - 30-38:一级页表索引 - 39-47:根页表索引 - 48-63:应当为0 页表项结构如下: - 0-35:页框号 - 40-43:权限(R/W/X/P) - 48:Dirty? - 49:Valid? - 50:Cache Enable? - 51:IsChild/(NotHasChild) - 52:IO/(NotRAM) 根页表寄存器负责存放当前进程的根页表地址,结构为根页表地址(64bit)。此外,MMU单元提供了最多3个页表寄存器,用于寄存当前进程的页表地址。 地址转换机构提供了总计256个直接映射快表以存储页表项信息。 ### 指令集定义 3.0.x处理器使用64bit定长精简指令集,并区分为不同的指令类型。 #### 指令分类 指令分为I(Integer)/M(Multiple)/A(Atomic)/F(Float)/V(Vector)/C(Control)六大功能类,以及R(Register)/I(Immediate)/J(Jump)/S(Special)/LI(Long Immediate,3.0.1及以后)五大格式类。 #### 指令结构(3.0.1及以后) 指令格式如下: | **Format Type** | **0-7** | **8-15** | **16-23** | **24-31** | **32-40** | **41-63** | |:----------------|:-------:|:--------:|:---------:|:---------:|:------------:|:-----------:| | R | opcode | rd | op2 | rs1 | rs2 | type | | I | opcode | rd | op2 | rs | imm\[24-31\] | imm\[0-23\] | | J | opcode | cond | op2 | rs | imm\[24-31\] | imm\[0-23\] | | S | opcode | rd | op2 | rs | imm\[24-31\] | imm\[0-23\] | | LI | opcode | rd | op2 | rs | imm\[24-31\] | imm\[0-23\] | #### 指令码内容 - Integer指令集(0x0_,3.0.1) Integer指令集是所有结构都必须实现的基本指令集,包含基本的数学和逻辑运算、位运算、内存基本读写、跳转、系统寄存器设置和系统调用功能。
指令对照如下:*全部的内存读写指令都通过`rs`提供基准地址* *Code和OP2都用十六进制表示*
*R/LI格式下指令的OP2与操作映射全部统一* - R格式(指令码范围:0-3) | **Code** | **Name** | **Op2** | **Format** | **Version** | **Usage** | |:--------:|:--------:|:-------:|:---------------:|:-----------:|:---------:| | 0 | nop | 0 | nop | 1 | none | | 1 | mov | 1 | mov rd,rs | 1 | | | 1 | neg | 2 | neg rd,rs | 1 | | | 1 | cmp | 3 | cmp rd,rs | 1 | | | 1 | iadd | 4 | iadd rd,rs1,rs2 | 1 | | | 1 | isub | 5 | isub rd,rs1,rs2 | 1 | | | 2 | uadd | 4 | uadd rd,rs1,rs2 | 1 | | | 2 | usub | 5 | usub rd,rs1,rs2 | 1 | | | 3 | not | 1 | not rd,rs | 1 | | | 3 | test | 2 | test rd,rs | 1 | | | 3 | and | 3 | and rd,rs1,rs2 | 1 | | | 3 | or | 4 | or rd,rs1,rs2 | 1 | | | 3 | xor | 5 | xor rd,rs1,rs2 | 1 | | | 3 | shl | 6 | shl rd,rs1,rs2 | 1 | | | 3 | shr | 7 | shr rd,rs1,rs2 | 1 | | | 3 | sar | 8 | sar rd,rs1,rs2 | 1 | | | 3 | rol | 9 | rol rd,rs1,rs2 | 1 | | | 3 | ror | a | ror rd,rs1,rs2 | 1 | | - LI格式(指令码范围:4-7,Res表示保留) | **Code** | **Name** | **OP2** | **Format** | **Version** | **Usage** | |:--------:|:--------:|:-------:|:-----------------:|:-----------:|:---------------------------:| | 8 | iaddi | 4 | iaddi rd,rs,imm | 1 | add rs and imm(32bit) to rd | | 8 | isubi | 5 | isubi rd,rs,imm | 1 | sub rs and imm(32bit) to rd | | 9 | set | *0xff* | set rd,*0xff*,imm | 1 | set rd to imm(32bit) | R/LI格式下OP2与指令映射关系如下: 1. Math 1. mov 2. neg 3. cmp(仅3.0.1) 4. add 5. sub 6. mul 7. div 8. mod 9. extu 10. exti 2. Logic 1. not 2. test(仅3.0.1) 3. and 4. or 5. xor 6. shl 7. shr 8. sar 9. rol 10. ror - I格式*输入输出时`LEN`最高位为1*(指令码范围:c,d) | **Code** | **Name** | **OP2** | **Format** | **Version** | **Usage** | |:--------:|:--------:|:-------:|:------------------------:|:-----------:|:----------------------------------------------------------:| | c | load | *LEN* | load len(rd),offset(rs) | 1 | load len(rd) from offset(rs),if `LEN>16` then load from IO | | d | store | *LEN* | store len(rd),offset(rs) | 1 | store len(rd) to offset(rs),if `LEN>16` then store to IO | - J格式*需要注意的是,imm采用替换方式,直接将Code低32位替换为imm*(指令码范围:e) | **Code** | **Name** | **OP2** | **Format** | **Version** | **Usage** | |:--------:|:--------:|:-------:|:------------------:|:-----------:|:---------:| | e | branch | 0 | branch cond,rs,imm | 1 | | | e | jmp | 1 | jmp imm | 1 | | | e | call | 2 | call imm | 1 | | | e | ret | 3 | ret | 1 | | - S格式(指令码范围:f) | **Code** | **Name** | **Op2** | **Format** | **Version** | **Usage** | |:--------:|:--------:|:-------:|:------------:|:-----------:|:-----------------------:| | f | trap | 1 | trap imm | 1 | calling system call | | f | iret | 8 | iret | 1 | return from trap | | f | kload | 9 | kload rd,rs | 1 | load `sreg` to `iregs` | | f | kstore | a | kstore rd,rs | 1 | store `iregs` to `sreg` | | f | flush | b | flush | 1 | refresh TLB | | f | halt | 1f | halt | 1 | stop machine | - Float指令集(0x1_,3.0.1) Float指令集功能是进行浮点计算,包括单精度和双精度两种。指令对照如下: - R格式(type由shift提供) | **Code** | **Name** | **Op2** | **Format** | **Version** | |:--------:|:--------:|:-------:|:--------------------:|:-----------:| | 11 | fmov | 1 | fmov rd,rs,type | 1 | | 11 | fneg | 2 | fneg rd,rs,type | 1 | | 11 | fcmp | 3 | fcmp rd,rs,type | 1 | | 11 | fadd | 4 | fadd rd,rs1,rs2,type | 1 | | 11 | fsub | 5 | fsub rd,rs1,rs2,type | 1 | | 11 | fmul | 6 | fmul rd,rs1,rs2,type | 1 | | 11 | fdiv | 7 | fdiv rd,rs1,rs2,type | 1 | | 13 | castf | 1 | castf rd,rs,type | 1 | | 14 | castd | 1 | castd rd,rs,type | 1 | | 15 | casti | 1 | casti rd,rs,type | 1 | - I格式 | **Code** | **Name** | **OP2** | **Format** | **Version** | |:--------:|:--------:|:-------:|:--------------------:|:-----------:| | 1c | fload | 4 | fload rd,offset(rs) | 1 | | 1d | fstore | 4 | fstore rd,offset(rs) | 1 | | 1c | dload | 8 | dload rd,offset(rs) | 1 | | 1d | dstore | 8 | dstore rd,offset(rs) | 1 | - Multiple指令集(0x2_,3.0.1) Multiple指令集功能包括:整数/小数乘除、整数的高位乘法、整数的取模运算。指令对照如下:(只有R格式指令) | **Code** | **Name** | **Op2** | **Format** | **Version** | |:--------:|:--------:|:-------:|:---------------:|:-----------:| | 21 | imul | 6 | imul rd,rs1,rs2 | 1 | | 21 | idiv | 7 | idiv rd,rs1,rs2 | 1 | | 21 | mod | 8 | mod rd,rs1,rs2 | 1 | | 22 | umul | 6 | umul rd,rs1,rs2 | 1 | | 22 | udiv | 7 | udiv rd,rs1,rs2 | 1 | | 23 | im(ul)h | 6 | imh rd,rs1,rs2 | 1 | | 23 | id(iv)h | 7 | idh rd,rs1,rs2 | 1 | | 24 | um(ul)h | 6 | umh rd,rs1,rs2 | 1 | | 24 | ud(iv)h | 7 | udh rd,rs1,rs2 | 1 | - Control指令集(0x3_,3.0.2) Control指令集功能包括:处理器之间的主从设置、寄存器设置、中断处理设置和处理器启停设置。指令对照如下:(只有R格式指令)需要额外说明的是,`mireg`和`msreg`指令负责进行寄存器不同状态之间的复制,只能在同一处理器的同一组寄存器(通用寄存器组或特殊寄存器组)之间进行复制。 | **Code** | **Name** | **Op2** | **Format** | **Version** | **Usage** | |:--------:|:--------:|:-------:|:------------------:|:-----------:|:-------------------------:| | 30 | seti | *cpuid* | seti *cpuid*,rd,rs | 2 | set `ireg` of target core | | 31 | sets | *cpuid* | sets *cpuid*,rd | 2 | set `sreg` of target core | | 33 | mireg | priv? | mireg rd,rs | 2 | move `ireg` between privs | | 37 | msreg | priv? | msreg rd,rs | 2 | move `sreg` between privs | - Atomic指令集(0x3_) - Vector指令集(0x4_) ### 中断定义 “沙箱”经典结构处理器支持中断系统,并允许对不同核心设置不同的中断状态。*需要注意的是,SandBox不支持嵌套中断。*中断标记应至少包含以下字段: | **Name** | **Position** | **Usage** | **MCause** | |:--------:|:------------:|:----------------------------:|:-----------:| | NMI | 0 | 不可屏蔽中断 | 0x00-0x0f | | CLK | 1 | 时钟中断 | 0x10 | | BREAK | 2 | 调试中断 | 0x20 | | TRAP | 3 | 陷阱中断 | 0x30-0x7f | | EXC | 8 | 异常中断 | 0x80-0x8f | | IO | 9 | IO控制器中断(启动阶段使用) | 0x90-0x9f | | INT0 | 16 | 电平型中断,高电平触发 | 0x100-0x13f | | INT1 | 20 | 电平型中断,低电平触发 | 0x140-0x17f | | EDGE0 | 24 | 跳跃型中断,上升沿触发 | 0x180-0x1bf | | EDGE1 | 28 | 跳跃型中断,下降沿触发 | 0x1c0-0x1ff | 异常标号映射如下: | **Name** | **Int Value** | **Description** | |:------------:|:-------------:|:---------------:| | DefaultError | 0x8f | 未归类的错误 | | WrongAccess | 0x80 | 无效特权级 | | PageFault | 0x81 | 缺页 | | AccessFail | 0x82 | 权限错误 | | IllegalAddr | 0x83 | 越界 | | WrongAddress | 0x84 | 无效地址 | | IllegalOP | 0x85 | 无效指令 | | IllegalVal | 0x86 | 无效操作码 | | IllegalInst | 0x87 | 指令集不支持 | | BusFault | 0x88 | 总线错误 | | DivideZero | 0x89 | 除零 | ### IO定义(3.0.2以前) “沙箱”3.0.0到3.0.1采用IO控制器来管理IO设备。
IO控制器分为以下几类:串行输入(对应于键盘)、串行输出(对应于控制台)、只读文件、只写文件、读写文件,其中串行输入和串行输出一次读写一个字节,读写文件一次读写一个页。其中,所有控制器都需要提供两个端口,偶数号端口用来传递数据,奇数号端口用来传递控制指令。
对于串行端口来说,只要设置为`READY`状态即可进行操作,通过读写端口进行读写,读写完成后端口状态自动设置为`DONE`。对于块端口(文件端口)来说,需要首先进行初始化,初始化时:`SET0`提供磁盘读写地址,`SET1`提供内存读写地址,两个都完成设置之后才能够设置为`READY`状态读写。 读写时需要使用`load`或`store`指令触发,并且不需要等待控制器返回状态码(后续可能会修复)。状态码定义如下: ```C++ enum IOSTATUS : uint8_t { READY = 0, DONE = 1, READ, WRITE, SETF = 0x10, SETM = 0x11, SETN = 0x12, GETF = 0x20, GETM = 0x21, GETN = 0x22, SHUTDOWN = 0x80, FAIL = 0xff }; ``` 需要特别说明的是,处理器的IO端口有2个进行了预分配,其中0号为串行输入,1号为串行输出。 ### IO定义(3.0.2以后) 自3.0.2开始,“沙箱”全部外接接口使用可编程IO控制器进行管理。
“沙箱”可编程IO控制器分为控制端口和数据端口,控制端口为偶数号(较小的端口号),数据端口为奇数号,不同的控制器内部逻辑可以自行实现,读写操作通过独立线程完成,触发时需要使用`store`指令向控制器写入`READY`状态,操作完成后端口状态自动设置为`DONE`,并自动上传中断信号。**需要说明的是,串行输入/串行输出每次读写一个字节,文件IO每次读写一个页,其余可自行设置,但是不多于64位(指向处理器)。**
控制器预定义枚举值如下: ```C++ enum PIOTYPE : uint8_t { NONE, SEIN = 1, SEOUT = 2, BLIN = 4, BLOUT = 8, BLIO = 12, TIMER = 16, MEMIN = 32, MEMOUT = 64 }; enum PIOSTATUS : uint16_t { DONE = 0, READY = 1, READ = 2, WRITE = 4, BUSY = 8, SET0 = 0x40, // Set Memory Address(DiskIO) SET1 = 0x50, // Set Memory Address(DiskIO) SET2 = 0x60, GET0 = 0x80, // Get Memory Address(DiskIO) GET1 = 0x90, // Get Memory Address(DiskIO) GET2 = 0xa0, BAD = 0x1000 }; ``` 处理器对IO端口的分配有6个默认端口,其中0号为串行输入,1号为串行输出,2号为磁盘控制器,3号为时钟,4号为内存块输入,5号为内存块输出。 ### 微指令控制器结构 自3.0.x开始,“沙箱”处理器将采用微指令控制器结构。微指令控制器包括以下部分: 1. 微指令寄存器(uIR) 2. 控制内存 3. 地址处理单元 4. 指向处理器内部组件的设备枚举 5. 微指令计数器(uPC) 微指令包括数据流向控制、外部读写控制、条件判定、下地址判定四个字段,每个字段依次为8位×2、8位、(8+16)位、16位。
数据流向控制分为两组,每组四位,对应源组件和目的组件。外部读写控制包括W/(!R)、IO/(!RAM)、BusRQ、Wait、RAM/(!Cache)等字段,条件判定包括外部条件判定和内部条件判定两部分,外部条件判定包括INT、NMI、Busy(总线忙)、Ready(总线准备好)四个,内部条件判定包括Priv、Check(符合跳转条件)、Error、Halt、CacheEN(Cache允许)、TLB_EN(TLB允许)、PageEN(分页允许)、Enable(指令集开放)。
下地址指令空间为0-65536,内容如下: - 0000-7eff:指令集执行阶段内容 - 7f00-7f0f:取指阶段 - 7f10-7f1f:取数阶段 - 7f20-7f2f:访存阶段 - 7f30-7f3f:写回阶段 - 7f40-7f4f:后处理阶段 - 7fe0-7fff:异常处理阶段 ## 3.1.x(汇编语言) ### 汇编语言ABI定义 “沙箱”3.1.x面向的硬件环境为“沙箱”3.0.x处理器系统,因此使用对应的ABI定义。具体定义结构如下: - arg0-arg7:参数0-7,对应REG#0-REG#7 - ret0-ret2:返回值0-2,对应REG#8-REG#10 - retaddr:返回地址,对应REG#11 - varia:变址地址,对应REG#12 - base:基地址,对应REG#13 - stack:栈地址,对应REG#14 - temp0-temp15:临时寄存器,对应REG#16-REG#31 ### 汇编语言格式定义 “沙箱”3.0.x以RISC-V语法为基础,并对部分伪操作进行修改得到,其中指令集参照前文3.0.x指令集格式。*3.8.x版本具备独立的汇编语法,另外声明。* “沙箱”3.0.x汇编提供如下伪操作内容: - `.section `:定义段,``允许如下内容: - `.text`:代码段 - `.data`:数据段 - `.bss`:未初始化数据段 - `.rodata`:只读数据段 - `.`:自定义名称的段 - `.macro `:定义宏 - `.proc `:定义过程 - `.end`:结束过程或段 - `.org `:设置起始地址(支持对过程/段/宏设置) - `.global [at ]`:定义全局变量,`at`选项提供起始地址 - `.align `:对齐到n字节(n应当为1,2,4,8) - `.byte `:定义字节 - `.2byte `:定义双字节 - `.4byte `:定义四字节 - `.8byte `:定义八字节 - `.string `:定义字符串 - `.equ `:定义常量 使用格式为`compile src.asm --version=$VER --command=$CMD [--out=$OUT]`,其中`$VER`为版本号,`$CMD`为命令行参数,`$OUT`为输出文件名。使用时,请将`$VER`对应的ABI标号和指令集对照表存放在程序目录中。 ## 3.8.x(栈结构虚拟机) ### 栈结构寄存器结构定义 “沙箱”栈结构虚拟机只提供一个程序计数器、一个标志寄存器,其余部分通过栈结构实现,栈当中存放SandObject结构体,并对结构体进行计算。SandObject包含的最基本类型为:整型(Int)、浮点(Float)、布尔值(Bool)、字符串(String)。**需要注意的是,栈结构虚拟机中不支持解释型语言,所有变量需要提前声明。** ### 栈结构指令集定义 “沙箱”栈结构虚拟机使用变长指令集,包括基本的数学和逻辑运算、位运算、内存基本读写、跳转和调用功能。
指令集格式如下: - 0-7:操作码(Code) - 8-15:操作数1(Operand1,用于指定二元运算的类型) - 16-48:操作数2(Operand2,用于指定操作数池/指令序列地址,*当且仅当Operand1=0xff时启用*) 指令码对照如下: | **Code(Hex)** | **Name** | **Format** | **Version** | |:--------------|:--------:|:------------:|:-----------:| | 0 | none | none | 1 | | 1 | binop | binop opcode | 1 | | 2 | load | load mem | 1 | | 3 | store | store mem | 1 | | 4 | jump | jump mem | 1 | | 5 | call | call mem | 1 | | 6 | ret | ret | 1 | | 11 | beq | beq mem | 1 | | 12 | blt | blt mem | 1 | | 13 | ble | ble mem | 1 | | 14 | bgt | bgt mem | 1 | | 15 | bge | bge mem | 1 | | 16 | bne | bne mem | 1 | ## 3.16.x(网络协议) “沙箱”网络协议是“沙箱”3.16.x的子系统,负责网络协议栈传输层及以上的实现。 “沙箱”网络协议通过IP数据报封装,包含独立的传输层结构和标记,并具有独立的差错控制、拥塞控制方案。