Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote-tracking branch 'nbrown/m0-c-single-deref' into m0

  • Loading branch information...
commit 9bde02013fe12d81c15c0264277390bfd276a7be 2 parents 0e5c911 + 2f1e85a
@cotto cotto authored
View
34 docs/pdds/draft/pdd32_m0.pod
@@ -140,8 +140,7 @@ Execution Environments" [TBC].
=head2 Scope of This Document
This document only covers M0 and the minimum VM necessary to support it.
-Anything beyond that, e.g. the meta-object model or in-memory layout of call
-frames, is beyond its scope.
+Anything beyond that, e.g. the meta-object model, is beyond its scope.
=head2 Call Frames
@@ -149,7 +148,7 @@ This is the central data structure at the M0 level. The call frame graph
contains most of the state that is needed to execute M0 bytecode. A pointer to
the current call frame will be passed to each op as the implicit first
argument, though this pointer (or equivalent) will not be stored in bytecode.
-It layout is described in detail in the C<Register Types and Call Frame
+It layout is described in detail in the L<Register Types and Call Frame
Structure> section.
Call frames were previously referred to as contexts. The name "call frame" was
@@ -793,14 +792,16 @@ are not require to have any defined semantics.
0x1D set_ref
0x1E set_byte
0x1F get_byte
- 0x20 csym
- 0x21 ccall_arg
- 0x22 ccall_ret
- 0x23 ccall
- 0x24 print_s
- 0x25 print_i
- 0x25 print_n
- 0x26 exit
+ 0x20 set_word
+ 0x21 get_word
+ 0x22 csym
+ 0x23 ccall_arg
+ 0x24 ccall_ret
+ 0x25 ccall
+ 0x26 print_s
+ 0x27 print_i
+ 0x28 print_n
+ 0x29 exit
=head2 Chunk Name Constants and Bytecode Loading
@@ -892,7 +893,7 @@ runloop does need to accomplish the following:
=item * execute the instruction
-=item * increment the pc, if needed
+=item * increment the pc by one, if needed
=back
@@ -1045,10 +1046,11 @@ data.
0 OP_FUNCS array of functions that implement ops
1 CHUNKS array of all loaded chunks
2 CHUNK_INFO array of chunk metadata (currently just names)
- 3 CALL_FRAMES array of all initial call frames
- 4 CONFIG static global config data
- 5 ARGC number of elements in ARGV
- 6 ARGV array of command-line arguments passed to the m0 program
+ 3 CHUNK_MAP
+ 4 CALL_FRAMES array of all initial call frames
+ 5 CONFIG static global config data
+ 6 ARGC number of elements in ARGV
+ 7 ARGV array of command-line arguments passed to the m0 program
C<CONFIG> should have at least the following values:
View
3  src/m0/c/include/m0.h
@@ -7,3 +7,6 @@
# define M0_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
3  src/m0/c/include/m0_compiler_defines.h
@@ -8,3 +8,6 @@
# define M0_COMPILER_DEFINES_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
3  src/m0/c/include/m0_constants.h
@@ -7,3 +7,6 @@
# define M0_CONSTANTS_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
3  src/m0/c/include/m0_interp.h
@@ -4,3 +4,6 @@
# define M0_INTERP_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
49 src/m0/c/include/m0_interp_structures.h
@@ -2,21 +2,14 @@
# include "m0_mob_structures.h"
# include <stdint.h>
-typedef struct {
- unsigned short mob_version;
- unsigned short ireg_size;
- unsigned short nreg_size;
- unsigned short opcode_t_size;
- unsigned short pointer_size;
- unsigned short endianness;
- M0_Chunk *first_chunk;
- M0_Chunk *last_chunk;
-} M0_Interp;
+typedef uint64_t M0_Config[8];
typedef struct {
uint64_t registers[256];
} M0_CallFrame;
+typedef uint64_t M0_Interp[8];
+
enum CF_NAMED_REGS {
CF,
PCF,
@@ -32,5 +25,41 @@ enum CF_NAMED_REGS {
SPILLCF
};
+enum M0_INTERP_DATA {
+ OP_FUNCS,
+ CHUNKS,
+ CHUNK_INFO,
+ CHUNK_MAP,
+ CALL_FRAMES,
+ CONFIG,
+ ARGC,
+ ARGV
+};
+
+enum M0_CONFIG_DATA {
+ CFG_M0V,
+ CFG_REGSZ,
+ CFG_CFSZ,
+ CFG_IREGSZ,
+ CFG_NREGSZ,
+ CFG_OPCODESZ,
+ CFG_PTRSZ,
+ CFG_ENDIANNESS
+};
+
+typedef enum {
+ INVALID,
+ NAMED,
+ INTEGER,
+ NUMBER,
+ STRING,
+ POINTER
+} M0_RegisterType;
+
+
+
# define M0_INTERP_STRUCTURES_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
3  src/m0/c/include/m0_mob.h
@@ -7,3 +7,6 @@ int load_mob_file( M0_Interp *interp, const char *filename );
# define M0_MOB_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
7 src/m0/c/include/m0_mob_structures.h
@@ -1,7 +1,9 @@
#ifndef M0_MOB_STRUCTURES_H
+# include <stdint.h>
typedef struct M0_Constants_Segment {
- const char **consts;
+ uint64_t *consts;
+ unsigned int *pointers;
unsigned long count;
} M0_Constants_Segment;
@@ -33,3 +35,6 @@ typedef struct M0_Chunk {
# define M0_MOB_STRUCTURES_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
3  src/m0/c/include/m0_ops.h
@@ -52,3 +52,6 @@ run_ops( M0_Interp *interp, M0_CallFrame *cf );
# define M0_OPS_H 1
#endif
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
29 src/m0/c/m0_interp.c
@@ -39,6 +39,9 @@ main( int argc, const char *argv[]) {
if (!interp)
exit(1);
+ (*interp)[ARGC] = argc - 1;
+ (*interp)[ARGV] = (uint64_t)&(argv[1]);
+
if (argc < 2) {
fprintf( stderr, "Usage: m0 <filename.mob>\n" );
interp_free( interp );
@@ -63,17 +66,28 @@ main( int argc, const char *argv[]) {
M0_Interp *
new_interp() {
- return calloc( 1, sizeof (M0_Interp) );
+ M0_Interp *interp = calloc( 1, sizeof (M0_Interp) );
+ M0_Config *config = calloc( 1, sizeof (M0_Config) );
+ (*config)[CFG_REGSZ] = 8;
+ (*config)[CFG_CFSZ] = sizeof( M0_CallFrame );
+
+ (*interp)[CONFIG] = (uint64_t)config;
+ return interp;
}
M0_CallFrame *
new_call_frame( M0_Interp *interp ) {
M0_CallFrame *frame = malloc( sizeof (M0_CallFrame) );
+ unsigned int i;
+ for(i = 0; i < 256; i++)
+ frame->registers[i] = (uint64_t)0;
/* this is a silly minimal hack for now */
- frame->registers[CHUNK] = (uint64_t)interp->first_chunk;
+ frame->registers[CHUNK] = (uint64_t)(*interp)[CHUNKS];
frame->registers[PC] = (uint64_t)0;
- frame->registers[CONSTS] = (uint64_t)interp->first_chunk->constants;
+ frame->registers[CONSTS] = (uint64_t)((M0_Chunk*) ((*interp)[CHUNKS]))->constants;
+ frame->registers[CF] = (uint64_t)frame;
+ frame->registers[INTERP] = (uint64_t)interp;
return frame;
}
@@ -86,14 +100,14 @@ call_frame_free( M0_Interp *interp, M0_CallFrame *cf ) {
void
interp_free( M0_Interp *interp ) {
- M0_Chunk *chunk = interp->first_chunk;
+ M0_Chunk *chunk = (M0_Chunk*)((*interp)[CHUNKS]);
while (chunk) {
M0_Chunk *next = chunk->next;
m0_chunk_free( chunk );
chunk = next;
}
-
+ free( ((void *)(*interp)[CONFIG]) );
free( interp );
}
@@ -119,7 +133,7 @@ m0_chunk_free_constants( M0_Constants_Segment *constants )
unsigned long i = 0;
for (i = 0; i < count; i++) {
- if ( constants->consts[i] )
+ if ( constants->consts[i] && constants->pointers[i])
free( (void *)constants->consts[i] );
}
@@ -150,3 +164,6 @@ m0_chunk_free_bytecode( M0_Bytecode_Segment *bytecode )
free( bytecode );
}
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
82 src/m0/c/m0_mob.c
@@ -19,9 +19,10 @@ parse_mob_dirseg( M0_Interp *interp, FILE *stream );
static int
parse_mob_chunks( M0_Interp *interp, FILE *stream );
-static void
+static M0_Chunk *
add_chunk( M0_Interp *interp, const char *name,
- unsigned long chunk_id, unsigned long name_length );
+ unsigned long chunk_id, unsigned long name_length,
+ M0_Chunk *chunk);
static M0_Constants_Segment *
parse_mob_constants_segment( M0_Interp *interp, FILE *stream );
@@ -117,7 +118,7 @@ validate_mob_version( M0_Interp *interp, FILE *stream ) {
int version = read_int_from_stream( stream );
if (version == 0) {
- interp->mob_version = 0;
+ ((uint64_t*)(*interp)[CONFIG])[CFG_M0V] = (uint64_t)0;
return 1;
}
@@ -127,11 +128,11 @@ validate_mob_version( M0_Interp *interp, FILE *stream ) {
int
parse_header_config( M0_Interp *interp, FILE *stream ) {
- interp->ireg_size = read_int_from_stream( stream );
- interp->nreg_size = read_int_from_stream( stream );
- interp->opcode_t_size = read_int_from_stream( stream );
- interp->pointer_size = read_int_from_stream( stream );
- interp->endianness = read_int_from_stream( stream );
+ ((uint64_t*)(*interp)[CONFIG])[CFG_IREGSZ] = read_int_from_stream( stream );
+ ((uint64_t*)(*interp)[CONFIG])[CFG_NREGSZ] = read_int_from_stream( stream );
+ ((uint64_t*)(*interp)[CONFIG])[CFG_OPCODESZ] = read_int_from_stream( stream );
+ ((uint64_t*)(*interp)[CONFIG])[CFG_PTRSZ] = read_int_from_stream( stream );
+ ((uint64_t*)(*interp)[CONFIG])[CFG_ENDIANNESS] = read_int_from_stream( stream );
return 1;
}
@@ -144,6 +145,7 @@ parse_mob_dirseg( M0_Interp *interp, FILE *stream ) {
const unsigned long seg_entry_count = read_long_from_stream( stream );
const unsigned long seg_byte_count = read_long_from_stream( stream );
unsigned long chunks_found = 0;
+ M0_Chunk *last_chunk = NULL;
UNUSED(seg_byte_count);
for (; chunks_found < seg_entry_count; chunks_found++) {
@@ -154,7 +156,7 @@ parse_mob_dirseg( M0_Interp *interp, FILE *stream ) {
UNUSED(seg_offset);
- add_chunk( interp, name, chunks_found, name_length);
+ last_chunk = add_chunk( interp, name, chunks_found, name_length, last_chunk);
}
}
@@ -162,23 +164,25 @@ parse_mob_dirseg( M0_Interp *interp, FILE *stream ) {
return 1;
}
-void
+M0_Chunk *
add_chunk( M0_Interp *interp, const char *name, unsigned long chunk_id,
- unsigned long name_length) {
- M0_Chunk *chunk = malloc( sizeof (M0_Chunk) );
+ unsigned long name_length,
+ M0_Chunk *chunk) {
+ if (!chunk) {
+ chunk = malloc( sizeof (M0_Chunk) );
+ } else {
+ chunk->next = malloc( sizeof (M0_Chunk) );
+ chunk = chunk->next;
+ }
chunk->id = chunk_id;
chunk->name = name;
chunk->name_length = name_length;
chunk->next = NULL;
- if (!interp->first_chunk) {
- interp->first_chunk = chunk;
- interp->last_chunk = chunk;
- }
- else {
- interp->last_chunk->next = chunk;
- interp->last_chunk = chunk;
+ if (!(*interp)[CHUNKS]) {
+ (*interp)[CHUNKS] = (uint64_t)chunk;
}
+ return chunk;
}
int
@@ -190,7 +194,7 @@ validate_segment_identifier( M0_Interp *interp, FILE *stream,
int
parse_mob_chunks( M0_Interp *interp, FILE *stream ) {
- M0_Chunk *chunk = interp->first_chunk;
+ M0_Chunk *chunk = (M0_Chunk*)(*interp)[CHUNKS];
while (chunk) {
chunk->constants = parse_mob_constants_segment( interp, stream );
@@ -213,28 +217,29 @@ parse_mob_constants_segment( M0_Interp *interp, FILE *stream ) {
unsigned long i = 0;
M0_Constants_Segment *segment =
malloc( sizeof( M0_Constants_Segment ) );
- segment->consts = malloc( sizeof ( char * ) * const_count );
- segment->count = const_count;
+ segment->consts = calloc(const_count, sizeof ( uint64_t ));
+ segment->pointers = calloc(const_count, sizeof ( unsigned int));
+ segment->count = const_count;
UNUSED( byte_count );
for (i = 0; i < const_count; i++) {
const unsigned long length = read_long_from_stream( stream );
- const char *constant = NULL;
- if (length <= 8) {
- constant = read_from_stream( stream, length );
- } else {
- int string_len = read_long_from_stream(stream);
- int encoding = read_long_from_stream(stream);
- if (encoding == 0) {
- constant = (char *)read_from_stream(stream, string_len);
- } else {
- constant = read_from_stream(stream, string_len);
- }
- }
-
- if (constant)
- segment->consts[i] = constant;
+ const char *constant = (char *) read_from_stream( stream, length);
+ if (length > 8) {
+ int encoding = *(long *)&(constant[4]);
+ if (encoding == 0) {
+ constant = (char *) &(constant[8]);
+ }
+ if (constant) {
+ segment->consts[i] = (uint64_t)constant;
+ segment->pointers[i] = 1;
+ }
+ } else {
+ if (constant)
+ segment->consts[i] = *(uint64_t*)constant;
+ }
+
}
return segment;
@@ -350,3 +355,6 @@ read_padding_from_stream( FILE *stream, size_t bytes ) {
return fread( &value, 1, bytes, stream ) == bytes;
}
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
253 src/m0/c/m0_ops.c
@@ -14,7 +14,7 @@ Copyright (C) 2011-2012, Parrot Foundation.
static void
m0_op_set_imm( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = ops[2] * 256 + ops[3];
+ frame->registers[ops[1]] = (uint64_t)(ops[2] * 256 + ops[3]);
}
static void
@@ -28,13 +28,17 @@ m0_op_deref( M0_CallFrame *frame, const unsigned char *ops )
M0_Constants_Segment *consts =
(M0_Constants_Segment *)frame->registers[ ref ];
unsigned long offset = frame->registers[ ops[3] ];
-
- frame->registers[ ops[1] ] = (uint64_t)consts->consts[ offset ];
+ frame->registers[ ops[1] ] = (uint64_t)consts->consts[offset];
break;
}
default:
+ {
+ unsigned long offset = frame->registers[ ops[3] ];
+ uint64_t * src = (uint64_t*)(frame->registers[ ops[2] ]);
+ frame->registers[ ops[1] ] = src[offset];
/* XXX: the rest of the system has non-uniform array handling */
break;
+ }
}
}
@@ -42,74 +46,135 @@ static void
m0_op_print_s( M0_CallFrame *frame, const unsigned char *ops )
{
/* note the lack of filehandle selection (ops[1]) for output */
- fprintf( stdout, "%s", (char *)frame->registers[ ops[2] ] );
+ fprintf( stdout, "%s", (char *)(frame->registers[ ops[2] ] + 8 ));
}
static void
m0_op_print_i( M0_CallFrame *frame, const unsigned char *ops )
{
/* note the lack of filehandle selection (ops[1]) for output */
- fprintf( stdout, "%d", (int)frame->registers[ ops[2] ] );
+ fprintf( stdout, "%d", (unsigned int)frame->registers[ ops[2] ] );
}
static void
m0_op_add_i( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = frame->registers[ops[2]] +
- frame->registers[ops[3]];
+ unsigned int r2 = *(unsigned int*)&frame->registers[ops[2]];
+ unsigned int r3 = *(unsigned int*)&frame->registers[ops[3]];
+ unsigned int *result = (unsigned int*) &(frame->registers[ops[1]]);
+ *result = r2 + r3;
+}
+
+static void
+m0_op_add_n( M0_CallFrame *frame, const unsigned char *ops )
+{
+ double r2 = *(double*)&frame->registers[ops[2]];
+ double r3 = *(double*)&frame->registers[ops[3]];
+ double *result = (double*) &(frame->registers[ops[1]]);
+ *result = r2 + r3;
}
static void
m0_op_sub_i( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = frame->registers[ops[2]] -
- frame->registers[ops[3]];
+ unsigned int r2 = *(unsigned int*)&frame->registers[ops[2]];
+ unsigned int r3 = *(unsigned int*)&frame->registers[ops[3]];
+ unsigned int *result = (unsigned int*) &(frame->registers[ops[1]]);
+ unsigned int temp_result = r2 - r3;
+ frame->registers[ops[1]] = (uint16_t)0;
+ *result = temp_result;
+}
+
+static void
+m0_op_sub_n( M0_CallFrame *frame, const unsigned char *ops )
+{
+ double r2 = *(double*)&frame->registers[ops[2]];
+ double r3 = *(double*)&frame->registers[ops[3]];
+ double *result = (double*) &(frame->registers[ops[1]]);
+ *result = r2 - r3;
}
static void
m0_op_convert_n_i( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = (double)(frame->registers[ops[2]]);
+ int64_t *r2 = (int64_t*) &(frame->registers[ops[2]]);
+ double *r1 = (double*) &(frame->registers[ops[1]]);
+ *r1 = (*r2);
}
static void
m0_op_convert_i_n( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = (int)(frame->registers[ops[2]]);
+ double *r2 = (double*) &(frame->registers[ops[2]]);
+ int64_t *r1 = (int64_t*) &(frame->registers[ops[1]]);
+ *r1 = *r2;
}
static void
m0_op_goto( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[PC] = 4*(256 * ops[1] + ops[2]);
+ frame->registers[PC] = 256 * ops[1] + ops[2];
}
static void
m0_op_goto_if( M0_CallFrame *frame, const unsigned char *ops )
{
if( frame->registers[ops[3]] )
- frame->registers[PC] = 4*(256 * ops[1] + ops[2]);
+ frame->registers[PC] = 256 * ops[1] + ops[2];
}
static void
m0_op_mult_i( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = frame->registers[ops[2]] *
- frame->registers[ops[3]];
+ unsigned int r2 = *(unsigned int*)&frame->registers[ops[2]];
+ unsigned int r3 = *(unsigned int*)&frame->registers[ops[3]];
+ unsigned int *result = (unsigned int*) &(frame->registers[ops[1]]);
+ *result = r2 * r3;
+}
+
+static void
+m0_op_mult_n( M0_CallFrame *frame, const unsigned char *ops )
+{
+ double r2 = *(double*)&frame->registers[ops[2]];
+ double r3 = *(double*)&frame->registers[ops[3]];
+ double *result = (double*) &(frame->registers[ops[1]]);
+ *result = r2 * r3;
}
static void
m0_op_div_i( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = frame->registers[ops[2]] /
- frame->registers[ops[3]];
+ unsigned int r2 = *(unsigned int*)&frame->registers[ops[2]];
+ unsigned int r3 = *(unsigned int*)&frame->registers[ops[3]];
+ unsigned int *result = (unsigned int*) &(frame->registers[ops[1]]);
+ *result = r2 / r3;
+}
+
+static void
+m0_op_div_n( M0_CallFrame *frame, const unsigned char *ops )
+{
+ double r2 = *(double*)&frame->registers[ops[2]];
+ double r3 = *(double*)&frame->registers[ops[3]];
+ double *result = (double*) &(frame->registers[ops[1]]);
+ *result = r2 / r3;
}
static void
m0_op_mod_i( M0_CallFrame *frame, const unsigned char *ops )
{
- frame->registers[ops[1]] = frame->registers[ops[2]] %
- frame->registers[ops[3]];
+ unsigned int r2 = *(unsigned int*)&frame->registers[ops[2]];
+ unsigned int r3 = *(unsigned int*)&frame->registers[ops[3]];
+ unsigned int *result = (unsigned int*) &(frame->registers[ops[1]]);
+ *result = r2 % r3;
+}
+
+static void
+m0_op_mod_n( M0_CallFrame *frame, const unsigned char *ops )
+{
+ double r2 = *(double*)&frame->registers[ops[2]];
+ double r3 = *(double*)&frame->registers[ops[3]];
+ double *result = (double*) &(frame->registers[ops[1]]);
+ *result = (int)(r2) % (int)(r3);
}
static void
@@ -148,10 +213,11 @@ m0_op_ashr( M0_CallFrame *frame, const unsigned char *ops )
}
static void
-m0_op_goto_chunk(M0_Interp *interp, M0_CallFrame *frame, const unsigned char *ops )
+m0_op_goto_chunk(M0_CallFrame *frame, const unsigned char *ops )
{
uint64_t new_pc = frame->registers[ops[2]];
- M0_Chunk *chunk = interp->first_chunk;
+ M0_Interp *interp = (M0_Interp *)frame->registers[INTERP];
+ M0_Chunk *chunk = (M0_Chunk*)((*interp)[CHUNKS]);
while(chunk) {
if( strncmp( chunk->name, (char *)frame->registers[ops[1]], chunk->name_length) == 0) {
frame->registers[CHUNK] = (uint64_t)chunk;
@@ -169,7 +235,7 @@ m0_op_goto_chunk(M0_Interp *interp, M0_CallFrame *frame, const unsigned char *op
}
static void
-m0_op_exit(M0_Interp *interp, M0_CallFrame *frame, const unsigned char *ops )
+m0_op_exit(M0_CallFrame *frame, const unsigned char *ops )
{
exit((int)frame->registers[ops[1]]);
}
@@ -191,14 +257,54 @@ m0_op_set_byte( M0_CallFrame *frame, const unsigned char *ops )
}
static void
-m0_op_get_byte( M0_CallFrame *frame, const unsigned char *ops )
+m0_op_set_word( M0_CallFrame *frame, const unsigned char *ops )
{
- const char *src = (char*)frame->registers[ops[3]];
+ const char* value = (char*)&frame->registers[ops[3]];
const int offset = frame->registers[ops[2]];
+ char *target = (char*) frame->registers[ops[1]];
+ memcpy(&target[4*offset],value,4*sizeof(char));
+}
+
+static void
+m0_op_set( M0_CallFrame *frame, const unsigned char *ops )
+{
+ frame->registers[ops[1]] = frame->registers[ops[2]];
+}
+
+static void
+m0_op_get_byte( M0_CallFrame *frame, const unsigned char *ops )
+{
+ const char *src = (char*)frame->registers[ops[2]];
+ const int offset = frame->registers[ops[3]];
char *target = (char*)&frame->registers[ops[1]];
*target = (char)src[offset];
}
+static void
+m0_op_get_word( M0_CallFrame *frame, const unsigned char *ops )
+{
+ const char *src = (char*)frame->registers[ops[2]];
+ const int offset = frame->registers[ops[3]];
+ char *target = (char*)&frame->registers[ops[1]];
+ frame->registers[ops[1]] = (uint64_t)0;
+ memcpy(target, &src[offset * 4], 4*sizeof(char));
+}
+
+static void
+m0_op_gc_alloc( M0_CallFrame *frame, const unsigned char *ops )
+{
+ const int bytes = frame->registers[ops[2]];
+ void *ptr = malloc( sizeof(char) * bytes );
+ frame->registers[ops[1]] = (uint64_t) ptr;
+}
+
+static void
+m0_op_set_ref( M0_CallFrame *frame, const unsigned char *ops )
+{
+ uint64_t *ptr = (uint64_t *)frame->registers[ops[1]];
+ const int offset = frame->registers[ops[2]];
+ ptr[offset] = frame->registers[ops[3]];
+}
int
run_ops( M0_Interp *interp, M0_CallFrame *cf ) {
@@ -214,117 +320,160 @@ run_ops( M0_Interp *interp, M0_CallFrame *cf ) {
const unsigned long op_count = bytecode->op_count;
/* XXX: access violation -- so produce an error? */
- if (pc / 4 >= op_count)
+ if (pc >= op_count)
return 0;
else {
- const unsigned char op = ops[pc];
+ const unsigned char op = ops[4*pc];
switch (op) {
case (M0_SET_IMM):
- m0_op_set_imm( cf, &ops[pc] );
+ m0_op_set_imm( cf, &ops[4*pc] );
break;
case (M0_DEREF):
- m0_op_deref( cf, &ops[pc] );
+ m0_op_deref( cf, &ops[4*pc] );
break;
case (M0_PRINT_S):
- m0_op_print_s( cf, &ops[pc] );
+ m0_op_print_s( cf, &ops[4*pc] );
break;
case (M0_PRINT_I):
- m0_op_print_i( cf, &ops[pc] );
+ m0_op_print_i( cf, &ops[4*pc] );
break;
case (M0_NOOP):
break;
case (M0_ADD_I):
- m0_op_add_i( cf, &ops[pc] );
+ m0_op_add_i( cf, &ops[4*pc] );
+ break;
+
+ case (M0_ADD_N):
+ m0_op_add_n( cf, &ops[4*pc] );
break;
case (M0_SUB_I):
- m0_op_sub_i( cf, &ops[pc] );
+ m0_op_sub_i( cf, &ops[4*pc] );
+ break;
+
+ case (M0_SUB_N):
+ m0_op_sub_n( cf, &ops[4*pc] );
break;
case (M0_GOTO):
- m0_op_goto( cf, &ops[pc] );
+ m0_op_goto( cf, &ops[4*pc] );
break;
case (M0_GOTO_IF):
- m0_op_goto_if( cf, &ops[pc] );
+ m0_op_goto_if( cf, &ops[4*pc] );
break;
case (M0_MULT_I):
- m0_op_mult_i( cf, &ops[pc] );
+ m0_op_mult_i( cf, &ops[4*pc] );
+ break;
+
+ case (M0_MULT_N):
+ m0_op_mult_n( cf, &ops[4*pc] );
break;
case (M0_DIV_I):
- m0_op_div_i( cf, &ops[pc] );
+ m0_op_div_i( cf, &ops[4*pc] );
+ break;
+
+ case (M0_DIV_N):
+ m0_op_div_n( cf, &ops[4*pc] );
break;
case (M0_MOD_I):
- m0_op_mod_i( cf, &ops[pc] );
+ m0_op_mod_i( cf, &ops[4*pc] );
+ break;
+
+ case (M0_MOD_N):
+ m0_op_mod_n( cf, &ops[4*pc] );
break;
case (M0_AND):
- m0_op_and( cf, &ops[pc] );
+ m0_op_and( cf, &ops[4*pc] );
break;
case (M0_OR):
- m0_op_or( cf, &ops[pc] );
+ m0_op_or( cf, &ops[4*pc] );
break;
case (M0_XOR):
- m0_op_xor( cf, &ops[pc] );
+ m0_op_xor( cf, &ops[4*pc] );
break;
case (M0_LSHR):
- m0_op_lshr( cf, &ops[pc] );
+ m0_op_lshr( cf, &ops[4*pc] );
break;
case (M0_ASHR):
- m0_op_ashr( cf, &ops[pc] );
+ m0_op_ashr( cf, &ops[4*pc] );
break;
case (M0_SHL):
- m0_op_shl( cf, &ops[pc] );
+ m0_op_shl( cf, &ops[4*pc] );
break;
case (M0_GOTO_CHUNK):
- m0_op_goto_chunk( interp ,cf, &ops[pc] );
+ m0_op_goto_chunk( cf, &ops[4*pc] );
break;
case (M0_SET_BYTE):
- m0_op_set_byte( cf, &ops[pc] );
+ m0_op_set_byte( cf, &ops[4*pc] );
+ break;
+
+ case (M0_SET_WORD):
+ m0_op_set_word( cf, &ops[4*pc] );
+ break;
+
+ case (M0_SET):
+ m0_op_set( cf, &ops[4*pc] );
break;
case (M0_GET_BYTE):
- m0_op_get_byte( cf, &ops[pc] );
+ m0_op_get_byte( cf, &ops[4*pc] );
+ break;
+
+ case (M0_GET_WORD):
+ m0_op_get_word( cf, &ops[4*pc] );
break;
case (M0_ITON):
- m0_op_convert_i_n( cf, &ops[pc] );
+ m0_op_convert_i_n( cf, &ops[4*pc] );
break;
case (M0_NTOI):
- m0_op_convert_n_i( cf, &ops[pc] );
+ m0_op_convert_n_i( cf, &ops[4*pc] );
+ break;
+
+ case (M0_GC_ALLOC):
+ m0_op_gc_alloc( cf, &ops[4*pc]);
+ break;
+
+ case (M0_SET_REF):
+ m0_op_set_ref( cf, &ops[4*pc]);
break;
case (M0_EXIT):
- m0_op_exit( interp, cf, &ops[pc]);
+ m0_op_exit( cf, &ops[4*pc]);
break;
default:
fprintf( stderr, "Unimplemented op: %d (%d, %d, %d)\n",
- op, ops[pc + 1], ops[pc + 2], ops[pc + 3] );
+ op, ops[4*pc + 1], ops[4*pc + 2], ops[4*pc + 3] );
break;
}
}
-
+ cf = (M0_CallFrame*)cf->registers[CF];
/* only branching ops definitely change the pc */
if (pc == (const unsigned long)cf->registers[PC])
- cf->registers[PC] += 4;
+ cf->registers[PC]++;
}
return 0;
}
+
+/* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+*/
View
2  src/m0/perl5/m0_assembler.pl
@@ -331,7 +331,7 @@ sub m0b_constants_seg {
m0_say "adding I constant $value to constants segment";
}
elsif ($type eq 'N') {
- $bytecode .= pack("if", 4, $value + 0.0);
+ $bytecode .= pack("id", 8, $value + 0.0);
m0_say "adding N constant $value to constants segment";
}
elsif ($type eq 'S' || $type eq '&') {
View
4 src/m0/perl5/m0_interp.pl
@@ -256,9 +256,9 @@ sub i {
sub n {
if (scalar(@_) == 2) {
my ($cf, $reg) = @_;
- return unpack('f', $cf->[$reg]);
+ return unpack('d', $cf->[$reg]);
}
- return pack('f', $_[0] );
+ return pack('d', $_[0] );
}
View
12 t/m0/integration/m0_and.m0
@@ -18,16 +18,16 @@
set_imm I3, 0, 8
sub_i I3, I3, I2
- goto_if xor_nok, I3
- goto xor_ok, x
+ goto_if and_nok, I3
+ goto and_ok, x
-xor_ok:
- set_imm S0, 0, 2
+and_nok:
+ set_imm S0, 0, 1
deref S0, CONSTS, S0
print_s I0, S0, x
-xor_nok:
- set_imm S0, 0, 1
+and_ok:
+ set_imm S0, 0, 2
deref S0, CONSTS, S0
print_s I0, S0, x
View
37 t/m0/integration/m0_args.m0
@@ -4,9 +4,11 @@
0 "1..2\n"
1 "\n"
2 "ok 1 - arg count: got 6 arguments!\n"
-3 "not ok 1 - arg count: didn't get 6 arguments\n"
+3 "not ok 1 - arg count: didn't get 6 arguments (got "
4 "ok 2 - arg contents: first argument was 'kittens'\n"
5 "not ok 2 - arg contents: first argument was 'kittens' # TODO M0 doesn't support this yet \n"
+6 " arguments)\n"
+7 "kittens"
.metadata
.bytecode
@@ -21,15 +23,20 @@
# I2 is the expected arg count
set_imm I2, 0, 6
- sub_i I1, I2, I1
+ sub_i I2, I2, I1
- goto_if argc_nok, I1
+ goto_if argc_nok, I2
goto argc_ok, x
argc_nok:
set_imm S0, 0, 3
deref S0, CONSTS, S0
print_s I0, S0, x
+ print_i I0, I1, x
+
+ set_imm S0, 0, 6
+ deref S0, CONSTS, S0
+ print_s I0, S0, x
goto argv_test, x
argc_ok:
@@ -45,7 +52,29 @@ argv_test:
set_imm I1, 0, 1
set_imm S0, 0, ARGV
deref S0, INTERP, S0
- deref S0, S0, I1
+ set_imm I2, 0, 1
+ get_word S0, S0, I2
+
+ set_imm S1, 0, 7
+ deref S1, CONSTS, S1
+
+ # I2 = number of bytes in string
+ get_word I2, S1, I0
+ sub_i I2, I2, I1
+
+string_cmp_loop:
+ sub_i I2, I2, I1
+ get_byte I3, S0, I2
+
+ set_imm I5, 0, 8
+ add_i I5, I2, I5
+ get_byte I4, S1, I5
+
+ sub_i I3, I3, I4
+ goto_if argv_nok, I3
+
+ goto_if string_cmp_loop, I2
+ goto argv_ok, x
# TODO: test S0 eq 'kittens'
View
4 t/m0/integration/m0_deref.m0
@@ -16,9 +16,9 @@
set_imm N0, 0, 3
deref N0, CONSTS, N0
set_imm N1, 0, 99
- sub_n N0, N0, N1
+ sub_i N0, N0, N1
- goto_if deref_nok, I3
+ goto_if deref_nok, N0
goto deref_ok, x
deref_nok:
View
8 t/m0/integration/m0_lshr.m0
@@ -21,13 +21,13 @@
goto_if lshr_nok, I3
goto lshr_ok, x
-lshr_ok:
- set_imm S0, 0, 2
+lshr_nok:
+ set_imm S0, 0, 1
deref S0, CONSTS, S0
print_s I0, S0, x
-lshr_nok:
- set_imm S0, 0, 1
+lshr_ok:
+ set_imm S0, 0, 2
deref S0, CONSTS, S0
print_s I0, S0, x
View
12 t/m0/integration/m0_or.m0
@@ -18,16 +18,16 @@
set_imm I3, 0, 91
sub_i I3, I3, I2
- goto_if xor_nok, I3
- goto xor_ok, x
+ goto_if or_nok, I3
+ goto or_ok, x
-xor_ok:
- set_imm S0, 0, 2
+or_nok:
+ set_imm S0, 0, 1
deref S0, CONSTS, S0
print_s I0, S0, x
-xor_nok:
- set_imm S0, 0, 1
+or_ok:
+ set_imm S0, 0, 2
deref S0, CONSTS, S0
print_s I0, S0, x
View
36 t/m0/integration/m0_pc_increment.m0
@@ -0,0 +1,36 @@
+.version 0
+.chunk "noop"
+.constants
+0 "1..1\n"
+1 "n"
+2 "ok 1 first test\n"
+.metadata
+.bytecode
+
+ # print the plan
+ set_imm S0, 0, 0
+ deref S0, CONSTS, S0
+ set_imm I0, 0, 1
+ print_s I0, S0, x
+
+ # load "n" into S0
+ set_imm S0, 0, 1
+ deref S0, CONSTS, S0
+
+ # load "ok...." into S1
+ set_imm S1, 0, 2
+ deref S1, CONSTS, S1
+
+ # skip ahead 2 instructions
+ set_imm I1, 0, 2
+ add_i PC, PC, I1
+
+ # print "n"
+ print_s I0, S0, x
+
+op_spacing_ok:
+ # print "ok ..."
+ print_s I0, S1, x
+
+# This code isn't really PASM, but the highlighting works well.
+# vim: expandtab shiftwidth=4 ft=pasm:
View
6 t/m0/integration/m0_poke_caller.m0
@@ -124,7 +124,7 @@ init_cf_pc:
# 3 register needed (2x I, 1x P)
# Set the new call frame's PC to the 'post_set' label so that when it's
# activated, control flow will continue as normal.
- set_imm I12, 0, 4
+ set_imm I12, 0, 3
add_i I12, I12, PC
set_imm I9, 0, PC
set_ref P0, I9, I12
@@ -161,10 +161,12 @@ restore_cf:
set_cf_pc:
# Set PCF[PC] to the invoke_cf + 1 so that when we invoke PCF with
# "set CF, PCF, x", control flow will continue at the next instruction.
- set_imm I1, 0, 3
+ set_imm I1, 0, 5
add_i I1, PC, I1
set_imm I9, 0, PC
set_ref PCF, I9, I1
+ set_imm I9, 0, CF
+ set_ref PCF, I9, PCF
invoke_cf:
set CF, PCF, x
View
2  t/m0/integration/m0_set.m0
@@ -17,7 +17,7 @@
deref N0, CONSTS, N0
set N1, N0, x
set_imm N0, 0, 99
- sub_n N0, N0, N1
+ sub_i N0, N0, N1
goto_if set_nok, N0
goto set_ok, x
View
2  t/m0/integration/m0_set_imm.m0
@@ -16,7 +16,7 @@
set_imm N0, 0, 3
deref N0, CONSTS, N0
set_imm N1, 0, 99
- sub_n N0, N0, N1
+ sub_i N0, N0, N1
goto_if set_imm_nok, N0
goto set_imm_ok, x
View
2  t/m0/integration/m0_set_ref.m0
@@ -19,7 +19,7 @@
set_imm N1, 0, 4
deref N1, CONSTS, N1
- sub_n N0, N0, N1
+ sub_i N0, N0, N1
goto_if set_ref_nok, N0
goto set_ref_ok, x
View
8 t/m0/integration/m0_shl.m0
@@ -21,13 +21,13 @@
goto_if shl_nok, I3
goto shl_ok, x
-shl_ok:
- set_imm S0, 0, 2
+shl_nok:
+ set_imm S0, 0, 1
deref S0, CONSTS, S0
print_s I0, S0, x
-shl_nok:
- set_imm S0, 0, 1
+shl_ok:
+ set_imm S0, 0, 2
deref S0, CONSTS, S0
print_s I0, S0, x
View
8 t/m0/integration/m0_xor.m0
@@ -21,13 +21,13 @@
goto_if xor_nok, I3
goto xor_ok, x
-xor_ok:
- set_imm S0, 0, 2
+xor_nok:
+ set_imm S0, 0, 1
deref S0, CONSTS, S0
print_s I0, S0, x
-xor_nok:
- set_imm S0, 0, 1
+xor_ok:
+ set_imm S0, 0, 2
deref S0, CONSTS, S0
print_s I0, S0, x
Please sign in to comment.
Something went wrong with that request. Please try again.