From 5a47c7eb69a3d0214cc321b2a650269af5cb38a4 Mon Sep 17 00:00:00 2001 From: Elyan Date: Sun, 3 Nov 2024 19:38:44 +0100 Subject: [PATCH] Added other instructions to the instruction set + begun work on instructions behavior --- cmd/asmtest/asmtest.go | 9 +-- cmd/simtest/main.go | 4 +- pkg/cpu/instr.go | 5 +- pkg/instr/instr.go | 74 +++++++++++------- pkg/instrset/Instrset.go | 133 ++++++++++++++++++++++++++++++--- pkg/register/register.go | 64 +++++++++++++++- pkg/sim/sim.go | 4 +- pkg/siminstr/siminstr.go | 13 ++++ pkg/siminstrset/siminstrset.go | 27 +++++++ 9 files changed, 282 insertions(+), 51 deletions(-) create mode 100644 pkg/siminstr/siminstr.go create mode 100644 pkg/siminstrset/siminstrset.go diff --git a/cmd/asmtest/asmtest.go b/cmd/asmtest/asmtest.go index f134669..3a61e7d 100644 --- a/cmd/asmtest/asmtest.go +++ b/cmd/asmtest/asmtest.go @@ -5,7 +5,9 @@ import ( "git.elyanpoujol.fr/elyan/central-arch/pkg/cpu" "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/siminstr" ) const ( @@ -15,12 +17,7 @@ const ( func main() { cpu := cpu.New(simcontext.SimContext{}, nil) - cpu.RegisterInstr(instr.InstrDesc{ - Mnemonic: "LDR", - VariantName: "LDRIR", - OpCode: 0x01, - Format: instr.A, - Formatter: func(i *instr.DecodedInstr) string { return "Hello" }}) + cpu.RegisterInstr(siminstr.SimInstrDesc{InstrDesc: &instrset.LDRIR, Behavior: nil}) fmt.Printf("MOV[6:0] = %#0x\n", cpu.GetOpCode(MOV_r1_r2)) fmt.Printf("SVC[6:0] = %#0x\n", cpu.GetOpCode(SVC_ffffff)) diff --git a/cmd/simtest/main.go b/cmd/simtest/main.go index 28c267b..e44c3f8 100644 --- a/cmd/simtest/main.go +++ b/cmd/simtest/main.go @@ -6,8 +6,8 @@ import ( "git.elyanpoujol.fr/elyan/central-arch/pkg/breakcfg" "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/siminstrset" ) type SysoutEventLogger struct{} @@ -30,7 +30,7 @@ func main() { sim := sim.New(simConfig, schedulerConfig, eventLogger) - sim.RegisterInstructionSet(instrset.CentralInstructionSet) + sim.RegisterInstructionSet(siminstrset.SimCentralInstructionSet[:]) /* sim.QueueStateAccess(func(s simstate.SimState) { diff --git a/pkg/cpu/instr.go b/pkg/cpu/instr.go index 52a13fb..6cf106d 100644 --- a/pkg/cpu/instr.go +++ b/pkg/cpu/instr.go @@ -4,13 +4,14 @@ import ( "log" "git.elyanpoujol.fr/elyan/central-arch/pkg/instr" + "git.elyanpoujol.fr/elyan/central-arch/pkg/siminstr" ) const instrMask = 0x7f -func (cpu *Cpu) RegisterInstr(instrDesc instr.InstrDesc) { +func (cpu *Cpu) RegisterInstr(desc siminstr.SimInstrDesc) { // 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 { diff --git a/pkg/instr/instr.go b/pkg/instr/instr.go index 58028d7..d655077 100644 --- a/pkg/instr/instr.go +++ b/pkg/instr/instr.go @@ -2,43 +2,39 @@ package instr import ( "git.elyanpoujol.fr/elyan/central-arch/pkg/register" - "git.elyanpoujol.fr/elyan/central-arch/pkg/simstate" ) type Instr uint32 type InstrFormat uint32 const ( - A InstrFormat = iota - B + A1 InstrFormat = iota + A2 + B1 + B2 C D1 D2 E ) +var instrFormatNames = [...]string{ + "A1", + "A2", + "B1", + "B2", + "C", + "D1", + "D2", + "E", +} + func (instrf InstrFormat) String() string { - switch instrf { - case A: - return "A" - - case B: - return "B" - - case C: - return "C" - - case D1: - return "D1" - - case D2: - return "D2" - - case E: - return "E" + if int(instrf) > len(instrFormatNames) { + panic("unknown instruction format") } - panic("unknown format") + return instrFormatNames[instrf] } type Cond uint32 @@ -63,9 +59,35 @@ const ( 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 { VariantName string @@ -73,7 +95,6 @@ type InstrDesc struct { OpCode uint32 Format InstrFormat Formatter InstrFormatter - Behavior InstrBehavior } type StandardFormatFields struct { @@ -92,8 +113,7 @@ type SubsystemFormatFields struct { } type DecodedInstr struct { - Format InstrFormat - OpCode uint32 + InstrDesc InstrDesc // A, B, C, D1 and D2 formats fields StandardFormatFields // E format fields diff --git a/pkg/instrset/Instrset.go b/pkg/instrset/Instrset.go index d7e1de1..e64b1ba 100644 --- a/pkg/instrset/Instrset.go +++ b/pkg/instrset/Instrset.go @@ -1,14 +1,129 @@ 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{ - {VariantName: "NOP", Mnemonic: "nop", OpCode: 0x0, Format: instr.D2, Formatter: nil, Behavior: nil}, - {VariantName: "LDRIR", Mnemonic: "ldr", OpCode: 0x1, Format: instr.A, Formatter: nil, Behavior: nil}, - {VariantName: "LDRIRW", Mnemonic: "ldr", OpCode: 0x2, Format: instr.A, Formatter: nil, Behavior: nil}, - {VariantName: "LDRIOW", Mnemonic: "ldr", OpCode: 0x3, Format: instr.A, Formatter: nil, Behavior: nil}, - {VariantName: "LDRR", Mnemonic: "ldr", OpCode: 0x4, Format: instr.A, Formatter: nil, Behavior: nil}, - {VariantName: "LDRRW", Mnemonic: "ldr", OpCode: 0x5, Format: instr.A, Formatter: nil, Behavior: nil}, - {VariantName: "LDROW", Mnemonic: "ldr", OpCode: 0x6, Format: instr.A, Formatter: nil, Behavior: nil}, - {VariantName: "SVC", Mnemonic: "svc", OpCode: 0x7f, Format: instr.D2, Formatter: nil, Behavior: nil}, + NOP, + SVC, + LDRIR, + LDRIRW, + LDRIOW, + LDRR, + LDRRW, + 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) } diff --git a/pkg/register/register.go b/pkg/register/register.go index f80ed88..053505c 100644 --- a/pkg/register/register.go +++ b/pkg/register/register.go @@ -12,17 +12,75 @@ const ( R5 R6 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 SP PC_USER SP_USER - PC_SYS - SP_SYS + PC_SVC + SP_SVC PC_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 const GPR_COUNT = 8 diff --git a/pkg/sim/sim.go b/pkg/sim/sim.go index acee490..e2c053b 100644 --- a/pkg/sim/sim.go +++ b/pkg/sim/sim.go @@ -6,11 +6,11 @@ import ( "git.elyanpoujol.fr/elyan/central-arch/pkg/cache" "git.elyanpoujol.fr/elyan/central-arch/pkg/cpu" "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/mmu" "git.elyanpoujol.fr/elyan/central-arch/pkg/ram" "git.elyanpoujol.fr/elyan/central-arch/pkg/simcontext" + "git.elyanpoujol.fr/elyan/central-arch/pkg/siminstr" ) 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 { s.cpu.RegisterInstr(instr) } diff --git a/pkg/siminstr/siminstr.go b/pkg/siminstr/siminstr.go new file mode 100644 index 0000000..b2800f6 --- /dev/null +++ b/pkg/siminstr/siminstr.go @@ -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 +} diff --git a/pkg/siminstrset/siminstrset.go b/pkg/siminstrset/siminstrset.go new file mode 100644 index 0000000..a272d2a --- /dev/null +++ b/pkg/siminstrset/siminstrset.go @@ -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}, +}