package gen import ( "fmt" "io" "math" "strings" "github.com/mmcloughlin/avo/internal/inst" ) type LoaderTest struct{} func (l LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error { p := &printer{w: w} p.printf("TEXT loadertest(SB), 0, $0\n") counts := map[string]int{} for _, i := range is { p.printf("\t// %s %s\n", i.Opcode, i.Summary) if skip, msg := l.skip(i.Opcode); skip { p.printf("\t// SKIP: %s\n", msg) counts["skip"]++ continue } for _, f := range i.Forms { as := args(f.Operands) p.printf("\t// %#v\n", f.Operands) if as == nil { p.printf("\t// TODO\n") counts["todo"]++ continue } p.printf("\t%s\t%s\n", i.Opcode, strings.Join(as, ", ")) counts["total"]++ } p.printf("\n") } p.printf("\tRET\n") for m, c := range counts { p.printf("// %s: %d\n", m, c) } return p.Err() } func (l LoaderTest) skip(opcode string) (bool, string) { prefixes := map[string]string{ "PUSH": "PUSH can produce 'unbalanced PUSH/POP' assembler error", "POP": "POP can produce 'unbalanced PUSH/POP' assembler error", } for p, m := range prefixes { if strings.HasPrefix(opcode, p) { return true, m } } return false, "" } func args(ops []inst.Operand) []string { as := make([]string, len(ops)) for i, op := range ops { a := arg(op.Type) if a == "" { return nil } as[i] = a } return as } // arg generates an argument for an operand of the given type. func arg(t string) string { m := map[string]string{ "1": "$1", // "3": "$3", // "imm2u": "$3", // "imm8": fmt.Sprintf("$%d", math.MaxInt8), // "imm16": fmt.Sprintf("$%d", math.MaxInt16), // "imm32": fmt.Sprintf("$%d", math.MaxInt32), // "imm64": fmt.Sprintf("$%d", math.MaxInt64), // "al": "AL", // "cl": "CL", // "r8": "CH", // "ax": "AX", // "r16": "SI", // "eax": "AX", // "r32": "DX", // "rax": "AX", // "r64": "R15", // "mm": "M5", // "xmm0": "X0", // "xmm": "X7", // // // "ymm": "Y13", // // // // // // // // // // // "m8": "8(AX)(CX*2)", // "m16": "16(AX)(CX*2)", // // "m32": "32(AX)(CX*2)", // // // "m64": "64(AX)(CX*2)", // // // "m128": "128(AX)(CX*2)", // // "m256": "256(AX)(CX*2)", // // // // // // // // // // // // // // // // // // // // // // // // // // // // Appear unused: "r8l": "????", // "r16l": "????", // "r32l": "????", // } return m[t] }