C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Virtual Machine implementation problem, Please help me to sp

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C Language
View previous topic :: View next topic  
Author Message
weidongtom@gmail.com
Guest





PostPosted: Mon May 07, 2007 9:12 am    Post subject: Virtual Machine implementation problem, Please help me to sp Reply with quote



Hi,

I tried to implement the Universal Machine as described in
http://www.boundvariable.org/task.shtml, and I managed to get one
implemented (After looking at what other's have done.) But when I use
to run a UM program, I kept on getting error messages. I have used
someone else's implementation and it runs fine. I have compared my
code with other's and I still can't figure it out what's wrong with
mine. So please help me out, after 3 days of debugging I don't think I
can ever make it. Here's my implementation. Thanks in advance.

#include <stdio.h> //printf(), putchar(), fprintf(), fread(),
fputchar(), strerror()
#include <string.h> //memcpy, memset
#include <stdlib.h> //malloc()
#include <errno.h> //errno
#include <sys/stat.h> //stat()

//internal data
typedef unsigned int u32;
typedef unsigned char u8;

//debug macros
#define DUMP_FILE_NAME "memory.dmp"
//#define PRINT_DEBUG_MSG
//#define DUMP_MEMORY
#ifdef PRINT_DEBUG_MSG
#define dprintf(x,...) printf(x,...)
#else
#define dprintf(x,...)
#endif

//decode macros
#define REG_A(codex) ((codex >> 6) & 7)
#define REG_B(codex) ((codex >> 3) & 7)
#define REG_C(codex) (codex & 7)
#define OPCODE(codex) ((codex >> 2Cool & 15)
#define SPEC_A(codex) ((codex >> 25) & 7)
#define SPEC_V(codex) (codex & 0x0fffffffL)


//opcodes
#define OP_CMOV 0
#define OP_INDEX 1
#define OP_AMAND 2
#define OP_ADD 3
#define OP_MUL 4
#define OP_DIV 5
#define OP_NAND 6
#define OP_HALT 7
#define OP_ALLOC 8
#define OP_FREE 9
#define OP_OUT 10
#define OP_IN 11
#define OP_LOAD 12
#define OP_ORTHO 13

//32 bit Universal Machine cpu struct
typedef struct UM32_{
u32 finger;
u32 r[8];
u32* program;
}UM32;

/*Change local small-endian to UM's internal big-endian
* ###require more work for portability
* this is to replace the inet/arpa.h's ntohl()
* ###
*/
void change_endian(u32* value){
u8 tmp1[4], tmp2[4];
memcpy((u32 *)tmp1, value, sizeof(u32));
tmp2[0] = tmp1[3];
tmp2[1] = tmp1[2];
tmp2[2] = tmp1[1];
tmp2[3] = tmp1[0];
memcpy(value, (u32 *)tmp2, sizeof(u32));
}

/* A wrapper for malloc() in stdlib.h */
void *my_malloc(size_t size){
void *tmp = malloc(size);
if(tmp != NULL)
return tmp;
else{
fprintf(stderr, "Falied in my_malloc() in attempt to allocate memory
of size: %d.\n",
size);
exit(1);
}
}

/* Create an array with size size+1,
* where array[-1] is used for holding the size of the array
* return a 32 bit arrayID (currently implemented as it's address)
*/
u32 create_array(u32 size){
u32 *tmp = (u32*)my_malloc(sizeof(u32)*size+1);
memset(tmp+1, 0, sizeof(u32)*size);
*tmp = size;
return (u32)(tmp+1);
}

#define GET_ARRAY_SIZE(arrayID) (*((u32*)(arrayID-1)))
#define ARRAY(arrayID) ((u32*)(arrayID))
#define WHOLE_ARRAY(arrayID) ((u32*)(arrayID)-1)

/* Delete an array created with create_array()*/
void delete_array(u32 arrayID){
free(WHOLE_ARRAY(arrayID));
}

/* Duplicate the content in from to that of to.
* original data in to is discarded.
*/
void copy2array0(UM32 *um, u32 src){
int size = (u32)GET_ARRAY_SIZE(src);
if(!(um->program))
free(um->program);
um->program = (u32*)my_malloc(sizeof(u32)*size+1);
memcpy(um->program, WHOLE_ARRAY(src), size+1);
um->program++;
}

void load_program(u32** membuffer, const char* filename){
int i, size_read, file_size, membuffer_size;
struct stat file_info;
FILE *infile;

//Find file info
if(stat(filename, &file_info)){
fprintf(stderr, "Failed to stat file: %s. %s\n", filename,
strerror(errno));
exit(1);
}
file_size = file_info.st_size;

//Open file
dprintf("Opening file: %s ...", filename);
infile = fopen(filename, "rb");
if(infile == NULL){
fprintf(stderr, "Failed to open file: %s. %s\n", filename,
strerror(errno));
exit(1);
}
dprintf("done\n");

//Read buffer
dprintf("Reading file content with size: %d ...", file_size);
membuffer_size = sizeof(uCool*file_size/sizeof(u32);
if(!(*membuffer))
free((*membuffer));
//(*membuffer) = (u32*)my_malloc(sizeof(u32)*membuffer_size);
(*membuffer) = (u32*)create_array(membuffer_size);
size_read = fread((*membuffer), sizeof(uCool, file_size,infile);
fclose(infile);
if(size_read != file_size && !feof(infile)){
fprintf(stderr, "Warning: failed to read all data.\n");
}
dprintf("done.\n");

//change the endian
dprintf("Changing small-endian data to big_endian ...\n");
for(i = 0; i < membuffer_size; i++){
dprintf(" %08x->", (*membuffer)[i]);
change_endian(&(*membuffer)[i]);
dprintf("%08x", (*membuffer)[i]);
if((i+1)%4 == 0)
dprintf("\n");
}
dprintf("\ndone.\n");
dprintf("Program of size: %d loaded.\n",
(*((*membuffer)-1))*sizeof(u32));
}

void init_um32(UM32* um, u32* program){
int i;
dprintf("Initializing the Universal Machine ...");
if(program == NULL){
fprintf(stderr, "Fatal Error in init_um32, program is NULL.\n");
exit(1);
}
dprintf("\nRegisters:");
for(i=0;i<8;i++){
um->r[i] = 0;
dprintf(" %08x", um->r[i]);
}
um->finger = 0;
um->program = program;
dprintf("\nfinger = %08x\nprogram loaded at %08x\n", um->finger,
(u32)um->program);
dprintf("done.\n");
}

void dump_memory(u32 *mem){
FILE *outfile = NULL;
int i;
if(mem == NULL){
fprintf(stderr, "UM Memory is null.\n");
exit(1);
}
outfile = fopen(DUMP_FILE_NAME, "w");
dprintf("Beginning memory dump of size: %d...\n", *(mem-1));
if(!outfile){
fprintf(stderr, "Error in dump_memory. Failed to open file: %s.
%s",
DUMP_FILE_NAME, strerror(errno));
exit(1);
}
for(i=0;i<*(mem-1); i++){
fprintf(outfile, " %08x", mem[i]);
if((i+1)%8 == 0)
fprintf(outfile, "\n");
}
dprintf("Done.\n");
fclose(outfile);
}

int bound_program(UM32 um, u32 index){
if(index > *(um.program-1))
return 1;
return 0;
}

int bound_array(u32 arrayID, u32 index){
if(!ARRAY(arrayID) || index > GET_ARRAY_SIZE(arrayID))
return 1;
return 0;
}

/* Execute one instruction
* return 1 on success
*/
#define R(a) um->r[a]
#define PROGRAM (um->program)
#define FINGER (um->finger)
int um_run(UM32 *um, int trace){
u8 opcode;
u32 a, b, c, codex;

if(bound_program(*um, FINGER)){
printf("Array Index out of bound.\n");
exit(1);
}
codex = PROGRAM[FINGER++];
opcode = OPCODE(codex);
a = REG_A(codex);
b = REG_B(codex);
c = REG_C(codex);

if(trace)
printf("\ncodex=%08x, opcode=%d, finger=%08x\n", codex, opcode,
FINGER);

if(opcode == OP_ORTHO){
a = SPEC_A(codex);
R(a) = SPEC_V(codex);
if(trace){
printf("OP_ORTHO, r[%d]=%u\n", a, R(a));
printf("registers: %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x
\n",
R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7));
}
return 1;
}
switch(opcode){
case OP_CMOV:
if(!R(c)){
R(a) = R(b);
if(trace){
printf("OP_CMOV, r[%d]=r[%d]=%08x\n", a, b, R(a));
}
}
break;
case OP_INDEX:
if(!R(b)){
if(bound_program(*um, R(c))){
printf("Index out of bound in accessing array0 at offset %08x\n",
R(c));
exit(0);
}
R(a) = PROGRAM[R(c)];
}
else{
if(bound_array(R(b), R(c))){
printf("Index out of bound in accessing array%d\n", R(b));
exit(1);
}
R(a) = ARRAY(R(b))[R(c)];
}
if(trace)
printf("OP_INDEX, r[%d]=array[%d][%d]=%08x\n", a, b, c, R(a));
break;
case OP_AMAND:
if(!R(a)){
if(bound_program(*um, R(b))){
printf("Index out of bound in accessing array0 at offset %08x\n",
R(c));
exit(0);
}
PROGRAM[R(b)] = R(c);
}
else{
if(bound_array(R(a), R(b))){
printf("Index out of bound in accessing array%d\n", R(b));
exit(1);
}
ARRAY(R(a))[R(b)] = R(c);
}
if(trace)
printf("OP_AMAND, array[%d][%d]=r[%d]=%08x\n", a, b, c, R(c));
break;
case OP_ADD:
R(a) = R(b) + R(c);
if(trace)
printf("OP_ADD, r[%d]=r[%d]+r[%d]=%08x\n", a, b, c, R(a));
break;
case OP_MUL:
R(a) = R(b) * R(c);
if(trace)
printf("OP_ADD, r[%d]=r[%d]*r[%d]=%08x\n", a, b, c, R(a));
break;
case OP_DIV:
R(a) = R(b) / R(c);
if(trace)
printf("OP_ADD, r[%d]=r[%d]/r[%d]=%08x\n", a, b, c, R(a));
break;
case OP_NAND:
R(a) = ~(R(b) & R(c));
if(trace)
printf("OP_ADD, r[%d]=~(r[%d]&r[%d])=%08x\n", a, b, c, R(a));
break;
case OP_HALT:
if(trace)
printf("OP_HALT, stopping program ... done.\n");
return 0;
break;
case OP_ALLOC:
R(b) = create_array(R(c));
if(trace)
printf("OP_ALLOC, r[%d]=create_array(r[%d])=%08x\n", b, c, R(b));
break;
case OP_FREE:
delete_array(R(c));
R(c) = 0;
if(trace)
printf("OP_REE, free(r[%d]=%08x)\n", c, R(c));
break;
case OP_OUT:
if(R(c) < 256){
putchar(R(c));
if(trace)
printf("OP_OUT, putchar(r[%d]=%08x)\n", c, R(c));
}
else
fprintf(stdout, "Warning, failed to output value %08x as char.\n",
R(c));
break;
case OP_IN:
R(c)=getchar();
if(trace)
printf("OP_IN, r[%d]=getchar()=%08x", c, R(c));
break;
case OP_LOAD:
if(R(b) != 0)
copy2array0(um, R(b));
FINGER = R(c);
if(trace){
printf("OP_LOAD, loading program into array0 from array[%d] at %08x
\n",
b, R(b));
printf("\tfinger=%08x\n", FINGER);
}
break;
default:
printf("Fatal Error: Bad opcode=%d, codex=%08x\n", opcode, codex);
return 0;
break;
}
if(trace)
printf("registers: %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x
\n",
R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7));
return 1;
}

int main(int argc, char *argv[]){
UM32 um;
u32 *program;
int run;

#ifndef NOT_GDB
argc = 2;
argv[1] = "sandmark.umz";
#endif
if(argc < 2){
printf("Usage: %s filename\n", argv[0]);
exit(0);
}
//load program
load_program(&program, argv[1]);
//initialize um
init_um32(&um, program);
#ifdef DUMP_MEMORY
dump_memory(program);
#endif
do{
run = um_run(&um, 1);
}while(run);
return 0;
}
Back to top
weidongtom@gmail.com
Guest





PostPosted: Tue May 08, 2007 9:12 am    Post subject: Re: Virtual Machine implementation problem, Please help me t Reply with quote



On May 8, 7:37 am, Old Wolf <oldw...@inspire.net.nz> wrote:
Quote:
But when I use
to run a UM program, I kept on getting error messages.

What error messages?

#define dprintf(x,...) printf(x,...)

This is non-standard (Conceivably your compiler allows it
as an extension; for the rest of my reply I'll assume
it doesn't).

If your compiler is compliant with C99 you can write:
#define dprintf(x, ...) printf(x, __VA_ARGS__)

after also including <stdarg.h> of course. If your compiler
does not support this then you will have to do something
else, such as:
#define dprintf printf

which would work in this case.

void change_endian(u32* value){
u8 tmp1[4], tmp2[4];
memcpy((u32 *)tmp1, value, sizeof(u32));

tmp1 might not be correctly aligned for u32.

tmp2[0] = tmp1[3];
tmp2[1] = tmp1[2];
tmp2[2] = tmp1[1];
tmp2[3] = tmp1[0];
memcpy(value, (u32 *)tmp2, sizeof(u32));
}

Code like this is likely to cause problems. You should re-write
the code to:
* Not depend on any endian issues
* Not use any casts
* Not rely on alignment

Of course there are one or two rare situations when casts
are necessary, but almost every one in your code is
masking potential undefined behaviour.

The above function could be improved to: (note, better
would be to write code that doesn't use it at all, and
the following would still cause trouble on the DS9000)

void change_endian(u32* value){
u8 *ptr = (u8 *)value;
u8 temp[4];

temp[0] = ptr[3];
temp[1] = ptr[2];
temp[2] = ptr[1];
temp[3] = ptr[0];

*value = temp;
}

Hi,

Thanks for your assistance, and I was able to make a few changes to
the code. That was the first time I ever post on a group so I didn't
know exactly what I have to say. Well, being a novice is never
easy...dump and stupid... But thanks for your help.

The code was able to be compiled by gcc 3.4.2 <mingw-speical>. As I am
developing it on Windows (and I am a novice) I don't know if there's
any replacement on my platform for the library function ntohl()
defined in <netinet/arpa.h> found in Linux/Unix, so that I can use it
to changed the UM binary file data (which is big-endian) to my local-
intel's small-endian 32 bit data, so I came up with:
void change_endian(u32* value);
to handle the problem which seems to have worked.

So, there's no compilation problem, but there's a runtime error:
"Array index out of bound."
codex=c0000032, opcode=12, finger=0000000e
OP_LOAD, loading program into array0 from array[6] at 00000000
finger=0400005b
registers: 00000000d, 02000014, 0400005b, 06000035, 00000000, 0000000,
00000000, 00000000

when run with this UM binary file: http://www.boundvariable.org/sandmark.umz
.. There's nothing wrong with the binary file, so I suspect there's
something wrong with the way I handle the array memory allocation, or
is there something wrong with how I change the endians (which seems to
be unlikely).

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <stdarg.h>

//internal data
typedef unsigned int u32;
typedef unsigned char u8;

//debug macros
#define DUMP_FILE_NAME "memory.dmp"
#define PRINT_DEBUG_MSG
#define DUMP_MEMORY

//decode macros
#define REG_A(codex) ((codex >> 6) & 7)
#define REG_B(codex) ((codex >> 3) & 7)
#define REG_C(codex) (codex & 7)
#define OPCODE(codex) ((codex >> 2Cool & 15)
#define SPEC_A(codex) ((codex >> 25) & 7)
#define SPEC_V(codex) (codex & 0x0fffffffL)


//opcodes
#define OP_CMOV 0
#define OP_INDEX 1
#define OP_AMAND 2
#define OP_ADD 3
#define OP_MUL 4
#define OP_DIV 5
#define OP_NAND 6
#define OP_HALT 7
#define OP_ALLOC 8
#define OP_FREE 9
#define OP_OUT 10
#define OP_IN 11
#define OP_LOAD 12
#define OP_ORTHO 13

//32 bit Universal Machine cpu struct
typedef struct UM32_{
u32 finger;
u32 r[8];
u32* program;
}UM32;

//function prototypes
void *my_malloc(size_t size);
u32* create_array(u32 size);
void delete_array(u32 *array);
u32 get_arrayID(u32 *array);
u32* get_array_by_ID(u32 ID);
void delete_array_by_ID(u32 ID);
u32 get_array_size(u32 *array);
void dprintf(const char *fmt, ...);

void dprintf(const char *fmt, ...){
#ifdef PRINT_DEBUG_MSG
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
#endif
return;
}

/*Change local small-endian to UM's internal big-endian
* this is a dirty hack to replace the netinet/arpa.h's ntohl()
*/
void change_endian(u32* value){
u8 tmp1[4], tmp2[4];
memcpy((u32 *)tmp1, value, sizeof(u32));
tmp2[0] = tmp1[3];
tmp2[1] = tmp1[2];
tmp2[2] = tmp1[1];
tmp2[3] = tmp1[0];
memcpy(value, (u32 *)tmp2, sizeof(u32));
}

/* A wrapper for malloc() in stdlib.h */
void *my_malloc(size_t size){
void *tmp = malloc(size);
if(tmp != NULL)
return tmp;
else{
fprintf(stderr, "Falied in my_malloc() in attempt to allocate memory
of size: %d.\n",
size);
exit(1);
}
}

/* Create an array with size size+1,
* where array[-1] is used for holding the size of the array.
* a pointer to array is returned.
*/
u32* create_array(u32 size){
u32 *tmp = (u32*)my_malloc((size+1)*sizeof(u32));
memset(tmp+1, 0, sizeof(u32)*size);
*tmp = size;
return (tmp+1);
}

/* Delete an array created with create_array()*/
void delete_array(u32 *array){
free(array-1);
}

/* Return the ID of an array created with create_array,
* which is the address fot its first element.
*/
u32 get_arrayID(u32 *array){
return (u32)array;
}

/* Return the array with ID ID (which is the address
* of the array.
*/
u32* get_array_by_ID(u32 ID){
return (u32*)ID;
}

/* Delete array with ID ID.*/
void delete_array_by_ID(u32 ID){
u32 *tmp = get_array_by_ID(ID);
delete_array(tmp);
}

/* Return the size of an array created with create_array.*/
u32 get_array_size(u32 *array){
return *(array-1);
}

/* Duplicate the content in from to that of to.
* original data in to is discarded.
*/
void copy_array(u32 *to, u32 *from){
int size = get_array_size(from);
if(!to)
delete_array(to);
to = create_array(size);
memcpy(to, from, size*sizeof(u32));
}

void load_program(u32** membuffer, const char* filename){
int i, size_read, file_size, membuffer_size;
struct stat file_info;
FILE *infile;

//Find file info
if(stat(filename, &file_info)){
fprintf(stderr, "Failed to stat file: %s. %s\n", filename,
strerror(errno));
exit(1);
}
file_size = file_info.st_size;

//Open file
dprintf("Opening file: %s ...", filename);
infile = fopen(filename, "rb");
if(infile == NULL){
fprintf(stderr, "Failed to open file: %s. %s\n", filename,
strerror(errno));
exit(1);
}
dprintf("done\n");

//Read buffer
dprintf("Reading file content with size: %d ...", file_size);
membuffer_size = sizeof(uCool*file_size/sizeof(u32) + 1;
if(!(*membuffer))
free((*membuffer));
(*membuffer) = create_array(membuffer_size);
size_read = fread((*membuffer), sizeof(uCool, file_size, infile);
if(size_read != file_size && !feof(infile)){
fprintf(stderr, "Warning: failed to read all data.\n");
}
fclose(infile);
dprintf("done.\n");

//change the endian
dprintf("Changing small-endian data to big_endian ...\n");
for(i = 0; i < membuffer_size; i++){
dprintf(" %08x->", (*membuffer)[i]);
change_endian(&(*membuffer)[i]);
dprintf("%08x", (*membuffer)[i]);
if((i+1)%4 == 0)
dprintf("\n");
}
dprintf("\ndone.\n");
dprintf("Program of size: %d loaded.\n",
(*((*membuffer)-1))*sizeof(u32));
}

void init_um32(UM32* um, u32* program){
int i;
dprintf("Initializing the Universal Machine ...");
if(program == NULL){
fprintf(stderr, "Fatal Error in init_um32, program is NULL.\n");
exit(1);
}
dprintf("\nRegisters:");
for(i=0;i<8;i++){
um->r[i] = 0;
dprintf(" %08x", um->r[i]);
}
um->finger = 0;
um->program = program;
dprintf("\nfinger = %08x\nprogram loaded at %08x\n", um->finger,
(u32)um->program);
dprintf("done.\n");
}

void dump_memory(u32 *mem){
FILE *outfile = NULL;
int i;
if(mem == NULL){
fprintf(stderr, "UM Memory is null.\n");
exit(1);
}
outfile = fopen(DUMP_FILE_NAME, "w");
dprintf("Beginning memory dump of size: %d...\n", *(mem-1));
if(!outfile){
fprintf(stderr, "Error in dump_memory. Failed to open file: %s.
%s",
DUMP_FILE_NAME, strerror(errno));
exit(1);
}
for(i=0;i<*(mem-1); i++){
fprintf(outfile, " %08x", mem[i]);
if((i+1)%8 == 0)
fprintf(outfile, "\n");
}
dprintf("Done.\n");
fclose(outfile);
}

int bound_program(UM32 um, u32 index){
if(index > *(um.program-1))
return 1;
return 0;
}

int bound_array(u32 arrayID, u32 index){
u32 *tmp = get_array_by_ID(arrayID);
if(!tmp || index > get_array_size(tmp))
return 1;
return 0;
}

/* Execute one instruction
* return 1 on success
*/
#define R(a) um->r[a]
#define PROGRAM (um->program)
#define FINGER (um->finger)
int um_run(UM32 *um, int trace){
u8 opcode;
u32 a, b, c, codex;

if(bound_program(*um, FINGER)){
printf("Array Index out of bound.\n");
exit(1);
}
codex = PROGRAM[FINGER++];
opcode = OPCODE(codex);
a = REG_A(codex);
b = REG_B(codex);
c = REG_C(codex);

if(trace)
printf("\ncodex=%08x, opcode=%d, finger=%08x\n", codex, opcode,
FINGER);

if(opcode == OP_ORTHO){
a = SPEC_A(codex);
R(a) = SPEC_V(codex);
if(trace){
printf("OP_ORTHO, r[%d]=%u\n", a, R(a));
printf("registers: %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x
\n",
R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7));
}
return 1;
}
switch(opcode){
case OP_CMOV:
if(!R(c)){
R(a) = R(b);
if(trace){
printf("OP_CMOV, r[%d]=r[%d]=%08x\n", a, b, R(a));
}
}
break;
case OP_INDEX:
if(!R(b)){
if(bound_program(*um, R(c))){
printf("Index out of bound in accessing array0 at offset %08x\n",
R(c));
exit(0);
}
R(a) = PROGRAM[R(c)];
}
else{
if(bound_array(R(b), R(c))){
printf("Index out of bound in accessing array%d\n", R(b));
exit(1);
}
R(a) = get_array_by_ID(R(b))[R(c)];
}
if(trace)
printf("OP_INDEX, r[%d]=array[%d][%d]=%08x\n", a, b, c, R(a));
break;
case OP_AMAND:
if(!R(a)){
if(bound_program(*um, R(b))){
printf("Index out of bound in accessing array0 at offset %08x\n",
R(c));
exit(0);
}
PROGRAM[R(b)] = R(c);
}
else{
if(bound_array(R(a), R(b))){
printf("Index out of bound in accessing array%d\n", R(b));
exit(1);
}
get_array_by_ID(R(a))[R(b)] = R(c);
}
if(trace)
printf("OP_AMAND, array[%d][%d]=r[%d]=%08x\n", a, b, c, R(c));
break;
case OP_ADD:
R(a) = R(b) + R(c);
if(trace)
printf("OP_ADD, r[%d]=r[%d]+r[%d]=%08x\n", a, b, c, R(a));
break;
case OP_MUL:
R(a) = R(b) * R(c);
if(trace)
printf("OP_ADD, r[%d]=r[%d]*r[%d]=%08x\n", a, b, c, R(a));
break;
case OP_DIV:
R(a) = R(b) / R(c);
if(trace)
printf("OP_ADD, r[%d]=r[%d]/r[%d]=%08x\n", a, b, c, R(a));
break;
case OP_NAND:
R(a) = ~(R(b) & R(c));
if(trace)
printf("OP_ADD, r[%d]=~(r[%d]&r[%d])=%08x\n", a, b, c, R(a));
break;
case OP_HALT:
if(trace)
printf("OP_HALT, stopping program ... done.\n");
return 0;
break;
case OP_ALLOC:
R(b) = get_arrayID(create_array(R(c)));
if(trace)
printf("OP_ALLOC, r[%d]=create_array(r[%d])=%08x\n", b, c, R(b));
break;
case OP_FREE:
delete_array_by_ID(R(c));
R(c) = 0;
if(trace)
printf("OP_REE, free(r[%d]=%08x)\n", c, R(c));
break;
case OP_OUT:
if(R(c) < 256){
putchar(R(c));
if(trace)
printf("OP_OUT, putchar(r[%d]=%08x)\n", c, R(c));
}
else
fprintf(stdout, "Warning, failed to output value %08x as char.\n",
R(c));
break;
case OP_IN:
R(c)=getchar();
if(trace)
printf("OP_IN, r[%d]=getchar()=%08x", c, R(c));
break;
case OP_LOAD:
if(R(b) != 0)
copy_array(um->program, get_array_by_ID(R(b)));
FINGER = R(c);
if(trace){
printf("OP_LOAD, loading program into array0 from array[%d] at %08x
\n",
b, R(b));
printf("\tfinger=%08x\n", FINGER);
}
break;
default:
printf("Fatal Error: Bad opcode=%d, codex=%08x\n", opcode, codex);
return 0;
break;
}
if(trace)
printf("registers: %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x
\n",
R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7));
return 1;
}

int main(int argc, char *argv[]){
UM32 um;
u32 *program;
int run;

#ifndef NOT_GDB
argc = 2;
argv[1] = "sandmark.umz";
#endif
if(argc < 2){
printf("Usage: %s filename\n", argv[0]);
exit(0);
}
//load program
load_program(&program, argv[1]);
//initialize um
init_um32(&um, program);
#ifdef DUMP_MEMORY
dump_memory(program);
#endif
do{
run = um_run(&um, 1);
}while(run);
return 0;
}
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C Language All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.