package asmc import ( "encoding/binary" "fmt" "math" "strings" "git.urbach.dev/cli/q/src/arm" "git.urbach.dev/cli/q/src/asm" ) func (c *compiler) compileARM(x asm.Instruction) { switch x.Mnemonic { case asm.CALL: switch x.Type { case asm.TypeLabel: label := c.assembler.Param.Label[x.Index] position := Address(len(c.code)) c.append(arm.Call(0)) pointer := &pointer{ Position: position, OpSize: 0, Size: 4, } pointer.Resolve = func() Address { destination, exists := c.codeLabels[label.Name] if !exists { panic(fmt.Sprintf("unknown jump label %s", label.Name)) } distance := (destination - position) / 4 return arm.Call(distance) } c.codePointers = append(c.codePointers, pointer) } case asm.LABEL: label := c.assembler.Param.Label[x.Index] c.codeLabels[label.Name] = Address(len(c.code)) c.append(arm.StorePair(arm.FP, arm.LR, arm.SP, -16)) c.append(arm.MoveRegisterRegister(arm.FP, arm.SP)) case asm.LOAD: switch x.Type { case asm.TypeMemoryRegister: operands := c.assembler.Param.MemoryRegister[x.Index] if operands.Address.OffsetRegister == math.MaxUint8 { c.append(arm.LoadRegister(operands.Register, operands.Address.Base, int16(operands.Address.Offset), operands.Address.Length)) } else { // TODO: LoadDynamicRegister panic("not implemented") } } case asm.MOVE: switch x.Type { case asm.TypeRegisterRegister: operands := c.assembler.Param.RegisterRegister[x.Index] c.append(arm.MoveRegisterRegister(operands.Destination, operands.Source)) case asm.TypeRegisterNumber: operands := c.assembler.Param.RegisterNumber[x.Index] c.append(arm.MoveRegisterNumber(operands.Register, operands.Number)) case asm.TypeRegisterLabel: operands := c.assembler.Param.RegisterLabel[x.Index] position := Address(len(c.code)) c.append(arm.LoadAddress(operands.Register, 0)) if strings.HasPrefix(operands.Label, "data ") { c.dataPointers = append(c.dataPointers, &pointer{ Position: position, OpSize: 0, Size: 4, Resolve: func() Address { destination, exists := c.dataLabels[operands.Label] if !exists { panic("unknown label") } destination += c.dataStart - c.codeStart distance := destination - position + 8 return arm.LoadAddress(operands.Register, int(distance)) }, }) } else { panic("not implemented") } } case asm.RETURN: c.append(arm.LoadPair(arm.FP, arm.LR, arm.SP, 16)) c.append(arm.Return()) case asm.SYSCALL: c.append(arm.Syscall()) default: panic("unknown mnemonic: " + x.Mnemonic.String()) } } func (c *compiler) append(code uint32) { c.code = binary.LittleEndian.AppendUint32(c.code, code) }