//STDMEM
//No virtual memory

//Defines:
//Ins_LoadMemory
//Ins_StoreMemory
//Ins_Push
//Ins_Pop
//Ins_BulkImmediate
//Scal_Malloc
//Scal_Free
//Scal_Free_SkipGet
//Scal_Realloc

!Ins_LoadMemory
.Ins_LoadMemory
LLOD R2 R2 R9
ADD R3 R3 R9
CPY R3 R2
RET

!Ins_StoreMemory
.Ins_StoreMemory
LLOD R3 R3 R9
ADD R2 R2 R9
CPY R3 R2
RET


!Ins_Push
.Ins_Push
LLOD R3 R3 R9
LOD R6 R5
LLOD R7 R6 @PD_STACK //stack location
BRZ .Ins_Push_CreateStack R7
ADD R8 R7 64 //R8 = stack cap
LLOD R6 R9 15
BGE .Ins_Push_StackOverflow R6 R8
BRL .Ins_Push_StackUnderflow R6 R7
.Ins_Push_CreateStack_Ret
INC R6 R6
STR R6 R3
LSTR R9 15 R6
RET

.Ins_Push_CreateStack
STR !VirtualRegister 64
PSH R3
SUB R3 !VirtualRegister R9
PSH R6
CAL !Scal_Malloc
POP R6
POP R3
LOD R7 !VirtualRegister //address
DEC R7 R7
LSTR R6 @PD_STACK R7
MOV R6 R7
JMP .Ins_Push_CreateStack_Ret


.Ins_Push_StackOverflow
STR !OSVar_ERROR 10
RET

.Ins_Push_StackUnderflow
STR !OSVar_ERROR 11
RET

!Ins_Pop
.Ins_Pop
LOD R6 R5
LLOD R6 R6 @PD_STACK //stack location
BRZ .Ins_Push_StackUnderflow R6
ADD R7 R6 64
LLOD R8 R9 15
BRG .Ins_Push_StackOverflow R8 R7
BLE .Ins_Push_StackUnderflow R8 R6
ADD R3 R3 R9
CPY R3 R8
DEC R8 R8
LSTR R9 15 R8
RET

!Ins_BulkImmediate
.Ins_BulkImmediate
LLOD R3 R3 R9
.Ins_BulkImmediate_Loop
INC R4 R4
OUT %ADDR R4
IN R6 %BUS
STR R3 R6
INC R3 R3
BNZ .Ins_BulkImmediate_Loop R6
RET

!Scal_Malloc
.Scal_Malloc
ADD R3 R3 R9
PSH R3
LOD R3 R3 //malloc size
BGE .Scal_Malloc_InvalidOp R3 @SMAX
LOD R1 !OSVar_MALLOCSADDR
PSH R0
.Scal_Malloc_Loop
MOV R7 R1
LOD R1 R1
BRE .Scal_Malloc_EOM R1 @MAX
AND R2 R1 @SMAX
AND R6 R1 @MSB
MOV R1 R7
BRZ .Scal_Malloc_Attempt R6
.Scal_Malloc_Attempt_Return
ADD R1 R1 R2
INC R1 R1
JMP .Scal_Malloc_Loop

.Scal_Malloc_Attempt
BRL .Scal_Malloc_Checkformerge R2 R3
OR R6 R3 @MSB
STR R1 R6
POP R0
POP R6
INC R1 R1
STR R6 R1 //return address of yeah
BRE .Scal_Malloc_Success R2 R3
ADD R1 R1 R3
SUB R2 R2 R3
DEC R2 R2
STR R1 R2
INC R1 R1
.Scal_Malloc_Success
DEC R1 R1
STR !OSVar_MALLOCSADDR R1
RET

.Scal_Malloc_Checkformerge
MOV R7 R1
ADD R1 R1 R2
INC R1 R1
LOD R6 R1
BRN .Scal_Malloc_Loop R6
ADD R2 R2 R6
INC R2 R2
BGE .Scal_Malloc_Loop R2 @SMAX //if combined are too big then don't merge
MOV R1 R7
STR R1 R2
JMP .Scal_Malloc_Loop

.Scal_Malloc_EOM
POP R1
BGE .Scal_Malloc_OOM R1 1
INC R1 R1
PSH R1
IMM R1 M0
JMP .Scal_Malloc_Loop

.Scal_Malloc_OOM
STR !OSVar_ERROR 4
POP R0
POP R0
RET

.Scal_Malloc_InvalidOp
STR !OSVar_ERROR 3
POP R0
POP R0
RET

!Scal_Free
.Scal_Free
LLOD R3 R3 R9
DEC R3 R3
!Scal_Free_SkipGet
.Scal_Free_SkipGet
LOD R1 R3
AND R1 R1 @SMAX
STR R3 R1
RET

!Scal_Realloc
.Scal_Realloc
ADD R3 R3 R9
PSH R3
LOD R3 R3 //size
PSH R3
SUB R3 !VirtualRegister R9 
CAL !Ins_Pop
LOD R6 !VirtualRegister //address
POP R3
DEC R6 R6
LOD R2 R6
AND R2 R2 0x7FFF
//if the new size is less than current size, then split
BRG .Scal_Realloc_expand R3 R2
SUB R2 R2 R3
DEC R2 R2
BRN .Scal_Realloc_end R2
OR R3 R3 0x8000
STR R6 R3
ADD R6 R6 R3
INC R6 R6
STR R6 R2
STR !OSVar_MALLOCSADDR R6
JMP .Scal_Realloc_end
//R7 = next part address
.Scal_Realloc_expand
ADD R7 R6 R2
INC R7 R7
LOD R8 R7
BRN .Scal_Realloc_Remalloc R8
SUB R1 R3 R2
DEC R1 R1
BRL .Scal_Realloc_Remalloc R8 R1
OR R3 R3 0x8000
STR R6 R3
BRE .Scal_Realloc_end R8 R3
ADD R7 R7 R1 //newaddr = nextaddr + R1 + 1
INC R7 R7 
STR !OSVar_MALLOCSADDR R7
SUB R8 R8 R1 //newsize = prevsize - R1 - 1
DEC R8 R8
STR R7 R8
.Scal_Realloc_end
POP R3
INC R6 R6
STR R3 R6
RET

.Scal_Realloc_Remalloc
PSH R6
PSH R2
STR !VirtualRegister R3
SUB R3 !VirtualRegister R9 
CAL .Scal_Malloc
LOD R7 !VirtualRegister
POP R2
POP R6
POP R3
STR R3 R7
//unalloc original (this should go after if I ever multithread the kernel but in this case it saves like 1 operation so)
STR R6 R2
//copy data
INC R6 R6
MOV R8 R7
.Scal_Realloc_CopyLoop
CPY R7 R6
INC R7 R7
INC R6 R6
DEC R2 R2
BNZ .Scal_Realloc_CopyLoop R2

RET
