Release 0.1.0

This commit is contained in:
Jeremiah Orians 2018-03-20 20:45:33 -04:00
parent 35d15cf61d
commit f513b3f6ac
No known key found for this signature in database
GPG Key ID: 7457821534D2ACCD
20 changed files with 1220 additions and 1666 deletions

View File

@ -25,6 +25,10 @@ Performance tuned hex1 to reduce both size and instruction count
Performance tuned hex0 to reduce both size and instruction count
Performance tuned hex2 to reduce both size and isntruction count
The stage0 vm now halts on ALL invalid instructions
Displacements in the Stage0-vm no longer match that of the Knight hardware platform; instead of from the start of the instruction, from the end of the immediate to the target address.
The Stage0-vm has relocated the 2OPI and 1OPI instructions and adjusted their encodings accordingly to simplify instruction size logic.
The Skip class instructions now lookup the first byte of the instruction that follows them and skips the appropriate size instead of 4 bytes always.
The assembler, disassembler and definitions files were adjusted accordingly
** Fixed
Fixed behavior of R@ thanks to reepca

View File

@ -329,84 +329,84 @@ void assemble(struct Token* p)
setExpression(p, "POPPC", "0D02001", 4);
/* 2OPI Group */
setExpression(p, "ADDI", "0E", 4);
setExpression(p, "ADDUI", "0F", 4);
setExpression(p, "SUBI", "10", 4);
setExpression(p, "SUBUI", "11", 4);
setExpression(p, "CMPI", "12", 4);
setExpression(p, "LOAD", "13", 4);
setExpression(p, "LOAD8", "14", 4);
setExpression(p, "LOADU8", "15", 4);
setExpression(p, "LOAD16", "16", 4);
setExpression(p, "LOADU16", "17", 4);
setExpression(p, "LOAD32", "18", 4);
setExpression(p, "LOADU32", "19", 4);
setExpression(p, "CMPUI", "1F", 4);
setExpression(p, "STORE", "20", 4);
setExpression(p, "STORE8", "21", 4);
setExpression(p, "STORE16", "22", 4);
setExpression(p, "STORE32", "23", 4);
setExpression(p, "ANDI", "B0", 4);
setExpression(p, "ORI", "B1", 4);
setExpression(p, "XORI", "B2", 4);
setExpression(p, "NANDI", "B3", 4);
setExpression(p, "NORI", "B4", 4);
setExpression(p, "XNORI", "B5", 4);
setExpression(p, "CMPJUMPI.G", "C0", 4);
setExpression(p, "CMPJUMPI.GE", "C1", 4);
setExpression(p, "CMPJUMPI.E", "C2", 4);
setExpression(p, "CMPJUMPI.NE", "C3", 4);
setExpression(p, "CMPJUMPI.LE", "C4", 4);
setExpression(p, "CMPJUMPI.L", "C5", 4);
setExpression(p, "CMPJUMPUI.G", "D0", 4);
setExpression(p, "CMPJUMPUI.GE", "D1", 4);
setExpression(p, "CMPJUMPUI.LE", "D4", 4);
setExpression(p, "CMPJUMPUI.L", "D5", 4);
setExpression(p, "ADDI", "E1000E", 6);
setExpression(p, "ADDUI", "E1000F", 6);
setExpression(p, "SUBI", "E10010", 6);
setExpression(p, "SUBUI", "E10011", 6);
setExpression(p, "CMPI", "E10012", 6);
setExpression(p, "LOAD", "E10013", 6);
setExpression(p, "LOAD8", "E10014", 6);
setExpression(p, "LOADU8", "E10015", 6);
setExpression(p, "LOAD16", "E10016", 6);
setExpression(p, "LOADU16", "E10017", 6);
setExpression(p, "LOAD32", "E10018", 6);
setExpression(p, "LOADU32", "E10019", 6);
setExpression(p, "CMPUI", "E1001F", 6);
setExpression(p, "STORE", "E10020", 6);
setExpression(p, "STORE8", "E10021", 6);
setExpression(p, "STORE16", "E10022", 6);
setExpression(p, "STORE32", "E10023", 6);
setExpression(p, "ANDI", "E100B0", 6);
setExpression(p, "ORI", "E100B1", 6);
setExpression(p, "XORI", "E100B2", 6);
setExpression(p, "NANDI", "E100B3", 6);
setExpression(p, "NORI", "E100B4", 6);
setExpression(p, "XNORI", "E100B5", 6);
setExpression(p, "CMPJUMPI.G", "E100C0", 6);
setExpression(p, "CMPJUMPI.GE", "E100C1", 6);
setExpression(p, "CMPJUMPI.E", "E100C2", 6);
setExpression(p, "CMPJUMPI.NE", "E100C3", 6);
setExpression(p, "CMPJUMPI.LE", "E100C4", 6);
setExpression(p, "CMPJUMPI.L", "E100C5", 6);
setExpression(p, "CMPJUMPUI.G", "E100D0", 6);
setExpression(p, "CMPJUMPUI.GE", "E100D1", 6);
setExpression(p, "CMPJUMPUI.LE", "E100D4", 6);
setExpression(p, "CMPJUMPUI.L", "E100D5", 6);
/* 1OPI Group */
setExpression(p, "JUMP.C", "2C0", 4);
setExpression(p, "JUMP.B", "2C1", 4);
setExpression(p, "JUMP.O", "2C2", 4);
setExpression(p, "JUMP.G", "2C3", 4);
setExpression(p, "JUMP.GE", "2C4", 4);
setExpression(p, "JUMP.E", "2C5", 4);
setExpression(p, "JUMP.NE", "2C6", 4);
setExpression(p, "JUMP.LE", "2C7", 4);
setExpression(p, "JUMP.L", "2C8", 4);
setExpression(p, "JUMP.Z", "2C9", 4);
setExpression(p, "JUMP.NZ", "2CA", 4);
setExpression(p, "JUMP.P", "2CB", 4);
setExpression(p, "JUMP.NP", "2CC", 4);
setExpression(p, "CALLI", "2D0", 4);
setExpression(p, "LOADI", "2D1", 4);
setExpression(p, "LOADUI", "2D2", 4);
setExpression(p, "SALI", "2D3", 4);
setExpression(p, "SARI", "2D4", 4);
setExpression(p, "SL0I", "2D5", 4);
setExpression(p, "SR0I", "2D6", 4);
setExpression(p, "SL1I", "2D7", 4);
setExpression(p, "SR1I", "2D8", 4);
setExpression(p, "LOADR", "2E0", 4);
setExpression(p, "LOADR8", "2E1", 4);
setExpression(p, "LOADRU8", "2E2", 4);
setExpression(p, "LOADR16", "2E3", 4);
setExpression(p, "LOADRU16", "2E4", 4);
setExpression(p, "LOADR32", "2E5", 4);
setExpression(p, "LOADRU32", "2E6", 4);
setExpression(p, "STORER", "2F0", 4);
setExpression(p, "STORER8", "2F1", 4);
setExpression(p, "STORER16", "2F2", 4);
setExpression(p, "STORER32", "2F3", 4);
setExpression(p, "CMPSKIPI.G", "A00", 4);
setExpression(p, "CMPSKIPI.GE", "A01", 4);
setExpression(p, "CMPSKIPI.E", "A02", 4);
setExpression(p, "CMPSKIPI.NE", "A03", 4);
setExpression(p, "CMPSKIPI.LE", "A04", 4);
setExpression(p, "CMPSKIPI.L", "A05", 4);
setExpression(p, "CMPSKIPUI.G", "A10", 4);
setExpression(p, "CMPSKIPUI.GE", "A11", 4);
setExpression(p, "CMPSKIPUI.LE", "A14", 4);
setExpression(p, "CMPSKIPUI.L", "A15", 4);
setExpression(p, "JUMP.C", "E0002C0", 6);
setExpression(p, "JUMP.B", "E0002C1", 6);
setExpression(p, "JUMP.O", "E0002C2", 6);
setExpression(p, "JUMP.G", "E0002C3", 6);
setExpression(p, "JUMP.GE", "E0002C4", 6);
setExpression(p, "JUMP.E", "E0002C5", 6);
setExpression(p, "JUMP.NE", "E0002C6", 6);
setExpression(p, "JUMP.LE", "E0002C7", 6);
setExpression(p, "JUMP.L", "E0002C8", 6);
setExpression(p, "JUMP.Z", "E0002C9", 6);
setExpression(p, "JUMP.NZ", "E0002CA", 6);
setExpression(p, "JUMP.P", "E0002CB", 6);
setExpression(p, "JUMP.NP", "E0002CC", 6);
setExpression(p, "CALLI", "E0002D0", 6);
setExpression(p, "LOADI", "E0002D1", 6);
setExpression(p, "LOADUI", "E0002D2", 6);
setExpression(p, "SALI", "E0002D3", 6);
setExpression(p, "SARI", "E0002D4", 6);
setExpression(p, "SL0I", "E0002D5", 6);
setExpression(p, "SR0I", "E0002D6", 6);
setExpression(p, "SL1I", "E0002D7", 6);
setExpression(p, "SR1I", "E0002D8", 6);
setExpression(p, "LOADR", "E0002E0", 6);
setExpression(p, "LOADR8", "E0002E1", 6);
setExpression(p, "LOADRU8", "E0002E2", 6);
setExpression(p, "LOADR16", "E0002E3", 6);
setExpression(p, "LOADRU16", "E0002E4", 6);
setExpression(p, "LOADR32", "E0002E5", 6);
setExpression(p, "LOADRU32", "E0002E6", 6);
setExpression(p, "STORER", "E0002F0", 6);
setExpression(p, "STORER8", "E0002F1", 6);
setExpression(p, "STORER16", "E0002F2", 6);
setExpression(p, "STORER32", "E0002F3", 6);
setExpression(p, "CMPSKIPI.G", "E000A00", 6);
setExpression(p, "CMPSKIPI.GE", "E000A01", 6);
setExpression(p, "CMPSKIPI.E", "E000A02", 6);
setExpression(p, "CMPSKIPI.NE", "E000A03", 6);
setExpression(p, "CMPSKIPI.LE", "E000A04", 6);
setExpression(p, "CMPSKIPI.L", "E000A05", 6);
setExpression(p, "CMPSKIPUI.G", "E000A10", 6);
setExpression(p, "CMPSKIPUI.GE", "E000A11", 6);
setExpression(p, "CMPSKIPUI.LE", "E000A14", 6);
setExpression(p, "CMPSKIPUI.L", "E000A15", 6);
/* 0OPI Group */
setExpression(p, "JUMP", "3C00", 4);
@ -483,7 +483,7 @@ void update_jumps(struct Token* head, struct Token* p)
if('@' == p->Text[0])
{
int16_t dist = 0;
dist = dest - p->address + 4;
dist = dest - p->address;
sprintf(p->Expression, "%04x", (uint16_t)dist);
}

View File

@ -156,84 +156,84 @@ DEFINE PUSHPC 0D02000
DEFINE POPPC 0D02001
# 2OPI Group
DEFINE ADDI 0E
DEFINE ADDUI 0F
DEFINE SUBI 10
DEFINE SUBUI 11
DEFINE CMPI 12
DEFINE LOAD 13
DEFINE LOAD8 14
DEFINE LOADU8 15
DEFINE LOAD16 16
DEFINE LOADU16 17
DEFINE LOAD32 18
DEFINE LOADU32 19
DEFINE CMPUI 1F
DEFINE STORE 20
DEFINE STORE8 21
DEFINE STORE16 22
DEFINE STORE32 23
DEFINE ANDI B0
DEFINE ORI B1
DEFINE XORI B2
DEFINE NANDI B3
DEFINE NORI B4
DEFINE XNORI B5
DEFINE CMPJUMPI.G C0
DEFINE CMPJUMPI.GE C1
DEFINE CMPJUMPI.E C2
DEFINE CMPJUMPI.NE C3
DEFINE CMPJUMPI.LE C4
DEFINE CMPJUMPI.L C5
DEFINE CMPJUMPUI.G D0
DEFINE CMPJUMPUI.GE D1
DEFINE CMPJUMPUI.LE D4
DEFINE CMPJUMPUI.L D5
DEFINE ADDI E1000E
DEFINE ADDUI E1000F
DEFINE SUBI E10010
DEFINE SUBUI E10011
DEFINE CMPI E10012
DEFINE LOAD E10013
DEFINE LOAD8 E10014
DEFINE LOADU8 E10015
DEFINE LOAD16 E10016
DEFINE LOADU16 E10017
DEFINE LOAD32 E10018
DEFINE LOADU32 E10019
DEFINE CMPUI E1001F
DEFINE STORE E10020
DEFINE STORE8 E10021
DEFINE STORE16 E10022
DEFINE STORE32 E10023
DEFINE ANDI E100B0
DEFINE ORI E100B1
DEFINE XORI E100B2
DEFINE NANDI E100B3
DEFINE NORI E100B4
DEFINE XNORI E100B5
DEFINE CMPJUMPI.G E100C0
DEFINE CMPJUMPI.GE E100C1
DEFINE CMPJUMPI.E E100C2
DEFINE CMPJUMPI.NE E100C3
DEFINE CMPJUMPI.LE E100C4
DEFINE CMPJUMPI.L E100C5
DEFINE CMPJUMPUI.G E100D0
DEFINE CMPJUMPUI.GE E100D1
DEFINE CMPJUMPUI.LE E100D4
DEFINE CMPJUMPUI.L E100D5
# 1OPI Group
DEFINE JUMP.C 2C0
DEFINE JUMP.B 2C1
DEFINE JUMP.O 2C2
DEFINE JUMP.G 2C3
DEFINE JUMP.GE 2C4
DEFINE JUMP.E 2C5
DEFINE JUMP.NE 2C6
DEFINE JUMP.LE 2C7
DEFINE JUMP.L 2C8
DEFINE JUMP.Z 2C9
DEFINE JUMP.NZ 2CA
DEFINE JUMP.P 2CB
DEFINE JUMP.NP 2CC
DEFINE CALLI 2D0
DEFINE LOADI 2D1
DEFINE LOADUI 2D2
DEFINE SALI 2D3
DEFINE SARI 2D4
DEFINE SL0I 2D5
DEFINE SR0I 2D6
DEFINE SL1I 2D7
DEFINE SR1I 2D8
DEFINE LOADR 2E0
DEFINE LOADR8 2E1
DEFINE LOADRU8 2E2
DEFINE LOADR16 2E3
DEFINE LOADRU16 2E4
DEFINE LOADR32 2E5
DEFINE LOADRU32 2E6
DEFINE STORER 2F0
DEFINE STORER8 2F1
DEFINE STORER16 2F2
DEFINE STORER32 2F3
DEFINE CMPSKIPI.G A00
DEFINE CMPSKIPI.GE A01
DEFINE CMPSKIPI.E A02
DEFINE CMPSKIPI.NE A03
DEFINE CMPSKIPI.LE A04
DEFINE CMPSKIPI.L A05
DEFINE CMPSKIPUI.G A10
DEFINE CMPSKIPUI.GE A11
DEFINE CMPSKIPUI.LE A14
DEFINE CMPSKIPUI.L A15
DEFINE JUMP.C E0002C0
DEFINE JUMP.B E0002C1
DEFINE JUMP.O E0002C2
DEFINE JUMP.G E0002C3
DEFINE JUMP.GE E0002C4
DEFINE JUMP.E E0002C5
DEFINE JUMP.NE E0002C6
DEFINE JUMP.LE E0002C7
DEFINE JUMP.L E0002C8
DEFINE JUMP.Z E0002C9
DEFINE JUMP.NZ E0002CA
DEFINE JUMP.P E0002CB
DEFINE JUMP.NP E0002CC
DEFINE CALLI E0002D0
DEFINE LOADI E0002D1
DEFINE LOADUI E0002D2
DEFINE SALI E0002D3
DEFINE SARI E0002D4
DEFINE SL0I E0002D5
DEFINE SR0I E0002D6
DEFINE SL1I E0002D7
DEFINE SR1I E0002D8
DEFINE LOADR E0002E0
DEFINE LOADR8 E0002E1
DEFINE LOADRU8 E0002E2
DEFINE LOADR16 E0002E3
DEFINE LOADRU16 E0002E4
DEFINE LOADR32 E0002E5
DEFINE LOADRU32 E0002E6
DEFINE STORER E0002F0
DEFINE STORER8 E0002F1
DEFINE STORER16 E0002F2
DEFINE STORER32 E0002F3
DEFINE CMPSKIPI.G E000A00
DEFINE CMPSKIPI.GE E000A01
DEFINE CMPSKIPI.E E000A02
DEFINE CMPSKIPI.NE E000A03
DEFINE CMPSKIPI.LE E000A04
DEFINE CMPSKIPI.L E000A05
DEFINE CMPSKIPUI.G E000A10
DEFINE CMPSKIPUI.GE E000A11
DEFINE CMPSKIPUI.LE E000A14
DEFINE CMPSKIPUI.L E000A15
# 0OPI Group
DEFINE JUMP 3C00

View File

@ -31,7 +31,7 @@ struct Instruction
char opcode[3];
uint32_t raw_XOP;
char XOP[6];
char operation[9];
char operation[13];
int16_t raw_Immediate;
char Immediate[7];
uint32_t HAL_CODE;
@ -865,19 +865,25 @@ void decode_0OP(struct Instruction* c)
void decode_Integer_2OPI(struct Instruction* c)
{
/* Parse Raw Data */
c->raw_Immediate = c->raw2*0x100 + c->raw3;
c->Immediate[0] = c->operation[4];
c->Immediate[1] = c->operation[5];
c->Immediate[2] = c->operation[6];
c->Immediate[3] = c->operation[7];
c->reg0 = c->raw1/16;
c->reg1 = c->raw1%16;
/* Get Immediate pieces */
c->raw_Immediate = fgetc(binary_file);
int a = fgetc(binary_file);
/* Unpack immediate */
unpack_byte(c->raw_Immediate, &(c->operation[8]));
unpack_byte(a, &(c->operation[10]));
/* Process registers and immediate */
c->raw_Immediate = c->raw_Immediate * 0x100 + a;
c->reg0 = c->raw3/16;
c->reg1 = c->raw3%16;
char Name[20] = "ILLEGAL_2OPI";
if(c->raw1 != 0) goto broken_2OPI;
/* Convert to Human readable form */
switch(c->raw0)
switch(c->raw2)
{
case 0x0E: /* ADDI */
{
@ -1046,6 +1052,7 @@ void decode_Integer_2OPI(struct Instruction* c)
}
default: /* Unknown 2OPI*/
{
broken_2OPI:
string_values(c, true);
return;
}
@ -1057,19 +1064,23 @@ void decode_Integer_2OPI(struct Instruction* c)
void decode_1OPI(struct Instruction* c)
{
/* Get Immediate pieces */
c->raw_Immediate = fgetc(binary_file);
int a = fgetc(binary_file);
/* Unpack immediate */
unpack_byte(c->raw_Immediate, &(c->operation[8]));
unpack_byte(a, &(c->operation[10]));
/* Parse Raw Data */
c->raw_Immediate = c->raw2*0x100 + c->raw3;
c->Immediate[0] = c->operation[3];
c->Immediate[1] = c->operation[4];
c->Immediate[2] = c->operation[5];
c->Immediate[3] = c->operation[6];
c->Immediate[4] = c->operation[7];
c->HAL_CODE = 0;
c->raw_XOP = c->raw1/16;
c->reg0 = c->raw1%16;
c->raw_Immediate = c->raw_Immediate*0x100 + a;
c->raw_XOP = c->raw3/16;
c->reg0 = c->raw3%16;
char Name[20] = "ILLEGAL_1OPI";
uint32_t Opcode = (c->raw0 * 16) + c->raw_XOP;
uint32_t Opcode = (c->raw2 * 16) + c->raw_XOP;
if(0 != c->raw1) goto Broken_1OPI;
/* Convert to Human readable form */
switch(Opcode)
@ -1291,6 +1302,7 @@ void decode_1OPI(struct Instruction* c)
}
default: /* Unknown 1OPI*/
{
Broken_1OPI:
string_values(c, true);
return;
}
@ -1403,54 +1415,62 @@ void eval_instruction(struct Instruction* c)
case 0x01: /* Integer 4OP */
{
decode_Integer_4OP(c);
address = address + 4;
break;
}
case 0x05: /* Integer 3OP */
{
decode_Integer_3OP(c);
address = address + 4;
break;
}
case 0x09: /* Integer 2OP */
{
decode_Integer_2OP(c);
address = address + 4;
break;
}
case 0x0D: /* 1OP */
{
decode_1OP(c);
break;
}
case 0x0E ... 0x2B: /* 2OPI */
case 0xB0 ... 0xDF:
{
decode_Integer_2OPI(c);
break;
}
case 0x2C ... 0x2F: /* 1OPI */
case 0xA0 ... 0xA1:
{
decode_1OPI(c);
address = address + 4;
break;
}
case 0x3C: /* Core 0OPI */
{
decode_0OPI(c);
address = address + 4;
break;
}
case 0x42: /* HALCODE */
{
decode_HALCODE(c);
address = address + 4;
break;
}
case 0xE1: /* 2OPI */
{
decode_Integer_2OPI(c);
address = address + 6;
break;
}
case 0xE0: /* 1OPI */
{
decode_1OPI(c);
address = address + 6;
break;
}
case 0x00: /* NOP */
case 0xFF: /* HALT */
{
decode_0OP(c);
address = address + 4;
break;
}
default: /* Not supported by this disassembler */
{
string_values(c, true);
address = address + 4;
return;
}
}
@ -1479,7 +1499,6 @@ int main(int argc, char **argv)
{
read_instruction(current);
eval_instruction(current);
address = address + 4;
byte = fgetc(binary_file);
ungetc(byte, binary_file);
}

View File

@ -69,6 +69,8 @@ this is primarily used for pointer comparisons involving hand encoded objects.
For pointers starting with &, it is assumed that the user wants the 32bit absolute address of the label;
this is primarily for hand encoding objects or instructions that want 32bit absolute addresses
Should one wish to manually calculate the displacement field of an instruction, simply subtract the address of the byte after the immediate from the address of the target.
*** More advanced?
It is possible for a hex2 assembler to support more than just the minimal set as defined above and is frequently the case on complicated instruction sets.
However, to be considered hex2 compliant a program should not depend on those additions.
@ -429,135 +431,6 @@ The Opcodes will be preserved should we wish in the future to be binary compatab
| ... | Reserved |
| 0D FF FF Fx | Reserved |
** 2OPI Groups
2OPI ii ii is the Immediate, a = b OP ii ii
*** 2OPI Integer
| Hex | Name | Comment |
|-------------+-----------------+--------------------------|
| 0E ab ii ii | ADDI a b ii ii | a = b + ii ii [signed] |
| 0F ab ii ii | ADDUI a b ii ii | a = b + ii ii [unsigned] |
| 10 ab ii ii | SUBI a b ii ii | a = b - ii ii [signed] |
| 11 ab ii ii | SUBUI a b ii ii | a = b - ii ii [unsigned] |
*** 2OPI Integer signed compare
| Hex | Name | Comment |
|-------------+----------------+--------------------------|
| 12 ab ii ii | CMPI a b ii ii | a = b CMP ii ii [signed] |
*** 2OPI Integer Load
| Hex | Name | Comment |
|-------------+-------------------+--------------------------------------|
| 13 ab ii ii | LOAD a b ii ii | a = MEM[b + ii ii] |
| 14 ab ii ii | LOAD8 a b ii ii | a = MEM[b + ii ii] [signed 8bits] |
| 15 ab ii ii | LOADU8 a b ii ii | a = MEM[b + ii ii] [unsigned 8bits] |
| 16 ab ii ii | LOAD16 a b ii ii | a = MEM[b + ii ii] [signed 16bits] |
| 17 ab ii ii | LOADU16 a b ii ii | a = MEM[b + ii ii] [unsigned 16bits] |
| 18 ab ii ii | LOAD32 a b ii ii | a = MEM[b + ii ii] [signed 32bits] |
| 19 ab ii ii | LOADU32 a b ii ii | a = MEM[b + ii ii] [unsigned 32bits] |
| 1A ab ii ii | Reserved | |
| 1B ab ii ii | Reserved | |
| 1C ab ii ii | Reserved | |
| 1D ab ii ii | Reserved | |
| 1E ab ii ii | Reserved | |
*** 2OPI Integer unsigned compare
| Hex | Name | Comment |
|-------------+-----------------+----------------------------|
| 1F ab ii ii | CMPUI a b ii ii | a = b CMP ii ii [unsigned] |
*** 2OPI Integer store
| Hex | Name | Comment |
|-------------+----------------+------------------------------------|
| 20 ab ii ii | STORE a b ii | MEM[b + ii ii] = a |
| 21 ab ii ii | STORE8 a b ii | MEM[b + ii ii] = a [signed 8bits] |
| 22 ab ii ii | STORE16 a b ii | MEM[b + ii ii] = a [signed 16bits] |
| 23 ab ii ii | STORE32 a b ii | MEM[b + ii ii] = a [signed 32bits] |
| 24 ab ii ii | Reserved | |
| 25 ab ii ii | Reserved | |
| 26 ab ii ii | Reserved | |
| 27 ab ii ii | Reserved | |
| 28 ab ii ii | Reserved | |
| 29 ab ii ii | Reserved | |
| 2A ab ii ii | Reserved | |
| 2B ab ii ii | Reserved | |
** 1OPI Groups
1OPI i ii ii is the Immediate, a = a OP i ii ii
*** Conditional Integer Jumps
| Hex | Name | Comment |
|-------------+-----------------+--------------------------------------|
| 2C 0a ii ii | JUMP.C a ii ii | Carry? a; PC = PC + i ii ii |
| 2C 1a ii ii | JUMP.B a ii ii | Borrow? a; PC = PC + i ii ii |
| 2C 2a ii ii | JUMP.O a ii ii | Overflow? a; PC = PC + i ii ii |
| 2C 3a ii ii | JUMP.G a ii ii | GT? a; PC = PC + i ii ii |
| 2C 4a ii ii | JUMP.GE a ii ii | GT? a \vert EQ? a; PC = PC + i ii ii |
| 2C 5a ii ii | JUMP.E a ii ii | EQ? a; PC = PC + i ii ii |
| 2C 6a ii ii | JUMP.NE a ii ii | NEQ? a; PC = PC + i ii ii |
| 2C 7a ii ii | JUMP.LE a ii ii | LT? a \vert EQ? a; PC = PC + i ii ii |
| 2C 8a ii ii | JUMP.L a ii ii | LT? a; PC = PC + i ii ii |
| 2C 9a ii ii | JUMP.Z a ii ii | ZERO? a; PC = PC + i ii ii |
| 2C Aa ii ii | JUMP.NZ a ii ii | NZERO? a; PC = PC + i ii ii |
| 2C Ba ii ii | JUMP.P | POSITIVE? a; PC = PC + ii ii |
| 2C Ca ii ii | JUMP.NP | NEGATIVE? a; PC = PC + ii ii |
| 2C Dx xx xx | Reserved | |
| 2C Ex xx xx | Reserved | |
| 2C Fx xx xx | Reserved | |
*** Branch Immediates
| Hex | Name | Comment |
|-------------+----------------+----------------------------------------------------------------|
| 2D 0a ii ii | CALLI a ii ii | MEM[a] = PC; a = a + (register size in bytes); PC = PC + ii ii |
| 2D 1a ii ii | LOADI a ii ii | a = ii ii (signed) |
| 2D 2a ii ii | LOADUI a ii ii | a = ii ii (unsigned) |
| 2D 3a ii ii | SALI a ii ii | a = a << ii ii [arithmetically] |
| 2D 4a ii ii | SARI a ii ii | a = a >> ii ii [arithmetically] |
| 2D 5a ii ii | SL0I a ii ii | a = a << ii ii [Fill with zeros] |
| 2D 6a ii ii | SR0I a ii ii | a = a >> ii ii [Fill with zeros] |
| 2D 7a ii ii | SL1I a ii ii | a = a << ii ii [Fill with ones] |
| 2D 8a ii ii | SR1I a ii ii | a = a >> ii ii [Fill with ones] |
*** Relative Loads
| Hex | Name | Comment |
|-------------+------------------+----------------------------------------|
| 2E 0a ii ii | LOADR a ii ii | a = MEM[ip + ii ii] |
| 2E 1a ii ii | LOADR8 a ii ii | a = MEM[ip + ii ii] [signed 8 bits] |
| 2E 2a ii ii | LOADRU8 a ii ii | a = MEM[ip + ii ii] [unsigned 8 bits] |
| 2E 3a ii ii | LOADR16 a ii ii | a = MEM[ip + ii ii] [signed 16 bits] |
| 2E 4a ii ii | LOADRU16 a ii ii | a = MEM[ip + ii ii] [unsigned 16 bits] |
| 2E 5a ii ii | LOADR32 a ii ii | a = MEM[ip + ii ii] [signed 32 bits] |
| 2E 6a ii ii | LOADRU32 a ii ii | a = MEM[ip + ii ii] [unsigned 32 bits] |
| 2E 7a ii ii | Reserved | |
| 2E 8a ii ii | Reserved | |
| 2E 9a ii ii | Reserved | |
| 2E Aa ii ii | Reserved | |
| 2E Ba ii ii | Reserved | |
| 2E Ca ii ii | Reserved | |
| 2E Da ii ii | Reserved | |
| 2E Ea ii ii | Reserved | |
| 2E Fa ii ii | Reserved | |
*** Relative Stores
| Hex | Name | Comment |
|-------------+------------------+--------------------------------------|
| 2F 0a ii ii | STORER a ii ii | MEM[ip + ii ii] = a |
| 2F 1a ii ii | STORER8 a ii ii | MEM[ip + ii ii] = a [signed 8 bits] |
| 2F 2a ii ii | STORER16 a ii ii | MEM[ip + ii ii] = a [signed 16 bits] |
| 2F 3a ii ii | STORER32 a ii ii | MEM[ip + ii ii] = a [signed 32 bits] |
| 2F 4a ii ii | Reserved | |
| 2F 5a ii ii | Reserved | |
| 2F 6a ii ii | Reserved | |
| 2F 7a ii ii | Reserved | |
| 2F 8a ii ii | Reserved | |
| 2F 9a ii ii | Reserved | |
| 2F Aa ii ii | Reserved | |
| 2F Ba ii ii | Reserved | |
| 2F Ca ii ii | Reserved | |
| 2F Da ii ii | Reserved | |
| 2F Ea ii ii | Reserved | |
| 2F Fa ii ii | Reserved | |
** 0OPI group
0OPI ii ii is the Immediate, OP ii ii
@ -674,37 +547,6 @@ DO NOT USE.
|-------------+----------|
| 43 00 00 00 | Reserved |
| ... | Reserved |
| 9F FF FF FF | Reserved |
** CMPSKIPI Group
| Hex | Name | Comment |
|-------------+----------------------+------------------------------------|
| A0 0a ii ii | CMPSKIPI.G a ii ii | a > ii ii ? Skip Next instruction |
| A0 1a ii ii | CMPSKIPI.GE a ii ii | a >= ii ii ? Skip Next instruction |
| A0 2a ii ii | CMPSKIPI.E a ii ii | a == ii ii ? Skip Next instruction |
| A0 3a ii ii | CMPSKIPI.NE a ii ii | a != ii ii ? Skip Next instruction |
| A0 4a ii ii | CMPSKIPI.LE a ii ii | a <= ii ii ? Skip Next instruction |
| A0 5a ii ii | CMPSKIPI.L a ii ii | a < ii ii ? Skip Next instruction |
| A0 6a ii ii | Reserved | |
| ... | Reserved | |
| A0 Fa ii ii | Reserved | |
| A1 0a ii ii | CMPSKIPUI.G a ii ii | a > ii ii ? Skip Next instruction |
| A1 1a ii ii | CMPSKIPUI.GE a ii ii | a >= ii ii ? Skip Next instruction |
| A1 2a ii ii | Reserved | |
| A1 3a ii ii | Reserved | |
| A1 4a ii ii | CMPSKIPUI.LE a ii ii | a <= ii ii ? Skip Next instruction |
| A1 5a ii ii | CMPSKIPUI.L a ii ii | a < ii ii ? Skip Next instruction |
| A1 6a ii ii | Reserved | |
| ... | Reserved | |
| A1 Fa ii ii | Reserved | |
** Reserved Block 2
At this time these instructions only produce a warning; but could do anything.
DO NOT USE.
| Hex | Name |
|-------------+----------|
| A2 00 00 00 | Reserved |
| ... | Reserved |
| AF FF FF FF | Reserved |
** Bit optimization group
@ -720,36 +562,198 @@ DO NOT USE.
| ... | Reserved | |
| BF FF FF FF | Reserved | |
** CMPJUMPI Group
| Hex | Name | Comment |
|-------------+------------------------+-------------------------------------|
| C0 ab ii ii | CMPJUMPI.G a b ii ii | a > b ? PC = PC + ii ii |
| C1 ab ii ii | CMPJUMPI.GE a b ii ii | a >= b ? PC = PC + ii ii |
| C2 ab ii ii | CMPJUMPI.E a b ii ii | a == b ? PC = PC + ii ii |
| C3 ab ii ii | CMPJUMPI.NE a b ii ii | a != b ? PC = PC + ii ii |
| C4 ab ii ii | CMPJUMPI.LE a b ii ii | a <= b ? PC = PC + ii ii |
| C5 ab ii ii | CMPJUMPI.L a b ii ii | a < b ? PC = PC + ii ii |
| C6 ab ii ii | Reserved | |
| ... | Reserved | |
| CF ab ii ii | Reserved | |
| D0 ab ii ii | CMPJUMPUI.G a b ii ii | a > b ? PC = PC + ii ii (unsigned) |
| D1 ab ii ii | CMPJUMPUI.GE a b ii ii | a >= b ? PC = PC + ii ii (unsigned) |
| D2 ab ii ii | Reserved | |
| D3 ab ii ii | Reserved | |
| D4 ab ii ii | CMPJUMPUI.LE a b ii ii | a <= b ? PC = PC + ii ii (unsigned) |
| D5 ab ii ii | CMPJUMPUI.L a b ii ii | a < b ? PC = PC + ii ii (unsigned) |
| D6 ab ii ii | Reserved | |
| ... | Reserved | |
| DF ab ii ii | Reserved | |
** Extended instruction block
This block specified for instructions that require immediates
*** 1OPI Groups
1OPI i ii ii is the Immediate, a = a OP i ii ii
** Reserved Block 3
**** Conditional Integer Jumps
| Hex | Name | Comment |
|-------------------+-----------------+--------------------------------------|
| E0 00 2C 0a ii ii | JUMP.C a ii ii | Carry? a; PC = PC + i ii ii |
| E0 00 2C 1a ii ii | JUMP.B a ii ii | Borrow? a; PC = PC + i ii ii |
| E0 00 2C 2a ii ii | JUMP.O a ii ii | Overflow? a; PC = PC + i ii ii |
| E0 00 2C 3a ii ii | JUMP.G a ii ii | GT? a; PC = PC + i ii ii |
| E0 00 2C 4a ii ii | JUMP.GE a ii ii | GT? a \vert EQ? a; PC = PC + i ii ii |
| E0 00 2C 5a ii ii | JUMP.E a ii ii | EQ? a; PC = PC + i ii ii |
| E0 00 2C 6a ii ii | JUMP.NE a ii ii | NEQ? a; PC = PC + i ii ii |
| E0 00 2C 7a ii ii | JUMP.LE a ii ii | LT? a \vert EQ? a; PC = PC + i ii ii |
| E0 00 2C 8a ii ii | JUMP.L a ii ii | LT? a; PC = PC + i ii ii |
| E0 00 2C 9a ii ii | JUMP.Z a ii ii | ZERO? a; PC = PC + i ii ii |
| E0 00 2C Aa ii ii | JUMP.NZ a ii ii | NZERO? a; PC = PC + i ii ii |
| E0 00 2C Ba ii ii | JUMP.P | POSITIVE? a; PC = PC + ii ii |
| E0 00 2C Ca ii ii | JUMP.NP | NEGATIVE? a; PC = PC + ii ii |
| E0 00 2C Dx xx xx | Reserved | |
| E0 00 2C Ex xx xx | Reserved | |
| E0 00 2C Fx xx xx | Reserved | |
**** Branch Immediates
| Hex | Name | Comment |
|-------------------+----------------+----------------------------------------------------------------|
| E0 00 2D 0a ii ii | CALLI a ii ii | MEM[a] = PC; a = a + (register size in bytes); PC = PC + ii ii |
**** Load Immediates
| Hex | Name | Comment |
|-------------------+----------------+----------------------------------------------------------------|
| E0 00 2D 1a ii ii | LOADI a ii ii | a = ii ii (signed) |
| E0 00 2D 2a ii ii | LOADUI a ii ii | a = ii ii (unsigned) |
**** Shift Immediates
| Hex | Name | Comment |
|-------------------+----------------+----------------------------------------------------------------|
| E0 00 2D 3a ii ii | SALI a ii ii | a = a << ii ii [arithmetically] |
| E0 00 2D 4a ii ii | SARI a ii ii | a = a >> ii ii [arithmetically] |
| E0 00 2D 5a ii ii | SL0I a ii ii | a = a << ii ii [Fill with zeros] |
| E0 00 2D 6a ii ii | SR0I a ii ii | a = a >> ii ii [Fill with zeros] |
| E0 00 2D 7a ii ii | SL1I a ii ii | a = a << ii ii [Fill with ones] |
| E0 00 2D 8a ii ii | SR1I a ii ii | a = a >> ii ii [Fill with ones] |
**** Relative Loads
| Hex | Name | Comment |
|-------------------+------------------+----------------------------------------|
| E0 00 2E 0a ii ii | LOADR a ii ii | a = MEM[ip + ii ii] |
| E0 00 2E 1a ii ii | LOADR8 a ii ii | a = MEM[ip + ii ii] [signed 8 bits] |
| E0 00 2E 2a ii ii | LOADRU8 a ii ii | a = MEM[ip + ii ii] [unsigned 8 bits] |
| E0 00 2E 3a ii ii | LOADR16 a ii ii | a = MEM[ip + ii ii] [signed 16 bits] |
| E0 00 2E 4a ii ii | LOADRU16 a ii ii | a = MEM[ip + ii ii] [unsigned 16 bits] |
| E0 00 2E 5a ii ii | LOADR32 a ii ii | a = MEM[ip + ii ii] [signed 32 bits] |
| E0 00 2E 6a ii ii | LOADRU32 a ii ii | a = MEM[ip + ii ii] [unsigned 32 bits] |
| E0 00 2E 7a ii ii | Reserved | |
| E0 00 2E 8a ii ii | Reserved | |
| E0 00 2E 9a ii ii | Reserved | |
| E0 00 2E Aa ii ii | Reserved | |
| E0 00 2E Ba ii ii | Reserved | |
| E0 00 2E Ca ii ii | Reserved | |
| E0 00 2E Da ii ii | Reserved | |
| E0 00 2E Ea ii ii | Reserved | |
| E0 00 2E Fa ii ii | Reserved | |
**** Relative Stores
| Hex | Name | Comment |
|-------------------+------------------+--------------------------------------|
| E0 00 2F 0a ii ii | STORER a ii ii | MEM[ip + ii ii] = a |
| E0 00 2F 1a ii ii | STORER8 a ii ii | MEM[ip + ii ii] = a [signed 8 bits] |
| E0 00 2F 2a ii ii | STORER16 a ii ii | MEM[ip + ii ii] = a [signed 16 bits] |
| E0 00 2F 3a ii ii | STORER32 a ii ii | MEM[ip + ii ii] = a [signed 32 bits] |
| E0 00 2F 4a ii ii | Reserved | |
| E0 00 2F 5a ii ii | Reserved | |
| E0 00 2F 6a ii ii | Reserved | |
| E0 00 2F 7a ii ii | Reserved | |
| E0 00 2F 8a ii ii | Reserved | |
| E0 00 2F 9a ii ii | Reserved | |
| E0 00 2F Aa ii ii | Reserved | |
| E0 00 2F Ba ii ii | Reserved | |
| E0 00 2F Ca ii ii | Reserved | |
| E0 00 2F Da ii ii | Reserved | |
| E0 00 2F Ea ii ii | Reserved | |
| E0 00 2F Fa ii ii | Reserved | |
**** CMPSKIPI Group
| Hex | Name | Comment |
|-------------------+----------------------+------------------------------------|
| E0 00 A0 0a ii ii | CMPSKIPI.G a ii ii | a > ii ii ? Skip Next instruction |
| E0 00 A0 1a ii ii | CMPSKIPI.GE a ii ii | a >= ii ii ? Skip Next instruction |
| E0 00 A0 2a ii ii | CMPSKIPI.E a ii ii | a == ii ii ? Skip Next instruction |
| E0 00 A0 3a ii ii | CMPSKIPI.NE a ii ii | a != ii ii ? Skip Next instruction |
| E0 00 A0 4a ii ii | CMPSKIPI.LE a ii ii | a <= ii ii ? Skip Next instruction |
| E0 00 A0 5a ii ii | CMPSKIPI.L a ii ii | a < ii ii ? Skip Next instruction |
| E0 00 A0 6a ii ii | Reserved | |
| ... | Reserved | |
| E0 00 A0 Fa ii ii | Reserved | |
| E0 00 A1 0a ii ii | CMPSKIPUI.G a ii ii | a > ii ii ? Skip Next instruction |
| E0 00 A1 1a ii ii | CMPSKIPUI.GE a ii ii | a >= ii ii ? Skip Next instruction |
| E0 00 A1 2a ii ii | Reserved | |
| E0 00 A1 3a ii ii | Reserved | |
| E0 00 A1 4a ii ii | CMPSKIPUI.LE a ii ii | a <= ii ii ? Skip Next instruction |
| E0 00 A1 5a ii ii | CMPSKIPUI.L a ii ii | a < ii ii ? Skip Next instruction |
| E0 00 A1 6a ii ii | Reserved | |
| ... | Reserved | |
| E0 00 A1 Fa ii ii | Reserved | |
*** 2OPI Groups
2OPI ii ii is the Immediate, a = b OP ii ii
**** 2OPI Integer
| Hex | Name | Comment |
|-------------------+-----------------+--------------------------|
| E1 00 0E ab ii ii | ADDI a b ii ii | a = b + ii ii [signed] |
| E1 00 0F ab ii ii | ADDUI a b ii ii | a = b + ii ii [unsigned] |
| E1 00 10 ab ii ii | SUBI a b ii ii | a = b - ii ii [signed] |
| E1 00 11 ab ii ii | SUBUI a b ii ii | a = b - ii ii [unsigned] |
**** 2OPI Integer signed compare
| Hex | Name | Comment |
|-------------------+----------------+--------------------------|
| E1 00 12 ab ii ii | CMPI a b ii ii | a = b CMP ii ii [signed] |
**** 2OPI Integer Load
| Hex | Name | Comment |
|-------------------+-------------------+--------------------------------------|
| E1 00 13 ab ii ii | LOAD a b ii ii | a = MEM[b + ii ii] |
| E1 00 14 ab ii ii | LOAD8 a b ii ii | a = MEM[b + ii ii] [signed 8bits] |
| E1 00 15 ab ii ii | LOADU8 a b ii ii | a = MEM[b + ii ii] [unsigned 8bits] |
| E1 00 16 ab ii ii | LOAD16 a b ii ii | a = MEM[b + ii ii] [signed 16bits] |
| E1 00 17 ab ii ii | LOADU16 a b ii ii | a = MEM[b + ii ii] [unsigned 16bits] |
| E1 00 18 ab ii ii | LOAD32 a b ii ii | a = MEM[b + ii ii] [signed 32bits] |
| E1 00 19 ab ii ii | LOADU32 a b ii ii | a = MEM[b + ii ii] [unsigned 32bits] |
| E1 00 1A ab ii ii | Reserved | |
| E1 00 1B ab ii ii | Reserved | |
| E1 00 1C ab ii ii | Reserved | |
| E1 00 1D ab ii ii | Reserved | |
| E1 00 1E ab ii ii | Reserved | |
**** 2OPI Integer unsigned compare
| Hex | Name | Comment |
|-------------------+-----------------+----------------------------|
| E1 00 1F ab ii ii | CMPUI a b ii ii | a = b CMP ii ii [unsigned] |
**** 2OPI Integer store
| Hex | Name | Comment |
|-------------------+----------------+------------------------------------|
| E1 00 20 ab ii ii | STORE a b ii | MEM[b + ii ii] = a |
| E1 00 21 ab ii ii | STORE8 a b ii | MEM[b + ii ii] = a [signed 8bits] |
| E1 00 22 ab ii ii | STORE16 a b ii | MEM[b + ii ii] = a [signed 16bits] |
| E1 00 23 ab ii ii | STORE32 a b ii | MEM[b + ii ii] = a [signed 32bits] |
| E1 00 24 ab ii ii | Reserved | |
| E1 00 25 ab ii ii | Reserved | |
| E1 00 26 ab ii ii | Reserved | |
| E1 00 27 ab ii ii | Reserved | |
| E1 00 28 ab ii ii | Reserved | |
| E1 00 29 ab ii ii | Reserved | |
| E1 00 2A ab ii ii | Reserved | |
| E1 00 2B ab ii ii | Reserved | |
**** CMPJUMPI Group
| Hex | Name | Comment |
|-------------------+------------------------+-------------------------------------|
| E1 00 C0 ab ii ii | CMPJUMPI.G a b ii ii | a > b ? PC = PC + ii ii |
| E1 00 C1 ab ii ii | CMPJUMPI.GE a b ii ii | a >= b ? PC = PC + ii ii |
| E1 00 C2 ab ii ii | CMPJUMPI.E a b ii ii | a == b ? PC = PC + ii ii |
| E1 00 C3 ab ii ii | CMPJUMPI.NE a b ii ii | a != b ? PC = PC + ii ii |
| E1 00 C4 ab ii ii | CMPJUMPI.LE a b ii ii | a <= b ? PC = PC + ii ii |
| E1 00 C5 ab ii ii | CMPJUMPI.L a b ii ii | a < b ? PC = PC + ii ii |
| E1 00 C6 ab ii ii | Reserved | |
| ... | Reserved | |
| E1 00 CF ab ii ii | Reserved | |
| E1 00 D0 ab ii ii | CMPJUMPUI.G a b ii ii | a > b ? PC = PC + ii ii (unsigned) |
| E1 00 D1 ab ii ii | CMPJUMPUI.GE a b ii ii | a >= b ? PC = PC + ii ii (unsigned) |
| E1 00 D2 ab ii ii | Reserved | |
| E1 00 D3 ab ii ii | Reserved | |
| E1 00 D4 ab ii ii | CMPJUMPUI.LE a b ii ii | a <= b ? PC = PC + ii ii (unsigned) |
| E1 00 D5 ab ii ii | CMPJUMPUI.L a b ii ii | a < b ? PC = PC + ii ii (unsigned) |
| E1 00 D6 ab ii ii | Reserved | |
| ... | Reserved | |
| E1 00 DF ab ii ii | Reserved | |
*** Reserved Block 2
At this time these instructions only produce a warning; but could do anything.
DO NOT USE.
| Hex | Name |
|-------------+----------|
| E0 00 00 00 | Reserved |
| ... | Reserved |
| FE FF FF FF | Reserved |
| Hex | Name |
|-------------------+----------|
| E1 01 00 00 00 00 | Reserved |
| ... | Reserved |
| EF FF FF FF FF FF | Reserved |
** 0OP
| Hex | Name | Comment |
@ -821,33 +825,23 @@ This ordering was selected simply because makes the starting IP address 0 and is
*** Class E 2OPI
This is a very rare and special group as each entry consumes a piece of the precious 256 entry opcode space.
|--------------+------------+------------+------------------|
| opcode 8bits | Reg0 4bits | Reg1 4bits | Immediate 16bits |
|--------------+------------+------------+------------------|
|--------------+------------+------------+------------+------------------|
| opcode 8bits | XOP 16bits | Reg0 4bits | Reg1 4bits | Immediate 16bits |
|--------------+------------+------------+------------+------------------|
| Opcode | Function group | Length in Bytes |
|---------+----------------+-----------------|
| 0E - 19 | Integer group | 4 |
| 1A - 1E | Reserved | Undefined |
| 1F - 23 | Integer group | 4 |
| 24 - 2B | Reserved | Undefined |
| B0 - B5 | Integer group | 4 |
| B6 - BF | Reserved | Undefined |
| C0 - C5 | Integer group | 4 |
| C6 - CF | Reserved | Undefined |
| D0 - D1 | Integer group | 4 |
| D2 - D3 | Reserved | Undefined |
| D4 - D5 | Integer group | 4 |
| Opcode | Function group | Length in Bytes |
|--------+----------------+-----------------|
| E1 | Integer group | 6 |
*** Class F 1OPI
|--------------+-----------+------------+------------------|
| opcode 8bits | XOP 4bits | Reg0 4bits | Immediate 16bits |
|--------------+-----------+------------+------------------|
|--------------+------------+------------+------------------|
| opcode 8bits | XOP 20bits | Reg0 4bits | Immediate 16bits |
|--------------+------------+------------+------------------|
| Opcode | Function group | Length in Bytes |
|--------+----------------+-----------------|
| E0 | Integer group | 6 |
| Opcode | Function group | Length in Bytes |
|---------+----------------+-----------------|
| 2C - 2F | Integer group | 4 |
| A0 - A1 | Integer group | 4 |
*** Class G 0OPI
|--------------+-----------+------------------|
@ -878,13 +872,16 @@ This is a very rare and special group as each entry consumes a piece of the prec
| FF | HALT | 4 |
** Exotic behavior
*** Illegal instructions
To ensure consistent behavior, all undefined opcodes are to be treated like illegal instructions and for hardware/operating system combinations that lack an illegal instruction handler, the result is that of HALT.
Should an illegal instruction handler be implemented, the implementor should if possible emulate the instruction via software and jump to instruction that follows.
*** Illegal encoding
Assemblers should throw an exception in the event that a register is compared to itself.
As such code is likely wrong and such sequences are reserved for future opcode harvesting in the event of opcode starvation.
*** compare and skip instructions
All compare and skip instructions lookup the first byte following themselves to determine the number of bytes to skip to allow the correct behavior to occur with shorter and longer instruction formats.
To ensure consistent behavior, all undefined opcodes are to be treated like illegal instructions and for hardware/operating system combinations that lack an illegal instruction handler, the result is that of HALT.
Assemblers should throw an exception in the event that a register is compared to itself as jumps and nops are the preferred alternative in such cases and their encoding could be repurposed in the event of opcode starvation.
*** compare and jump instructions
Assemblers should throw an exception in the event that a register is compared to itself as jumps and nops are the preferred alternative in such cases and their encoding could be repurposed in the event of opcode starvation.
*** HALCODE
On systems that support an IOMMU and Kernel mode, all HALCODES can be modified or replaced by the kernel. Those listed in this document are those that must be supported on bootup.

View File

@ -46,8 +46,8 @@ stage0_monitor: hex stage0/stage0_monitor.hex0 | roms
stage1_assembler-0: hex stage1/stage1_assembler-0.hex0 | roms
./bin/hex < stage1/stage1_assembler-0.hex0 > roms/stage1_assembler-0
SET: stage1_assembler-0 vm stage1/SET.hex0 | roms
./bin/vm --rom roms/stage1_assembler-0 --tape_01 stage1/SET.hex0 --tape_02 roms/SET
SET: stage1_assembler-2 vm stage1/SET.hex2 | roms
./bin/vm --rom roms/stage1_assembler-2 --tape_01 stage1/SET.hex2 --tape_02 roms/SET
DEHEX: stage1_assembler-0 vm stage1/dehex.hex0 | roms
./bin/vm --rom roms/stage1_assembler-0 --tape_01 stage1/dehex.hex0 --tape_02 roms/DEHEX

View File

@ -1,7 +1,7 @@
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 is free software: you an redistribute it and/or modify
## stage0 is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
@ -14,122 +14,132 @@
## You should have received a copy of the GNU General Public License
## along with stage0. If not, see <http://www.gnu.org/licenses/>.
# :start
2D2B0001 # LOADUI R11 1 ; Our toggle
2D2D0600 # LOADUI R13 0x600 ; Where we are starting our Stack
# ;; R14 will be storing our condition
0D00002F # FALSE R15 ; Our holder
# :start 0
E0002D2B0001 # LOADUI R11 1 ; Our toggle
E0002D2D0600 # LOADUI R13 0x600 ; Where we are starting our Stack
# ;; R14 will be storing our condition
0D00002F # FALSE R15 ; Our holder
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
42100001 # FOPEN_WRITE
E0002D201100 # LOADUI R0 0x1100
42100001 # FOPEN_WRITE
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
E0002D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
# :loop
2D210000 # LOADUI R1 0 ; Read from tty
42100100 # FGETC ; Read a Char
A030000d # CMPSKIPI.NE R0 13 ; Replace all CR
2D20000a # LOADUI R0 10 ; WIth LF
42100200 # FPUTC ; Display the Char to User
# :loop 24
E0002D210000 # LOADUI R1 0 ; Read from tty
42100100 # FGETC ; Read a Char
E000A030000d # CMPSKIPI.NE R0 13 ; Replace all CR
E0002D20000a # LOADUI R0 10 ; WIth LF
42100200 # FPUTC ; Display the Char to User
# ;; Check for Ctrl-D
A0300004 # CMPSKIPI.NE R0 4
3C0000d0 # JUMP @finish
E000A0300004 # CMPSKIPI.NE R0 4
3C000112 # JUMP @finish
# ;; Check for EOF
2CC000cc # JUMP.NP R0 @finish
E0002CC0010c # JUMP.NP R0 @finish
# :.L1
2D211101 # LOADUI R1 0x1101 ; Write to TAPE_02
42100200 # FPUTC ; Print the Char
2D0D0034 # CALLI R13 @hex ; Convert it
2CC0ffd4 # JUMP.NP R0 @loop ; Don't use nonhex chars
2C9B0010 # JUMP.Z R11 @.L99 ; Jump if toggled
# ;; Write out unprocessed byte
E0002D211101 # LOADUI R1 0x1101 ; Write to TAPE_02
42100200 # FPUTC ; Print the Char
# ;; Convert byte to nybble
E0002D0D003e # CALLI R13 @hex ; Convert it
# ;; Get another byte if nonhex
E0002CC0ffc0 # JUMP.NP R0 @loop ; Don't use nonhex chars
# ;; Deal with the case of second nybble
E0002C9B000e # JUMP.Z R11 @second_nybble ; Jump if toggled
# ;; Process first byte of pair
B0F0000f # ANDI R15 R0 0x0F ; Store First nibble
0D00002B # FALSE R11 ; Flip the toggle
3C00ffc4 # JUMP @loop
E100B0F0000f # ANDI R15 R0 0x0F ; Store First nibble
0D00002B # FALSE R11 ; Flip the toggle
3C00ffac # JUMP @loop
# :.L99
2D5F0004 # SL0I R15 4 ; Shift our first nibble
B000000f # ANDI R0 R0 0x0F ; Mask out top
0500000F # ADD R0 R0 R15 ; Combine nibbles
2D1B0001 # LOADI R11 1 ; Flip the toggle
2D211100 # LOADUI R1 0x1100 ; Write the combined byte
42100200 # FPUTC ; To TAPE_01
3C00ffa8 # JUMP @loop ; Try to get more bytes
# ;; Combined second nybble in pair with first
# :second_nybble 78
E0002D5F0004 # SL0I R15 4 ; Shift our first nibble
E100B000000f # ANDI R0 R0 0x0F ; Mask out top
0500000F # ADD R0 R0 R15 ; Combine nibbles
# :hex
# ;; Writeout and prepare for next cycle
E0002D1B0001 # LOADI R11 1 ; Flip the toggle
E0002D211100 # LOADUI R1 0x1100 ; Write the combined byte
42100200 # FPUTC ; To TAPE_01
3C00ff88 # JUMP @loop ; Try to get more bytes
# :hex 9c
# ;; Deal with line comments starting with #
1FE00023 # CMPUI R14 R0 35
2C5E0060 # JUMP.E R14 @ascii_comment
E1001FE00023 # CMPUI R14 R0 35
E0002C5E007e # JUMP.E R14 @ascii_comment
# ;; Deal with line comments starting with ;
1FE0003b # CMPUI R14 R0 59
2C5E0058 # JUMP.E R14 @ascii_comment
E1001FE0003b # CMPUI R14 R0 59
E0002C5E0072 # JUMP.E R14 @ascii_comment
# ;; Deal with all ascii less than '0'
1FE00030 # CMPUI R14 R0 48
2C8E0048 # JUMP.L R14 @ascii_other
E1001FE00030 # CMPUI R14 R0 48
E0002C8E005e # JUMP.L R14 @ascii_other
# ;; Deal with '0'-'9'
1FE00039 # CMPUI R14 R0 57
2C7E0028 # JUMP.LE R14 @ascii_num
E1001FE00039 # CMPUI R14 R0 57
E0002C7E0034 # JUMP.LE R14 @ascii_num
# ;; Deal with all ascii less than 'A'
1FE00041 # CMPUI R14 R0 65
2C8E0038 # JUMP.L R14 @ascii_other
E1001FE00041 # CMPUI R14 R0 65
E0002C8E0046 # JUMP.L R14 @ascii_other
# ;; Deal with 'A'-'F'
1FE00046 # CMPUI R14 R0 70
2C7E0028 # JUMP.LE R14 @ascii_high
E1001FE00046 # CMPUI R14 R0 70
E0002C7E0030 # JUMP.LE R14 @ascii_high
# ;; Deal with all ascii less than 'a'
1FE00061 # CMPUI R14 R0 97
2C8E0028 # JUMP.L R14 @ascii_other
E1001FE00061 # CMPUI R14 R0 97
E0002C8E002e # JUMP.L R14 @ascii_other
# ;; Deal with 'a'-'f'
1FE00066 # CMPUI R14 R0 102
2C7E0010 # JUMP.LE R14 @ascii_low
E1001FE00066 # CMPUI R14 R0 102
E0002C7E000e # JUMP.LE R14 @ascii_low
# ;; Ignore the rest
3C00001c # JUMP @ascii_other
3C00001e # JUMP @ascii_other
# :ascii_num
11000030 # SUBUI R0 R0 48
0D01001D # RET R13
# :ascii_num 100
E10011000030 # SUBUI R0 R0 48
0D01001D # RET R13
# :ascii_low
11000057 # SUBUI R0 R0 87
0D01001D # RET R13
# :ascii_low 10a
E10011000057 # SUBUI R0 R0 87
0D01001D # RET R13
# :ascii_high
11000037 # SUBUI R0 R0 55
0D01001D # RET R13
# :ascii_high 114
E10011000037 # SUBUI R0 R0 55
0D01001D # RET R13
# :ascii_other
0D000030 # TRUE R0
0D01001D # RET R13
# :ascii_other 11e
0D000030 # TRUE R0
0D01001D # RET R13
# :ascii_comment
2D210000 # LOADUI R1 0 ; Read from tty
42100100 # FGETC ; Read another char
A030000d # CMPSKIPI.NE R0 13 ; Replace all CR
2D20000a # LOADUI R0 10 ; WIth LF
42100200 # FPUTC ; Let the user see it
1FE0000a # CMPUI R14 R0 10 ; Stop at the end of line
2D211101 # LOADUI R1 0x1101 ; Write to TAPE_02
42100200 # FPUTC ; The char we just read
2C6Effe0 # JUMP.NE R14 @ascii_comment ; Otherwise keep looping
3C00ffd4 # JUMP @ascii_other
# :ascii_comment 126
E0002D210000 # LOADUI R1 0 ; Read from tty
42100100 # FGETC ; Read another char
E000A030000d # CMPSKIPI.NE R0 13 ; Replace all CR
E0002D20000a # LOADUI R0 10 ; WIth LF
42100200 # FPUTC ; Let the user see it
E1001FE0000a # CMPUI R14 R0 10 ; Stop at the end of line
E0002D211101 # LOADUI R1 0x1101 ; Write to TAPE_02
42100200 # FPUTC ; The char we just read
E0002C6Effd0 # JUMP.NE R14 @ascii_comment ; Otherwise keep looping
3C00ffc4 # JUMP @ascii_other
# :finish
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
2D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT
# :finish 15a
E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT

View File

@ -16,22 +16,22 @@
:start
# ;; We will be using R13 for storage of Head
2D2E 4000 # LOADUI R14 0x4000 ; Our malloc pointer (Initialized)
2D2F $stack # LOADUI R15 $stack ; Put stack at end of program
E0002D2E 4000 # LOADUI R14 0x4000 ; Our malloc pointer (Initialized)
E0002D2F $stack # LOADUI R15 $stack ; Put stack at end of program
# ;; Main program
# ;; Reads contents of Tape_01 and applies all Definitions
# ;; Writes results to Tape_02
# ;; Accepts no arguments and HALTS when done
:main
2D0F @Tokenize_Line # CALLI R15 @Tokenize_Line ; Call Tokenize_Line
2D0F @reverse_list # CALLI R15 @reverse_list ; Reverse the list of tokens
2D0F @Identify_Macros # CALLI R15 @Identify_Macros ; Tag all nodes that are macros
2D0F @Line_Macro # CALLI R15 @Line_Macro ; Apply macros down nodes
2D0F @Process_String # CALLI R15 @Process_String ; Convert string values to Hex16
2D0F @Eval_Immediates # CALLI R15 @Eval_Immediates ; Convert numbers to hex
2D0F @Preserve_Other # CALLI R15 @Preserve_Other ; Ensure labels/Pointers aren't lost
2D0F @Print_Hex # CALLI R15 @Print_Hex ; Write Nodes to Tape_02
E0002D0F @Tokenize_Line # CALLI R15 @Tokenize_Line ; Call Tokenize_Line
E0002D0F @reverse_list # CALLI R15 @reverse_list ; Reverse the list of tokens
E0002D0F @Identify_Macros # CALLI R15 @Identify_Macros ; Tag all nodes that are macros
E0002D0F @Line_Macro # CALLI R15 @Line_Macro ; Apply macros down nodes
E0002D0F @Process_String # CALLI R15 @Process_String ; Convert string values to Hex16
E0002D0F @Eval_Immediates # CALLI R15 @Eval_Immediates ; Convert numbers to hex
E0002D0F @Preserve_Other # CALLI R15 @Preserve_Other ; Ensure labels/Pointers aren't lost
E0002D0F @Print_Hex # CALLI R15 @Print_Hex ; Write Nodes to Tape_02
FFFFFFFF # HALT ; We are Done
@ -40,7 +40,7 @@ FFFFFFFF # HALT ; We are Done
# ;; Returns to whatever called it
:Tokenize_Line
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
E0002D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
0D00002D # FALSE R13 ; Head is NULL
09000510 # MOVE R1 R0 ; Read Tape_01
@ -48,53 +48,53 @@ FFFFFFFF # HALT ; We are Done
42100100 # FGETC ; Get a Char
# ;; Deal with lines comments starting with #
A0300023 # CMPSKIPI.NE R0 35
E000A0300023 # CMPSKIPI.NE R0 35
3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment
# ;; Deal with Line comments starting with ;
A030003b # CMPSKIPI.NE R0 59
E000A030003b # CMPSKIPI.NE R0 59
3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment
# ;; Deal with Tab
A0300009 # CMPSKIPI.NE R0 9
E000A0300009 # CMPSKIPI.NE R0 9
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Deal with New line
A030000a # CMPSKIPI.NE R0 10
E000A030000a # CMPSKIPI.NE R0 10
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Deal with space characters
A0300020 # CMPSKIPI.NE R0 32
E000A0300020 # CMPSKIPI.NE R0 32
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Stop if EOF
A0100000 # CMPSKIPI.GE R0 0
E000A0100000 # CMPSKIPI.GE R0 0
3C00 @Tokenize_Line_Done # JUMP @Tokenize_Line_Done
# ;; Allocate a new Node
0900042E # COPY R2 R14 ; Get address of new Node
0FEE0010 # ADDUI R14 R14 16 ; Allocate 16 Bytes
23E20008 # STORE32 R14 R2 8 ; Set Text pointer
E1000FEE0010 # ADDUI R14 R14 16 ; Allocate 16 Bytes
E10023E20008 # STORE32 R14 R2 8 ; Set Text pointer
# ;; Deal with Strings wrapped in \"
A0300022 # CMPSKIPI.NE R0 34
E000A0300022 # CMPSKIPI.NE R0 34
3C00 @Store_String # JUMP @Store_String
# ;; Deal with Strings wrapped in '
A0300027 # CMPSKIPI.NE R0 39
E000A0300027 # CMPSKIPI.NE R0 39
3C00 @Store_String # JUMP @Store_String
# ;; Everything else is an atom store it
2D0F @Store_Atom # CALLI R15 @Store_Atom
E0002D0F @Store_Atom # CALLI R15 @Store_Atom
:Tokenize_Line_1
23D20000 # STORE32 R13 R2 0 ; Set p->next to head
E10023D20000 # STORE32 R13 R2 0 ; Set p->next to head
090005D2 # MOVE R13 R2 ; Set head to p
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Keep getting tokens
:Tokenize_Line_Done
# ;; Done reading File
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
0D01001F # RET R15
@ -108,9 +108,9 @@ A0300027 # CMPSKIPI.NE R0 39
# ; Using R2 as next
:reverse_list_0
2C90 @reverse_list_done # JUMP.Z R0 @reverse_list_done ; Stop if NULL == head
13200000 # LOAD R2 R0 0 ; next = head->next
20100000 # STORE R1 R0 0 ; head->next = root
E0002C90 @reverse_list_done # JUMP.Z R0 @reverse_list_done ; Stop if NULL == head
E10013200000 # LOAD R2 R0 0 ; next = head->next
E10020100000 # STORE R1 R0 0 ; head->next = root
09000510 # MOVE R1 R0 ; root = head
09000502 # MOVE R0 R2 ; head = next
3C00 @reverse_list_0 # JUMP @reverse_list_0 ; Keep looping
@ -128,7 +128,7 @@ A0300027 # CMPSKIPI.NE R0 39
# ;; Comment never existed
:Purge_Line_Comment
42100100 # FGETC ; Get another Char
A020000a # CMPSKIPI.E R0 10 ; Stop When LF is reached
E000A020000a # CMPSKIPI.E R0 10 ; Stop When LF is reached
3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment ; Otherwise keep looping
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Return as if this never happened
@ -143,15 +143,15 @@ A020000a # CMPSKIPI.E R0 10 ; Stop When LF is reached
09000430 # COPY R3 R0 ; Copy Char for comparison
:Store_String_0
210E0000 # STORE8 R0 R14 0 ; Store the Byte
E100210E0000 # STORE8 R0 R14 0 ; Store the Byte
42100100 # FGETC ; Get next Byte
0FEE0001 # ADDUI R14 R14 1 ; Prep for next loop
C303 @Store_String_0 # CMPJUMPI.NE R0 R3 @Store_String_0 ; Loop if matching not found
E1000FEE0001 # ADDUI R14 R14 1 ; Prep for next loop
E100C303 @Store_String_0 # CMPJUMPI.NE R0 R3 @Store_String_0 ; Loop if matching not found
# ;; Clean up
0FEE0004 # ADDUI R14 R14 4 ; Correct Malloc
2D200002 # LOADUI R0 2 ; Using type string
23020004 # STORE32 R0 R2 4 ; Set node type
E1000FEE0004 # ADDUI R14 R14 4 ; Correct Malloc
E0002D200002 # LOADUI R0 2 ; Using type string
E10023020004 # STORE32 R0 R2 4 ; Set node type
3C00 @Tokenize_Line_1 # JUMP @Tokenize_Line_1
@ -160,14 +160,14 @@ C303 @Store_String_0 # CMPJUMPI.NE R0 R3 @Store_String_0 ; Loop if matching not
# ;; And node pointer in R2
# ;; Modifies node Text to point to string
:Store_Atom
210E0000 # STORE8 R0 R14 0 ; Store the Byte
E100210E0000 # STORE8 R0 R14 0 ; Store the Byte
42100100 # FGETC ; Get next Byte
0FEE0001 # ADDUI R14 R14 1 ; Prep for next loop
A0300009 # CMPSKIPI.NE R0 9 ; If char is Tab
E1000FEE0001 # ADDUI R14 R14 1 ; Prep for next loop
E000A0300009 # CMPSKIPI.NE R0 9 ; If char is Tab
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
A030000a # CMPSKIPI.NE R0 10 ; If char is LF
E000A030000a # CMPSKIPI.NE R0 10 ; If char is LF
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
A0300020 # CMPSKIPI.NE R0 32 ; If char is Space
E000A0300020 # CMPSKIPI.NE R0 32 ; If char is Space
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
# ;; Otherwise loop
@ -175,7 +175,7 @@ A0300020 # CMPSKIPI.NE R0 32 ; If char is Space
:Store_Atom_Done
# ;; Cleanup
0FEE0001 # ADDUI R14 R14 1 ; Correct Malloc
E1000FEE0001 # ADDUI R14 R14 1 ; Correct Malloc
0D01001F # RET R15
@ -199,10 +199,10 @@ A0300020 # CMPSKIPI.NE R0 32 ; If char is Space
:cmpbyte
0503A024 # LOADXU8 R0 R2 R4 ; Get a byte of our first string
0503A134 # LOADXU8 R1 R3 R4 ; Get a byte of our second string
0F440001 # ADDUI R4 R4 1 ; Prep for next loop
E1000F440001 # ADDUI R4 R4 1 ; Prep for next loop
05004001 # CMP R0 R0 R1 ; Compare the bytes
A0210000 # CMPSKIPI.E R1 0 ; Stop if byte is NULL
2C50 @cmpbyte # JUMP.E R0 @cmpbyte ; Loop if bytes are equal
E000A0210000 # CMPSKIPI.E R1 0 ; Stop if byte is NULL
E0002C50 @cmpbyte # JUMP.E R0 @cmpbyte ; Loop if bytes are equal
# ;; Done
# ;; Restore registers
@ -220,40 +220,40 @@ A0210000 # CMPSKIPI.E R1 0 ; Stop if byte is NULL
# ;; Return to whatever called it
:Identify_Macros
# ;; Initializ
2D2101d0 # LOADUI R1 $Identify_Macros_string
E0002D21 $Identify_Macros_string # LOADUI R1 $Identify_Macros_string
0900042D # COPY R2 R13 ; i = head
# ;; Main Loop
:Identify_Macros_0
18020008 # LOAD32 R0 R2 8 ; Get Pointer to Text
2D0F @strcmp # CALLI R15 @strcmp
2C60 @Identify_Macros_1 # JUMP.NE R0 @Identify_Macros_1
E10018020008 # LOAD32 R0 R2 8 ; Get Pointer to Text
E0002D0F @strcmp # CALLI R15 @strcmp
E0002C60 @Identify_Macros_1 # JUMP.NE R0 @Identify_Macros_1
# ;; It is a definition
# ;; Set i->Type = macro
2D200001 # LOADUI R0 1 ; The Enum value for macro
23020004 # STORE32 R0 R2 4 ; Set node type
E0002D200001 # LOADUI R0 1 ; The Enum value for macro
E10023020004 # STORE32 R0 R2 4 ; Set node type
# ;; Set i->Text = i->Next->Text
18420000 # LOAD32 R4 R2 0 ; Get Next
18040008 # LOAD32 R0 R4 8 ; Get Next->Text
23020008 # STORE32 R0 R2 8 ; Set i->Text = Next->Text
E10018420000 # LOAD32 R4 R2 0 ; Get Next
E10018040008 # LOAD32 R0 R4 8 ; Get Next->Text
E10023020008 # STORE32 R0 R2 8 ; Set i->Text = Next->Text
# ;; Set i->Expression = i->next->next->Text
18440000 # LOAD32 R4 R4 0 ; Get Next->Next
18040008 # LOAD32 R0 R4 8 ; Get Next->Next->Text
18340004 # LOAD32 R3 R4 4 ; Get Next->Next->type
A0330002 # CMPSKIPI.NE R3 2 ; If node is a string
0F000001 # ADDUI R0 R0 1 ; Skip first char
2302000c # STORE32 R0 R2 12 ; Set Expression = Next->Next->Text
E10018440000 # LOAD32 R4 R4 0 ; Get Next->Next
E10018040008 # LOAD32 R0 R4 8 ; Get Next->Next->Text
E10018340004 # LOAD32 R3 R4 4 ; Get Next->Next->type
E000A0330002 # CMPSKIPI.NE R3 2 ; If node is a string
E1000F000001 # ADDUI R0 R0 1 ; Skip first char
E1002302000c # STORE32 R0 R2 12 ; Set Expression = Next->Next->Text
# ;; Set i->Next = i->Next->Next->Next
18440000 # LOAD32 R4 R4 0 ; Get Next->Next->Next
23420000 # STORE32 R4 R2 0 ; Set i->Next = Next->Next->Next
E10018440000 # LOAD32 R4 R4 0 ; Get Next->Next->Next
E10023420000 # STORE32 R4 R2 0 ; Set i->Next = Next->Next->Next
:Identify_Macros_1
18220000 # LOAD32 R2 R2 0 ; Get node->next
2CA2 @Identify_Macros_0 # JUMP.NZ R2 @Identify_Macros_0 ; Loop if i not NULL
E10018220000 # LOAD32 R2 R2 0 ; Get node->next
E0002CA2 @Identify_Macros_0 # JUMP.NZ R2 @Identify_Macros_0 ; Loop if i not NULL
0D01001F # RET R15
:Identify_Macros_string
@ -269,13 +269,13 @@ A0330002 # CMPSKIPI.NE R3 2 ; If node is a string
# ;; Main loop
:Line_Macro_0
18300004 # LOAD32 R3 R0 4 ; Load Node type
1820000c # LOAD32 R2 R0 12 ; Load Expression pointer
18100008 # LOAD32 R1 R0 8 ; Load Text pointer
18000000 # LOAD32 R0 R0 0 ; Load Next pointer
A0330001 # CMPSKIPI.NE R3 1 ; If a macro
2D0F @setExpression # CALLI R15 @setExpression ; Apply to other nodes
2CA0 @Line_Macro_0 # JUMP.NZ R0 @Line_Macro_0 ; If Next is Null Don't loop
E10018300004 # LOAD32 R3 R0 4 ; Load Node type
E1001820000c # LOAD32 R2 R0 12 ; Load Expression pointer
E10018100008 # LOAD32 R1 R0 8 ; Load Text pointer
E10018000000 # LOAD32 R0 R0 0 ; Load Next pointer
E000A0330001 # CMPSKIPI.NE R3 1 ; If a macro
E0002D0F @setExpression # CALLI R15 @setExpression ; Apply to other nodes
E0002CA0 @Line_Macro_0 # JUMP.NZ R0 @Line_Macro_0 ; If Next is Null Don't loop
0D01001F # RET R15
@ -293,17 +293,17 @@ A0330001 # CMPSKIPI.NE R3 1 ; If a macro
09000440 # COPY R4 R0 ; Use R4 for Node pointer
:setExpression_0
18340004 # LOAD32 R3 R4 4 ; Load type into R3
A0330001 # CMPSKIPI.NE R3 1 ; Check if Macro
E10018340004 # LOAD32 R3 R4 4 ; Load type into R3
E000A0330001 # CMPSKIPI.NE R3 1 ; Check if Macro
3C00 @setExpression_1 # JUMP @setExpression_1 ; Move to next if Macro
18040008 # LOAD32 R0 R4 8 ; Load Text pointer into R0 for Comparision
2D0F @strcmp # CALLI R15 @strcmp ; compare Text and Macro Text
2C60 @setExpression_1 # JUMP.NE R0 @setExpression_1 ; Move to next if not Match
2324000c # STORE32 R2 R4 12 ; Set node->Expression = Exp
E10018040008 # LOAD32 R0 R4 8 ; Load Text pointer into R0 for Comparision
E0002D0F @strcmp # CALLI R15 @strcmp ; compare Text and Macro Text
E0002C60 @setExpression_1 # JUMP.NE R0 @setExpression_1 ; Move to next if not Match
E1002324000c # STORE32 R2 R4 12 ; Set node->Expression = Exp
:setExpression_1
18440000 # LOAD32 R4 R4 0 ; Load Next
2CA4 @setExpression_0 # JUMP.NZ R4 @setExpression_0 ; Loop if next isn't NULL
E10018440000 # LOAD32 R4 R4 0 ; Load Next
E0002CA4 @setExpression_0 # JUMP.NZ R4 @setExpression_0 ; Loop if next isn't NULL
:setExpression_Done
# ;; Restore registers
@ -321,30 +321,30 @@ A0330001 # CMPSKIPI.NE R3 1 ; Check if Macro
:Process_String_0
# ;; Get node type
18100004 # LOAD32 R1 R0 4 ; Load Type
A0210002 # CMPSKIPI.E R1 2 ; If not a string
E10018100004 # LOAD32 R1 R0 4 ; Load Type
E000A0210002 # CMPSKIPI.E R1 2 ; If not a string
3C00 @Process_String_Done # JUMP @Process_String_Done ; Just go to next
# ;; Its a string
18100008 # LOAD32 R1 R0 8 ; Get Text pointer
14210000 # LOAD8 R2 R1 0 ; Get first char of Text
E10018100008 # LOAD32 R1 R0 8 ; Get Text pointer
E10014210000 # LOAD8 R2 R1 0 ; Get first char of Text
# ;; Deal with '
A0220027 # CMPSKIPI.E R2 39 ; If char is not '
E000A0220027 # CMPSKIPI.E R2 39 ; If char is not '
3C00 @Process_String_1 # JUMP @Process_String_1 ; Move to next label
# ;; Simply use Hex strings as is
0F110001 # ADDUI R1 R1 1 ; Move Text pointer by 1
2310000c # STORE32 R1 R0 12 ; Set expression to Text + 1
E1000F110001 # ADDUI R1 R1 1 ; Move Text pointer by 1
E1002310000c # STORE32 R1 R0 12 ; Set expression to Text + 1
3C00 @Process_String_Done # JUMP @Process_String_Done ; And move on
:Process_String_1
# ;; Deal with \"
2D0F @Hexify_String # CALLI R15 @Hexify_String
E0002D0F @Hexify_String # CALLI R15 @Hexify_String
:Process_String_Done
18000000 # LOAD32 R0 R0 0 ; Load Next
2CA0 @Process_String_0 # JUMP.NZ R0 @Process_String_0 ; If Next isn't NULL Recurse down list
E10018000000 # LOAD32 R0 R0 0 ; Load Next
E0002CA0 @Process_String_0 # JUMP.NZ R0 @Process_String_0 ; If Next isn't NULL Recurse down list
0D01001F # RET R15
@ -360,20 +360,20 @@ A0220027 # CMPSKIPI.E R2 39 ; If char is not '
# ;; Initialize
09000510 # MOVE R1 R0 ; Move R0 out of the way
23E1000c # STORE32 R14 R1 12 ; Set node expression pointer
18110008 # LOAD32 R1 R1 8 ; Load Text pointer into R2
0F110001 # ADDUI R1 R1 1 ; SKip leading \"
E10023E1000c # STORE32 R14 R1 12 ; Set node expression pointer
E10018110008 # LOAD32 R1 R1 8 ; Load Text pointer into R2
E1000F110001 # ADDUI R1 R1 1 ; SKip leading \"
# ;; Main Loop
:Hexify_String_0
18010000 # LOAD32 R0 R1 0 ; Load 4 bytes into R0 from Text
B02000ff # ANDI R2 R0 0xFF ; Preserve byte to check for NULL
2D0F @hex32 # CALLI R15 @hex32 ; Convert to hex and store in Expression
0F110004 # ADDUI R1 R1 4 ; Pointer Text pointer to next 4 bytes
2CA2 @Hexify_String_0 # JUMP.NZ R2 @Hexify_String_0
E10018010000 # LOAD32 R0 R1 0 ; Load 4 bytes into R0 from Text
E100B02000ff # ANDI R2 R0 0xFF ; Preserve byte to check for NULL
E0002D0F @hex32 # CALLI R15 @hex32 ; Convert to hex and store in Expression
E1000F110004 # ADDUI R1 R1 4 ; Pointer Text pointer to next 4 bytes
E0002CA2 @Hexify_String_0 # JUMP.NZ R2 @Hexify_String_0
# ;; Done
0FEE0001 # ADDUI R14 R14 1 ; Correct malloc value
E1000FEE0001 # ADDUI R14 R14 1 ; Correct malloc value
0902800F # POPR R0 R15
0D01001F # RET R15
@ -385,26 +385,26 @@ B02000ff # ANDI R2 R0 0xFF ; Preserve byte to check for NULL
# ;; Returns to whatever called it
:hex32
0902000F # PUSHR R0 R15
2D600010 # SR0I R0 16 ; Do high word first
2D0F @hex16 # CALLI R15 @hex16
E0002D600010 # SR0I R0 16 ; Do high word first
E0002D0F @hex16 # CALLI R15 @hex16
0902800F # POPR R0 R15
:hex16
0902000F # PUSHR R0 R15
2D600008 # SR0I R0 8 ; Do high byte first
2D0F @hex8 # CALLI R15 @hex8
E0002D600008 # SR0I R0 8 ; Do high byte first
E0002D0F @hex8 # CALLI R15 @hex8
0902800F # POPR R0 R15
:hex8
0902000F # PUSHR R0 R15
2D600004 # SR0I R0 4 ; Do high nybble first
2D0F @hex4 # CALLI R15 @hex4
E0002D600004 # SR0I R0 4 ; Do high nybble first
E0002D0F @hex4 # CALLI R15 @hex4
0902800F # POPR R0 R15
:hex4
B000000f # ANDI R0 R0 0xF ; isolate nybble
0F000030 # ADDUI R0 R0 48 ; convert to ascii
A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
0F000007 # ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
210E0000 # STORE8 R0 R14 0 ; Store Hex Char
0FEE0001 # ADDUI R14 R14 1 ; Increment address pointer
E100B000000f # ANDI R0 R0 0xF ; isolate nybble
E1000F000030 # ADDUI R0 R0 48 ; convert to ascii
E000A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
E1000F000007 # ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
E100210E0000 # STORE8 R0 R14 0 ; Store Hex Char
E1000FEE0001 # ADDUI R14 R14 1 ; Increment address pointer
0D01001F # RET R15 ; Get next nybble or return if done
@ -418,24 +418,24 @@ A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
# ;; Process Text
:Eval_Immediates_0
18230000 # LOAD32 R2 R3 0 ; Load Node->Next
1803000c # LOAD32 R0 R3 12 ; Load Expression pointer
2CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Expression is set
18030004 # LOAD32 R0 R3 4 ; Load Node type
2CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Typed
18030008 # LOAD32 R0 R3 8 ; Load Text pointer
14100000 # LOAD8 R1 R0 0 ; Get first char of Text
2D0F @numerate_string # CALLI R15 @numerate_string ; Convert to number in R0
A0210030 # CMPSKIPI.E R1 48 ; Skip next comparision if '0'
2C90 @Eval_Immediates_1 # JUMP.Z R0 @Eval_Immediates_1 ; Don't do anything if string isn't a number
20E3000c # STORE R14 R3 12 ; Preserve pointer to expression
2D0F @hex16 # CALLI R15 @hex16 ; Shove our number into expression
0FEE0001 # ADDUI R14 R14 1 ; Allocate enough space for a null
E10018230000 # LOAD32 R2 R3 0 ; Load Node->Next
E1001803000c # LOAD32 R0 R3 12 ; Load Expression pointer
E0002CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Expression is set
E10018030004 # LOAD32 R0 R3 4 ; Load Node type
E0002CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Typed
E10018030008 # LOAD32 R0 R3 8 ; Load Text pointer
E10014100000 # LOAD8 R1 R0 0 ; Get first char of Text
E0002D0F @numerate_string # CALLI R15 @numerate_string ; Convert to number in R0
E000A0210030 # CMPSKIPI.E R1 48 ; Skip next comparision if '0'
E0002C90 @Eval_Immediates_1 # JUMP.Z R0 @Eval_Immediates_1 ; Don't do anything if string isn't a number
E10020E3000c # STORE R14 R3 12 ; Preserve pointer to expression
E0002D0F @hex16 # CALLI R15 @hex16 ; Shove our number into expression
E1000FEE0001 # ADDUI R14 R14 1 ; Allocate enough space for a null
# ;; Handle looping
:Eval_Immediates_1
09000532 # MOVE R3 R2 ; Prepare for next loop
2CA3 @Eval_Immediates_0 # JUMP.NZ R3 @Eval_Immediates_0 ; And loop
E0002CA3 @Eval_Immediates_0 # JUMP.NZ R3 @Eval_Immediates_0 ; And loop
0D01001F # RET R15
@ -454,55 +454,55 @@ A0210030 # CMPSKIPI.E R1 48 ; Skip next comparision if '0'
09000510 # MOVE R1 R0 ; Get Text pointer out of the way
0D000022 # FALSE R2 ; Set Negative flag to false
0D000023 # FALSE R3 ; Set current count to Zero
14010001 # LOAD8 R0 R1 1 ; Get second byte
A0300078 # CMPSKIPI.NE R0 120 ; If the second byte is x
E10014010001 # LOAD8 R0 R1 1 ; Get second byte
E000A0300078 # CMPSKIPI.NE R0 120 ; If the second byte is x
3C00 @numerate_string_hex # JUMP @numerate_string_hex ; treat string like hex
# ;; Deal with Decimal input
2D24000a # LOADUI R4 10 ; Multiply by 10
14010000 # LOAD8 R0 R1 0 ; Get a byte
A030002d # CMPSKIPI.NE R0 45 ; If - toggle flag
E0002D24000a # LOADUI R4 10 ; Multiply by 10
E10014010000 # LOAD8 R0 R1 0 ; Get a byte
E000A030002d # CMPSKIPI.NE R0 45 ; If - toggle flag
0D000032 # TRUE R2 ; So that we know to negate
A0220000 # CMPSKIPI.E R2 0 ; If toggled
0F110001 # ADDUI R1 R1 1 ; Move to next
E000A0220000 # CMPSKIPI.E R2 0 ; If toggled
E1000F110001 # ADDUI R1 R1 1 ; Move to next
:numerate_string_dec
14010000 # LOAD8 R0 R1 0 ; Get a byte
A0300000 # CMPSKIPI.NE R0 0 ; If NULL
E10014010000 # LOAD8 R0 R1 0 ; Get a byte
E000A0300000 # CMPSKIPI.NE R0 0 ; If NULL
3C00 @numerate_string_done # JUMP @numerate_string_done ; Be done
05006334 # MUL R3 R3 R4 ; Shift counter by 10
10000030 # SUBI R0 R0 48 ; Convert ascii to number
A0100000 # CMPSKIPI.GE R0 0 ; If less than a number
E10010000030 # SUBI R0 R0 48 ; Convert ascii to number
E000A0100000 # CMPSKIPI.GE R0 0 ; If less than a number
3C00 @numerate_string_done # JUMP @numerate_string_done ; Terminate NOW
A050000a # CMPSKIPI.L R0 10 ; If more than a number
E000A050000a # CMPSKIPI.L R0 10 ; If more than a number
3C00 @numerate_string_done # JUMP @numerate_string_done ; Terminate NOW
05001330 # ADDU R3 R3 R0 ; Don't add to the count
0F110001 # ADDUI R1 R1 1 ; Move onto next byte
E1000F110001 # ADDUI R1 R1 1 ; Move onto next byte
3C00 @numerate_string_dec # JUMP @numerate_string_dec
# ;; Deal with Hex input
:numerate_string_hex
14010000 # LOAD8 R0 R1 0 ; Get a byte
A0200030 # CMPSKIPI.E R0 48 ; All hex strings start with 0x
E10014010000 # LOAD8 R0 R1 0 ; Get a byte
E000A0200030 # CMPSKIPI.E R0 48 ; All hex strings start with 0x
3C00 @numerate_string_done # JUMP @numerate_string_done ; Be done if not a match
0F110002 # ADDUI R1 R1 2 ; Move to after leading 0x
E1000F110002 # ADDUI R1 R1 2 ; Move to after leading 0x
:numerate_string_hex_0
14010000 # LOAD8 R0 R1 0 ; Get a byte
2C90 @numerate_string_done # JUMP.Z R0 @numerate_string_done ; If NULL Be done
2D530004 # SL0I R3 4 ; Shift counter by 16
10000030 # SUBI R0 R0 48 ; Convert ascii number to number
A050000a # CMPSKIPI.L R0 10 ; If A-F
10000007 # SUBI R0 R0 7 ; Shove into Range
A0500010 # CMPSKIPI.L R0 16 ; If a-f
10000020 # SUBI R0 R0 32 ; Shove into Range
E10014010000 # LOAD8 R0 R1 0 ; Get a byte
E0002C90 @numerate_string_done # JUMP.Z R0 @numerate_string_done ; If NULL Be done
E0002D530004 # SL0I R3 4 ; Shift counter by 16
E10010000030 # SUBI R0 R0 48 ; Convert ascii number to number
E000A050000a # CMPSKIPI.L R0 10 ; If A-F
E10010000007 # SUBI R0 R0 7 ; Shove into Range
E000A0500010 # CMPSKIPI.L R0 16 ; If a-f
E10010000020 # SUBI R0 R0 32 ; Shove into Range
05001330 # ADDU R3 R3 R0 ; Add to the count
0F110001 # ADDUI R1 R1 1 ; Get next Hex
E1000F110001 # ADDUI R1 R1 1 ; Get next Hex
3C00 @numerate_string_hex_0 # JUMP @numerate_string_hex_0
# ;; Clean up
:numerate_string_done
A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
E000A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
09000033 # NEG R3 R3 ; Make the number negative
09000503 # MOVE R0 R3 ; Put number in R0
@ -523,18 +523,18 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
# ;; Process Node
:Preserve_Other_0
18200000 # LOAD32 R2 R0 0 ; Load Node->Next
18100004 # LOAD32 R1 R0 4 ; Load Node type
2CA1 @Preserve_Other_1 # JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Typed
1810000c # LOAD32 R1 R0 12 ; Load Expression pointer
2CA1 @Preserve_Other_1 # JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Expression is set
18100008 # LOAD32 R1 R0 8 ; Load Text pointer
2310000c # STORE32 R1 R0 12 ; Set Expression pointer to Text pointer
E10018200000 # LOAD32 R2 R0 0 ; Load Node->Next
E10018100004 # LOAD32 R1 R0 4 ; Load Node type
E0002CA1 @Preserve_Other_1 # JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Typed
E1001810000c # LOAD32 R1 R0 12 ; Load Expression pointer
E0002CA1 @Preserve_Other_1 # JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Expression is set
E10018100008 # LOAD32 R1 R0 8 ; Load Text pointer
E1002310000c # STORE32 R1 R0 12 ; Set Expression pointer to Text pointer
# ;; Loop through nodes
:Preserve_Other_1
09000502 # MOVE R0 R2 ; Prepare for next loop
2CA0 @Preserve_Other_0 # JUMP.NZ R0 @Preserve_Other_0
E0002CA0 @Preserve_Other_0 # JUMP.NZ R0 @Preserve_Other_0
0D01001F # RET R15
@ -543,28 +543,28 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
# ;; Starting with HEAD
:Print_Hex
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
E0002D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
# ;; Initialize
0900040D # COPY R0 R13 ; Start with HEAD
2D211101 # LOADUI R1 0x1101 ; Write to Tape_02
E0002D211101 # LOADUI R1 0x1101 ; Write to Tape_02
:Print_Hex_0
18200000 # LOAD32 R2 R0 0 ; Load Node->Next
18300004 # LOAD32 R3 R0 4 ; Load Node type
1800000c # LOAD32 R0 R0 12 ; Load Expression pointer
10330001 # SUBI R3 R3 1 ; Check for Macros
2C93 @Print_Hex_1 # JUMP.Z R3 @Print_Hex_1 ; Don't print Macros
2D0F @Print_Line # CALLI R15 @Print_Line ; Print the Expression
E10018200000 # LOAD32 R2 R0 0 ; Load Node->Next
E10018300004 # LOAD32 R3 R0 4 ; Load Node type
E1001800000c # LOAD32 R0 R0 12 ; Load Expression pointer
E10010330001 # SUBI R3 R3 1 ; Check for Macros
E0002C93 @Print_Hex_1 # JUMP.Z R3 @Print_Hex_1 ; Don't print Macros
E0002D0F @Print_Line # CALLI R15 @Print_Line ; Print the Expression
# ;; Loop down the nodes
:Print_Hex_1
09000502 # MOVE R0 R2 ; Prepare for next loop
2CA0 @Print_Hex_0 # JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL
E0002CA0 @Print_Hex_0 # JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL
# ;; Done writing File
2D201101 # LOADUI R0 0x1101 ; Close TAPE_01
E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_01
42100002 # FCLOSE
0D01001F # RET R15
@ -579,16 +579,16 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
09000530 # MOVE R3 R0 ; Get Pointer safely out of the way
:Print_Line_0
15030000 # LOADU8 R0 R3 0 ; Get our first byte
A0300000 # CMPSKIPI.NE R0 0 ; If the loaded byte is NULL
E10015030000 # LOADU8 R0 R3 0 ; Get our first byte
E000A0300000 # CMPSKIPI.NE R0 0 ; If the loaded byte is NULL
3C00 @Print_Line_Done # JUMP @Print_Line_Done ; Be done
42100200 # FPUTC ; Otherwise print
0F330001 # ADDUI R3 R3 1 ; Increment for next loop
E1000F330001 # ADDUI R3 R3 1 ; Increment for next loop
3C00 @Print_Line_0 # JUMP @Print_Line_0 ; And Loop
# ;; Clean up
:Print_Line_Done
2D20000a # LOADUI R0 10 ; Put in Newline char
E0002D20000a # LOADUI R0 10 ; Put in Newline char
42100200 # FPUTC ; Write it out
0D01001F # RET R15

View File

@ -1,432 +0,0 @@
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 is free software: you an redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## stage0 is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with stage0. If not, see <http://www.gnu.org/licenses/>.
# :start
2D2F0394 # LOADUI R15 $stack ; Put stack at end of program
# ;; We will be using R14 for our condition codes
# ;; We will be using R13 for storage of Head
# ;; Main program
# ;; Reads contents of Tape_01 and writes desired contents onto Tape_02
# ;; Accepts no arguments and HALTS when done
# :main
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
# ;; Prepare to Read File
0D00002E # FALSE R14
0D000021 # FALSE R1
2D0F0018 # CALLI R15 @ReadFile
# ;; Done reading File
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
# ;; Enter Editor Loop
090005D1 # MOVE R13 R1 ; Set R13 to Head
2D0F0134 # CALLI R15 @EditorLoop
# ;; And We are Done
FFFFFFFF # HALT
# ;; Readfile function
# ;; Recieves pointer to head in R1
# ;; Creates Nodes and imports text until EOF
# ;; Alters R0 R1 R14
# ;; Returns to whatever called it
# :ReadFile
# ;; Allocate another Node
2D20000c # LOADUI R0 12
2D0F0100 # CALLI R15 @malloc
# ;; Get another line into list
0902001F # PUSHR R1 R15
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
2D0F001c # CALLI R15 @Readline
0902801F # POPR R1 R15
09000301 # SWAP R0 R1
2D0F00a0 # CALLI R15 @addline
09000301 # SWAP R0 R1
# ;; Loop if not reached EOF
2C9Effdc # JUMP.Z R14 @ReadFile
0D01001F # RET R15
# ;; Readline function
# ;; Recieves Pointer to node in R0
# ;; And Input in R1
# ;; Allocates Text segment on Heap
# ;; Sets node's pointer to Text segment
# ;; Sets R14 to True if EOF reached
# ;; Returns to whatever called it
# :Readline
# ;; Preserve registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize
09000540 # MOVE R4 R0
2D200100 # LOADUI R0 256
2D0F00bc # CALLI R15 @malloc
09000520 # MOVE R2 R0
0D000023 # FALSE R3
# :Readline_0
42100100 # FGETC ; Read a Char
# ;; Flag if reached EOF
A0100000 # CMPSKIPI.GE R0 0
0D00003E # TRUE R14
# ;; Stop if EOF
A0100000 # CMPSKIPI.GE R0 0
3C00003c # JUMP @Readline_2
# ;; Handle Backspace
A020007f # CMPSKIPI.E R0 127
3C000010 # JUMP @Readline_1
# ;; Move back 1 character if R3 > 0
A0430000 # CMPSKIPI.LE R3 0
11330001 # SUBUI R3 R3 1
# ;; Hopefully they keep typing
3C00ffdc # JUMP @Readline_0
# :Readline_1
# ;; Replace all CR with LF
A030000d # CMPSKIPI.NE R0 13
2D20000a # LOADUI R0 10
# ;; Store the Byte
05049023 # STOREX8 R0 R2 R3
# ;; Check for EOL
A030000a # CMPSKIPI.NE R0 10
3C000014 # JUMP @Readline_2
# ;; Prevent lines from exceeding 255 chars
A04300ff # CMPSKIPI.LE R3 255
3C00000c # JUMP @Readline_2
# ;; Prep for next loop
0F330001 # ADDUI R3 R3 1
3C00ffb8 # JUMP @Readline_0
# :Readline_2
# ;; Set Text pointer
23240008 # STORE32 R2 R4 8
# ;; Restore Registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15
# ;; addline Function
# ;; Recieves pointers in R0 R1
# ;; Alters R0 if NULL
# ;; Appends nodes together
# ;; Returns to whatever called it
# :addline
# ;; Preserve Registers
0902002F # PUSHR R2 R15
0902001F # PUSHR R1 R15
0902000F # PUSHR R0 R15
# ;; Handle if Head is NULL
2CA00010 # JUMP.NZ R0 @addline_0
0902800F # POPR R0 R15
0902001F # PUSHR R1 R15
3C000020 # JUMP @addline_2
# :addline_0
# ;; Handle if Head->next is NULL
18200000 # LOAD32 R2 R0 0
2CA20010 # JUMP.NZ R2 @addline_1
# ;; Set head->next = p
23100000 # STORE32 R1 R0 0
# ;; Set p->prev = head
23010004 # STORE32 R0 R1 4
3C00000c # JUMP @addline_2
# :addline_1
# ;; Handle case of Head->next not being NULL
18000000 # LOAD32 R0 R0 0
2D0Fffcc # CALLI R15 @addline
# :addline_2
# ;; Restore registers
0902800F # POPR R0 R15
0902801F # POPR R1 R15
0902802F # POPR R2 R15
0D01001F # RET R15
# ;; Primative malloc function
# ;; Recieves number of bytes to allocate in R0
# ;; Returns pointer to block of that size in R0
# ;; Returns to whatever called it
# :malloc
# ;; Preserve registers
0902001F # PUSHR R1 R15
# ;; Get current malloc pointer
2E010020 # LOADR R1 @malloc_pointer
# ;; Deal with special case
A0310000 # CMPSKIPI.NE R1 0 ; If Zero set to our start of heap space
2D214000 # LOADUI R1 0x4000
# ;; update malloc pointer
09000301 # SWAP R0 R1
05000101 # ADD R1 R0 R1
2F01000c # STORER R1 @malloc_pointer
# ;; Done
# ;; Restore registers
0902801F # POPR R1 R15
0D01001F # RET R15
# ;; Our static value for malloc pointer
# :malloc_pointer
00000000 # NOP
# ;; Editor Loop
# ;; Provides user interaction
# ;; Requires R13 to be pointer to Head
# ;; Internally loops
# ;; Returns nothing
# :EditorLoop
0D000021 # FALSE R1 ; Read from tty
42100100 # FGETC ; Read a Char
# ;; Quit if q
A0300071 # CMPSKIPI.NE R0 113
0D01001F # RET R15
# ;; Print if p
1FE00070 # CMPUI R14 R0 112
2C6E0014 # JUMP.NE R14 @EditorLoop_0
180D0008 # LOAD32 R0 R13 8
0D000021 # FALSE R1
2D0F0118 # CALLI R15 @PrintLine
3C00ffdc # JUMP @EditorLoop
# :EditorLoop_0
# ;; Move forward if f
1FE00066 # CMPUI R14 R0 102
2C6E0014 # JUMP.NE R14 @EditorLoop_1
180D0000 # LOAD32 R0 R13 0 ; Load head->next
# ;; If head->next isn't null make it the new head
A0200000 # CMPSKIPI.E R0 0
090005D0 # MOVE R13 R0
3C00ffc4 # JUMP @EditorLoop
# :EditorLoop_1
# ;; Move backward if b
1FE00062 # CMPUI R14 R0 98
2C6E0014 # JUMP.NE R14 @EditorLoop_2
180D0004 # LOAD32 R0 R13 4 ; Load head->prev
# ;; If head->prev isn't null make it the new head
A0200000 # CMPSKIPI.E R0 0
090005D0 # MOVE R13 R0
3C00ffac # JUMP @EditorLoop
# :EditorLoop_2
# ;; Edit Line if e
1FE00065 # CMPUI R14 R0 101
2C6E0014 # JUMP.NE R14 @EditorLoop_3
# ;; Change Head's Text
0900040D # COPY R0 R13
0D000021 # FALSE R1 ; Read from tty
2D0Ffe98 # CALLI R15 @Readline
3C00ff94 # JUMP @EditorLoop
# :EditorLoop_3
# ;; Writeout to tape_02 if w
1FE00077 # CMPUI R14 R0 119
2C6E0028 # JUMP.NE R14 @EditorLoop_4
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
0900040D # COPY R0 R13
2D211101 # LOADUI R1 0x1101
2D0F0058 # CALLI R15 @GetRoot
2D0F0074 # CALLI R15 @PrintAll
2D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
3C00ff68 # JUMP @EditorLoop
# :EditorLoop_4
# ;; Append node if a
1FE00061 # CMPUI R14 R0 97
2C6E0010 # JUMP.NE R14 @EditorLoop_5
0900040D # COPY R0 R13
2D0F00dc # CALLI R15 @AppendLine
3C00ff54 # JUMP @EditorLoop
# :EditorLoop_5
# ;; Insert node if i
1FE00069 # CMPUI R14 R0 105
2C6E0010 # JUMP.NE R14 @EditorLoop_6
0900040D # COPY R0 R13
2D0F0108 # CALLI R15 @InsertLine
3C00ff40 # JUMP @EditorLoop
# :EditorLoop_6
# ;; Delete node if d
1FE00064 # CMPUI R14 R0 100
2C6E0014 # JUMP.NE R14 @EditorLoop_7
0900040D # COPY R0 R13
2D0F0134 # CALLI R15 @RemoveLine
090005D0 # MOVE R13 R0
3C00ff28 # JUMP @EditorLoop
# :EditorLoop_7
3C00ff24 # JUMP @EditorLoop
# ;; GetRoot function
# ;; Walks backwards through nodes until beginning
# ;; Recieves node pointer in R0 and Returns result in R0
# ;; Returns to whatever called it
# :GetRoot
# ;; Preserve registers
0902001F # PUSHR R1 R15
# :GetRoot_0
# ;; Get Head->Prev
18100004 # LOAD32 R1 R0 4
A0310000 # CMPSKIPI.NE R1 0
3C00000c # JUMP @GetRoot_1
09000501 # MOVE R0 R1
3C00fff0 # JUMP @GetRoot_0
# :GetRoot_1
# ;; Restore registers
0902801F # POPR R1 R15
0D01001F # RET R15
# ;; Printall Function
# ;; Prints all lines to Interface in R1
# ;; Starting at node in R0
# ;; Does not alter registers
# ;; Returns to whatever called it
# :PrintAll
# ;; Preserve registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
# :PrintAll_0
18200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2
18000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text
2D0F0024 # CALLI R15 @PrintLine ; Prints Head->Text
A0320000 # CMPSKIPI.NE R2 0 ; If Head->Next is NULL
3C00000c # JUMP @PrintAll_1 ; Stop Looping
09000502 # MOVE R0 R2 ; Otherwise Move to Next Node
3C00ffe8 # JUMP @PrintAll_0 ; And Loop
# :PrintAll_1
# ;; Restore registers
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15
# ;; Printline function
# ;; Recieves a string pointer in R0
# ;; Prints string interface specified in R1
# ;; Does not alter registers
# ;; Returns to whatever called it
# :PrintLine
# ;; Preserve registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
# ;; Initialize
09000520 # MOVE R2 R0
0D000023 # FALSE R3
# ;; Deal with NULL Pointer
A0320000 # CMPSKIPI.NE R2 0
3C00001c # JUMP @PrintLine_1
# :PrintLine_0
0503A023 # LOADXU8 R0 R2 R3 ; Load char from string
# ;; Don't print NULLs
A0300000 # CMPSKIPI.NE R0 0
3C000010 # JUMP @PrintLine_1
42100200 # FPUTC
# ; Print the char
0F330001 # ADDUI R3 R3 1 ; Prep for next loop
3C00ffec # JUMP @PrintLine_0
# :PrintLine_1
# ;; Restore registers
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15
# ;; AppendLine Function
# ;; Recieves a Node in R0
# ;; Creates a new Node and appends it
# ;; Does not alter registers
# ;; Returns to whatever calls it
# :AppendLine
# ;; Preserve registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
# ;; Initialize
09000510 # MOVE R1 R0
# ;; Allocate another Node
2D20000c # LOADUI R0 12
2D0Ffe40 # CALLI R15 @malloc
# ;; Check if head->Next is null
18210000 # LOAD32 R2 R1 0
A0220000 # CMPSKIPI.E R2 0 ; If head->Next is something
23020004 # STORE32 R0 R2 4 ; Set head->next->prev to p
# ;; Setup p and head
23200000 # STORE32 R2 R0 0 ; p->next = head->next
23100004 # STORE32 R1 R0 4 ; p->prev = head
23010000 # STORE32 R0 R1 0 ; head->next = p
# ;; Restore Registers
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15
# ;; InsertLine Function
# ;; Recieves a Node in R0
# ;; Creates a new Node and prepends it
# ;; Does not alter registers
# ;; Returns to whatever called it
# :InsertLine
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
# ;; Initialize
09000510 # MOVE R1 R0
# ;; Allocate another Node
2D20000c # LOADUI R0 12
2D0Ffe00 # CALLI R15 @malloc
# ;; Check if Head->Prev is Null
18210004 # LOAD32 R2 R1 4
A0220000 # CMPSKIPI.E R2 0 ; If head->prev is something
23020000 # STORE32 R0 R2 0 ; Set head->prev->next to p
# ;; Setup p and head
23200004 # STORE32 R2 R0 4 ; p->prev = head->prev
23100000 # STORE32 R1 R0 0 ; p->next = head
23010004 # STORE32 R0 R1 4 ; head->prev = p
# ;; Restore Registers
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15
# ;; RemoveLine Function
# ;; Recieves Node in R0
# ;; Returns replacement node in R0
# ;; Returns to whatever called it
# :RemoveLine
# ;; Preserve Registers
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
# ;; Initialize
09000510 # MOVE R1 R0
18010004 # LOAD32 R0 R1 4 ; put p->prev in R0
18210000 # LOAD32 R2 R1 0 ; put p->next in R2
# ;; Keep links
A0200000 # CMPSKIPI.E R0 0 ; If p->prev is not null
23200000 # STORE32 R2 R0 0 ; p->prev->next = p->next
A0220000 # CMPSKIPI.E R2 0 ; If p->next is not null
23020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev
# ;; Attempt to save what is left of the list
A0300000 # CMPSKIPI.NE R0 0 ; If p->prev is null
09000502 # MOVE R0 R2 ; return p->next
# ;; Restore Registers
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0D01001F # RET R15
# ;; Where our stack begins
# :stack

View File

@ -1,7 +1,7 @@
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 is free software: you an redistribute it and/or modify
## stage0 is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
@ -15,28 +15,28 @@
## along with stage0. If not, see <http://www.gnu.org/licenses/>.
:start
2D2F $stack # LOADUI R15 $stack ; Put stack at end of program
E0002D2F $stack # LOADUI R15 $stack ; Put stack at end of program
# ;; We will be using R14 for our condition codes
# ;; We will be using R13 for storage of Head
E0002D2C4000 # LOADUI R12 0x4000 ; We will be using R12 for the HEAP
# ;; Main program
# ;; Reads contents of Tape_01 and writes desired contents onto Tape_02
# ;; Accepts no arguments and HALTS when done
:main
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
E0002D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
# ;; Prepare to Read File
0D00002E # FALSE R14
0D000021 # FALSE R1
2D0F @ReadFile # CALLI R15 @ReadFile
E0002D0F @ReadFile # CALLI R15 @ReadFile
# ;; Done reading File
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
# ;; Enter Editor Loop
090005D1 # MOVE R13 R1 ; Set R13 to Head
2D0F @EditorLoop # CALLI R15 @EditorLoop
E0002D0F @EditorLoop # CALLI R15 @EditorLoop
# ;; And We are Done
FFFFFFFF # HALT
@ -48,18 +48,18 @@ FFFFFFFF # HALT
# ;; Returns to whatever called it
:ReadFile
# ;; Allocate another Node
2D20000c # LOADUI R0 12
2D0F @malloc # CALLI R15 @malloc
0900040C # COPY R0 R12 ; Copy Current free into R0
E1000FCC000c # ADDUI R12 R12 12 ; Allocate Node
# ;; Get another line into list
0902001F # PUSHR R1 R15
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
2D0F @Readline # CALLI R15 @Readline
E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
E0002D0F @Readline # CALLI R15 @Readline
0902801F # POPR R1 R15
09000301 # SWAP R0 R1
2D0F @addline # CALLI R15 @addline
E0002D0F @addline # CALLI R15 @addline
09000301 # SWAP R0 R1
# ;; Loop if not reached EOF
2C9E @ReadFile # JUMP.Z R14 @ReadFile
E0002C9E @ReadFile # JUMP.Z R14 @ReadFile
0D01001F # RET R15
@ -79,44 +79,49 @@ FFFFFFFF # HALT
0902004F # PUSHR R4 R15
# ;; Initialize
09000540 # MOVE R4 R0
2D200100 # LOADUI R0 256
2D0F @malloc # CALLI R15 @malloc
0900040C # COPY R0 R12 ; Get where space is free
09000520 # MOVE R2 R0
0D000023 # FALSE R3
:Readline_0
42100100 # FGETC ; Read a Char
# ;; Flag if reached EOF
A0100000 # CMPSKIPI.GE R0 0
E000A0100000 # CMPSKIPI.GE R0 0
0D00003E # TRUE R14
# ;; Stop if EOF
A0100000 # CMPSKIPI.GE R0 0
E000A0100000 # CMPSKIPI.GE R0 0
3C00 @Readline_2 # JUMP @Readline_2
# ;; Handle Backspace
A020007f # CMPSKIPI.E R0 127
E000A020007f # CMPSKIPI.E R0 127
3C00 @Readline_1 # JUMP @Readline_1
# ;; Move back 1 character if R3 > 0
A0430000 # CMPSKIPI.LE R3 0
11330001 # SUBUI R3 R3 1
E000A0430000 # CMPSKIPI.LE R3 0
E10011330001 # SUBUI R3 R3 1
# ;; Hopefully they keep typing
3C00 @Readline_0 # JUMP @Readline_0
:Readline_1
# ;; Replace all CR with LF
A030000d # CMPSKIPI.NE R0 13
2D20000a # LOADUI R0 10
E000A030000d # CMPSKIPI.NE R0 13
E0002D20000a # LOADUI R0 10
# ;; Store the Byte
05049023 # STOREX8 R0 R2 R3
# ;; Check for EOL
A030000a # CMPSKIPI.NE R0 10
3C00 @Readline_2 # JUMP @Readline_2
# ;; Prevent lines from exceeding 255 chars
A04300ff # CMPSKIPI.LE R3 255
3C00 @Readline_2 # JUMP @Readline_2
# ;; Prep for next loop
0F330001 # ADDUI R3 R3 1
E1000F330001 # ADDUI R3 R3 1
# ;; Check for EOL
E000A030000a # CMPSKIPI.NE R0 10
3C00 @Readline_2 # JUMP @Readline_2
# ;; Otherwise loop
3C00 @Readline_0 # JUMP @Readline_0
:Readline_2
# ;; Set Text pointer
23240008 # STORE32 R2 R4 8
E000A0230000 # CMPSKIPI.E R3 0 ; Don't bother for Empty strings
E10023240008 # STORE32 R2 R4 8
# ;; Correct Malloc
05000CC3 # ADD R12 R12 R3 ; Ensure actually allocates exactly the amount of space required
# ;; Restore Registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
@ -137,23 +142,26 @@ A04300ff # CMPSKIPI.LE R3 255
0902001F # PUSHR R1 R15
0902000F # PUSHR R0 R15
# ;; Handle if Head is NULL
2CA0 @addline_0 # JUMP.NZ R0 @addline_0
E0002CA0 @addline_0 # JUMP.NZ R0 @addline_0
0902800F # POPR R0 R15
0902001F # PUSHR R1 R15
3C00 @addline_2 # JUMP @addline_2
:addline_0
# ;; Handle if Head->next is NULL
18200000 # LOAD32 R2 R0 0
2CA2 @addline_1 # JUMP.NZ R2 @addline_1
E10018200000 # LOAD32 R2 R0 0
E0002CA2 @addline_1 # JUMP.NZ R2 @addline_1
# ;; Set head->next = p
23100000 # STORE32 R1 R0 0
E10023100000 # STORE32 R1 R0 0
# ;; Set p->prev = head
23010004 # STORE32 R0 R1 4
E10023010004 # STORE32 R0 R1 4
3C00 @addline_2 # JUMP @addline_2
:addline_1
# ;; Handle case of Head->next not being NULL
18000000 # LOAD32 R0 R0 0
2D0F @addline # CALLI R15 @addline
E10018000000 # LOAD32 R0 R0 0 ; Move to next node
E10018200000 # LOAD32 R2 R0 0 ; Get node->next
E000A0220000 # CMPSKIPI.E R2 0 ; If it is not null
3C00 @addline_1 # JUMP @addline_1 ; Move to the next node and try again
3C00 @addline_0 # JUMP @addline_0 ; Else simply act as if we got this node in the first place
:addline_2
# ;; Restore registers
0902800F # POPR R0 R15
@ -162,31 +170,6 @@ A04300ff # CMPSKIPI.LE R3 255
0D01001F # RET R15
# ;; Primative malloc function
# ;; Recieves number of bytes to allocate in R0
# ;; Returns pointer to block of that size in R0
# ;; Returns to whatever called it
:malloc
# ;; Preserve registers
0902001F # PUSHR R1 R15
# ;; Get current malloc pointer
2E01 @malloc_pointer # LOADR R1 @malloc_pointer
# ;; Deal with special case
A0310000 # CMPSKIPI.NE R1 0 ; If Zero set to our start of heap space
2D214000 # LOADUI R1 0x4000
# ;; update malloc pointer
09000301 # SWAP R0 R1
05000101 # ADD R1 R0 R1
2F01 @malloc_pointer # STORER R1 @malloc_pointer
# ;; Done
# ;; Restore registers
0902801F # POPR R1 R15
0D01001F # RET R15
# ;; Our static value for malloc pointer
:malloc_pointer
00000000 # NOP
# ;; Editor Loop
# ;; Provides user interaction
# ;; Requires R13 to be pointer to Head
@ -196,76 +179,76 @@ A0310000 # CMPSKIPI.NE R1 0 ; If Zero set to our start of heap space
0D000021 # FALSE R1 ; Read from tty
42100100 # FGETC ; Read a Char
# ;; Quit if q
A0300071 # CMPSKIPI.NE R0 113
E000A0300071 # CMPSKIPI.NE R0 113
0D01001F # RET R15
# ;; Print if p
1FE00070 # CMPUI R14 R0 112
2C6E @EditorLoop_0 # JUMP.NE R14 @EditorLoop_0
180D0008 # LOAD32 R0 R13 8
E1001FE00070 # CMPUI R14 R0 112
E0002C6E @EditorLoop_0 # JUMP.NE R14 @EditorLoop_0
E100180D0008 # LOAD32 R0 R13 8
0D000021 # FALSE R1
2D0F @PrintLine # CALLI R15 @PrintLine
E0002D0F @PrintLine # CALLI R15 @PrintLine
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_0
# ;; Move forward if f
1FE00066 # CMPUI R14 R0 102
2C6E @EditorLoop_1 # JUMP.NE R14 @EditorLoop_1
180D0000 # LOAD32 R0 R13 0 ; Load head->next
E1001FE00066 # CMPUI R14 R0 102
E0002C6E @EditorLoop_1 # JUMP.NE R14 @EditorLoop_1
E100180D0000 # LOAD32 R0 R13 0 ; Load head->next
# ;; If head->next isn't null make it the new head
A0200000 # CMPSKIPI.E R0 0
E000A0200000 # CMPSKIPI.E R0 0
090005D0 # MOVE R13 R0
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_1
# ;; Move backward if b
1FE00062 # CMPUI R14 R0 98
2C6E @EditorLoop_2 # JUMP.NE R14 @EditorLoop_2
180D0004 # LOAD32 R0 R13 4 ; Load head->prev
E1001FE00062 # CMPUI R14 R0 98
E0002C6E @EditorLoop_2 # JUMP.NE R14 @EditorLoop_2
E100180D0004 # LOAD32 R0 R13 4 ; Load head->prev
# ;; If head->prev isn't null make it the new head
A0200000 # CMPSKIPI.E R0 0
E000A0200000 # CMPSKIPI.E R0 0
090005D0 # MOVE R13 R0
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_2
# ;; Edit Line if e
1FE00065 # CMPUI R14 R0 101
2C6E @EditorLoop_3 # JUMP.NE R14 @EditorLoop_3
E1001FE00065 # CMPUI R14 R0 101
E0002C6E @EditorLoop_3 # JUMP.NE R14 @EditorLoop_3
# ;; Change Head's Text
0900040D # COPY R0 R13
0D000021 # FALSE R1 ; Read from tty
2D0F @Readline # CALLI R15 @Readline
E0002D0F @Readline # CALLI R15 @Readline
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_3
# ;; Writeout to tape_02 if w
1FE00077 # CMPUI R14 R0 119
2C6E @EditorLoop_4 # JUMP.NE R14 @EditorLoop_4
E1001FE00077 # CMPUI R14 R0 119
E0002C6E @EditorLoop_4 # JUMP.NE R14 @EditorLoop_4
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
E0002D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
0900040D # COPY R0 R13
2D211101 # LOADUI R1 0x1101
2D0F @GetRoot # CALLI R15 @GetRoot
2D0F @PrintAll # CALLI R15 @PrintAll
2D201101 # LOADUI R0 0x1101 ; Close TAPE_02
E0002D211101 # LOADUI R1 0x1101
E0002D0F @GetRoot # CALLI R15 @GetRoot
E0002D0F @PrintAll # CALLI R15 @PrintAll
E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_4
# ;; Append node if a
1FE00061 # CMPUI R14 R0 97
2C6E @EditorLoop_5 # JUMP.NE R14 @EditorLoop_5
E1001FE00061 # CMPUI R14 R0 97
E0002C6E @EditorLoop_5 # JUMP.NE R14 @EditorLoop_5
0900040D # COPY R0 R13
2D0F @AppendLine # CALLI R15 @AppendLine
E0002D0F @AppendLine # CALLI R15 @AppendLine
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_5
# ;; Insert node if i
1FE00069 # CMPUI R14 R0 105
2C6E @EditorLoop_6 # JUMP.NE R14 @EditorLoop_6
E1001FE00069 # CMPUI R14 R0 105
E0002C6E @EditorLoop_6 # JUMP.NE R14 @EditorLoop_6
0900040D # COPY R0 R13
2D0F @InsertLine # CALLI R15 @InsertLine
E0002D0F @InsertLine # CALLI R15 @InsertLine
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_6
# ;; Delete node if d
1FE00064 # CMPUI R14 R0 100
2C6E @EditorLoop_7 # JUMP.NE R14 @EditorLoop_7
E1001FE00064 # CMPUI R14 R0 100
E0002C6E @EditorLoop_7 # JUMP.NE R14 @EditorLoop_7
0900040D # COPY R0 R13
2D0F @RemoveLine # CALLI R15 @RemoveLine
E0002D0F @RemoveLine # CALLI R15 @RemoveLine
090005D0 # MOVE R13 R0
3C00 @EditorLoop # JUMP @EditorLoop
:EditorLoop_7
@ -281,8 +264,8 @@ A0200000 # CMPSKIPI.E R0 0
0902001F # PUSHR R1 R15
:GetRoot_0
# ;; Get Head->Prev
18100004 # LOAD32 R1 R0 4
A0310000 # CMPSKIPI.NE R1 0
E10018100004 # LOAD32 R1 R0 4
E000A0310000 # CMPSKIPI.NE R1 0
3C00 @GetRoot_1 # JUMP @GetRoot_1
09000501 # MOVE R0 R1
3C00 @GetRoot_0 # JUMP @GetRoot_0
@ -303,10 +286,10 @@ A0310000 # CMPSKIPI.NE R1 0
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
:PrintAll_0
18200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2
18000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text
2D0F @PrintLine # CALLI R15 @PrintLine ; Prints Head->Text
A0320000 # CMPSKIPI.NE R2 0 ; If Head->Next is NULL
E10018200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2
E10018000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text
E0002D0F @PrintLine # CALLI R15 @PrintLine ; Prints Head->Text
E000A0320000 # CMPSKIPI.NE R2 0 ; If Head->Next is NULL
3C00 @PrintAll_1 # JUMP @PrintAll_1 ; Stop Looping
09000502 # MOVE R0 R2 ; Otherwise Move to Next Node
3C00 @PrintAll_0 # JUMP @PrintAll_0 ; And Loop
@ -333,16 +316,16 @@ A0320000 # CMPSKIPI.NE R2 0 ; If Head->Next is NULL
09000520 # MOVE R2 R0
0D000023 # FALSE R3
# ;; Deal with NULL Pointer
A0320000 # CMPSKIPI.NE R2 0
E000A0320000 # CMPSKIPI.NE R2 0
3C00 @PrintLine_1 # JUMP @PrintLine_1
:PrintLine_0
0503A023 # LOADXU8 R0 R2 R3 ; Load char from string
# ;; Don't print NULLs
A0300000 # CMPSKIPI.NE R0 0
E000A0300000 # CMPSKIPI.NE R0 0
3C00 @PrintLine_1 # JUMP @PrintLine_1
42100200 # FPUTC
# ; Print the char
0F330001 # ADDUI R3 R3 1 ; Prep for next loop
E1000F330001 # ADDUI R3 R3 1 ; Prep for next loop
3C00 @PrintLine_0 # JUMP @PrintLine_0
:PrintLine_1
# ;; Restore registers
@ -366,16 +349,16 @@ A0300000 # CMPSKIPI.NE R0 0
# ;; Initialize
09000510 # MOVE R1 R0
# ;; Allocate another Node
2D20000c # LOADUI R0 12
2D0F @malloc # CALLI R15 @malloc
0900040C # COPY R0 R12
E1000FCC000c # ADDUI R12 R12 12
# ;; Check if head->Next is null
18210000 # LOAD32 R2 R1 0
A0220000 # CMPSKIPI.E R2 0 ; If head->Next is something
23020004 # STORE32 R0 R2 4 ; Set head->next->prev to p
E10018210000 # LOAD32 R2 R1 0
E000A0220000 # CMPSKIPI.E R2 0 ; If head->Next is something
E10023020004 # STORE32 R0 R2 4 ; Set head->next->prev to p
# ;; Setup p and head
23200000 # STORE32 R2 R0 0 ; p->next = head->next
23100004 # STORE32 R1 R0 4 ; p->prev = head
23010000 # STORE32 R0 R1 0 ; head->next = p
E10023200000 # STORE32 R2 R0 0 ; p->next = head->next
E10023100004 # STORE32 R1 R0 4 ; p->prev = head
E10023010000 # STORE32 R0 R1 0 ; head->next = p
# ;; Restore Registers
0902802F # POPR R2 R15
0902801F # POPR R1 R15
@ -396,16 +379,16 @@ A0220000 # CMPSKIPI.E R2 0 ; If head->Next is something
# ;; Initialize
09000510 # MOVE R1 R0
# ;; Allocate another Node
2D20000c # LOADUI R0 12
2D0F @malloc # CALLI R15 @malloc
0900040C # COPY R0 R12
E1000FCC000c # ADDUI R12 R12 12
# ;; Check if Head->Prev is Null
18210004 # LOAD32 R2 R1 4
A0220000 # CMPSKIPI.E R2 0 ; If head->prev is something
23020000 # STORE32 R0 R2 0 ; Set head->prev->next to p
E10018210004 # LOAD32 R2 R1 4
E000A0220000 # CMPSKIPI.E R2 0 ; If head->prev is something
E10023020000 # STORE32 R0 R2 0 ; Set head->prev->next to p
# ;; Setup p and head
23200004 # STORE32 R2 R0 4 ; p->prev = head->prev
23100000 # STORE32 R1 R0 0 ; p->next = head
23010004 # STORE32 R0 R1 4 ; head->prev = p
E10023200004 # STORE32 R2 R0 4 ; p->prev = head->prev
E10023100000 # STORE32 R1 R0 0 ; p->next = head
E10023010004 # STORE32 R0 R1 4 ; head->prev = p
# ;; Restore Registers
0902802F # POPR R2 R15
0902801F # POPR R1 R15
@ -423,15 +406,15 @@ A0220000 # CMPSKIPI.E R2 0 ; If head->prev is something
0902002F # PUSHR R2 R15
# ;; Initialize
09000510 # MOVE R1 R0
18010004 # LOAD32 R0 R1 4 ; put p->prev in R0
18210000 # LOAD32 R2 R1 0 ; put p->next in R2
E10018010004 # LOAD32 R0 R1 4 ; put p->prev in R0
E10018210000 # LOAD32 R2 R1 0 ; put p->next in R2
# ;; Keep links
A0200000 # CMPSKIPI.E R0 0 ; If p->prev is not null
23200000 # STORE32 R2 R0 0 ; p->prev->next = p->next
A0220000 # CMPSKIPI.E R2 0 ; If p->next is not null
23020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev
E000A0200000 # CMPSKIPI.E R0 0 ; If p->prev is not null
E10023200000 # STORE32 R2 R0 0 ; p->prev->next = p->next
E000A0220000 # CMPSKIPI.E R2 0 ; If p->next is not null
E10023020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev
# ;; Attempt to save what is left of the list
A0300000 # CMPSKIPI.NE R0 0 ; If p->prev is null
E000A0300000 # CMPSKIPI.NE R0 0 ; If p->prev is null
09000502 # MOVE R0 R2 ; return p->next
# ;; Restore Registers
0902802F # POPR R2 R15

View File

@ -18,6 +18,7 @@
LOADUI R15 $stack ; Put stack at end of program
;; We will be using R14 for our condition codes
;; We will be using R13 for storage of Head
LOADUI R12 0x4000 ; We will be using R12 for the HEAP
;; Main program
@ -52,8 +53,8 @@
;; Returns to whatever called it
:ReadFile
;; Allocate another Node
LOADUI R0 12
CALLI R15 @malloc
COPY R0 R12 ; Copy Current free into R0
ADDUI R12 R12 12 ; Allocate Node
;; Get another line into list
PUSHR R1 R15
LOADUI R1 0x1100 ; Read from tape_01
@ -83,8 +84,7 @@
PUSHR R4 R15
;; Initialize
MOVE R4 R0
FALSE R0 ; Get where space is free
CALLI R15 @malloc
COPY R0 R12 ; Get where space is free
MOVE R2 R0
FALSE R3
:Readline_0
@ -132,8 +132,7 @@
CMPSKIPI.E R3 0 ; Don't bother for Empty strings
STORE32 R2 R4 8
;; Correct Malloc
MOVE R0 R3 ; Ensure actually allocates exactly
CALLI R15 @malloc ; the amount of space required
ADD R12 R12 R3 ; Ensure actually allocates exactly the amount of space required
;; Restore Registers
POPR R4 R15
POPR R3 R15
@ -187,33 +186,6 @@
RET R15
;; Primative malloc function
;; Recieves number of bytes to allocate in R0
;; Returns pointer to block of that size in R0
;; Returns to whatever called it
:malloc
;; Preserve registers
PUSHR R1 R15
;; Get current malloc pointer
LOADR R1 @malloc_pointer
;; Deal with special case
CMPSKIPI.NE R1 0 ; If Zero set to our start of heap space
LOADUI R1 0x4000
;; update malloc pointer
SWAP R0 R1
ADD R1 R0 R1
STORER R1 @malloc_pointer
;; Done
;; Restore registers
POPR R1 R15
RET R15
;; Our static value for malloc pointer
:malloc_pointer
NOP
;; Editor Loop
;; Provides user interaction
;; Requires R13 to be pointer to Head
@ -414,8 +386,8 @@
;; Initialize
MOVE R1 R0
;; Allocate another Node
LOADUI R0 12
CALLI R15 @malloc
COPY R0 R12
ADDUI R12 R12 12
;; Check if head->Next is null
LOAD32 R2 R1 0
@ -447,8 +419,8 @@
;; Initialize
MOVE R1 R0
;; Allocate another Node
LOADUI R0 12
CALLI R15 @malloc
COPY R0 R12
ADDUI R12 R12 12
;; Check if Head->Prev is Null
LOAD32 R2 R1 4

View File

@ -1,7 +1,7 @@
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 is free software: you an redistribute it and/or modify
## stage0 is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
@ -16,7 +16,7 @@
# :start
0D00002E # FALSE R14 ; R14 will be storing our current address
2D2F00e0 # LOADUI R15 $end ; We will be using R15 for our stack
E0002D2F0118 # LOADUI R15 $end ; We will be using R15 for our stack
# ;; Main program functionality
@ -24,29 +24,29 @@
# ;; Accepts no arguments and HALTS when done
# :main
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
E0002D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
E0002D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
# ;; Perform main loop
# :main_0
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
42100100 # FGETC ; Read a Char
# ;; Check for EOF
A0100000 # CMPSKIPI.GE R0 0
E000A0100000 # CMPSKIPI.GE R0 0
3C000010 # JUMP @main_1
# ;; Process that byte
2D0F0020 # CALLI R15 @dehex
E0002D0F0022 # CALLI R15 @dehex
# ;; Increment address
0FEE0001 # ADDUI R14 R14 1
E1000FEE0001 # ADDUI R14 R14 1
# ;; Get next byte
3C00ffe8 # JUMP @main_0
3C00ffdc # JUMP @main_0
# :main_1
# ;; Close up as we are done
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
2D201101 # LOADUI R0 0x1101 ; Close TAPE_02
E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT
@ -56,29 +56,29 @@ FFFFFFFF # HALT
# ;; Prints address every 4th byte
# ;; Alters R0
# ;; Returns to whatever called it
# :dehex
# :dehex 5a
0902001F # PUSHR R1 R15 ; Preserve R1
0902000F # PUSHR R0 R15 ; Save byte until after address
B00E0003 # ANDI R0 R14 3 ; Get mod 4 of address
2D211101 # LOADUI R1 0x1101 ; We want it on TAPE_02
A0200000 # CMPSKIPI.E R0 0 ; if not zero
3C000024 # JUMP @dehex_0 ; Skip placing address
E100B00E0003 # ANDI R0 R14 3 ; Get mod 4 of address
E0002D211101 # LOADUI R1 0x1101 ; We want it on TAPE_02
E000A0200000 # CMPSKIPI.E R0 0 ; if not zero
3C000028 # JUMP @dehex_0 ; Skip placing address
# ;; Prepend new line
2D20000a # LOADUI R0 10 ; First print line feed
E0002D20000a # LOADUI R0 10 ; First print line feed
42100200 # FPUTC ; Write it
# ;; Write out address
0900040E # COPY R0 R14 ; Prep for call
2D0F002c # CALLI R15 @hex32 ; Let it handle the details
E0002D0F0030 # CALLI R15 @hex32 ; Let it handle the details
# ;; Write out : char
2D20003a # LOADUI R0 58 ; Prep
E0002D20003a # LOADUI R0 58 ; Prep
42100200 # FPUTC ; Write it
# ;; Write out tab
2D200009 # LOADUI R0 9 ; Prep
E0002D200009 # LOADUI R0 9 ; Prep
42100200 # FPUTC ; Write it
# :dehex_0
# :dehex_0 a0
0902800F # POPR R0 R15 ; Restore byte recieved
2D0F0034 # CALLI R15 @hex8 ; Use a subset
2D200020 # LOADUI R0 32 ; Prep for writing space
E0002D0F003a # CALLI R15 @hex8 ; Use a subset
E0002D200020 # LOADUI R0 32 ; Prep for writing space
42100200 # FPUTC ; Write it
0902801F # POPR R1 R15 ; Restore R1
0D01001F # RET R15 ; Return to caller
@ -88,26 +88,27 @@ A0200000 # CMPSKIPI.E R0 0 ; if not zero
# ;; Accepts 32bit value in R0
# ;; Require R1 to be the device to write the results
# ;; Returns to whatever called it
# :hex32
# :hex32 bc
0902000F # PUSHR R0 R15
2D600010 # SR0I R0 16 ; Do high word first
2D0F0008 # CALLI R15 @hex16
E0002D600010 # SR0I R0 16 ; Do high word first
E0002D0F0004 # CALLI R15 @hex16
0902800F # POPR R0 R15
# :hex16
# :hex16 d0
0902000F # PUSHR R0 R15
2D600008 # SR0I R0 8 ; Do high byte first
2D0F0008 # CALLI R15 @hex8
E0002D600008 # SR0I R0 8 ; Do high byte first
E0002D0F0004 # CALLI R15 @hex8
0902800F # POPR R0 R15
# :hex8
# :hex8 e4
0902000F # PUSHR R0 R15
2D600004 # SR0I R0 4 ; Do high nybble first
2D0F0008 # CALLI R15 @hex4
E0002D600004 # SR0I R0 4 ; Do high nybble first
E0002D0F0004 # CALLI R15 @hex4
0902800F # POPR R0 R15
# :hex4
B000000f # ANDI R0 R0 0x000F ; isolate nybble
0F000030 # ADDUI R0 R0 48 ; convert to ascii
A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
0F000007 # ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
# :hex4 f8
E100B000000f # ANDI R0 R0 0x000F ; isolate nybble
E1000F000030 # ADDUI R0 R0 48 ; convert to ascii
E000A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
E1000F000007 # ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
42100200 # FPUTC ; Print char
0D01001F # RET R15 ; Get next nybble or return if done
# :end
# ;; Where we are putting our stack
# :end 118

View File

@ -14,97 +14,97 @@
## You should have received a copy of the GNU General Public License
## along with stage0. If not, see <http://www.gnu.org/licenses/>.
#:start
2D2B0001 # LOADUI R11 1 ; Our toggle
# :start 0
E0002D2B0001 # LOADUI R11 1 ; Our toggle
# ;; R14 is storing our condition code
# ;; R15 is storing our nybble
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
E0002D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
E0002D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
# ;; Main program loop
# ;; Halts when done
# :loop 18
42100100 # FGETC ; Read a Char
# :loop 20
42100100 # FGETC ; Read a Char
# ;; Check for EOF
2CC00098 # JUMP.NP R0 @finish
3C000038 # JUMP @hex ; Convert it
E0002CC000b8 # JUMP.NP R0 @finish
3C000044 # JUMP @hex ; Convert it
# :loop_1 24
2CC0fff4 # JUMP.NP R0 @loop ; Don't use nonhex chars
2C9B0010 # JUMP.Z R11 @loop_2 ; Jump if toggled
# :loop_1 2e
E0002CC0ffec # JUMP.NP R0 @loop ; Don't use nonhex chars
E0002C9B000e # JUMP.Z R11 @loop_2 ; Jump if toggled
# ;; Process first byte of pair
B0F0000f # ANDI R15 R0 0xF ; Store First nibble
0D00002B # FALSE R11 ; Flip the toggle
3C00ffe4 # JUMP @loop
E100B0F0000f # ANDI R15 R0 0xF ; Store First nibble
0D00002B # FALSE R11 ; Flip the toggle
3C00ffd8 # JUMP @loop
# :loop_2 38
2D5F0004 # SL0I R15 4 ; Shift our first nibble
B000000f # ANDI R0 R0 0xF ; Mask out top
0500000F # ADD R0 R0 R15 ; Combine nibbles
2D1B0001 # LOADI R11 1 ; Flip the toggle
2D211101 # LOADUI R1 0x1101 ; Write the combined byte
42100200 # FPUTC ; To TAPE_02
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
3C00ffc4 # JUMP @loop ; Try to get more bytes
# :loop_2 48
E0002D5F0004 # SL0I R15 4 ; Shift our first nibble
E100B000000f # ANDI R0 R0 0xF ; Mask out top
0500000F # ADD R0 R0 R15 ; Combine nibbles
E0002D1B0001 # LOADI R11 1 ; Flip the toggle
E0002D211101 # LOADUI R1 0x1101 ; Write the combined byte
42100200 # FPUTC ; To TAPE_02
E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
3C00ffae # JUMP @loop ; Try to get more bytes
# ;; Hex function
# ;; Converts Ascii chars to their hex values
# ;; Or -1 if not a hex char
# ;; Returns to whatever called it
# :hex 58
# :hex 72
# ;; Deal with line comments starting with #
A0300023 # CMPSKIPI.NE R0 35
3C000044 # JUMP @ascii_comment
E000A0300023 # CMPSKIPI.NE R0 35
3C000050 # JUMP @ascii_comment
# ;; Deal with line comments starting with ;
A030003b # CMPSKIPI.NE R0 59
3C00003c # JUMP @ascii_comment
E000A030003b # CMPSKIPI.NE R0 59
3C000046 # JUMP @ascii_comment
# ;; Deal with all ascii less than '0'
A0100030 # CMPSKIPI.GE R0 48
3C000040 # JUMP @ascii_other
E000A0100030 # CMPSKIPI.GE R0 48
3C00004a # JUMP @ascii_other
# ;; Deal with '0'-'9'
A0000039 # CMPSKIPI.G R0 57
3C00001c # JUMP @ascii_num
E000A0000039 # CMPSKIPI.G R0 57
3C00001e # JUMP @ascii_num
# ;; Unset high bit to set everything into uppercase
B00000df # ANDI R0 R0 0xDF
E100B00000df # ANDI R0 R0 0xDF
# ;; Deal with all ascii less than 'A'
A0100041 # CMPSKIPI.GE R0 65
3C00002c # JUMP @ascii_other
E000A0100041 # CMPSKIPI.GE R0 65
3C000030 # JUMP @ascii_other
# ;; Deal with 'A'-'F'
A0000046 # CMPSKIPI.G R0 70
3C000010 # JUMP @ascii_high
E000A0000046 # CMPSKIPI.G R0 70
3C00000e # JUMP @ascii_high
# ;; Ignore the rest
3C000020 # JUMP @ascii_other
3C000022 # JUMP @ascii_other
# :ascii_num 90
11000030 # SUBUI R0 R0 48
3C00ff90 # JUMP @loop_1
# :ascii_high 98
11000037 # SUBUI R0 R0 55
3C00ff88 # JUMP @loop_1
# :ascii_comment a0
42100100 # FGETC ; Read another char
A020000a # CMPSKIPI.E R0 10 ; Stop at the end of line
3C00fff8 # JUMP @ascii_comment ; Otherwise keep looping
# :ascii_other ac
0D000030 # TRUE R0
3C00ff74 # JUMP @loop_1
# :ascii_num b8
E10011000030 # SUBUI R0 R0 48
3C00ff6c # JUMP @loop_1
# :ascii_high c2
E10011000037 # SUBUI R0 R0 55
3C00ff62 # JUMP @loop_1
# :ascii_comment cc
42100100 # FGETC ; Read another char
E000A020000a # CMPSKIPI.E R0 10 ; Stop at the end of line
3C00fff2 # JUMP @ascii_comment ; Otherwise keep looping
# :ascii_other da
0D000030 # TRUE R0
3C00ff4c # JUMP @loop_1
# ;; Finish function
# ;; Cleans up at the end of the program
# ;; Performs the HALT
# :finish b4
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
2D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT
# :finish e2
E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT

View File

@ -14,203 +14,204 @@
## You should have received a copy of the GNU General Public License
## along with stage0. If not, see <http://www.gnu.org/licenses/>.
#:start 0
2D2B0200 # LOADUI R11 0x200 ; Where we are putting our address pointers
0D00003C # TRUE R12 ; Our toggle
0D00002D # FALSE R13 ; Our PC counter
2D2E0040 # LOADUI R14 $getLables_2 ; our first iterator
# :start 0
E0002D2B0200 # LOADUI R11 0x200 ; Where we are putting our address pointers
0D00003C # TRUE R12 ; Our toggle
0D00002D # FALSE R13 ; Our PC counter
E0002D2E0050 # LOADUI R14 $getLables_2 ; our first iterator
# ;; We will be using R15 for holding our processed nybbles
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
E0002D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
E0002D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
# ;; Function for collecting the address of all labels
#:getLables 24
42100100 # FGETC ; Read a Char
2CC00048 # JUMP.NP R0 @stage2 ; Check for EOF
# :getLables 2e
42100100 # FGETC ; Read a Char
# ;; Check for EOF
E0002CC00052 # JUMP.NP R0 @stage2
# ;; Check for Label
A030003A # CMPSKIPI.NE R0 58 ; If the Char is : the next char is the label
3C000030 # JUMP @storeLabel
E000A030003a # CMPSKIPI.NE R0 58 ; If the Char is : the next char is the label
3C000036 # JUMP @storeLabel
# ;; Check for pointer to label
A0300040 # CMPSKIPI.NE R0 64 ; If the Char is @ the next char is the pointer to a label
3C00001C # JUMP @ignorePointer
E000A0300040 # CMPSKIPI.NE R0 64 ; If the Char is @ the next char is the pointer to a label
3C00001e # JUMP @ignorePointer
# ;; Otherwise attempt to process
3C0000DC # JUMP @hex ; Convert it
3C000100 # JUMP @hex ; Convert it
#:getLables_2 40
2CC0FFE4 # JUMP.NP R0 @getLables ; Don't record, nonhex values
090006CC # NOT R12 R12 ; Flip the toggle
2C9CFFDC # JUMP.Z R12 @getLables ; First half doesn't need anything
# :getLables_2 50
E0002CC0ffd8 # JUMP.NP R0 @getLables ; Don't record, nonhex values
090006CC # NOT R12 R12 ; Flip the toggle
E0002C9Cffce # JUMP.Z R12 @getLables ; First half doesn't need anything
# ;; Deal with case of second half of byte
0FDD0001 # ADDUI R13 R13 1 ; increment PC now that we have a full byte
3C00FFD4 # JUMP @getLables
E1000FDD0001 # ADDUI R13 R13 1 ; increment PC now that we have a full byte
3C00ffc4 # JUMP @getLables
#:ignorePointer 54
# :ignorePointer 6a
# ;; Ignore the pointer for now
42100100 # FGETC ; Read a Char
0FDD0002 # ADDUI R13 R13 2 ; The pointer will end up taking 2 bytes
3C00FFC8 # JUMP @getLables
42100100 # FGETC ; Read a Char
E1000FDD0002 # ADDUI R13 R13 2 ; The pointer will end up taking 2 bytes
3C00ffb6 # JUMP @getLables
# ;; Function for storing the address of the label
#:storeLabel 60
# :storeLabel 78
# ;; Get the char of the Label
42100100 # FGETC ; Read a Char
42100100 # FGETC ; Read a Char
# ;; We require 2 bytes to store the pointer values
2D500001 # SL0I R0 1 ; Thus we multiply our label by 2
E0002D500001 # SL0I R0 1 ; Thus we multiply our label by 2
# ;; Store the current Program counter
0504ADB0 # STOREX16 R13 R11 R0
0504ADB0 # STOREX16 R13 R11 R0
# ;; Label is safely stored, return
3C00FFB8 # JUMP @getLables
3C00ffa4 # JUMP @getLables
# ;; Now that we have all of the label addresses,
# ;; We can process input to produce our output
#:stage2 70
# :stage2 8a
# ;; We first need to rewind tape_01 to perform our second pass
2D201100 # LOADUI R0 0x1100
42100003 # REWIND
E0002D201100 # LOADUI R0 0x1100
42100003 # REWIND
# ;; Reset our toggle and counter
2D291101 # LOADUI R9 0x1101 ; Where to write the combined byte
0D00003C # TRUE R12 ; Our toggle
0D00002D # FALSE R13 ; Our PC counter
2D2E00A4 # LOADUI R14 $loop_hex ; The hex return target
E0002D291101 # LOADUI R9 0x1101 ; Where to write the combined byte
0D00003C # TRUE R12 ; Our toggle
0D00002D # FALSE R13 ; Our PC counter
E0002D2E00ca # LOADUI R14 $loop_hex ; The hex return target
# :loop a8
42100100 # FGETC ; Read a Char
#:loop 88
42100100 # FGETC ; Read a Char
# ;; Check for EOF
2CC000E8 # JUMP.NP R0 @finish
E0002CC0010e # JUMP.NP R0 @finish
# ;; Check for Label
A030003A # CMPSKIPI.NE R0 58 ; Make sure we jump over the label
3C000044 # JUMP @ignoreLabel
E000A030003a # CMPSKIPI.NE R0 58 ; Make sure we jump over the label
3C00004e # JUMP @ignoreLabel
# ;; Check for Pointer
A0300040 # CMPSKIPI.NE R0 64 ; If it is a pointer Deal with it
3C000044 # JUMP @storePointer
E000A0300040 # CMPSKIPI.NE R0 64 ; If it is a pointer Deal with it
3C00004c # JUMP @storePointer
# ;; Process Char
3C000078 # JUMP @hex ; Convert it
3C000086 # JUMP @hex ; Convert it
#:loop_hex a4
2CC0FFE4 # JUMP.NP R0 @loop ; Don't use nonhex chars
090006CC # NOT R12 R12 ; Flip the toggle
2CAC000C # JUMP.NZ R12 @loop_second_nybble ; Jump if toggled
# :loop_hex ca
E0002CC0ffd8 # JUMP.NP R0 @loop ; Don't use nonhex chars
090006CC # NOT R12 R12 ; Flip the toggle
E0002CAC000a # JUMP.NZ R12 @loop_second_nybble ; Jump if toggled
# ;; Process first byte of pair
B0F0000F # ANDI R15 R0 0xF ; Store First nibble
3C00FFD4 # JUMP @loop
E100B0F0000f # ANDI R15 R0 0xF ; Store First nibble
3C00ffc4 # JUMP @loop
#:loop_second_nybble b8
2D5F0004 # SL0I R15 4 ; Shift our first nibble
B000000F # ANDI R0 R0 0xF ; Mask out top
0500000F # ADD R0 R0 R15 ; Combine nibbles
09000319 # SWAP R1 R9 ; Set to write to tape_2
42100200 # FPUTC ; To TAPE_02
09000319 # SWAP R1 R9 ; Restore from tape_1
0FDD0001 # ADDUI R13 R13 1 ; increment PC now that we have a full byte
3C00FFB4 # JUMP @loop ; Try to get more bytes
# :loop_second_nybble e4
E0002D5F0004 # SL0I R15 4 ; Shift our first nibble
E100B000000f # ANDI R0 R0 0xF ; Mask out top
0500000F # ADD R0 R0 R15 ; Combine nibbles
09000319 # SWAP R1 R9 ; Set to write to tape_2
42100200 # FPUTC ; To TAPE_02
09000319 # SWAP R1 R9 ; Restore from tape_1
E1000FDD0001 # ADDUI R13 R13 1 ; increment PC now that we have a full byte
3C00ff9e # JUMP @loop ; Try to get more bytes
#:ignoreLabel d8
# :ignoreLabel 10a
# ;; Consume next char
42100100 # FGETC ; Read a Char
3C00FFAC # JUMP @loop
42100100 # FGETC ; Read a Char
3C00ff96 # JUMP @loop
#:storePointer e0
# :storePointer 112
# ;; Correct the PC to reflect the size of the pointer
0FDD0002 # ADDUI R13 R13 2 ; Exactly 2 bytes
E1000FDD0002 # ADDUI R13 R13 2 ; Exactly 2 bytes
# ;; Get the char of the Label
42100100 # FGETC ; Read a Char
42100100 # FGETC ; Read a Char
# ;; Since we stored a short pointer taking up 2 bytes
2D500001 # SL0I R0 1 ; Thus we multiply our label by 2 to get where it is stored
0503C3B0 # LOADXU16 R3 R11 R0 ; Load the address of the label
E0002D500001 # SL0I R0 1 ; Thus we multiply our label by 2 to get where it is stored
0503C3B0 # LOADXU16 R3 R11 R0 ; Load the address of the label
# ;; We now have to calculate the distance and store the 2 bytes
0500233D # SUB R3 R3 R13 ; First determine the difference between the current PC and the stored PC of the label
0F330004 # ADDUI R3 R3 4 ; Adjust for relative positioning
0500233D # SUB R3 R3 R13 ; First determine the difference between the current PC and the stored PC of the label
# ;; Store Upper byte
B003FF00 # ANDI R0 R3 0xFF00 ; Mask out everything but top byte
2D400008 # SARI R0 8 ; Drop the bottom 8 bits
09000319 # SWAP R1 R9 ; Write the byte
42100200 # FPUTC ; To TAPE_02
E100B003ff00 # ANDI R0 R3 0xFF00 ; Mask out everything but top byte
E0002D400008 # SARI R0 8 ; Drop the bottom 8 bits
09000319 # SWAP R1 R9 ; Write the byte
42100200 # FPUTC ; To TAPE_02
# ;; Store Lower byte
B00300FF # ANDI R0 R3 0xFF ; Preserve bottom half for later
42100200 # FPUTC ; Write the byte to TAPE_02
09000319 # SWAP R1 R9 ; Restore Read
3C00FF74 # JUMP @loop
E100B00300ff # ANDI R0 R3 0xFF ; Preserve bottom half for later
42100200 # FPUTC ; Write the byte to TAPE_02
09000319 # SWAP R1 R9 ; Restore Read
3C00ff58 # JUMP @loop
# ;; Hex function
# ;; Returns hex value of ascii char
# ;; Or -1 if not a hex char
#:hex 118
# :hex 150
# ;; Deal with line comments starting with #
A0300023 # CMPSKIPI.NE R0 35
3C000044 # JUMP @ascii_comment
E000A0300023 # CMPSKIPI.NE R0 35
3C000050 # JUMP @ascii_comment
# ;; Deal with line comments starting with ;
A030003B # CMPSKIPI.NE R0 59
3C00003C # JUMP @ascii_comment
E000A030003b # CMPSKIPI.NE R0 59
3C000046 # JUMP @ascii_comment
# ;; Deal with all ascii less than '0'
A0100030 # CMPSKIPI.GE R0 48
3C000040 # JUMP @ascii_other
E000A0100030 # CMPSKIPI.GE R0 48
3C00004a # JUMP @ascii_other
# ;; Deal with '0'-'9'
A0000039 # CMPSKIPI.G R0 57
3C00001C # JUMP @ascii_num
E000A0000039 # CMPSKIPI.G R0 57
3C00001e # JUMP @ascii_num
# ;; Deal with all ascii less than 'A'
A0100041 # CMPSKIPI.GE R0 65
3C000030 # JUMP @ascii_other
E000A0100041 # CMPSKIPI.GE R0 65
3C000036 # JUMP @ascii_other
# ;; Unset high bit to set everything into uppercase
B00000DF # ANDI R0 R0 0xDF
E100B00000df # ANDI R0 R0 0xDF
# ;; Deal with 'A'-'F'
A0000046 # CMPSKIPI.G R0 70
3C000010 # JUMP @ascii_high
E000A0000046 # CMPSKIPI.G R0 70
3C00000e # JUMP @ascii_high
# ;; Ignore the rest
3C000020 # JUMP @ascii_other
3C000022 # JUMP @ascii_other
#:ascii_num 150
11000030 # SUBUI R0 R0 48
0D01000E # JSR_COROUTINE R14
#:ascii_high 158
11000037 # SUBUI R0 R0 55
0D01000E # JSR_COROUTINE R14
#:ascii_comment 160
42100100 # FGETC ; Read another char
A020000A # CMPSKIPI.E R0 10 ; Stop at the end of line
3C00FFF8 # JUMP @ascii_comment ; Otherwise keep looping
#:ascii_other 16c
0D000030 # TRUE R0
0D01000E # JSR_COROUTINE R14
# :ascii_num 196
E10011000030 # SUBUI R0 R0 48
0D01000E # JSR_COROUTINE R14
# :ascii_high 1a0
E10011000037 # SUBUI R0 R0 55
0D01000E # JSR_COROUTINE R14
# :ascii_comment 1aa
42100100 # FGETC ; Read another char
E000A020000a # CMPSKIPI.E R0 10 ; Stop at the end of line
3C00fff2 # JUMP @ascii_comment ; Otherwise keep looping
# :ascii_other 1b8
0D000030 # TRUE R0
0D01000E # JSR_COROUTINE R14
#:finish 174
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
2D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT
# :finish 1c0
E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT
# ;; Where all of our pointers will be stored for our locations
#:table 188
# :table 1d8

View File

@ -145,7 +145,6 @@
;; We now have to calculate the distance and store the 2 bytes
SUB R3 R3 R13 ; First determine the difference between the current PC and the stored PC of the label
ADDUI R3 R3 4 ; Adjust for relative positioning
;; Store Upper byte
ANDI R0 R3 0xFF00 ; Mask out everything but top byte

View File

@ -30,37 +30,37 @@
# ;; We will be using R13 for our register size in bytes
# ;; We will be using R14 for our head-node
2D2F @1 # LOADUI R15 $stack ; We will be using R15 for our stack
E0002D2F 0400 # LOADUI R15 $stack ; We will be using R15 for our stack
# ;; Main program functionality
# ;; Reads in Tape_01 and writes out results onto Tape_02
# ;; Accepts no arguments and HALTS when done
# :main 4
# :main 6
:2
# ;; Initialize header info
0D000010 # READSCID R0 ; Get process capabilities
B010000f # ANDI R1 R0 0xF ; We only care about size nybble
2D200001 # LOADUI R0 1 ; Assume we are 8bit
E100B010000f # ANDI R1 R0 0xF ; We only care about size nybble
E0002D200001 # LOADUI R0 1 ; Assume we are 8bit
05032D01 # SL0 R13 R0 R1 ; Let size nybble correct answer
0900049D # COPY R9 R13 ; Prepare Header size
2D590001 # SL0I R9 1 ; Double to make proper size
E0002D590001 # SL0I R9 1 ; Double to make proper size
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
E0002D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
# ;; Intialize environment
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
0D00002C # FALSE R12 ; Set holder to zero
0D00002B # FALSE R11 ; Set PC counter to zero
0D00002A # FALSE R10 ; Our toggle
2D280500 # LOADUI R8 0x500 ; Where we want our heap to start
E0002D280700 # LOADUI R8 0x700 ; Where we want our heap to start
# ;; Perform first pass
2D0F @3 # CALLI R15 @first_pass
E0002D0F @3 # CALLI R15 @first_pass
# ;; We need to rewind tape_01 to perform our second pass
2D201100 # LOADUI R0 0x1100
E0002D201100 # LOADUI R0 0x1100
42100003 # REWIND
# ;; Reintialize environment
@ -69,14 +69,14 @@ B010000f # ANDI R1 R0 0xF ; We only care about size nybble
0D00002A # FALSE R10 ; Our toggle
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
E0002D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
2D0F @4 # CALLI R15 @second_pass
E0002D0F @4 # CALLI R15 @second_pass
# ;; Close up as we are done
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
2D201101 # LOADUI R0 0x1101 ; Close TAPE_02
E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
42100002 # FCLOSE
FFFFFFFF # HALT
@ -85,41 +85,41 @@ FFFFFFFF # HALT
# ;; Reads Tape_01 and creates our label table
# ;; Will Overwrite R0 R10 R11
# ;; Returns to Main function when done
# :first_pass 70
# :first_pass 8a
:3
42100100 # FGETC ; Read a Char
# ;; Check for EOF
A0100000 # CMPSKIPI.GE R0 0
E000A0100000 # CMPSKIPI.GE R0 0
0D01001F # RET R15
# ;; Check for and deal with label (:)
A030003a # CMPSKIPI.NE R0 58
E000A030003a # CMPSKIPI.NE R0 58
3C00 @5 # JUMP @storeLabel
# ;; Check for and deal with pointers to labels
# ;; Starting with (@)
A0300040 # CMPSKIPI.NE R0 64
E000A0300040 # CMPSKIPI.NE R0 64
3C00 @6 # JUMP @ThrowAwayPointer
# ;; Then dealing with ($)
A0300024 # CMPSKIPI.NE R0 36
E000A0300024 # CMPSKIPI.NE R0 36
3C00 @6 # JUMP @ThrowAwayPointer
# ;; Now check for absolute addresses (&)
A0300026 # CMPSKIPI.NE R0 38
E000A0300026 # CMPSKIPI.NE R0 38
3C00 @7 # JUMP @ThrowAwayAddress
# ;; Otherwise attempt to process
2D0F @8 # CALLI R15 @hex ; Convert it
2CC0 @3 # JUMP.NP R0 @first_pass ; Don't record, nonhex values
E0002D0F @8 # CALLI R15 @hex ; Convert it
E0002CC0 @3 # JUMP.NP R0 @first_pass ; Don't record, nonhex values
# ;; Flip the toggle
090006AA # NOT R10 R10
2C9A @3 # JUMP.Z R10 @first_pass ; Jump if toggled
E0002C9A @3 # JUMP.Z R10 @first_pass ; Jump if toggled
# ;; Deal with case of second half of byte
0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte
E1000FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte
3C00 @3 # JUMP @first_pass
@ -128,49 +128,49 @@ A0300026 # CMPSKIPI.NE R0 38
# ;; To write desired contents onto Tape_02
# ;; Will Overwrite R0 R10 R11
# ;; Returns to Main function when done
# :second_pass b4
# :second_pass e0
:4
42100100 # FGETC ; Read a Char
# ;; Check for EOF
A0100000 # CMPSKIPI.GE R0 0
E000A0100000 # CMPSKIPI.GE R0 0
0D01001F # RET R15
# ;; Check for and deal with label
A030003a # CMPSKIPI.NE R0 58
E000A030003a # CMPSKIPI.NE R0 58
3C00 @9 # JUMP @ThrowAwayLabel
# ;; Check for and deal with Pointers to labels
A0300040 # CMPSKIPI.NE R0 64 ; @ for relative
E000A0300040 # CMPSKIPI.NE R0 64 ; @ for relative
3C00 @a # JUMP @StoreRelativePointer
A0300024 # CMPSKIPI.NE R0 36 ; $ for absolute
E000A0300024 # CMPSKIPI.NE R0 36 ; $ for absolute
3C00 @b # JUMP @StoreAbsolutePointer
A0300026 # CMPSKIPI.NE R0 38 ; & for address
E000A0300026 # CMPSKIPI.NE R0 38 ; & for address
3C00 @c # JUMP @StoreAbsoluteAddress
# ;; Process everything else
2D0F @8 # CALLI R15 @hex ; Attempt to Convert it
A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values
E0002D0F @8 # CALLI R15 @hex ; Attempt to Convert it
E000A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values
3C00 @4 # JUMP @second_pass ; Move onto Next char
# ;; Determine if we got a full byte
090006AA # NOT R10 R10
2C9A @d # JUMP.Z R10 @second_pass_0 ; Jump if toggled
E0002C9A @d # JUMP.Z R10 @second_pass_0 ; Jump if toggled
# ;; Deal with case of first half of byte
B0C0000f # ANDI R12 R0 0x0F ; Store our first nibble
E100B0C0000f # ANDI R12 R0 0x0F ; Store our first nibble
3C00 @4 # JUMP @second_pass
# :second_pass_0 fc
# :second_pass_0 13a
:d
# ;; Deal with case of second half of byte
2D5C0004 # SL0I R12 4 ; Shift our first nybble
B000000f # ANDI R0 R0 0x0F ; Mask out top
E0002D5C0004 # SL0I R12 4 ; Shift our first nybble
E100B000000f # ANDI R0 R0 0x0F ; Mask out top
0500000C # ADD R0 R0 R12 ; Combine nybbles
2D211101 # LOADUI R1 0x1101 ; Write the combined byte
E0002D211101 # LOADUI R1 0x1101 ; Write the combined byte
42100200 # FPUTC ; To TAPE_02
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte
E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
E1000FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte
3C00 @4 # JUMP @second_pass
@ -179,18 +179,18 @@ B000000f # ANDI R0 R0 0x0F ; Mask out top
# ;; Its static variable for storing the next index to be used
# ;; Will overwrite R0
# ;; Returns to first pass when done
# :storeLabel 11c
# :storeLabel 164
:5
09000408 # COPY R0 R8 ; get current malloc
05000889 # ADD R8 R8 R9 ; update malloc
# ;; Add node info
05048B0D # STOREX R11 R0 R13 ; Store the PC of the label
20E00000 # STORE R14 R0 0 ; Store the Previous Head
E10020E00000 # STORE R14 R0 0 ; Store the Previous Head
090005E0 # MOVE R14 R0 ; Update Head
# ;; Store the name of the Label
2D0F @e # CALLI R15 @writeout_token
E0002D0F @e # CALLI R15 @writeout_token
# ;; And be done
3C00 @3 # JUMP @first_pass
@ -203,14 +203,13 @@ B000000f # ANDI R0 R0 0x0F ; Mask out top
# ;; Writes out the offset
# ;; Modifies R0 R11
# ;; Jumps back into Pass2
# :StoreRelativePointer 138
# :StoreRelativePointer 184
:a
# ;; Correct the PC to reflect the size of the pointer
0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes
2D0F @o # CALLI R15 @Match_string ; Find the Match
E1000FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes
E0002D0F @o # CALLI R15 @Match_string ; Find the Match
0500200B # SUB R0 R0 R11 ; Determine the difference
0F000004 # ADDUI R0 R0 4 ; Adjust for relative positioning
2D0F @p # CALLI R15 @ProcessImmediate ; Write out the value
E0002D0F @p # CALLI R15 @ProcessImmediate ; Write out the value
3C00 @4 # JUMP @second_pass
@ -221,12 +220,12 @@ B000000f # ANDI R0 R0 0x0F ; Mask out top
# ;; Writes out the absolute address of match
# ;; Modifies R0 R11
# ;; Jumps back into Pass2
# :StoreAbsolutePointer 150
# :StoreAbsolutePointer 1a4
:b
# ;; Correct the PC to reflect the size of the pointer
0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes
2D0F @o # CALLI R15 @Match_string ; Find the Match
2D0F @p # CALLI R15 @ProcessImmediate ; Write out the value
E1000FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes
E0002D0F @o # CALLI R15 @Match_string ; Find the Match
E0002D0F @p # CALLI R15 @ProcessImmediate ; Write out the value
3C00 @4 # JUMP @second_pass
@ -237,16 +236,16 @@ B000000f # ANDI R0 R0 0x0F ; Mask out top
# ;; Writes out the full absolute address [32 bit machine]
# ;; Modifies R0 R11
# ;; Jumpbacs back into Pass2
# :StoreAbsoluteAddress 160
# :StoreAbsoluteAddress 1ba
:c
# ;; COrrect the PC to reflect the size of the address
0FBB0004 # ADDUI R11 R11 4 ; 4 Bytes on 32bit machines
2D0F @o # CALLI R15 @Match_string ; Find the Match
B020ffff # ANDI R2 R0 0xFFFF ; Save bottom half for next function
2D400010 # SARI R0 16 ; Drop bottom 16 bits
2D0F @p # CALLI R15 @ProcessImmediate ; Write out top 2 bytes
# ;; Correct the PC to reflect the size of the address
E1000FBB0004 # ADDUI R11 R11 4 ; 4 Bytes on 32bit machines
E0002D0F @o # CALLI R15 @Match_string ; Find the Match
E100B020ffff # ANDI R2 R0 0xFFFF ; Save bottom half for next function
E0002D400010 # SARI R0 16 ; Drop bottom 16 bits
E0002D0F @p # CALLI R15 @ProcessImmediate ; Write out top 2 bytes
09000502 # MOVE R0 R2 ; Use the saved 16bits
2D0F @p # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes
E0002D0F @p # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes
3C00 @4 # JUMP @second_pass
@ -254,7 +253,7 @@ B020ffff # ANDI R2 R0 0xFFFF ; Save bottom half for next function
# ;; Writes the Token [minus first char] to the address
# ;; given by malloc and updates malloc pointer
# ;; Returns starting address of string
# :writeout_token 180
# :writeout_token 1e6
:e
# ;; Preserve registers
0902001F # PUSHR R1 R15
@ -264,30 +263,30 @@ B020ffff # ANDI R2 R0 0xFFFF ; Save bottom half for next function
09000428 # COPY R2 R8 ; Get current malloc pointer
# ;; Our core loop
# :writeout_token_0 18c
# :writeout_token_0 1f2
:r
42100100 # FGETC ; Get another byte
# ;; Deal with termination cases
A0300020 # CMPSKIPI.NE R0 32 ; Finished if space
E000A0300020 # CMPSKIPI.NE R0 32 ; Finished if space
3C00 @q # JUMP @writeout_token_done
A0300009 # CMPSKIPI.NE R0 9 ; Finished if tab
E000A0300009 # CMPSKIPI.NE R0 9 ; Finished if tab
3C00 @q # JUMP @writeout_token_done
A030000a # CMPSKIPI.NE R0 10 ; Finished if newline
E000A030000a # CMPSKIPI.NE R0 10 ; Finished if newline
3C00 @q # JUMP @writeout_token_done
A030ffff # CMPSKIPI.NE R0 -1 ; Finished if EOF
E000A030ffff # CMPSKIPI.NE R0 -1 ; Finished if EOF
3C00 @q # JUMP @writeout_token_done
# ;; Deal with valid input
21080000 # STORE8 R0 R8 0 ; Write out the byte
0F880001 # ADDUI R8 R8 1 ; Increment
E10021080000 # STORE8 R0 R8 0 ; Write out the byte
E1000F880001 # ADDUI R8 R8 1 ; Increment
3C00 @r # JUMP @writeout_token_0 ; Keep looping
# ;; Clean up now that we are done
# :writeout_token_done 1bc
# :writeout_token_done 22e
:q
# ;; Fix malloc
0F880001 # ADDUI R8 R8 1
E1000F880001 # ADDUI R8 R8 1
# ;; Prepare for return
09000502 # MOVE R0 R2
@ -305,33 +304,33 @@ A030ffff # CMPSKIPI.NE R0 -1 ; Finished if EOF
# ;; Reads a token
# ;; Then returns address of match in R0
# ;; Returns to whatever called it
# :Match_string 1d0
# :Match_string 244
:o
# ;; Preserve registers
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
# ;; Initialize for Loop
2D0F @e # CALLI R15 @writeout_token ; Get our desired string
E0002D0F @e # CALLI R15 @writeout_token ; Get our desired string
09000510 # MOVE R1 R0 ; Position our desired string
0900042E # COPY R2 R14 ; Begin at our head node
# ;; Loop until we find a match
# :Match_string_0 1e4
# :Match_string_0 25a
:h
05000029 # ADD R0 R2 R9 ; Where the string is located
2D0F @f # CALLI R15 @strcmp
2C50 @g # JUMP.E R0 @Match_string_1 ; It is a match!
E0002D0F @f # CALLI R15 @strcmp
E0002C50 @g # JUMP.E R0 @Match_string_1 ; It is a match!
# ;; Prepare for next loop
13220000 # LOAD R2 R2 0 ; Move to next node
2CA2 @h # JUMP.NZ R2 @Match_string_0 ; Keep looping
E10013220000 # LOAD R2 R2 0 ; Move to next node
E0002CA2 @h # JUMP.NZ R2 @Match_string_0 ; Keep looping
0D000032 # TRUE R2 ; Set result to -1 if not found
# :Match_string_1 1fc
# :Match_string_1 27a
:g
# ;; Store the correct answer
A022ffff # CMPSKIPI.E R2 -1 ; Otherwise get the value
E000A022ffff # CMPSKIPI.E R2 -1 ; Otherwise get the value
0503802D # LOADX R0 R2 R13 ; Get the value we care about
# ;; Restore registers
@ -344,7 +343,7 @@ A022ffff # CMPSKIPI.E R2 -1 ; Otherwise get the value
# ;; Recieves two pointers in R0 and R1
# ;; Returns the difference between the strings in R0
# ;; Returns to whatever called it
# :strcmp 210
# :strcmp 290
:f
# ;; Preserve registers
0902001F # PUSHR R1 R15
@ -355,16 +354,16 @@ A022ffff # CMPSKIPI.E R2 -1 ; Otherwise get the value
# ;; Setup registers
09000520 # MOVE R2 R0
09000531 # MOVE R3 R1
2D240000 # LOADUI R4 0
E0002D240000 # LOADUI R4 0
# :cmpbyte 22c
# :cmpbyte 2ae
:i
0503A024 # LOADXU8 R0 R2 R4 ; Get a byte of our first string
0503A134 # LOADXU8 R1 R3 R4 ; Get a byte of our second string
0F440001 # ADDUI R4 R4 1 ; Prep for next loop
E1000F440001 # ADDUI R4 R4 1 ; Prep for next loop
05004101 # CMP R1 R0 R1 ; Compare the bytes
A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL
2C51 @i # JUMP.E R1 @cmpbyte ; Loop if bytes are equal
E000A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL
E0002C51 @i # JUMP.E R1 @cmpbyte ; Loop if bytes are equal
# ;; Done
09000501 # MOVE R0 R1 ; Prepare for return
@ -382,7 +381,7 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL
# ;; Writes out the values to Tape_02
# ;; Doesn't modify registers
# ;; Returns to whatever called it
# :ProcessImmediate 25c
# :ProcessImmediate 2e4
:p
# ;; Preserve registers
0902000F # PUSHR R0 R15
@ -390,12 +389,12 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL
0902002F # PUSHR R2 R15
# ;; Break up Immediate
B02000ff # ANDI R2 R0 0xFF ; Put lower byte in R2
2D400008 # SARI R0 8 ; Drop Bottom byte from R0
B00000ff # ANDI R0 R0 0xFF ; Maskout everything outside of top byte
E100B02000ff # ANDI R2 R0 0xFF ; Put lower byte in R2
E0002D400008 # SARI R0 8 ; Drop Bottom byte from R0
E100B00000ff # ANDI R0 R0 0xFF ; Maskout everything outside of top byte
# ;; Write out Top Byte
2D211101 # LOADUI R1 0x1101 ; Write the byte
E0002D211101 # LOADUI R1 0x1101 ; Write the byte
42100200 # FPUTC ; To TAPE_02
# ;; Write out bottom Byte
@ -416,10 +415,10 @@ B00000ff # ANDI R0 R0 0xFF ; Maskout everything outside of top byte
# ;; for Pass1, Will update R11 and modify R0
# ;; Will return to the start of first_pass
# ;; Never call this function, only jump to it
# :ThrowAwayPointer 294
# :ThrowAwayPointer 324
:6
0FBB0002 # ADDUI R11 R11 2 ; Pointers always take up 2 bytes
2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
E1000FBB0002 # ADDUI R11 R11 2 ; Pointers always take up 2 bytes
E0002D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
3C00 @3 # JUMP @first_pass ; Then return to the proper place
@ -428,10 +427,10 @@ B00000ff # ANDI R0 R0 0xFF ; Maskout everything outside of top byte
# ;; for Pass1, Will update R11 and modify R0
# ;; Will return to the start of first_pass
# ;; Never call this function, conly jump to it
# :ThrowAwayAddress 2a0
# :ThrowAwayAddress 334
:7
0FBB0004 # ADDUI R11 R11 4 ; Addresses on 32bit systems take up 4 bytes
2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
E1000FBB0004 # ADDUI R11 R11 4 ; Addresses on 32bit systems take up 4 bytes
E0002D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
3C00 @3 # JUMP @first_pass ; Then return to the proper place
@ -440,9 +439,9 @@ B00000ff # ANDI R0 R0 0xFF ; Maskout everything outside of top byte
# ;; for Pass2, Will update R11 and modify R0
# ;; Will return to the start of second_pass
# ;; Never call this function, only jump to it
# :ThrowAwayLabel 2ac
# :ThrowAwayLabel 344
:9
2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
E0002D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
3C00 @4 # JUMP @second_pass
@ -451,24 +450,24 @@ B00000ff # ANDI R0 R0 0xFF ; Maskout everything outside of top byte
# ;; The rest of the characters in a token
# ;; This Will alter the values of R0 R1
# ;; Returns back to whatever called it
# :throwAwayToken 2b4
# :throwAwayToken 34e
:j
42100100 # FGETC ; Read a Char
# ;; Stop looping if space
A0300020 # CMPSKIPI.NE R0 32
E000A0300020 # CMPSKIPI.NE R0 32
0D01001F # RET R15
# ;; Stop looping if tab
A0300009 # CMPSKIPI.NE R0 9
E000A0300009 # CMPSKIPI.NE R0 9
0D01001F # RET R15
# ;; Stop looping if newline
A030000a # CMPSKIPI.NE R0 10
E000A030000a # CMPSKIPI.NE R0 10
0D01001F # RET R15
# ;; Stop looping if EOF
A030ffff # CMPSKIPI.NE R0 -1
E000A030ffff # CMPSKIPI.NE R0 -1
0D01001F # RET R15
# ;; Otherwise keep looping
@ -482,58 +481,58 @@ A030ffff # CMPSKIPI.NE R0 -1
# ;; Returning the converted value of a hex character
# ;; This function will alter the values of R0
# ;; Returns back to whatever called it
# :hex 2dc
# :hex 37e
:8
# ;; Deal with line comments starting with #
A0300023 # CMPSKIPI.NE R0 35
E000A0300023 # CMPSKIPI.NE R0 35
3C00 @k # JUMP @ascii_comment
# ;; Deal with line comments starting with ;
A030003b # CMPSKIPI.NE R0 59
E000A030003b # CMPSKIPI.NE R0 59
3C00 @k # JUMP @ascii_comment
# ;; Deal with all ascii less than '0'
A0100030 # CMPSKIPI.GE R0 48
E000A0100030 # CMPSKIPI.GE R0 48
3C00 @l # JUMP @ascii_other
# ;; Deal with '0'-'9'
A0000039 # CMPSKIPI.G R0 57
E000A0000039 # CMPSKIPI.G R0 57
3C00 @m # JUMP @ascii_num
# ;; Deal with all ascii less than 'A'
A0100041 # CMPSKIPI.GE R0 65
E000A0100041 # CMPSKIPI.GE R0 65
3C00 @l # JUMP @ascii_other
# ;; Unset high bit to set everything into uppercase
B00000df # ANDI R0 R0 0xDF
E100B00000df # ANDI R0 R0 0xDF
# ;; Deal with 'A'-'F'
A0000046 # CMPSKIPI.G R0 70
E000A0000046 # CMPSKIPI.G R0 70
3C00 @n # JUMP @ascii_high
# ;; Ignore the rest
3C00 @l # JUMP @ascii_other
# :ascii_num 314
# :ascii_num 3c4
:m
11000030 # SUBUI R0 R0 48
E10011000030 # SUBUI R0 R0 48
0D01001F # RET R15
# :ascii_high 31c
# :ascii_high 3ce
:n
11000037 # SUBUI R0 R0 55
E10011000037 # SUBUI R0 R0 55
0D01001F # RET R15
# :ascii_comment 324
# :ascii_comment 3d8
:k
42100100 # FGETC ; Read another char
2CC0 @l # JUMP.NP R0 @ascii_other ; Stop with EOF
A020000a # CMPSKIPI.E R0 10 ; Stop at the end of line
E0002CC0 @l # JUMP.NP R0 @ascii_other ; Stop with EOF
E000A020000a # CMPSKIPI.E R0 10 ; Stop at the end of line
3C00 @k # JUMP @ascii_comment ; Otherwise keep looping
# :ascii_other 334
# :ascii_other 3ec
:l
0D000030 # TRUE R0
0D01001F # RET R15
# ;; Where we will putting our stack
# :stack 33c
# :stack 3f4
:1

View File

@ -52,7 +52,7 @@
FALSE R12 ; Set holder to zero
FALSE R11 ; Set PC counter to zero
FALSE R10 ; Our toggle
LOADUI R8 0x500 ; Where we want our heap to start
LOADUI R8 0x700 ; Where we want our heap to start
;; Perform first pass
CALLI R15 @first_pass
@ -205,7 +205,6 @@
ADDUI R11 R11 2 ; Exactly 2 bytes
CALLI R15 @Match_string ; Find the Match
SUB R0 R0 R11 ; Determine the difference
ADDUI R0 R0 4 ; Adjust for relative positioning
CALLI R15 @ProcessImmediate ; Write out the value
JUMP @second_pass

View File

@ -1,10 +1,10 @@
8f465d3ec1cba00a7d024a1964e74bb6d241f86a73c77d95d8ceb10d09c8f7b9 roms/CAT
59f0502748af32e3096e026a95e77216179cccfe803a05803317414643e2fcec roms/DEHEX
b3a910f18c6bc0ef4aa7a53cb3f0216a9f143319da67ed2a02210fe88b1e1131 roms/forth
7c3887f791999aa9c1b8415d8e5be93afcf916b505296d9da7bd7a22531a84b5 roms/lisp
47bc5a29e37bbe4cac31ba612f5e452210b0c4364e529116b9a1c4976912c29d roms/M0
24a4d74eb2eb7a82e68335643855658b27b5a6c3b13db473539f3e08d6f26ceb roms/SET
0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb roms/stage0_monitor
3ea7fed1429400c1d6fc5b85180c4114755dfb1e6b88d69e7ecc465a40523bc8 roms/stage1_assembler-0
b6aabcc3418a0a28f4ed32ace43b20103d9d21dffae03e7936cb14fa0e044013 roms/stage1_assembler-1
7b02babee42a3c05b001fb44fb0917383d8f185e2817d57ad2349a4b36dfa4ed roms/stage1_assembler-2
695698ebc7ed1d3acbcded1bd832a6b49b9a7c2a37c216a9fccdc0e89e976e99 roms/CAT
662b14485df5da61c3f5ad63151932985914b2fe074c21798e20ba2d83b45ecc roms/DEHEX
f4bbf9e9c4828170d0c153ac265382dc705643f95efd2a029243326d426be5a4 roms/forth
2b80849180d5fb3757bcca2471b6337808e5b5ca80b18d93fa82ddef0435b84b roms/lisp
3020b194ead31ae19ba66fc35ed95465514373f6005896350d1608c9efabbdca roms/M0
059d38e34275029f2de5f600f08fe01bd13cd173f7da58e3fbec7114074beff2 roms/SET
23929c57f41414f57583457d0500f22b5b1c80f39c79522e23c8b13e5afb191d roms/stage0_monitor
13b45134a88c1c6db349cb40f82269cee9edfce71ac644dc0e137bad053bf5ce roms/stage1_assembler-0
156f555fce5b02f52445652b1ed0b443295706cdfbe23c5a021bd4efc77179bb roms/stage1_assembler-1
2c02c50958f489a660a4915d2a9e207a0c61f411d42628bdaf4dcf6bf7149a9d roms/stage1_assembler-2

View File

@ -133,29 +133,37 @@ void decode_1OP(struct Instruction* c)
}
/* Deal with 2OPI */
void decode_2OPI(struct Instruction* c)
void decode_2OPI(struct lilith* vm, struct Instruction* c)
{
c->raw_Immediate = c->raw2*0x100 + c->raw3;
c->raw_Immediate = (uint8_t)vm->memory[vm->ip];
vm->ip = vm->ip + 1;
uint8_t hold = (uint8_t)vm->memory[vm->ip];
vm->ip = vm->ip + 1;
c->raw_Immediate = c->raw_Immediate*0x100 + hold;
c->Immediate[0] = c->operation[4];
c->Immediate[1] = c->operation[5];
c->Immediate[2] = c->operation[6];
c->Immediate[3] = c->operation[7];
c->reg0 = c->raw1/16;
c->reg1 = c->raw1%16;
c->reg0 = c->raw3/16;
c->reg1 = c->raw3%16;
}
/* Deal with 1OPI */
void decode_1OPI(struct Instruction* c)
void decode_1OPI(struct lilith* vm, struct Instruction* c)
{
c->raw_Immediate = c->raw2*0x100 + c->raw3;
c->raw_Immediate = (uint8_t)vm->memory[vm->ip];
vm->ip = vm->ip + 1;
uint8_t hold = (uint8_t)vm->memory[vm->ip];
vm->ip = vm->ip + 1;
c->raw_Immediate = c->raw_Immediate*0x100 + hold;
c->Immediate[0] = c->operation[4];
c->Immediate[1] = c->operation[5];
c->Immediate[2] = c->operation[6];
c->Immediate[3] = c->operation[7];
c->HAL_CODE = 0;
c->raw_XOP = c->raw1/16;
c->XOP[0] = c->operation[2];
c->reg0 = c->raw1%16;
c->raw_XOP = c->raw3/16;
c->XOP[0] = c->operation[7];
c->reg0 = c->raw3%16;
}
/* Deal with 0OPI */
void decode_0OPI(struct Instruction* c)
@ -1698,7 +1706,7 @@ bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c)
/* 0x0E ... 0x2B */
/* 0xB0 ... 0xDF */
switch(c->raw0)
switch(c->raw2)
{
case 0x0E: /* ADDI */
{
@ -2082,7 +2090,7 @@ bool eval_Integer_1OPI(struct lilith* vm, struct Instruction* c)
char Name[20] = "ILLEGAL_1OPI";
#endif
uint32_t Opcode = (c->raw0 * 16) + c->raw_XOP;
uint32_t Opcode = (c->raw2 * 16) + c->raw_XOP;
switch(Opcode)
{
@ -2650,17 +2658,15 @@ void eval_instruction(struct lilith* vm, struct Instruction* current)
eval_1OP_Int(vm, current);
break;
}
case 0x0E ... 0x2B: /* Integer 2OPI */
case 0xB0 ... 0xDF:
case 0xE1: /* Integer 2OPI */
{
decode_2OPI(current);
decode_2OPI(vm, current);
eval_2OPI_Int(vm, current);
break;
}
case 0x2C ... 0x2F: /* Integer 1OPI */
case 0xA0 ... 0xA1:
case 0xE0: /* Integer 1OPI */
{
decode_1OPI(current);
decode_1OPI(vm, current);
eval_Integer_1OPI(vm, current);
break;
}

View File

@ -24,10 +24,17 @@ FILE* tape_02;
char tty_getchar();
#endif
/* Stub as the current specification makes all instructions 4 bytes but future enhancements may change that */
/* Use first byte of next instruction to identify size */
int next_instruction_size(struct lilith* vm)
{
return 4;
uint8_t c = (uint8_t)vm->memory[vm->ip];
switch(c)
{
case 0xE0: return 6;
case 0xE1: return 6;
default: return 4;
}
}
/* Correctly write out bytes on little endian hardware */
@ -1310,8 +1317,7 @@ void JUMP_C(struct lilith* vm, struct Instruction* c)
{
if(Carry_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1319,8 +1325,7 @@ void JUMP_B(struct lilith* vm, struct Instruction* c)
{
if(Borrow_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1328,8 +1333,7 @@ void JUMP_O(struct lilith* vm, struct Instruction* c)
{
if(Overflow_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1337,8 +1341,7 @@ void JUMP_G(struct lilith* vm, struct Instruction* c)
{
if(GreaterThan_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1346,8 +1349,7 @@ void JUMP_GE(struct lilith* vm, struct Instruction* c)
{
if(GreaterThan_bit_set(vm->reg[c->reg0]) || EQual_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1355,8 +1357,7 @@ void JUMP_E(struct lilith* vm, struct Instruction* c)
{
if(EQual_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1364,8 +1365,7 @@ void JUMP_NE(struct lilith* vm, struct Instruction* c)
{
if(!EQual_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1373,8 +1373,7 @@ void JUMP_LE(struct lilith* vm, struct Instruction* c)
{
if(LessThan_bit_set(vm->reg[c->reg0]) || EQual_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1382,8 +1381,7 @@ void JUMP_L(struct lilith* vm, struct Instruction* c)
{
if(LessThan_bit_set(vm->reg[c->reg0]))
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1391,8 +1389,7 @@ void JUMP_Z(struct lilith* vm, struct Instruction* c)
{
if(0 == vm->reg[c->reg0])
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1400,8 +1397,7 @@ void JUMP_NZ(struct lilith* vm, struct Instruction* c)
{
if(0 != vm->reg[c->reg0])
{
/* Adust the IP relative the the start of this instruction*/
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1414,7 +1410,7 @@ void CALLI(struct lilith* vm, struct Instruction* c)
vm->reg[c->reg0] = vm->reg[c->reg0] + reg_size;
/* Update PC */
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
void LOADI(struct lilith* vm, struct Instruction* c)
@ -1459,60 +1455,60 @@ void SR1I(struct lilith* vm, struct Instruction* c)
void LOADR(struct lilith* vm, struct Instruction* c)
{
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate -4), false, reg_size);
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate), false, reg_size);
}
void LOADR8(struct lilith* vm, struct Instruction* c)
{
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate -4), true, 1);
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate), true, 1);
}
void LOADRU8(struct lilith* vm, struct Instruction* c)
{
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate -4), false, 1);
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate), false, 1);
}
void LOADR16(struct lilith* vm, struct Instruction* c)
{
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate -4), true, 2);
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate), true, 2);
}
void LOADRU16(struct lilith* vm, struct Instruction* c)
{
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate -4), false, 2);
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate), false, 2);
}
void LOADR32(struct lilith* vm, struct Instruction* c)
{
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate -4), true, 4);
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate), true, 4);
}
void LOADRU32(struct lilith* vm, struct Instruction* c)
{
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate -4), false, 4);
vm->reg[c->reg0] = readin_bytes(vm, (vm->ip + c->raw_Immediate), false, 4);
}
void STORER(struct lilith* vm, struct Instruction* c)
{
writeout_bytes(vm, (vm->ip + c->raw_Immediate - 4), vm->reg[c->reg0], reg_size);
writeout_bytes(vm, (vm->ip + c->raw_Immediate), vm->reg[c->reg0], reg_size);
}
void STORER8(struct lilith* vm, struct Instruction* c)
{
writeout_bytes(vm, (vm->ip + c->raw_Immediate - 4), vm->reg[c->reg0], 1);
writeout_bytes(vm, (vm->ip + c->raw_Immediate), vm->reg[c->reg0], 1);
}
void STORER16(struct lilith* vm, struct Instruction* c)
{
writeout_bytes(vm, (vm->ip + c->raw_Immediate - 4), vm->reg[c->reg0], 2);
writeout_bytes(vm, (vm->ip + c->raw_Immediate), vm->reg[c->reg0], 2);
}
void STORER32(struct lilith* vm, struct Instruction* c)
{
writeout_bytes(vm, (vm->ip + c->raw_Immediate - 4), vm->reg[c->reg0], 4);
writeout_bytes(vm, (vm->ip + c->raw_Immediate), vm->reg[c->reg0], 4);
}
void JUMP(struct lilith* vm, struct Instruction* c)
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
void JUMP_P(struct lilith* vm, struct Instruction* c)
@ -1521,7 +1517,7 @@ void JUMP_P(struct lilith* vm, struct Instruction* c)
tmp1 = (signed_vm_register)(vm->reg[c->reg0]);
if(0 <= tmp1)
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1531,7 +1527,7 @@ void JUMP_NP(struct lilith* vm, struct Instruction* c)
tmp1 = (signed_vm_register)(vm->reg[c->reg0]);
if(0 > tmp1)
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1542,7 +1538,7 @@ void CMPJUMPI_G(struct lilith* vm, struct Instruction* c)
tmp2 = (signed_vm_register)(vm->reg[c->reg1]);
if(tmp1 > tmp2)
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1553,7 +1549,7 @@ void CMPJUMPI_GE(struct lilith* vm, struct Instruction* c)
tmp2 = (signed_vm_register)(vm->reg[c->reg1]);
if(tmp1 >= tmp2)
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1561,7 +1557,7 @@ void CMPJUMPI_E(struct lilith* vm, struct Instruction* c)
{
if((vm->reg[c->reg0]) == (vm->reg[c->reg1]))
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1569,7 +1565,7 @@ void CMPJUMPI_NE(struct lilith* vm, struct Instruction* c)
{
if((vm->reg[c->reg0]) != (vm->reg[c->reg1]))
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1580,7 +1576,7 @@ void CMPJUMPI_LE(struct lilith* vm, struct Instruction* c)
tmp2 = (signed_vm_register)(vm->reg[c->reg1]);
if(tmp1 <= tmp2)
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1591,7 +1587,7 @@ void CMPJUMPI_L(struct lilith* vm, struct Instruction* c)
tmp2 = (signed_vm_register)(vm->reg[c->reg1]);
if(tmp1 < tmp2)
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1599,7 +1595,7 @@ void CMPJUMPUI_G(struct lilith* vm, struct Instruction* c)
{
if((vm->reg[c->reg0]) > (vm->reg[c->reg1]))
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1607,7 +1603,7 @@ void CMPJUMPUI_GE(struct lilith* vm, struct Instruction* c)
{
if((vm->reg[c->reg0]) >= (vm->reg[c->reg1]))
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1615,7 +1611,7 @@ void CMPJUMPUI_LE(struct lilith* vm, struct Instruction* c)
{
if((vm->reg[c->reg0]) <= (vm->reg[c->reg1]))
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1623,7 +1619,7 @@ void CMPJUMPUI_L(struct lilith* vm, struct Instruction* c)
{
if((vm->reg[c->reg0]) < (vm->reg[c->reg1]))
{
vm->ip = vm->ip + c->raw_Immediate - 4;
vm->ip = vm->ip + c->raw_Immediate;
}
}
@ -1635,7 +1631,7 @@ void CMPSKIPI_G(struct lilith* vm, struct Instruction* c)
if(tmp1 > tmp2)
{
vm->ip = vm->ip + 4;
vm->ip = vm->ip + next_instruction_size(vm);
}
}