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]
}