You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|ddda2c6ae9||5 years ago|
|src/DSL||5 years ago|
|test||5 years ago|
|.gitignore||5 years ago|
|ChangeLog.md||5 years ago|
|LICENSE||5 years ago|
|README.md||5 years ago|
|Setup.hs||5 years ago|
|fancy_banner.png||5 years ago|
|package.yaml||5 years ago|
|screenshot.png||5 years ago|
|stack.yaml||5 years ago|
DSL.SixtyFiveOhTwo: A 65C02 Assembly eDSL in Haskell
... shut up, show me the code!
Here's some example code utilizing all of the features of the eDSL:
import DSL.SixtyFiveOhTwo accumulatorLoadNStore :: Instruction accumulatorLoadNStore = do lda (Immediate 0x10) sta (Absolute 0x0200) rts (Implied) myProgram :: Instruction myProgram = do define "accumulatorLoadNStore" accumulatorLoadNStore call "accumulatorLoadNStore"
Here's a fun little snippet that adds 10 to the accumulator using Haskell Monad Magic™️:
test3f2 :: Instruction test3f2 = replicateM_ 10 (inc (Accumulator))
Everything that this module exposes is in src/DSL/SixtyFiveOhTwo.hs. A quick browse through this file will reveal the full extent of the features of this eDSL.
What is this?
This is an embedded Domain Specific Language 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.
What does the language provide me?
- Full coverage. Everything bit of code that the 65C02 can understand is represented in this language. Everywhere
waican 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:
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
- Type safety. Every addressing mode is represented the Haskell type system, and thus issues will be caught at compile time. The
AddressingModeADT is used to represent a function's addressing mode, and opcodes do not take addressing modes that they do not support.
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
- Easy abstractions. The
callkeywords automatically generate the code necessary to create and call subroutines.
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