813 lines
24 KiB
C
813 lines
24 KiB
C
#include "executerImp.h"
|
|
#include "../common/graph.h"
|
|
#include "../common/platform.h"
|
|
|
|
void instruction_nop(proc_t *proc, opcode_data_t *instruction) {
|
|
//noop
|
|
}
|
|
void instruction_add_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0+arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i+instruction->arg1.i);
|
|
}
|
|
void instruction_sub_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0-arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i-instruction->arg1.i);
|
|
}
|
|
void instruction_mul_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0*arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i*instruction->arg1.i);
|
|
}
|
|
void instruction_div_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0/arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i/instruction->arg1.i);
|
|
}
|
|
void instruction_mod_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0%arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i%instruction->arg1.i);
|
|
}
|
|
void instruction_neg_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(-arg0)
|
|
Stack_pushInt(&proc->stack, -instruction->arg0.i);
|
|
}
|
|
void instruction_shlt(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0<<(arg1%32))
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i<<(instruction->arg1.i%32));
|
|
}
|
|
void instruction_shrt(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0>>(arg1%32))
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i>>(instruction->arg1.i%32));
|
|
}
|
|
void instruction_and(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0&arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i&instruction->arg1.i);
|
|
}
|
|
void instruction_or(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0|arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i|instruction->arg1.i);
|
|
}
|
|
void instruction_xor(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0^arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i^instruction->arg1.i);
|
|
}
|
|
void instruction_not(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(~arg0)
|
|
Stack_pushInt(&proc->stack, ~instruction->arg0.i);
|
|
}
|
|
void instruction_and_l(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0&&arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i&&instruction->arg1.i);
|
|
}
|
|
void instruction_or_l(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0||arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i|instruction->arg1.i);
|
|
}
|
|
void instruction_xor_l(proc_t *proc, opcode_data_t *instruction) {
|
|
int and=instruction->arg0.i&&instruction->arg1.i;
|
|
int or=instruction->arg0.i||instruction->arg1.i;
|
|
//push(and&&!or)
|
|
Stack_pushInt(&proc->stack, and&&!or);
|
|
}
|
|
void instruction_not_l(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(!arg0)
|
|
Stack_pushInt(&proc->stack, !instruction->arg0.i);
|
|
}
|
|
void instruction_is_l(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0!=0)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i!=0);
|
|
}
|
|
void instruction_lt_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0<arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i<instruction->arg1.i);
|
|
}
|
|
void instruction_le_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0<=arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i<instruction->arg1.i);
|
|
}
|
|
void instruction_gt_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0>arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i>instruction->arg1.i);
|
|
}
|
|
void instruction_ge_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0>=arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i>=instruction->arg1.i);
|
|
}
|
|
void instruction_eq_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0==arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i==instruction->arg1.i);
|
|
}
|
|
void instruction_neq_i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0!=arg)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i!=instruction->arg1.i);
|
|
}
|
|
void instruction_push(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0)
|
|
Stack_push(&proc->stack, instruction->arg0);
|
|
}
|
|
void instruction_dup(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0)
|
|
//push(arg0)
|
|
Stack_push(&proc->stack, instruction->arg0);
|
|
Stack_push(&proc->stack, instruction->arg0);
|
|
}
|
|
void instruction_pop(proc_t *proc, opcode_data_t *instruction) {
|
|
//noop with arg0
|
|
}
|
|
void instruction_swap(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0)
|
|
//push(arg1)
|
|
Stack_push(&proc->stack, instruction->arg0);
|
|
Stack_push(&proc->stack, instruction->arg1);
|
|
}
|
|
void instruction_high(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0<<16)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.i<<16);
|
|
}
|
|
void instruction_top(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(stack.top)
|
|
Stack_pushInt(&proc->stack, proc->stack.top);
|
|
}
|
|
void instruction_jmp(proc_t *proc, opcode_data_t *instruction) {
|
|
integral_t addr=instruction->arg0.i;
|
|
if(addr<0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_jump, addr);
|
|
return;
|
|
}
|
|
//store(arg0, r0)
|
|
proc->registers[0].i=addr;
|
|
}
|
|
void instruction_jif(proc_t *proc, opcode_data_t *instruction) {
|
|
//if(arg1) jmp(arg0)
|
|
if(instruction->arg1.i) instruction_jmp(proc, instruction);
|
|
}
|
|
void instruction_jnt(proc_t *proc, opcode_data_t *instruction) {
|
|
//if(!arg1) jmp(arg0)
|
|
if(!instruction->arg1.i) instruction_jmp(proc, instruction);
|
|
}
|
|
void instruction_jind(proc_t *proc, opcode_data_t *instruction) {
|
|
integral_t addr=instruction->arg0.i+instruction->arg1.i;
|
|
if(addr<0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_jump, addr);
|
|
return;
|
|
}
|
|
//store(arg0+arg1, r0)
|
|
proc->registers[0].i=addr;
|
|
}
|
|
void instruction_call(proc_t *proc, opcode_data_t *instruction) {
|
|
integral_t addr=instruction->arg0.i;
|
|
if(addr<0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_jump, addr);
|
|
return;
|
|
}
|
|
//push(r0)
|
|
Stack_push(&proc->stack, proc->registers[0]);
|
|
//store(arg0, r0)
|
|
proc->registers[0].i=addr;
|
|
}
|
|
void instruction_cif(proc_t *proc, opcode_data_t *instruction) {
|
|
//if(arg1) call(arg0)
|
|
if(instruction->arg1.i) instruction_call(proc, instruction);
|
|
}
|
|
void instruction_cnt(proc_t *proc, opcode_data_t *instruction) {
|
|
//if(!arg1) call(arg0)
|
|
if(!instruction->arg1.i) instruction_call(proc, instruction);
|
|
}
|
|
void instruction_store(proc_t *proc, opcode_data_t *instruction) {
|
|
//store(rarg1, arg0)
|
|
proc->registers[instruction->arg0.i%256]=instruction->arg1;
|
|
}
|
|
void instruction_stind(proc_t *proc, opcode_data_t *instruction) {
|
|
//store(arg1, arg0)
|
|
proc->registers[instruction->arg0.i%256]=instruction->arg1;
|
|
}
|
|
void instruction_puind(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(rarg0)
|
|
Stack_push(&proc->stack, proc->registers[instruction->arg0.i%256]);
|
|
}
|
|
void instruction_swreg(proc_t *proc, opcode_data_t *instruction) {
|
|
//swap(rarg0, rarg1)
|
|
proc_object_t a=proc->registers[instruction->arg0.i%256];
|
|
proc->registers[instruction->arg0.i%256]=proc->registers[instruction->arg1.i%256];
|
|
proc->registers[instruction->arg1.i%256]=a;
|
|
}
|
|
void instruction_swregi(proc_t *proc, opcode_data_t *instruction) {
|
|
//swap(rarg0, rarg1)
|
|
proc_object_t a=proc->registers[instruction->arg0.i%256];
|
|
proc->registers[instruction->arg0.i%256]=proc->registers[instruction->arg1.i%256];
|
|
proc->registers[instruction->arg1.i%256]=a;
|
|
}
|
|
void instruction_halt(proc_t *proc, opcode_data_t *instruction) {
|
|
//status(status&~PROC_STATUS_running)
|
|
proc->status&=~PROC_STATUS_running;
|
|
}
|
|
void instruction_reset(proc_t *proc, opcode_data_t *instruction) {
|
|
//status(PROC_STATUS_running)
|
|
proc->status=PROC_STATUS_running;
|
|
//inth(-1)
|
|
proc->intHandler=-1;
|
|
//foreach(r:r0,r255) store(0, r)
|
|
for(int i=0; i<256; i++) proc->registers[i].i=0;
|
|
//initStack()
|
|
initStack(&proc->stack);
|
|
}
|
|
void instruction_int(proc_t *proc, opcode_data_t *instruction) {
|
|
//int(arg0|INTERRUPT_user_mask)
|
|
Proc_interrupt(proc, instruction->arg0.i|INTERRUPT_user_mask, instruction->arg1.i);
|
|
}
|
|
void instruction_inth(proc_t *proc, opcode_data_t *instruction) {
|
|
//inth(arg0)
|
|
proc->intHandler=instruction->arg0.i;
|
|
}
|
|
void instruction_stat_g(proc_t *proc, opcode_data_t *instruction) {
|
|
//push((status>>(arg0%32))&1)
|
|
Stack_pushInt(&proc->stack, (proc->status>>(instruction->arg0.i%32))&1);
|
|
}
|
|
void instruction_stat_s(proc_t *proc, opcode_data_t *instruction) {
|
|
//status((status&~(1<<arg0))|(arg1<<arg0))
|
|
proc->status&=~(1<<(instruction->arg0.i%32));
|
|
proc->status|=(instruction->arg1.i&1)<<(instruction->arg0.i%32);
|
|
}
|
|
void instruction_stat(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(status)
|
|
Stack_pushInt(&proc->stack, proc->status);
|
|
}
|
|
#define pop(arg) Stack_popInt(&proc->stack, &arg)
|
|
void instruction_ext(proc_t *proc, opcode_data_t *instruction) {
|
|
//ext(arg0)
|
|
int arg0=0, arg1=0, arg2=0, arg3=0, arg4=0, arg5=0;
|
|
switch(instruction->arg0.i) {
|
|
case 0x00:
|
|
//ext 0 is nop
|
|
break;
|
|
|
|
//graphical ext
|
|
case 0x01:
|
|
//ext 1 is printVram()
|
|
Graph_printVram();
|
|
break;
|
|
case 0x02:
|
|
//ext 2 is pixelSet(x, y, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
Graph_pixelSet(arg0, arg1, arg2);
|
|
break;
|
|
case 0x03:
|
|
//ext 3 is pixelSet(x, y, COLOR_WHITE)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
Graph_pixelSet(arg0, arg1, COLOR_WHITE);
|
|
break;
|
|
case 0x04:
|
|
//ext 4 is pixelSet(x, y, COLOR_BLACK)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
Graph_pixelSet(arg0, arg1, COLOR_BLACK);
|
|
break;
|
|
case 0x05:
|
|
//ext 5 is pixelGet(x, y)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
Stack_pushInt(&proc->stack, Graph_pixelGet(arg0, arg1));
|
|
break;
|
|
case 0x06:
|
|
//ext 6 is line(x1, y1, x2, y2, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
pop(arg3);
|
|
pop(arg4);
|
|
Graph_line(arg0, arg1, arg2, arg3, arg4);
|
|
break;
|
|
case 0x07:
|
|
//ext 7 is lineH(y, x1, x2, color)
|
|
pop(arg0); //y
|
|
pop(arg1); //x1
|
|
pop(arg2); //x2
|
|
pop(arg3); //color
|
|
Graph_lineH(arg0, arg1, arg2, arg3);
|
|
break;
|
|
case 0x08:
|
|
//ext 8 is lineV(x, y1, y2, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
pop(arg3);
|
|
Graph_lineV(arg0, arg1, arg2, arg3);
|
|
break;
|
|
case 0x09:
|
|
//ext 9 is rect(x, y, w, h, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
pop(arg3);
|
|
pop(arg4);
|
|
Graph_rect(arg0, arg1, arg2, arg3, arg4);
|
|
break;
|
|
case 0x0a:
|
|
//ext 10 is rectFill(x, y, w, h, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
pop(arg3);
|
|
pop(arg4);
|
|
Graph_rectFill(arg0, arg1, arg2, arg3, arg4);
|
|
break;
|
|
case 0x0b:
|
|
//ext 11 is fill(color)
|
|
pop(arg0);
|
|
Graph_fill(arg0);
|
|
break;
|
|
case 0x0c:
|
|
//ext 12 is fill(COLOR_WHITE)
|
|
Graph_fill(COLOR_WHITE);
|
|
break;
|
|
case 0x0d:
|
|
//ext 13 is circle(x, y, r, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
pop(arg3);
|
|
Graph_circle(arg0, arg1, arg2, arg3);
|
|
break;
|
|
case 0x0e:
|
|
//ext 14 is circleFill(x, y, r, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
pop(arg3);
|
|
Graph_circleFill(arg0, arg1, arg2, arg3);
|
|
break;
|
|
case 0x0f:
|
|
//ext 15 is sprite(x, y, address[length])
|
|
pop(arg0); //x
|
|
pop(arg1); //y
|
|
pop(arg2); //length
|
|
pop(arg3); //address
|
|
if(arg2<=0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_arg, 0x10f);
|
|
return;
|
|
} else {
|
|
//check memory access
|
|
proc->lastAddress=arg3;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(!(access&MMU_ACCESS_r)) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
return;
|
|
}
|
|
|
|
//allocate sprite memory
|
|
char* ptr=malloc(arg2);
|
|
if(!ptr) {
|
|
Proc_interrupt(proc, INTERRUPT_unknown, 0x10f);
|
|
return;
|
|
}
|
|
|
|
//read sprite into RAM
|
|
Mmu_readBlock(&proc->mmu, ptr, arg3, arg2);
|
|
|
|
//draw sprite
|
|
Graph_sprite(arg0, arg1, ptr);
|
|
|
|
//free allocated RAM
|
|
free(ptr);
|
|
}
|
|
break;
|
|
case 0x10:
|
|
//ext 16 is horizontal(y, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
Graph_horizontal(arg0, arg1);
|
|
break;
|
|
case 0x11:
|
|
//ext 17 is vertical(x, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
Graph_vertical(arg0, arg1);
|
|
break;
|
|
case 0x12:
|
|
//ext 18 is shiftH(dist, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
Graph_shiftH(arg0, arg1);
|
|
break;
|
|
case 0x13:
|
|
//ext 19 is shiftV(dist, color)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
Graph_shiftV(arg0, arg1);
|
|
break;
|
|
case 0x14:
|
|
//ext 20 is copy(srcX, srcY, w, h, destX, destY)
|
|
pop(arg0);
|
|
pop(arg1);
|
|
pop(arg2);
|
|
pop(arg3);
|
|
pop(arg4);
|
|
pop(arg5);
|
|
Graph_copy(arg0, arg1, arg2, arg3, arg4, arg5);
|
|
break;
|
|
|
|
//platform-specific ext
|
|
case 0x20:
|
|
//ext 32 is getPlatform()
|
|
Stack_pushInt(&proc->stack, PLATFORM_CODE);
|
|
break;
|
|
|
|
//file operations
|
|
case 0x30:
|
|
//ext 48 is open(path(address[length]), mode)
|
|
pop(arg0); //address
|
|
pop(arg1); //length
|
|
pop(arg2); //mode
|
|
if(arg1<=0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_arg, 0x130);
|
|
return;
|
|
} else {
|
|
//check memory access
|
|
proc->lastAddress=arg0;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(!(access&MMU_ACCESS_r)) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
return;
|
|
}
|
|
|
|
//allocate memory
|
|
char* ptr=malloc(arg1+1);
|
|
if(!ptr) {
|
|
Proc_interrupt(proc, INTERRUPT_unknown, 0x130);
|
|
return;
|
|
}
|
|
ptr[arg0]='\0';
|
|
|
|
//read path
|
|
Mmu_readBlock(&proc->mmu, ptr, arg0, arg1);
|
|
|
|
//open file
|
|
Stack_pushInt(&proc->stack, File_open(ptr, arg2));
|
|
|
|
//free allocated RAM
|
|
free(ptr);
|
|
}
|
|
break;
|
|
case 0x31:
|
|
//ext 49 is close(fd)
|
|
pop(arg0); //fd
|
|
Stack_pushInt(&proc->stack, File_close(arg0));
|
|
break;
|
|
case 0x32:
|
|
//ext 50 is length(fd)
|
|
pop(arg0); //fd
|
|
Stack_pushInt(&proc->stack, File_length(arg0));
|
|
break;
|
|
case 0x33:
|
|
//ext 51 is truncate(fd, size)
|
|
pop(arg0); //fd
|
|
pop(arg1); //size
|
|
Stack_pushInt(&proc->stack, File_truncate(arg0, arg1));
|
|
break;
|
|
case 0x34:
|
|
//ext 52 is delete(path(address[length]))
|
|
pop(arg0); //address
|
|
pop(arg1); //length
|
|
if(arg1<=0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_arg, 0x134);
|
|
return;
|
|
} else {
|
|
//check memory access
|
|
proc->lastAddress=arg0;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(!(access&MMU_ACCESS_r)) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
return;
|
|
}
|
|
|
|
//allocate memory
|
|
char* ptr=malloc(arg1+1);
|
|
if(!ptr) {
|
|
Proc_interrupt(proc, INTERRUPT_unknown, 0x134);
|
|
return;
|
|
}
|
|
ptr[arg0]='\0';
|
|
|
|
//read path into RAM
|
|
Mmu_readBlock(&proc->mmu, ptr, arg0, arg1);
|
|
|
|
//delete path
|
|
Stack_pushInt(&proc->stack, File_delete(ptr));
|
|
|
|
//free allocated RAM
|
|
free(ptr);
|
|
}
|
|
break;
|
|
case 0x35:
|
|
//ext 53 is mkdir(path(address[length]))
|
|
pop(arg0); //address
|
|
pop(arg1); //length
|
|
if(arg1<=0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_arg, 0x135);
|
|
return;
|
|
} else {
|
|
//check memory access
|
|
proc->lastAddress=arg0;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(!(access&MMU_ACCESS_r)) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
return;
|
|
}
|
|
|
|
//allocate memory
|
|
char* ptr=malloc(arg1+1);
|
|
if(!ptr) {
|
|
Proc_interrupt(proc, INTERRUPT_unknown, 0x135);
|
|
return;
|
|
}
|
|
ptr[arg0]='\0';
|
|
|
|
//read path into RAM
|
|
Mmu_readBlock(&proc->mmu, ptr, arg0, arg1);
|
|
|
|
//mkdir
|
|
Stack_pushInt(&proc->stack, File_mkdir(ptr));
|
|
|
|
//free allocated RAM
|
|
free(ptr);
|
|
}
|
|
break;
|
|
case 0x36:
|
|
//ext 54 is read(fd, offset, address, length)
|
|
pop(arg0); //fd
|
|
pop(arg1); //offset
|
|
pop(arg2); //address
|
|
pop(arg3); //length
|
|
if(arg3<0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_arg, 0x136);
|
|
return;
|
|
} else if(arg3==0) {
|
|
Stack_pushInt(&proc->stack, File_write(arg0, arg1, 0x00000000, 0));
|
|
} else {
|
|
//check memory access
|
|
proc->lastAddress=arg2;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(!(access&MMU_ACCESS_w)) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_write, proc->lastAddress);
|
|
return;
|
|
}
|
|
|
|
//allocate sprite memory
|
|
char* ptr=malloc(arg3);
|
|
if(!ptr) {
|
|
Proc_interrupt(proc, INTERRUPT_unknown, 0x136);
|
|
return;
|
|
}
|
|
|
|
//read from file
|
|
Stack_pushInt(&proc->stack, File_read(arg0, arg1, ptr, arg3));
|
|
|
|
//write back into processor memory
|
|
Mmu_writeBlock(&proc->mmu, ptr, arg2, arg3);
|
|
|
|
//free allocated RAM
|
|
free(ptr);
|
|
}
|
|
break;
|
|
case 0x37:
|
|
//ext 55 is write(fd, offset, address, length)
|
|
pop(arg0); //fd
|
|
pop(arg1); //offset
|
|
pop(arg2); //address
|
|
pop(arg3); //length
|
|
if(arg3<0) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_arg, 0x137);
|
|
return;
|
|
} else if(arg3==0) {
|
|
Stack_pushInt(&proc->stack, File_write(arg0, arg1, 0x00000000, 0));
|
|
} else {
|
|
//check memory access
|
|
proc->lastAddress=arg2;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(!(access&MMU_ACCESS_r)) {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
return;
|
|
}
|
|
|
|
//allocate memory
|
|
char* ptr=malloc(arg3);
|
|
if(!ptr) {
|
|
Proc_interrupt(proc, INTERRUPT_unknown, 0x137);
|
|
return;
|
|
}
|
|
|
|
//read data into RAM
|
|
Mmu_readBlock(&proc->mmu, ptr, arg2, arg3);
|
|
|
|
//write to file
|
|
Stack_pushInt(&proc->stack, File_write(arg0, arg1, ptr, arg3));
|
|
|
|
//free allocated RAM
|
|
free(ptr);
|
|
}
|
|
break;
|
|
|
|
//unknown ext
|
|
default:
|
|
Proc_interrupt(proc, INTERRUPT_illegal_instruction, instruction->arg0.i);
|
|
}
|
|
}
|
|
void instruction_mem_wr(proc_t *proc, opcode_data_t *instruction) {
|
|
proc->lastAddress=instruction->arg0.i;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(access&MMU_ACCESS_r) {
|
|
word_t result;
|
|
//push(readWord(arg0))
|
|
Mmu_readWord(&proc->mmu, &result, proc->lastAddress);
|
|
Stack_pushInt(&proc->stack, result.i);
|
|
} else {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
}
|
|
}
|
|
void instruction_mem_ww(proc_t *proc, opcode_data_t *instruction) {
|
|
proc->lastAddress=instruction->arg0.i;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(access&MMU_ACCESS_w) {
|
|
//writeWord(arg0, arg1)
|
|
Mmu_writeWord(&proc->mmu, instruction->arg1.word, proc->lastAddress);
|
|
} else {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_write, proc->lastAddress);
|
|
}
|
|
}
|
|
void instruction_mem_hr(proc_t *proc, opcode_data_t *instruction) {
|
|
proc->lastAddress=instruction->arg0.i;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(access&MMU_ACCESS_r) {
|
|
half_word_t result;
|
|
//push(readHalfWord(arg0))
|
|
Mmu_readHalfWord(&proc->mmu, &result, proc->lastAddress);
|
|
Stack_pushInt(&proc->stack, (result.bytes[0]<<8)|result.bytes[1]);
|
|
} else {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
}
|
|
}
|
|
void instruction_mem_hw(proc_t *proc, opcode_data_t *instruction) {
|
|
proc->lastAddress=instruction->arg0.i;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(access&MMU_ACCESS_w) {
|
|
half_word_t hw;
|
|
hw.s=(short) instruction->arg1.i&0xffff;
|
|
//writeHalfWord(arg0, arg1)
|
|
Mmu_writeHalfWord(&proc->mmu, hw, proc->lastAddress);
|
|
} else {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_write, proc->lastAddress);
|
|
}
|
|
}
|
|
void instruction_mem_br(proc_t *proc, opcode_data_t *instruction) {
|
|
proc->lastAddress=instruction->arg0.i;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(access&MMU_ACCESS_r) {
|
|
char result;
|
|
//push(readByte(arg0))
|
|
Mmu_readByte(&proc->mmu, &result, proc->lastAddress);
|
|
Stack_pushInt(&proc->stack, result);
|
|
} else {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_read, proc->lastAddress);
|
|
}
|
|
}
|
|
void instruction_mem_bw(proc_t *proc, opcode_data_t *instruction) {
|
|
proc->lastAddress=instruction->arg0.i;
|
|
int access=Mmu_checkAccess(&proc->mmu, proc->lastAddress);
|
|
if(access&MMU_ACCESS_w) {
|
|
char c;
|
|
c=(char) instruction->arg1.i%0xff;
|
|
//writeByte(arg0, arg1)
|
|
Mmu_writeByte(&proc->mmu, c, proc->lastAddress);
|
|
} else {
|
|
Proc_interrupt(proc, INTERRUPT_illegal_write, proc->lastAddress);
|
|
}
|
|
}
|
|
void instruction_lastad(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(lastad)
|
|
Stack_pushInt(&proc->stack, proc->lastAddress);
|
|
}
|
|
void instruction_sub(proc_t *proc, opcode_data_t *instruction) {
|
|
//subscribe(arg0)
|
|
proc->subscribed|=instruction->arg0.i;
|
|
}
|
|
void instruction_unsub(proc_t *proc, opcode_data_t *instruction) {
|
|
//unsubscribe(arg0)
|
|
proc->subscribed&=~instruction->arg0.i;
|
|
}
|
|
void instruction_extend(proc_t *proc, opcode_data_t *instruction) {
|
|
//illegal by itself
|
|
illegalInstruction(proc, instruction);
|
|
}
|
|
|
|
void instructionExt_nop(proc_t *proc, opcode_data_t *instruction) {
|
|
//noop
|
|
}
|
|
void instructionExt_add_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0+arg1)
|
|
Stack_pushDec(&proc->stack, instruction->arg0.d+instruction->arg1.d);
|
|
}
|
|
void instructionExt_sub_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0-arg1)
|
|
Stack_pushDec(&proc->stack, instruction->arg0.d-instruction->arg1.d);
|
|
}
|
|
void instructionExt_mul_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0*arg1)
|
|
Stack_pushDec(&proc->stack, instruction->arg0.d*instruction->arg1.d);
|
|
}
|
|
void instructionExt_div_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0/arg1)
|
|
Stack_pushDec(&proc->stack, instruction->arg0.d/instruction->arg1.d);
|
|
}
|
|
void instructionExt_pow_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement pow with math.h
|
|
}
|
|
void instructionExt_neg_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(-arg0)
|
|
Stack_pushDec(&proc->stack, -instruction->arg0.d);
|
|
}
|
|
void instructionExt_sqrt(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement sqrt with math.h
|
|
}
|
|
void instructionExt_cbrt(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement cbrt with math.h
|
|
}
|
|
void instructionExt_hypot(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement hypot with math.h
|
|
}
|
|
void instructionExt_exp(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement exp with math.h
|
|
}
|
|
void instructionExt_ln(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement ln with math.h
|
|
}
|
|
void instructionExt_floor(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement floor with math.h
|
|
}
|
|
void instructionExt_ceil(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement ceil with math.h
|
|
}
|
|
void instructionExt_round(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement round with math.h
|
|
}
|
|
void instructionExt_cos(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement cos with math.h
|
|
}
|
|
void instructionExt_sin(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement sin with math.h
|
|
}
|
|
void instructionExt_tan(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement tan with math.h
|
|
}
|
|
void instructionExt_atan(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement atan with math.h
|
|
}
|
|
void instructionExt_atan2(proc_t *proc, opcode_data_t *instruction) {
|
|
//TODO implement atan2 with math.h
|
|
}
|
|
void instructionExt_lt_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0<arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.d<instruction->arg1.d);
|
|
}
|
|
void instructionExt_le_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0<=arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.d<=instruction->arg1.d);
|
|
}
|
|
void instructionExt_gt_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0>arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.d>instruction->arg1.d);
|
|
}
|
|
void instructionExt_ge_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0>=arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.d>=instruction->arg1.d);
|
|
}
|
|
void instructionExt_eq_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0==arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.d==instruction->arg1.d);
|
|
}
|
|
void instructionExt_neq_d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(arg0!=arg1)
|
|
Stack_pushInt(&proc->stack, instruction->arg0.d!=instruction->arg1.d);
|
|
}
|
|
void instructionExt_i2d(proc_t *proc, opcode_data_t *instruction) {
|
|
//push((decimal_t) arg0)
|
|
Stack_pushDec(&proc->stack, (decimal_t) instruction->arg0.i);
|
|
}
|
|
void instructionExt_d2i(proc_t *proc, opcode_data_t *instruction) {
|
|
//push((integral_t) arg0)
|
|
Stack_pushInt(&proc->stack, (decimal_t) instruction->arg0.d);
|
|
}
|
|
void instructionExt_cst_pi(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(pi)
|
|
Stack_pushDec(&proc->stack, 3.14159265359); //TODO do better with math.h
|
|
}
|
|
void instructionExt_cst_e(proc_t *proc, opcode_data_t *instruction) {
|
|
//push(e)
|
|
Stack_pushDec(&proc->stack, 2.71828182846); //TODO do better with math.h
|
|
}
|
|
|
|
void illegalInstruction(proc_t *proc, opcode_data_t *instruction) {
|
|
//int(INTERRUPT_illegal_instruction)
|
|
Proc_interrupt(proc, INTERRUPT_illegal_instruction, instruction->op);
|
|
}
|