Skip to content

Commit 1bb0d77

Browse files
committed
Added tests and then implementation for the new scoping ops to create a
pointer to local variables on the stack. Possible to create a new block and end it. Can use get to access local vars from the current scope or the containing static scope. Can use local to save a little op space and get vars from the current block. The only thing to note is that these accessors only take words for the block and scope so one is limited to 255 local vars, including array sizes. It might be better to make them use dwords to allow for more, or expect that the programmer can use static or free memory for this task. The other possible issue is that begin used in a function may cause issues as the previous block in nested function calls may not be the static scope of the function but instead the scope of the calling function, which is not the desired behaviour.
1 parent cd4c47a commit 1bb0d77

File tree

2 files changed

+106
-4
lines changed

2 files changed

+106
-4
lines changed

main.c

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ enum OP{ HALT=0x00,
144144
ADD_F, SUB_F, MULT_F, DIV_F, // 59
145145
EQ_F, LT_F, GT_F, // 5C
146146
PRINT_F, READ_F, // 5E
147+
148+
BEGIN, END, SCP, // 61
149+
LOCAL, LOCAL_D, LOCAL_Q, // 64
150+
GET, GET_D, GET_Q, // 67
147151
};
148152

149153
// Simple Memory /////////////////////////////////////////////////////////////
@@ -185,6 +189,17 @@ static inline void set_qword(WORD* mem, ADDR addr, QWORD data) {
185189
mem[addr+3] = (WORD)data;
186190
}
187191

192+
static inline ADDR get_block(WORD* mem, ADDR scp, WORD scopes_above) {
193+
ADDR block = get_address(mem, scp);
194+
ADDR next = block;
195+
for (size_t i = 0; i < scopes_above; i++) {
196+
next = get_address(mem, next);
197+
if (next == 0xffff) break;
198+
block = next;
199+
}
200+
return block;
201+
}
202+
188203
// I/O ///////////////////////////////////////////////////////////////////////
189204
size_t read_program(WORD* mem, const char* filename) {
190205
FILE* fptr = fopen(filename, "rb");
@@ -232,7 +247,7 @@ void debug_memory(WORD* mem, ADDR start, ADDR end) {
232247
// Main //////////////////////////////////////////////////////////////////////
233248
int main( int argc, char *argv[] ) {
234249
// Some variables we need
235-
ADDR sp, bp, pc, ra, fp, prog_len, brk;
250+
ADDR sp, bp, pc, ra, fp, prog_len, brk, scp;
236251
WORD* mem;
237252

238253
// Allocate memory for the VM
@@ -261,11 +276,12 @@ int main( int argc, char *argv[] ) {
261276
bp = LAST_ADDR - 3;
262277
fp = bp;
263278
sp = bp;
279+
scp = bp;
264280

265281
// To help keep track if memory in this offset is accidentaly accessed
266-
mem[bp] = 0xaa;
267-
mem[bp+1] = 0xbb;
268-
mem[bp+2] = 0xcc;
282+
mem[bp] = 0xff;
283+
mem[bp+1] = 0xff;
284+
mem[bp+2] = 0x00;
269285
mem[bp+3] = 0x00;
270286

271287
// Debug info
@@ -791,6 +807,54 @@ int main( int argc, char *argv[] ) {
791807
break;
792808
}
793809

810+
/// Blocks ///
811+
case BEGIN:
812+
sp-=2;
813+
set_address(mem, sp, scp);
814+
scp = sp;
815+
break;
816+
case END:
817+
sp = scp + 2;
818+
scp = get_address(mem, scp);
819+
break;
820+
case LOCAL:
821+
mem[--sp] = mem[(scp - 1) - mem[++pc]];
822+
break;
823+
case LOCAL_D:
824+
sp-=2;
825+
set_dword(mem, sp, get_dword(mem, (scp - 2) - mem[++pc]));
826+
break;
827+
case LOCAL_Q:
828+
sp-=4;
829+
set_qword(mem, sp, get_qword(mem, (scp - 4) - mem[++pc]));
830+
break;
831+
case GET:
832+
{
833+
WORD scope = mem[++pc];
834+
WORD offset = mem[++pc];
835+
ADDR block = get_block(mem, scp, scope);
836+
mem[--sp] = mem[(block - 1) - offset];
837+
}
838+
break;
839+
case GET_D:
840+
{
841+
WORD scope = mem[++pc];
842+
WORD offset = mem[++pc];
843+
ADDR block = get_block(mem, scp, scope);
844+
sp-=2;
845+
set_dword(mem, sp, get_dword(mem, (block - 2) - offset));
846+
}
847+
break;
848+
case GET_Q:
849+
{
850+
WORD scope = mem[++pc];
851+
WORD offset = mem[++pc];
852+
ADDR block = get_block(mem, scp, scope);
853+
sp-=4;
854+
set_qword(mem, sp, get_qword(mem, (block - 4) - offset));
855+
}
856+
break;
857+
794858
/// BAD OP CODE ///
795859
default:
796860
fprintf(stderr, "Error: Unknown OP code: 0x%02x\n", mem[pc]);

test/test_movement_ops.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,44 @@
152152
"10 00 0a 55 00",
153153
"ff ff"
154154
),
155+
156+
### Blocks and scoping ###
157+
Test(
158+
"Create a new block and GET upper scope local var",
159+
"01 aa 5F 01 bb 65 01 00 00",
160+
"aa bb ff fc aa"
161+
),
162+
Test(
163+
"Create a new block and GET_D upper scope local var",
164+
"10 aa bb 5F 01 cc 66 01 00 00",
165+
"aa bb cc ff fc aa bb"
166+
),
167+
Test(
168+
"Create a new block and GET_Q upper scope local var",
169+
"1F aa bb cc dd 5F 01 ee 67 01 00 00",
170+
"aa bb cc dd ee ff fc aa bb cc dd"
171+
),
172+
Test(
173+
"Create a new block and GET upper scope local var then END",
174+
"01 aa 5F 01 bb 65 01 00 60 00",
175+
"aa"
176+
),
177+
Test(
178+
"Create a new block and get LOCAL var",
179+
"01 aa 5F 01 bb 01 cc 01 dd 62 01 00",
180+
"cc dd cc bb ff fc aa"
181+
),
182+
Test(
183+
"Create a new block and get LOCAL_D var",
184+
"01 aa 5F 01 bb 10 cc ee 01 dd 63 01 00",
185+
"cc ee dd cc ee bb ff fc aa"
186+
),
187+
Test(
188+
"Create a new block and get LOCAL_Q var",
189+
"01 aa 5F 01 bb 1F cc ee ff 22 01 dd 64 01 00",
190+
"cc ee ff 22 dd cc ee ff 22 bb ff fc aa"
191+
),
192+
155193
]
156194

157195

0 commit comments

Comments
 (0)