initial commit

forgot to start a git repo, so i've gotten plenty of stuff done
master
Drake 2 years ago
commit dcc4ae1ecd

@ -0,0 +1,14 @@
code = """
;comment parsing test
IRX ;increment RAX
IRY ;increment RAY
DBG ;RAX=1,RAY=1
LDX $00
LDY #AF
STY $FFFF
DBG ;RAY=175,0xFFFF=175
"""

@ -0,0 +1,87 @@
#the closest thing to writing raw ASM
import re
code = """LOL 01 010f
LOL 01 0113
LOL 01 0115
LOL 01 0117
LOL 00 0117
JML 0000
DBG"""
out = """#include <stdint.h>
int8_t PRG_BIN[] = {
"""
def writeHex(str):
global out
out += f"{str}, "
count = 1
for i in re.split("\n| ",code):
match i:
case "INC":
writeHex("0x01")
case "IRA":
writeHex("0x02")
case "IRX":
writeHex("0x03")
case "IRY":
writeHex("0x04")
case "DNC":
writeHex("0x05")
case "DCA":
writeHex("0x06")
case "DCX":
writeHex("0x07")
case "DCY":
writeHex("0x07")
case "JEA":
writeHex("0x10")
case "JER":
writeHex("0x11")
case "JML":
writeHex("0x1A")
case "JMA":
writeHex("0x1B")
case "LXA":
writeHex("0x20")
case "LXL":
writeHex("0x21")
case "LYA":
writeHex("0x22")
case "LYL":
writeHex("0x23")
case "LAA":
writeHex("0x24")
case "LAL":
writeHex("0x25")
case "LOA":
writeHex("0x26")
case "LOL":
writeHex("0x27")
case "STX":
writeHex("0x2A")
case "STY":
writeHex("0x2B")
case "STA":
writeHex("0x2C")
case "DBG":
writeHex("0xFF")
case other:
if len(i) == 4: #assume memory address
writeHex(f"0x{i[0]+i[1]}")
writeHex(f"0x{i[2]+i[3]}")
elif len(i) == 2:
writeHex(f"0x{i}")
else:
writeHex("0x00")
count+=1
out = out.rstrip(", ")
out += f""", 0xFC
}};
int PRG_LEN = {count};
"""
print(out)

@ -0,0 +1,93 @@
#reads TESM code, outputs rawASM
code = """vput 1 0
vput 1 4
vput 1 6
prnt
jmp 0
dump"""
OFFSET = 0x00FF #how far into memory should we store TESM memory banks
prc = 0
hist = []
def intToHex(addr, video=False):
addr = int(addr)
if video:
if addr > 7:
return OFFSET+16+7 #clamp value
return OFFSET+16+addr
else:
if addr > 15:
return OFFSET+15 #clamp value
return OFFSET+addr
def hexstr(integer, len=2, inc=True):
global prc
if inc:
prc+=int(len/2)
return "{0:0{1}x}".format(integer, len)
for line in code.split("\n"):
inst = line.split(" ")
match inst[0]:
case "put":
hist.append(prc)
print(f"LOL {hexstr(int(inst[1]))} {hexstr(intToHex(inst[2]), 4)}")
prc+=1
case "vput":
hist.append(prc)
print(f"LOL {hexstr(int(inst[1]))} {hexstr(intToHex(inst[2], True), 4)}")
prc+=1
case "equl":
hist.append(prc)
arg1 = hexstr(intToHex(inst[1]), 4)
arg2 = hexstr(intToHex(inst[2]), 4)
arg3 = hexstr(intToHex(inst[3]), 4)
print(f"""JEA {arg1} {arg2} {hexstr(prc+5,4,False)}
JML {hexstr(prc+9,4,False)}
LOL {hexstr(1,2,False)} {arg3}""")
prc+=8
case "vequl":
hist.append(prc)
arg1 = hexstr(intToHex(inst[1], True), 4)
arg2 = hexstr(intToHex(inst[2], True), 4)
arg3 = hexstr(intToHex(inst[3], True), 4)
print(f"""JEA {arg1} {arg2} {hexstr(prc+5,4,False)}
JML {hexstr(prc+9,4,False)}
LOL {hexstr(1,2,False)} {arg3}""")
prc+=8
case "cpy":
hist.append(prc)
arg1 = hexstr(intToHex(inst[1]), 4)
arg2 = hexstr(intToHex(inst[2], True), 4)
print(f"""LOA {arg1} {arg2}""")
prc+=5
case "mov":
hist.append(prc)
arg1 = hexstr(intToHex(inst[1]), 4)
arg2 = hexstr(intToHex(inst[2], True), 4)
print(f"""LOA {arg1} {arg2}
LOL {hexstr(0,2,False)} {arg1}""")
prc+=9
case "prnt":
hist.append(prc)
print(f"""LOL 01 0117
LOL 00 0117""")
prc+=7
case "jmp":
hist.append(prc)
print(f"""JML {hexstr(hist[int(inst[1])],4,False)}""")
prc+=3
case "dump":
hist.append(prc)
print("DBG")
prc+=1
case "vdump":
hist.append(prc)
print("DBG")
prc+=1
case other:
hist.append(prc)
print("NOP")
prc+=1

1
emu/.gitignore vendored

@ -0,0 +1 @@
bin/

@ -0,0 +1,3 @@
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

@ -0,0 +1,28 @@
CC ?= gcc
target ?= $(shell ${CC} -dumpmachine)
CC_FLAGS ?=
CC_FLAGS := ${CC_FLAGS} -Ilib
DESTDIR ?= /
.PHONY: all debug clean build-release install
all:
@$(shell mkdir -p bin)
all: main
main:
@${CC} -o bin/main src/main.c ${CC_FLAGS}
debug: CC_FLAGS:=-g -O0 -v -fsanitize=undefined -fsanitize=address ${CC_FLAGS}
debug: all
clean:
@rm -rf bin
release: CC_FLAGS:=-O3 ${CC_FLAGS}
release: all
release:
@strip bin/*
tar -czf release.tar.gz bin/*
install:
@install -m 777 bin/main ${DESTDIR}/usr/local/bin

@ -0,0 +1,2 @@
-Ilib
-DDRAKECU_VERSION="placeholder"

Binary file not shown.

@ -0,0 +1,42 @@
;THIS SUBROUTINE ARRANGES THE 8-BIT ELEMENTS OF A LIST IN ASCENDING
;ORDER. THE STARTING ADDRESS OF THE LIST IS IN LOCATIONS $30 AND
;$31. THE LENGTH OF THE LIST IS IN THE FIRST BYTE OF THE LIST. LOCATION
;$32 IS USED TO HOLD AN EXCHANGE FLAG.
lda #$05
sta $30
sta $33
lda #$A4
sta $34
lda #$07
sta $35
lda #$F6
sta $36
lda #$44
lda $37
SORT8 ldy #$00 ;TURN EXCHANGE FLAG OFF (= 0)
sty $32
lda ($30),Y ;FETCH ELEMENT COUNT
tax ; AND PUT IT INTO X
iny ;POINT TO FIRST ELEMENT IN LIST
dex ;DECREMENT ELEMENT COUNT
NXTEL lda ($30),Y ;FETCH ELEMENT
iny
cmp ($30),Y ;IS IT LARGER THAN THE NEXT ELEMENT?
bcc CHKEND
beq CHKEND
;YES. EXCHANGE ELEMENTS IN MEMORY
pha ; BY SAVING LOW BYTE ON STACK.
lda ($30),Y ; THEN GET HIGH BYTE AND
dey ; STORE IT AT LOW ADDRESS
sta ($30),Y
pla ;PULL LOW BYTE FROM STACK
iny ; AND STORE IT AT HIGH ADDRESS
sta ($30),Y
lda #$FF ;TURN EXCHANGE FLAG ON (= -1)
sta $32
CHKEND dex ;END OF LIST?
bne NXTEL ;NO. FETCH NEXT ELEMENT
bit $32 ;YES. EXCHANGE FLAG STILL OFF?
bmi SORT8 ;NO. GO THROUGH LIST AGAIN
rts ;YES. LIST IS NOW ORDERED

@ -0,0 +1,4 @@
inc $00E7
inc $0001
inx
iny

@ -0,0 +1,8 @@
#!/bin/sh
mkdir -p bin
for i in *.asm
do
xa -v -o bin/`echo $i | sed "s/.asm/.bin/g"` -l bin/`echo $i | sed "s/.asm/.lst/g"` $i
done

@ -0,0 +1,27 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
uint8_t memory[0xFFFF + 1]; //16kib memory (probably)
//0x0000 - 0x00FF is Zero Paged
//0x0100 - 0x01FF is system stack
uint16_t prc = 0; //16bit program counter
uint8_t spt = 0; //8bit stack pointer
uint8_t acc = 0; //8bit accumulator
uint8_t irx,iry = 0; //2 8bit index registers
struct status {
bool carry; //carry flag
bool zero; //zero flag
bool ird; //interrupt disable flag
bool dec; //decimal mode flag for arithmetic
bool brk; //break bit
bool overflow; //overflow flag
bool neg; //negative flag
};
struct status cpuStatus;

@ -0,0 +1,6 @@
#include <stdint.h>
int8_t PRG_BIN[] = {
0x27, 0x01, 0x01, 0x0f, 0x27, 0x01, 0x01, 0x13, 0x27, 0x01, 0x01, 0x15, 0x27, 0x01, 0x01, 0x17, 0x27, 0x00, 0x01, 0x17, 0x1A, 0x00, 0x00, 0xFF, 0xFC
};
int PRG_LEN = 19;

@ -0,0 +1,147 @@
#include "constants.h"
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
void memview() {
for (int i = 0x00; i <= 0xFFFF; i++) {
if (memory[i] != 0x00) {
printf("Mem Address 0x%04X: 0x%04X\n", i, memory[i]);
}
}
printf("rax - %d\n", irx);
printf("ray - %d\n", iry);
printf("acc - %d\n", acc);
printf("prc - %d\n", prc);
}
int emulate(uint8_t exec[], int size, uint8_t addr) {
//uint8_t* program = (uint8_t*)exec;
/*for (int i = addr, i2=0; i < size+addr; i++) {
memory[i] = exec[i2];
i2++;
}*/ //not needed: LRIS has separate prgrom
while (prc < UINT16_MAX) { //FIXME: this can cause a vuln where you can at least read OOB memory (jumping past the 0xFC)
uint8_t inst = exec[prc];
switch (inst) {
case 0x00: //NOP
break;
case 0x03: //INC RX
irx++;
break;
case 0x04: //INC RY
iry++;
break;
case 0x10: { //A/L JIE
uint8_t upper = exec[++prc];
uint8_t lower = exec[++prc];
uint16_t addr1 = 256U*upper+lower;
upper = exec[++prc];
lower = exec[++prc];
uint16_t addr2 = 256U*upper+lower;
upper = exec[++prc];
lower = exec[++prc];
uint16_t newPRC = 256U*upper+lower;
if (memory[addr1] == memory[addr2]) {
prc = newPRC-1; //we need to account for the prc++ at the end of the loop
} else { /* DO NOTHING */ }
break;
}
case 0x1A: { //LITERAL JMP
uint8_t upper = exec[++prc];
uint8_t lower = exec[++prc];
uint16_t addr = 256U*upper+lower;
prc = memory[addr]-1;
break;
}
case 0x20: { //ABSOLUTE LDX
uint8_t upper = exec[++prc];
uint8_t lower = exec[++prc];
uint16_t addr = 256U*upper+lower;
irx = memory[addr];
break;
}
case 0x23: { //LITERAL LDY
uint8_t val = exec[++prc];
iry = val;
break;
}
case 0x26: { //ABSOLUTE LOD
uint8_t upper = exec[++prc];
uint8_t lower = exec[++prc];
uint16_t addr1 = 256U*upper+lower;
upper = exec[++prc];
lower = exec[++prc];
uint16_t addr2 = 256U*upper+lower;
memory[addr2] = memory[addr1];
break;
}
case 0x27: { //LITERAL LOD
uint8_t val = exec[++prc];
uint8_t upper = exec[++prc];
uint8_t lower = exec[++prc];
uint16_t addr = 256U*upper+lower;
memory[addr] = val;
break;
}
case 0x2B: { //STY
uint8_t upper = exec[++prc];
uint8_t lower = exec[++prc];
uint16_t addr = 256U*upper+lower;
memory[addr] = iry;
break;
}
case 0x50:
acc = ~(irx & iry);
case 0xFC:
_exit(0);
case 0xFF:
memview();
break;
default:
printf("Opcode 0x%02X\n not implemented!\n", inst);
memview();
_exit(0);
}
//printf("Ran inst 0x%02X\n", inst);
//memview();
prc++;
if (memory[0x010F+8]) {
int charcode = 0;
if (memory[0x010F]) {
charcode += 64;
//printf("%d\n", charcode);
}
if (memory[0x0110]) {
charcode += 32;
//printf("%d\n", charcode);
}
if (memory[0x0111]) {
charcode += 16;
//printf("%d\n", charcode);
}
if (memory[0x0112]) {
charcode += 8;
//printf("%d\n", charcode);
}
if (memory[0x0113]) {
charcode += 4;
//printf("%d\n", charcode);
}
if (memory[0x0114]) {
charcode += 2;
//printf("%d\n", charcode);
}
if (memory[0x0115]) {
charcode += 1;
//printf("%d\n", charcode);
}
printf("%c%c", charcode, memory[0x0116] ? '\n' : 0x0);
}
}
printf("out of length");
return 0;
}

@ -0,0 +1,85 @@
#include "constants.h"
#include "file.h"
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <getopt.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <stdlib.h>
#include "emu.c"
uint16_t* fileRead(char* name) {
FILE* fp = fopen(name, "rb");
if (!(access(name, F_OK) == 0)) {
errno = -1;
printf("Hi?\n");
return 0;
}
struct stat st;
stat(name, &st);
int length = st.st_size;
uint16_t rbuf[length+1];
for (int i = 0; i < length; i++) {
fread(&rbuf[i], 2, 1, fp);
}
fclose(fp);
uint16_t* tmp = rbuf;
return tmp;
}
//blanks out memory and initializes various things
int init() {
for (int i = 0; i <= 0xFFFF; i++) { //blank memory
memory[i] = 0x00;
}
cpuStatus.brk = 0;
cpuStatus.carry = 0;
cpuStatus.dec = 0;
cpuStatus.ird = 0;
cpuStatus.neg = 0;
cpuStatus.overflow = 0;
cpuStatus.zero = 0;
return 0;
}
void help(char* exe) {
printf("%s - a 6502 emulator.\n"
" Usage: %s [prg]", exe, exe);
}
int main(int argc, char* argv[]) {
char* filename = *++argv; //TODO: jankiest thing ever
/*uint16_t* binary = (uint16_t*)fileRead(filename);
//uint16_t binary[] = {0xe7e6, 0xeaea, 0x01e6, 0xe8ea, 0xc8ea, 0x00ea};
int size = sizeof(binary)/sizeof(binary[0])+1;
uint8_t exec[size*2];
for (int i,i2 = 0; i < size-1; i++) {
printf("%04X\n", binary[i]);
uint8_t lsb = (binary[i] & 0xFF);
uint8_t hsb = (binary[i] & 0xFF00) >> 8;
exec[i2] = lsb;
exec[++i2] = hsb;
i2++;
}*/
uint8_t* exec = (uint8_t*)PRG_BIN;
int size = PRG_LEN;
printf("Program ROM:\n");
for (int i = 0; i < size; i++) {
printf("0x%02X\n", exec[i]);
}
emulate(exec, size, 0x0400); //hacky lol
return 0;
}

@ -0,0 +1,481 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title></title></head><body><h2>LRIS CPU/ASM specification (wip)</h2>
<p><del>shamelessly ripped off</del> very inspired by 6502 because its the only thing i kinda know</p>
<h3>Registers</h3>
<table>
<thead>
<tr>
<th>Register</th>
<th>Purpose</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>ACC</td>
<td>Stores the result of any calculation opcodes (if in ACC mode)</td>
<td>1 byte</td>
</tr>
<tr>
<td>RAX</td>
<td>General purpose register</td>
<td>1 byte</td>
</tr>
<tr>
<td>RAY</td>
<td>General purpose register</td>
<td>1 byte</td>
</tr>
</tbody>
</table>
<h3>Memory</h3>
<ul>
<li>Up to 64kib of RAM</li>
<li>Up to 64kib of Program ROM</li>
</ul>
<h3>Addressing Modes</h3>
<h4>Absolute</h4>
<p>Directly reads from a 2 byte memory address with instruction.</p>
<pre><code>LDX $0A2F
</code></pre>
<p><sub><sup>Note: 1 byte addresses should be padded by the assembler.</sup></sub></p>
<h4>Literal</h4>
<p>Uses a literal byte, in place of reading from a memory address.</p>
<pre><code>LDX #0A2F
</code></pre>
<p><sub><sup>Note: 1 byte addresses should be padded by the assembler.</sup></sub></p>
<h3>Opcodes</h3>
<p>NOTE: these do not specify a higher level assembly langauge, only the opcodes interpreted by the CPU itself (ie there cannot be 3 increments for the different registers that all use <code>INC</code>)</p>
<h4>NOP- No Operation</h4>
<p>seriously?</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>N/A</td>
<td>NOP</td>
<td><code>$00</code></td>
<td>1 byte</td>
</tr>
</tbody>
</table>
<h4>INC - Increment</h4>
<p>what do you think it does</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Increments the value at specified memory address</td>
<td><code>$01</code></td>
<td>3 bytes</td>
</tr>
<tr>
<td>Accumulator</td>
<td>Increments the accumulator</td>
<td><code>$02</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>RX</td>
<td>Increments the RAX register</td>
<td><code>$03</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>RY</td>
<td>Increments the RAY register</td>
<td><code>$04</code></td>
<td>1 byte</td>
</tr>
</tbody>
</table>
<h4>DNC - Decrement</h4>
<p>what do you think it does (pt. 2)</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Decrements the value at specified memory address</td>
<td><code>$05</code></td>
<td>3 bytes</td>
</tr>
<tr>
<td>Accumulator</td>
<td>Decrements the accumulator</td>
<td><code>$06</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>RX</td>
<td>Decrements the RAX register</td>
<td><code>$07</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>RY</td>
<td>Decrements the RAY register</td>
<td><code>$08</code></td>
<td>1 byte</td>
</tr>
</tbody>
</table>
<h4>JIE - Jump If Equal</h4>
<p>jumps if something is equal to other something</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute/Literal</td>
<td>Sets PRC to value if memory address is equal to other memory address</td>
<td><code>$10</code></td>
<td>7 bytes</td>
</tr>
<tr>
<td>Register/Literal</td>
<td>Sets PRC to value if RAX and RAY are equal</td>
<td><code>$11</code></td>
<td>1 byte</td>
</tr>
</tbody>
</table>
<h4>JMP - Jump</h4>
<p>jumps unconditionally</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Literal</td>
<td>Sets PRC to a literal value</td>
<td><code>$1A</code></td>
<td>3 bytes</td>
</tr>
<tr>
<td>Absolute</td>
<td>Sets PRC to the value of a byte in memory</td>
<td><code>$1B</code></td>
<td>3 bytes</td>
</tr>
</tbody>
</table>
<h5>Example:</h5>
<pre><code>;OP PRC ADDR ADDR
JIE 0x00A2 0x0013 0x0014
</code></pre>
<h4>LDX - Load [RA]X</h4>
<p>loads a value into RAX</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Loads the value of another byte of memory into RAX</td>
<td><code>$20</code></td>
<td>3 bytes</td>
</tr>
<tr>
<td>Literal</td>
<td>Loads a literal byte into RAX</td>
<td><code>$21</code></td>
<td>2 bytes</td>
</tr>
</tbody>
</table>
<h4>LDX - Load [RA]Y</h4>
<p>loads a value into RAY</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Loads the value of another byte of memory into RAY</td>
<td><code>$22</code></td>
<td>3 bytes</td>
</tr>
<tr>
<td>Literal</td>
<td>Loads a literal byte into RAY</td>
<td><code>$23</code></td>
<td>2 bytes</td>
</tr>
</tbody>
</table>
<h4>LDA - Load A(ccumulator)</h4>
<p>loads a value into the accumulator</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Loads the value of another byte of memory into ACC</td>
<td><code>$24</code></td>
<td>3 bytes</td>
</tr>
<tr>
<td>Literal</td>
<td>Loads a literal byte into ACC</td>
<td><code>$25</code></td>
<td>2 bytes</td>
</tr>
</tbody>
</table>
<h4>LOD - Load Address</h4>
<p>loads a value into an address</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Loads the value of another byte of memory into the memory address</td>
<td><code>$26</code></td>
<td>5 bytes</td>
</tr>
<tr>
<td>Literal</td>
<td>Loads a literal byte into the memory address</td>
<td><code>$27</code></td>
<td>4 bytes</td>
</tr>
</tbody>
</table>
<h4>STX - Store [RA]X</h4>
<p>stores RAX into a memory address</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Loads the value of RAX into a byte of memory</td>
<td><code>$2A</code></td>
<td>3 bytes</td>
</tr>
</tbody>
</table>
<h4>STY - Store [RA]Y</h4>
<p>stores RAY into a memory address</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Loads the value of RAY into a byte of memory</td>
<td><code>$2B</code></td>
<td>3 bytes</td>
</tr>
</tbody>
</table>
<h4>STA - Store A(ccumulator)</h4>
<p>stores the accumulator into a memory address</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute</td>
<td>Loads the value of ACC into a byte of memory</td>
<td><code>$2C</code></td>
<td>3 bytes</td>
</tr>
</tbody>
</table>
<h4>ADD - Adds Two Values</h4>
<p>adds two values of various source into a register or memory address</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>RAX</td>
<td>Adds RAX to the value in ACC, and stores it into ACC</td>
<td><code>$40</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>RAY</td>
<td>Adds RAY to the value in ACC, and stores it into ACC</td>
<td><code>$41</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>Absolute/Absolute</td>
<td>Adds the values of two memory addresses, and stores it into ACC</td>
<td><code>$42</code></td>
<td>5 bytes</td>
</tr>
<tr>
<td>Absolute/ACC</td>
<td>Adds the value of a memory address into the value in ACC, and stores it into ACC</td>
<td><code>$43</code></td>
<td>3 bytes</td>
</tr>
</tbody>
</table>
<h4>Sub - Subtracts Two Values</h4>
<p>subtracts two values of various source into a register or memory address</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>RAX</td>
<td>Subtracts RAX from the value in ACC, and stores it into ACC</td>
<td><code>$45</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>RAY</td>
<td>Subtracts RAY from the value in ACC, and stores it into ACC</td>
<td><code>$46</code></td>
<td>1 byte</td>
</tr>
<tr>
<td>Absolute/Absolute</td>
<td>Subtracts the first address value by the second address value, and stores it into ACC</td>
<td><code>$47</code></td>
<td>5 bytes</td>
</tr>
<tr>
<td>Absolute/ACC</td>
<td>Subtracts the value of a memory address from the value in ACC, and stores it into ACC</td>
<td><code>$48</code></td>
<td>3 bytes</td>
</tr>
</tbody>
</table>
<h4>HLT - Halt Operation</h4>
<p>entirely stops execution and attempts to shutdown on hardware</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>N/A</td>
<td></td>
<td><code>$FC</code></td>
<td></td>
</tr>
</tbody>
</table>
<h4>DBG - Debug</h4>
<p>(in emulators) print a view of memory<br />
(in hardware or an optimizing assembler) NOP</p>
<table>
<thead>
<tr>
<th>Addressing</th>
<th>Action</th>
<th>Opcode</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>N/A</td>
<td></td>
<td><code>$FF</code></td>
<td></td>
</tr>
</tbody>
</table>
</body></html>

@ -0,0 +1,158 @@
## LRIS CPU/ASM specification (wip)
~~shamelessly ripped off~~ very inspired by 6502 because it's the only thing i kinda know
### Registers
| Register | Purpose | Size |
| --- | --- | --- |
| ACC | Stores the result of any calculation opcodes (if in ACC mode) | 1 byte |
| RAX | General purpose register | 1 byte |
| RAY | General purpose register | 1 byte |
### Memory
- Up to 64kib of RAM
- Up to 64kib of Program ROM
### Addressing Modes
#### Absolute
Directly reads from a 2 byte memory address with instruction.
```
LDX $0A2F
```
<sub><sup>Note: 1 byte addresses should be padded by the assembler.</sup></sub>
#### Literal
Uses a literal byte, in place of reading from a memory address.
```
LDX #0A2F
```
<sub><sup>Note: 1 byte addresses should be padded by the assembler.</sup></sub>
### Opcodes
NOTE: these do not specify a higher level assembly langauge, only the opcodes interpreted by the CPU itself (ie there cannot be 3 increments for the different registers that all use `INC`)
#### NOP- No Operation
seriously?
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| N/A | NOP | `$00` | 1 byte |
#### INC - Increment
what do you think it does
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Increments the value at specified memory address | `$01` | 3 bytes |
| Accumulator | Increments the accumulator | `$02` | 1 byte |
| RX | Increments the RAX register | `$03` | 1 byte |
| RY | Increments the RAY register | `$04` | 1 byte |
#### DNC - Decrement
what do you think it does (pt. 2)
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Decrements the value at specified memory address | `$05` | 3 bytes |
| Accumulator | Decrements the accumulator | `$06` | 1 byte |
| RX | Decrements the RAX register | `$07` | 1 byte |
| RY | Decrements the RAY register | `$08` | 1 byte |
#### JIE - Jump If Equal
jumps if something is equal to other something
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute/Literal | Sets PRC to value if memory address is equal to other memory address | `$10` | 7 bytes |
| Register/Literal | Sets PRC to value if RAX and RAY are equal | `$11` | 1 byte |
#### JMP - Jump
jumps unconditionally
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Literal | Sets PRC to a literal value | `$1A` | 3 bytes
| Absolute | Sets PRC to the value of a byte in memory | `$1B` | 3 bytes
##### Example:
```
;OP PRC ADDR ADDR
JIE 0x00A2 0x0013 0x0014
```
#### LDX - Load [RA]X
loads a value into RAX
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Loads the value of another byte of memory into RAX | `$20` | 3 bytes |
| Literal | Loads a literal byte into RAX | `$21` | 2 bytes |
#### LDY - Load [RA]Y
loads a value into RAY
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Loads the value of another byte of memory into RAY | `$22` | 3 bytes |
| Literal | Loads a literal byte into RAY | `$23` | 2 bytes |
#### LDA - Load A(ccumulator)
loads a value into the accumulator
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Loads the value of another byte of memory into ACC | `$24` | 3 bytes |
| Literal | Loads a literal byte into ACC | `$25` | 2 bytes |
#### LOD - Load Address
loads a value into an address
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Loads the value of another byte of memory into the memory address | `$26` | 5 bytes |
| Literal | Loads a literal byte into the memory address | `$27` | 4 bytes |
#### STX - Store [RA]X
stores RAX into a memory address
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Loads the value of RAX into a byte of memory | `$2A` | 3 bytes |
#### STY - Store [RA]Y
stores RAY into a memory address
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Loads the value of RAY into a byte of memory | `$2B` | 3 bytes |
#### STA - Store A(ccumulator)
stores the accumulator into a memory address
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Absolute | Loads the value of ACC into a byte of memory | `$2C` | 3 bytes |
#### ADD - Adds Two Values
adds two values of various source into a register or memory address
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| RAX | Adds RAX to the value in ACC, and stores it into ACC | `$40` | 1 byte |
| RAY | Adds RAY to the value in ACC, and stores it into ACC | `$41` | 1 byte |
| Absolute/Absolute | Adds the values of two memory addresses, and stores it into ACC | `$42` | 5 bytes |
| Absolute/ACC | Adds the value of a memory address into the value in ACC, and stores it into ACC | `$43` | 3 bytes |
#### SUB - Subtracts Two Values
subtracts two values of various source into a register or memory address
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| RAX | Subtracts RAX from the value in ACC, and stores it into ACC | `$45` | 1 byte |
| RAY | Subtracts RAY from the value in ACC, and stores it into ACC | `$46` | 1 byte |
| Absolute/Absolute | Subtracts the first address' value by the second address' value, and stores it into ACC | `$47` | 5 bytes |
| Absolute/ACC | Subtracts the value of a memory address from the value in ACC, and stores it into ACC | `$48` | 3 bytes |
#### NAD - NAND
if you don't know what a NAND is why are you looking at opcode documentation
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| Register | Performs a bitwise NAND on RAX and RAY and stores it into ACC | `$50` | 1 byte |
#### HLT - Halt Operation
entirely stops execution and attempts to shutdown on hardware
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| N/A | | `$FC` | |
#### DBG - Debug
(in emulators) print a view of memory
(in hardware or an optimizing assembler) NOP
| Addressing | Action | Opcode | Size |
| --- | --- | --- | --- |
| N/A | | `$FF` | |