sixty-five-oh-two/README.md

80 lines
3.2 KiB
Markdown
Raw Permalink Normal View History

2018-05-26 19:20:20 +00:00
# DSL.SixtyFiveOhTwo: A 65C02 Assembly eDSL in Haskell
2018-05-26 20:51:33 +00:00
[![Hackage](https://img.shields.io/hackage/v/sixty-five-oh-two.svg)](https://hackage.haskell.org/package/sixty-five-oh-two) ![100% 65C02 Coverage](https://img.shields.io/badge/65C02%20coverage-100%25-brightgreen.svg) ![GitHub stars](https://img.shields.io/github/stars/Aearnus/sixty-five-oh-two.svg?style=social&label=Stars)
2018-05-25 08:50:04 +00:00
2018-05-26 19:49:42 +00:00
![Example image](https://raw.githubusercontent.com/Aearnus/sixty-five-oh-two/master/fancy_banner.png)
2018-05-25 08:51:32 +00:00
2018-05-25 08:50:04 +00:00
_... shut up, show me the code!_
2018-05-26 08:56:48 +00:00
Here's some example code utilizing all of the features of the eDSL:
2018-05-25 08:50:04 +00:00
```haskell
2018-05-26 20:15:02 +00:00
import DSL.SixtyFiveOhTwo
2018-05-25 08:50:04 +00:00
accumulatorLoadNStore :: Instruction
accumulatorLoadNStore = do
lda (Immediate 0x10)
sta (Absolute 0x0200)
rts (Implied)
myProgram :: Instruction
myProgram = do
define "accumulatorLoadNStore" accumulatorLoadNStore
call "accumulatorLoadNStore"
```
2018-05-26 08:56:48 +00:00
2018-05-26 19:20:20 +00:00
Here's a fun little snippet that adds 10 to the accumulator using Haskell Monad Magic:tm::
2018-05-26 08:56:48 +00:00
```haskell
test3f2 :: Instruction
test3f2 = replicateM_ 10 (inc (Accumulator))
```
2018-05-25 08:50:04 +00:00
2018-05-26 19:49:42 +00:00
Everything that this module exposes is in [src/DSL/SixtyFiveOhTwo.hs](https://github.com/Aearnus/sixty-five-oh-two/blob/master/src/DSL/SixtyFiveOhTwo.hs). A quick browse through this file will reveal the full extent of the features of this eDSL.
2018-05-26 19:20:20 +00:00
2018-05-26 19:34:04 +00:00
## What is this?
2018-05-26 19:34:36 +00:00
This is an **e**mbedded **D**omain **S**pecific **L**anguage that allows a user to write code that runs on the 65C02 CPU. This is the CPU that runs devices such as the Apple II, Commodore 64, or the NES.
2018-05-26 19:34:04 +00:00
2018-05-26 19:20:20 +00:00
## What does the language provide me?
2018-05-26 19:24:09 +00:00
* **Full coverage**. Everything bit of code that the 65C02 can understand is represented in this language. Everywhere `adc` to `wai` can be used. These opcodes are represented as generic operations, each of which simply append to the bytecode that gets passed into it. Here's an example of the definition for a certain opcode:
2018-05-26 19:20:20 +00:00
```haskell
lda :: AddressingMode -> Instruction
lda (Immediate b) = genericOp 169 b
lda (ZeroPage b) = genericOp 165 b
lda (ZeroPageX b) = genericOp 181 b
lda (Absolute b) = genericTwoByteOp 173 b
lda (AbsoluteX b) = genericTwoByteOp 189 b
lda (AbsoluteY b) = genericTwoByteOp 185 b
lda (ZeroPageIndirect b) = genericOp 178 b
lda (IndirectX b) = genericOp 161 b
lda (IndirectY b) = genericOp 177 b
```
2018-05-26 19:24:09 +00:00
* **Type safety**. Every addressing mode is represented the Haskell type system, and thus issues will be caught at compile time. The `AddressingMode` ADT is used to represent a function's addressing mode, and opcodes do not take addressing modes that they do not support.
2018-05-26 19:20:20 +00:00
```haskell
data AddressingMode =
Implied |
Accumulator |
Immediate Word8 |
Relative Int8 | -- Signed
ZeroPageRelative Int8 | -- Signed
Absolute Word16 |
AbsoluteX Word16 |
AbsoluteY Word16 |
ZeroPage Word8 |
ZeroPageX Word8 |
ZeroPageY Word8 |
ZeroPageIndirect Word8 |
Indirect Word16 |
IndirectX Word8 |
IndirectY Word8
```
2018-05-26 19:24:09 +00:00
* **Easy abstractions**. The `define` and `call` keywords automatically generate the code necessary to create and call subroutines.
2018-05-26 19:34:04 +00:00
## Support or Donate
Please contact me if you have any wish to support this project or any other projects I've worked on. The information is in `package.yaml`.