Added other instructions to the instruction set + begun work on instructions behavior

This commit is contained in:
Elyan 2024-11-03 19:38:44 +01:00
parent 866eebd43d
commit 5a47c7eb69
9 changed files with 282 additions and 51 deletions

View File

@ -5,7 +5,9 @@ import (
"git.elyanpoujol.fr/elyan/central-arch/pkg/cpu" "git.elyanpoujol.fr/elyan/central-arch/pkg/cpu"
"git.elyanpoujol.fr/elyan/central-arch/pkg/instr" "git.elyanpoujol.fr/elyan/central-arch/pkg/instr"
"git.elyanpoujol.fr/elyan/central-arch/pkg/instrset"
"git.elyanpoujol.fr/elyan/central-arch/pkg/simcontext" "git.elyanpoujol.fr/elyan/central-arch/pkg/simcontext"
"git.elyanpoujol.fr/elyan/central-arch/pkg/siminstr"
) )
const ( const (
@ -15,12 +17,7 @@ const (
func main() { func main() {
cpu := cpu.New(simcontext.SimContext{}, nil) cpu := cpu.New(simcontext.SimContext{}, nil)
cpu.RegisterInstr(instr.InstrDesc{ cpu.RegisterInstr(siminstr.SimInstrDesc{InstrDesc: &instrset.LDRIR, Behavior: nil})
Mnemonic: "LDR",
VariantName: "LDRIR",
OpCode: 0x01,
Format: instr.A,
Formatter: func(i *instr.DecodedInstr) string { return "Hello" }})
fmt.Printf("MOV[6:0] = %#0x\n", cpu.GetOpCode(MOV_r1_r2)) fmt.Printf("MOV[6:0] = %#0x\n", cpu.GetOpCode(MOV_r1_r2))
fmt.Printf("SVC[6:0] = %#0x\n", cpu.GetOpCode(SVC_ffffff)) fmt.Printf("SVC[6:0] = %#0x\n", cpu.GetOpCode(SVC_ffffff))

View File

@ -6,8 +6,8 @@ import (
"git.elyanpoujol.fr/elyan/central-arch/pkg/breakcfg" "git.elyanpoujol.fr/elyan/central-arch/pkg/breakcfg"
"git.elyanpoujol.fr/elyan/central-arch/pkg/events" "git.elyanpoujol.fr/elyan/central-arch/pkg/events"
"git.elyanpoujol.fr/elyan/central-arch/pkg/instrset"
"git.elyanpoujol.fr/elyan/central-arch/pkg/sim" "git.elyanpoujol.fr/elyan/central-arch/pkg/sim"
"git.elyanpoujol.fr/elyan/central-arch/pkg/siminstrset"
) )
type SysoutEventLogger struct{} type SysoutEventLogger struct{}
@ -30,7 +30,7 @@ func main() {
sim := sim.New(simConfig, schedulerConfig, eventLogger) sim := sim.New(simConfig, schedulerConfig, eventLogger)
sim.RegisterInstructionSet(instrset.CentralInstructionSet) sim.RegisterInstructionSet(siminstrset.SimCentralInstructionSet[:])
/* /*
sim.QueueStateAccess(func(s simstate.SimState) { sim.QueueStateAccess(func(s simstate.SimState) {

View File

@ -4,13 +4,14 @@ import (
"log" "log"
"git.elyanpoujol.fr/elyan/central-arch/pkg/instr" "git.elyanpoujol.fr/elyan/central-arch/pkg/instr"
"git.elyanpoujol.fr/elyan/central-arch/pkg/siminstr"
) )
const instrMask = 0x7f const instrMask = 0x7f
func (cpu *Cpu) RegisterInstr(instrDesc instr.InstrDesc) { func (cpu *Cpu) RegisterInstr(desc siminstr.SimInstrDesc) {
// TODO Implement it // TODO Implement it
log.Printf("Registered: %+v\n", instrDesc) log.Printf("Registered: %s\n", desc.InstrDesc.VariantName)
} }
func (cpu *Cpu) GetOpCode(i instr.Instr) uint32 { func (cpu *Cpu) GetOpCode(i instr.Instr) uint32 {

View File

@ -2,43 +2,39 @@ package instr
import ( import (
"git.elyanpoujol.fr/elyan/central-arch/pkg/register" "git.elyanpoujol.fr/elyan/central-arch/pkg/register"
"git.elyanpoujol.fr/elyan/central-arch/pkg/simstate"
) )
type Instr uint32 type Instr uint32
type InstrFormat uint32 type InstrFormat uint32
const ( const (
A InstrFormat = iota A1 InstrFormat = iota
B A2
B1
B2
C C
D1 D1
D2 D2
E E
) )
func (instrf InstrFormat) String() string { var instrFormatNames = [...]string{
switch instrf { "A1",
case A: "A2",
return "A" "B1",
"B2",
case B: "C",
return "B" "D1",
"D2",
case C: "E",
return "C"
case D1:
return "D1"
case D2:
return "D2"
case E:
return "E"
} }
panic("unknown format") func (instrf InstrFormat) String() string {
if int(instrf) > len(instrFormatNames) {
panic("unknown instruction format")
}
return instrFormatNames[instrf]
} }
type Cond uint32 type Cond uint32
@ -63,9 +59,35 @@ const (
SLE // Signed Lower or Equal, Z==1 && N!=V SLE // Signed Lower or Equal, Z==1 && N!=V
) )
type InstrFormatter func(*DecodedInstr) string var condNames = [...]string{
"al",
"eq",
"neq",
"uge",
"cs",
"ult",
"cc",
"neg",
"pos",
"vs",
"vc",
"ugt",
"ule",
"sge",
"slt",
"sgt",
"sle",
}
type InstrBehavior func(*DecodedInstr, simstate.SimState) error func (cond Cond) String() string {
if int(cond) > len(condNames) {
panic("unknown instruction condition")
}
return condNames[cond]
}
type InstrFormatter func(*DecodedInstr) string
type InstrDesc struct { type InstrDesc struct {
VariantName string VariantName string
@ -73,7 +95,6 @@ type InstrDesc struct {
OpCode uint32 OpCode uint32
Format InstrFormat Format InstrFormat
Formatter InstrFormatter Formatter InstrFormatter
Behavior InstrBehavior
} }
type StandardFormatFields struct { type StandardFormatFields struct {
@ -92,8 +113,7 @@ type SubsystemFormatFields struct {
} }
type DecodedInstr struct { type DecodedInstr struct {
Format InstrFormat InstrDesc InstrDesc
OpCode uint32
// A, B, C, D1 and D2 formats fields // A, B, C, D1 and D2 formats fields
StandardFormatFields StandardFormatFields
// E format fields // E format fields

View File

@ -1,14 +1,129 @@
package instrset package instrset
import "git.elyanpoujol.fr/elyan/central-arch/pkg/instr" import (
"fmt"
"git.elyanpoujol.fr/elyan/central-arch/pkg/instr"
)
var CentralInstructionSet = []instr.InstrDesc{ var CentralInstructionSet = []instr.InstrDesc{
{VariantName: "NOP", Mnemonic: "nop", OpCode: 0x0, Format: instr.D2, Formatter: nil, Behavior: nil}, NOP,
{VariantName: "LDRIR", Mnemonic: "ldr", OpCode: 0x1, Format: instr.A, Formatter: nil, Behavior: nil}, SVC,
{VariantName: "LDRIRW", Mnemonic: "ldr", OpCode: 0x2, Format: instr.A, Formatter: nil, Behavior: nil}, LDRIR,
{VariantName: "LDRIOW", Mnemonic: "ldr", OpCode: 0x3, Format: instr.A, Formatter: nil, Behavior: nil}, LDRIRW,
{VariantName: "LDRR", Mnemonic: "ldr", OpCode: 0x4, Format: instr.A, Formatter: nil, Behavior: nil}, LDRIOW,
{VariantName: "LDRRW", Mnemonic: "ldr", OpCode: 0x5, Format: instr.A, Formatter: nil, Behavior: nil}, LDRR,
{VariantName: "LDROW", Mnemonic: "ldr", OpCode: 0x6, Format: instr.A, Formatter: nil, Behavior: nil}, LDRRW,
{VariantName: "SVC", Mnemonic: "svc", OpCode: 0x7f, Format: instr.D2, Formatter: nil, Behavior: nil}, LDROW,
MOVR,
MOVI,
MOVNI,
BIO,
BAIO,
BXI,
BXR,
SSR,
SSW,
}
// Miscellaneous Instructions
var NOP = instr.InstrDesc{VariantName: "NOP", Mnemonic: "nop", OpCode: 0x0, Format: instr.D2, Formatter: nopFormatter}
var SVC = instr.InstrDesc{VariantName: "SVC", Mnemonic: "svc", OpCode: 0x7f, Format: instr.D2, Formatter: svcFormatter}
// Memory-Related Instructions
// TODO Add "str" variants
var LDRIR = instr.InstrDesc{VariantName: "LDRIR", Mnemonic: "ldr", OpCode: 0x1, Format: instr.B1, Formatter: ldrirFormatter}
var LDRIRW = instr.InstrDesc{VariantName: "LDRIRW", Mnemonic: "ldr", OpCode: 0x2, Format: instr.B1, Formatter: ldrirwFormatter}
var LDRIOW = instr.InstrDesc{VariantName: "LDRIOW", Mnemonic: "ldr", OpCode: 0x3, Format: instr.B1, Formatter: ldriowFormatter}
var LDRR = instr.InstrDesc{VariantName: "LDRR", Mnemonic: "ldr", OpCode: 0x4, Format: instr.A1, Formatter: ldrrFormatter}
var LDRRW = instr.InstrDesc{VariantName: "LDRRW", Mnemonic: "ldr", OpCode: 0x5, Format: instr.A1, Formatter: ldrrwFormatter}
var LDROW = instr.InstrDesc{VariantName: "LDROW", Mnemonic: "ldr", OpCode: 0x6, Format: instr.A1, Formatter: ldrowFormatter}
// Register Manipulation Instructions
var MOVR = instr.InstrDesc{VariantName: "MOVR", Mnemonic: "mov", OpCode: 0xd, Format: instr.B1, Formatter: movrFormatter}
var MOVI = instr.InstrDesc{VariantName: "MOVI", Mnemonic: "mov", OpCode: 0xe, Format: instr.C, Formatter: moviFormatter}
var MOVNI = instr.InstrDesc{VariantName: "MOVNI", Mnemonic: "movn", OpCode: 0x13, Format: instr.C, Formatter: movniFormatter}
// Branching Instructions
var BIO = instr.InstrDesc{VariantName: "BIO", Mnemonic: "b", OpCode: 0xf, Format: instr.D1, Formatter: bioFormatter}
var BAIO = instr.InstrDesc{VariantName: "BAIO", Mnemonic: "b", OpCode: 0x10, Format: instr.D2, Formatter: baioFormatter}
var BXI = instr.InstrDesc{VariantName: "BXI", Mnemonic: "bx", OpCode: 0x11, Format: instr.B2, Formatter: bxiFormatter}
var BXR = instr.InstrDesc{VariantName: "BXR", Mnemonic: "bx", OpCode: 0x12, Format: instr.A2, Formatter: bxrFormatter}
// Subsystems Instructions
var SSR = instr.InstrDesc{VariantName: "SSR", Mnemonic: "ssr", OpCode: 0x7d, Format: instr.E, Formatter: ssrFormatter}
var SSW = instr.InstrDesc{VariantName: "SSW", Mnemonic: "ssw", OpCode: 0x7e, Format: instr.E, Formatter: sswFormatter}
func nopFormatter(i *instr.DecodedInstr) string {
return i.InstrDesc.Mnemonic
}
func svcFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s 0x%06x", i.InstrDesc.Mnemonic, i.Imm)
}
func ldrirFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, [%s, %#04x]", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Rs1, int32(i.Imm)*4)
}
func ldrirwFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, ![%s, %#04x]", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Rs1, int32(i.Imm)*4)
}
func ldriowFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, [%s, %#04x]!", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Rs1, int32(i.Imm)*4)
}
func ldrrFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, [%s, %s]", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Rs1, i.Rs2)
}
func ldrrwFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, ![%s, %s]", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Rs1, i.Rs2)
}
func ldrowFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, [%s, %s]!", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Rs1, i.Rs2)
}
func movrFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, %s", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Rs1)
}
func moviFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %s, %#04x", i.InstrDesc.Mnemonic, i.Condition, i.Rd, i.Imm)
}
func movniFormatter(i *instr.DecodedInstr) string {
val := int32(0xffff0000 + i.Imm&0xffff)
return fmt.Sprintf("%s.%s %s, %#04x", i.InstrDesc.Mnemonic, i.Condition, i.Rd, val)
}
func bioFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s %#06x", i.InstrDesc.Mnemonic, i.Condition, int32(i.Imm)*4)
}
func baioFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s %#06x", i.InstrDesc.Mnemonic, int32(i.Imm))
}
func bxiFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s [%s, %#06x]", i.InstrDesc.Mnemonic, i.Condition, i.Rs1, int32(i.Imm)*4)
}
func bxrFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s.%s [%s, %s]", i.InstrDesc.Mnemonic, i.Condition, i.Rs1, i.Rs2)
}
func ssrFormatter(i *instr.DecodedInstr) string {
return fmt.Sprintf("%s ss%d, %s, sr%d, %#02x", i.InstrDesc.Mnemonic, i.Sid, i.Reg, i.Sre, i.Cmd)
}
func sswFormatter(i *instr.DecodedInstr) string {
return ssrFormatter(i)
} }

View File

@ -12,17 +12,75 @@ const (
R5 R5
R6 R6
R7 R7
LR CpuRegister = iota + 15 RESERVED_8
RESERVED_9
RESERVED_10
RESERVED_11
RESERVED_12
RESERVED_13
RESERVED_14
RESERVED_15
RESERVED_16
RESERVED_17
RESERVED_18
RESERVED_19
RESERVED_20
RESERVED_21
RESERVED_22
LR
PC PC
SP SP
PC_USER PC_USER
SP_USER SP_USER
PC_SYS PC_SVC
SP_SYS SP_SVC
PC_FAULT PC_FAULT
SP_FAULT SP_FAULT
) )
var cpuRegisterNames = [...]string{
"r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
"reserved_8",
"reserved_9",
"reserved_10",
"reserved_11",
"reserved_12",
"reserved_13",
"reserved_14",
"reserved_15",
"reserved_16",
"reserved_17",
"reserved_18",
"reserved_19",
"reserved_20",
"reserved_21",
"reserved_22",
"lr",
"pc",
"sp",
"pc_user",
"sp_user",
"pc_svc",
"sp_svc",
"pc_fault",
"sp_fault",
}
func (r CpuRegister) String() string {
if int(r) > len(cpuRegisterNames) {
panic("unknown register")
}
return cpuRegisterNames[r]
}
// General purpose registers count // General purpose registers count
const GPR_COUNT = 8 const GPR_COUNT = 8

View File

@ -6,11 +6,11 @@ import (
"git.elyanpoujol.fr/elyan/central-arch/pkg/cache" "git.elyanpoujol.fr/elyan/central-arch/pkg/cache"
"git.elyanpoujol.fr/elyan/central-arch/pkg/cpu" "git.elyanpoujol.fr/elyan/central-arch/pkg/cpu"
"git.elyanpoujol.fr/elyan/central-arch/pkg/events" "git.elyanpoujol.fr/elyan/central-arch/pkg/events"
"git.elyanpoujol.fr/elyan/central-arch/pkg/instr"
"git.elyanpoujol.fr/elyan/central-arch/pkg/memory" "git.elyanpoujol.fr/elyan/central-arch/pkg/memory"
"git.elyanpoujol.fr/elyan/central-arch/pkg/mmu" "git.elyanpoujol.fr/elyan/central-arch/pkg/mmu"
"git.elyanpoujol.fr/elyan/central-arch/pkg/ram" "git.elyanpoujol.fr/elyan/central-arch/pkg/ram"
"git.elyanpoujol.fr/elyan/central-arch/pkg/simcontext" "git.elyanpoujol.fr/elyan/central-arch/pkg/simcontext"
"git.elyanpoujol.fr/elyan/central-arch/pkg/siminstr"
) )
type SimStatus struct { type SimStatus struct {
@ -111,7 +111,7 @@ func (s *Sim) Stop() {
} }
} }
func (s *Sim) RegisterInstructionSet(instrSet []instr.InstrDesc) { func (s *Sim) RegisterInstructionSet(instrSet []siminstr.SimInstrDesc) {
for _, instr := range instrSet { for _, instr := range instrSet {
s.cpu.RegisterInstr(instr) s.cpu.RegisterInstr(instr)
} }

13
pkg/siminstr/siminstr.go Normal file
View File

@ -0,0 +1,13 @@
package siminstr
import (
"git.elyanpoujol.fr/elyan/central-arch/pkg/instr"
"git.elyanpoujol.fr/elyan/central-arch/pkg/simstate"
)
type InstrBehavior func(*instr.DecodedInstr, simstate.SimState) error
type SimInstrDesc struct {
InstrDesc *instr.InstrDesc
Behavior InstrBehavior
}

View File

@ -0,0 +1,27 @@
package siminstrset
import (
"git.elyanpoujol.fr/elyan/central-arch/pkg/instrset"
"git.elyanpoujol.fr/elyan/central-arch/pkg/siminstr"
)
// TODO Add behaviors
var SimCentralInstructionSet = [...]siminstr.SimInstrDesc{
{InstrDesc: &instrset.NOP, Behavior: nil},
{InstrDesc: &instrset.SVC, Behavior: nil},
{InstrDesc: &instrset.LDRIR, Behavior: nil},
{InstrDesc: &instrset.LDRIRW, Behavior: nil},
{InstrDesc: &instrset.LDRIOW, Behavior: nil},
{InstrDesc: &instrset.LDRR, Behavior: nil},
{InstrDesc: &instrset.LDRRW, Behavior: nil},
{InstrDesc: &instrset.LDROW, Behavior: nil},
{InstrDesc: &instrset.MOVR, Behavior: nil},
{InstrDesc: &instrset.MOVI, Behavior: nil},
{InstrDesc: &instrset.MOVNI, Behavior: nil},
{InstrDesc: &instrset.BIO, Behavior: nil},
{InstrDesc: &instrset.BAIO, Behavior: nil},
{InstrDesc: &instrset.BXI, Behavior: nil},
{InstrDesc: &instrset.BXR, Behavior: nil},
{InstrDesc: &instrset.SSR, Behavior: nil},
{InstrDesc: &instrset.SSW, Behavior: nil},
}