Deluxe68 - A simple register allocator frontend for 68k assembly

Overview

Deluxe68

Deluxe68 is a simple (stupid) register allocator frontend for 68k assembly. It is a source to source translator, so you'll need your regular assembler to assemble its output. All is does it automate some tedious register allocation for you.

Usage

Usage is simple:

deluxe68 input.s output.s

Marking up source code

The following extensions are provided:

Allocating registers

To pull from the data register pool, use @dreg:

            @dreg   a, b, [...]
            moveq   #0,@a
            moveq   #1,@b

Similarly, @areg allocates address registers. The stack pointer is automatically reserved and will never be allocated:

            @areg   ptr
            lea     foo(pc),@ptr

Killing registers

Use @kill to return a register to the pool:

            @dreg   a
            [.. code using @a ..]
            @kill   a
            moveq   #0,@a           ; now generates an error!

Renaming an allocated register

Often in assembly programming, the purpose of a register changes. You can express that by renaming the register:

            ; @xcoordptr = x coordinate buffer

            @dreg	x0,x1
            move.w	(@xcoordptr)+,@x0
            move.w	(@xcoordptr)+,@x1
            sub.w	@x0,@x1
            @rename @x1,@deltax         ; @x1 is now no longer a coordinate 

            ; ...

            @kill x0,deltax             ; x1 is now gone, and using it will result in an error

Using allocated registers

You can subsitute @name for a register in any instruction or macro invokation. The only caveat is if the register has been spilled, in which case you'll instead get a reference to the stack which can generate a memory-to-memory instruction that doesn't assemble. In that case, rework the code.

Spilling and restoring registers

To explicitly spill a named register to the stack (returning it to the pool) you can use @spill:

            @dreg   a
            moveq   #0,@a
            @spill  a               ; a is now on stack
            ...
            ...                     ; more code involving more data register allocation
            ...
            @restore a              ; a is now back in the same register it lived in before

@spill and @restore can also work with real registers. Spilling a real register ensures that there is nothing named in that real register. This is useful when calling external code.

Reserving and unreserving registers

To reserve a real register you can use @reserve:

            @reserve d0             ; d0 is no longer available to the allocator
            moveq   #0,d0
            ...
            @unreserve d0           ; return d0 to the register allocator

Calling subroutines

When you want to call a subroutine then you typically need to place arguments in specific registers. Use @spill/@reserve pairs to prepare the registers for use, and @unreserve/@restore pairs when you are done:

            @spill  a0,d1
            @reserve a0,d1
            move.l  @foo,a0
            move.l  @bar,d1
            bsr     SomeExternalCode
            @unreserve a0,d1
            @restore a0,d1

If a0 or d1 are not allocated, the @spill/@restore operations will do nothing. The @reserve/@unreserve operations are for bookkeeping, and will generate no code.

Procedures

Mark a procedure entry point with @proc ProcedureName(<reg>: name, [<reg>: name ...]). You can also use @proc ProcedureName (that is, omitting the register-name part entirely) if your procedure has no arguments.

Doing so accomplishes two things:

  • It generates an automatic movem.l that stores all touched registers to the stack
  • All live registers are killed automatically

Similarly, instead of rts, use @endproc. This puts the inverse movem.l in place, and also emits the rts instruction.

Any registers declared in the procedure header are automatically live and not available for allocation in the procedure. You can however @kill them to return them to the pool.

Example

This input:

                    @proc   Foo(a0:ptr, d0:count)

                    @dreg   sum

                    moveq   #0,@sum
                    subq    #1,@count
    .loop           add.w   (@ptr)+,@sum
                    dbf     @count,.loop

                    move.w  @sum,d0
                    @endproc

Generates output similar to:

                    ; @proc   Foo(a0:ptr, d0:count)
                    ; live reg a0 => ptr
                    ; live reg d0 => count

    Foo:
                    movem.l d1,-(sp)

                    ; @dreg   sum
                    ; live reg d1 => sum

                    moveq   #0,d1
                    subq    #1,d0
    .loop           add.w   (a0)+,d1
                    dbf     d0,.loop

                    move.w  d1,d0
                    ; @endproc
                    movem.l (sp)+,d1
                    rts

License

This software is available under the BSD 2-clause license:

Copyright (c) 2016, Andreas Fredriksson All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

You might also like...
Shows different icons for 64 and 32-bit DLLs. Register with RegSvr32 to install

DllIconHandler This project demonstrates how to create a Shell Icon Handler, that is loaded by Explorer.exe. An icon handler can show different icons

Provenance - An iOS & tvOS Frontend for Multiple Emulators
Provenance - An iOS & tvOS Frontend for Multiple Emulators

iOS & tvOS multi-emulator frontend, supporting various Atari, Bandai, NEC, Nintendo, Sega, SNK and Sony console systems…

Writing a basic compiler frontend following  LLVM's tutorial, with complete added supports Hindi and UTF-8 in general
Writing a basic compiler frontend following LLVM's tutorial, with complete added supports Hindi and UTF-8 in general

सारस | SARAS Started with following LLVM's tutorial In development, a hobby project only JIT is broken right now, 'jit' branch par code hai uska Compi

A single header C++ wasm frontend library leveraging Emscripten
A single header C++ wasm frontend library leveraging Emscripten

Livid Livid is a single header C++ wasm frontend library leveraging Emscripten. Usage The code looks something like this: #include "livid/livid.hpp" #

Operating System Coded in Assembly and C

SimpleOS Operating System Coded in Assembly and C. Has a Virtual Filesystem, Simple Shell, GDT and IDT, and more. Planning to add networking functiona

Tails is a fast, minimal Forth-like interpreter core in C++ with no assembly

Tails is a minimal, fast Forth-like interpreter core. It uses no assembly code, only C++, but an elegant tail-recursion technique inspired by Wasm3 makes it nearly as efficient as hand-written assembly. I created it as a one-day hack to celebrate May Forth 2021 … then kept going because it's fun.

PNPASSIST: A “SMART” BUILD PLATFORM FOR MANUAL PCB ASSEMBLY

PnPAssist Description The PnPAssist is an open source innovative CNC table that position the next SMT component with a proper orientation for you to m

Assembly HellGate implementation that directly calls Windows System Calls and displays the PPID of the explorer.exe process
Assembly HellGate implementation that directly calls Windows System Calls and displays the PPID of the explorer.exe process

Custom HellsGate Implementation Assembly HellGate implementation that directly calls Windows System Calls and displays the PPID of the explorer.exe pr

Cobalt Strike User-Defined Reflective Loader written in Assembly & C for advanced evasion capabilities.
Cobalt Strike User-Defined Reflective Loader written in Assembly & C for advanced evasion capabilities.

Cobalt Strike User-Defined Reflective Loader Cobalt Strike User-Defined Reflective Loader written in Assembly & C for advanced evasion capabilities. B

Comments
  • Introduce @rename oldname,newname

    Introduce @rename oldname,newname

    Sometimes, when you write code, you load a value into a register but then you gradually mutate it to represent something else. Example:

    ; @xcoordptr = x coordinate buffer
    
    	@dreg	x0,x1
    	move.w	(@xcoordptr)+,@x0
    	move.w	(@xcoordptr)+,@x1
    	sub.w	@x0,@x1
    
    ; @x1 is now no longer a coordinate -- it would more aptly be called @dx
    

    It would be nice to be able to rename a live register using @rename oldname,newname syntax.

    opened by Kalmalyzer 1
  • @proc syntax requires at least one argument in function call

    @proc syntax requires at least one argument in function call

    Sometimes I want to declare functions which take no input arguments. I would expect one of these two syntaxes to work:

    	@proc a
    	...
    	@endproc
    

    or

    	@proc a ()
    	...
    	@endproc
    

    However, both make deluxe68 complain about syntax errors. Perhaps add support for this?

    opened by Kalmalyzer 0
  • Simple functions result in invalid movem prologue/epilogue

    Simple functions result in invalid movem prologue/epilogue

    The following code does not need to preserve any registers. Deluxe68 should not emit any movems for saving/restoring under those circumstances. Instead, deluxe68 is currently emitting syntactically incorrect movems.

    Input:

    		@proc ClearBitPlane (a0:bitplane)
    
    		movem.l d0-d1/a0-a1,-(sp)
    		move.l	#SP_BPLSIZE,d0
    		bsr	ClearMemory
    		movem.l (sp)+,d0-d1/a0-a1
    
    		@endproc
    

    Output:

    		; 		@proc ClearBitPlane (a0:bitplane)
    
    		; live reg a0 => bitplane
    ClearBitPlane:
    		movem.l ,-(sp)
    
    
    		movem.l d0-d1/a0-a1,-(sp)
    
    		move.l	#SP_BPLSIZE,d0
    
    		bsr	ClearMemory
    
    		movem.l (sp)+,d0-d1/a0-a1
    
    
    
    		; 		@endproc
    
    		movem.l (sp)+,
    		rts
    
    opened by Kalmalyzer 0
Owner
Andreas Fredriksson
Andreas Fredriksson
anthemtotheego 366 Sep 29, 2022
Register Allocator for 8086

Local Register Allocator for 8086 Table of contents What is this? Motivation Scope Basic algorithm 8086-specific approach Implementation details Resou

Alexey Frunze 66 Sep 21, 2022
Create a Jupyter Kernel for 8085 Microprocessor assembly language that can interpret assembly-level programs right from the Jupyter notebook.

Create a Jupyter Kernel for 8085 Microprocessor assembly language that can interpret assembly-level programs right from the Jupyter notebook.

Sarita Singh 5 May 11, 2022
Visual Studio extension for assembly syntax highlighting and code completion in assembly files and the disassembly window

Asm-Dude Assembly syntax highlighting and code assistance for assembly source files and the disassembly window for Visual Studio 2015, 2017 and 2019.

Henk-Jan Lebbink 4k Sep 29, 2022
A clone of the puzzle game Lights Out for the 68k Macintosh.

MacLO MacLO is a clone of the puzzle game Lights Out for the 68k Macintosh. It is a port of ArduLO for the Arduboy. MacLO is B&W and has been tested o

Jon Thysell 11 Aug 3, 2022
Simple IEEE 754 float point to register converter

i3ecnv Simple IEEE 754 float point to register converter Usage IEEE 754 converter: Type: i3ecnv <double value> Example 1 ./i3ecnv 1.2 Value DO

Fábio Pereira da Silva 1 Nov 28, 2021
This repository is to explain how the SN74HC595 register works

Register_SN74HC595 This repository is to explain how the SN74HC595 register works Aujourd’hui on va apprendre à comment augmenter le nombre de sortie

mugiwarra229 5 Jun 8, 2021
An API For the federal register!

Federal Register API This is an api that can return values from differnt endpoints in the federal register given specific inputs and values, it downlo

null 1 Oct 15, 2021
Register for Hacktoberfest and make four pull requests (PRs) between October 1st-31st to grab free SWAGS

⭐️ Projects and Codes ⭐️ This is beginner friendly repo. We aim for beginners to start with their first contributions to open-source. If you are looki

Joel Sunny Varghese 9 Sep 4, 2022