Because I was bored this evening, I implemented the clone operators.
Dan?
Brian
# compute the factorial....recursively!
# lets do it for the numbers 0 to 6
main:
set I1,0
$loop:
print "fact of "
print I1
print " is: "
set I0,I1
bsr fact
print I0
print "\n"
inc I1,1
eq I1,7,$done
branch $loop
$done:
end
# I0 is the number to compute
fact:
clonei
lt I0,2,$is_one
set I1,I0
dec I0,1
bsr fact
mul I0,I0,I1
save I0
branch $done
$is_one:
set I0,1
save I0
$done:
popi
restore I0
ret
? test.pasm
? test.inc
? test.list
? fact.pasm
? interp_guts.c
? config.h
? basic_opcodes.c
? DCn.diff
? macro.pbc
? macro.list
? local_label.pbc
? test.pbc
? euclid.pbc
? macro.pasm
? test2.pbc
? test3.pbc
? mytest.pasm
? cequ.code
? assemble.pl-new_macros
? mytest.pbc
? op_info.c
? frame_test.pbc
? fact.pbc
? frame_test.pasm
? clone.diff
? include/parrot/op_info.h
? t/test.pbc
? t/test1.c
? t/test1
Index: core.ops
===================================================================
RCS file: /home/perlcvs/parrot/core.ops,v
retrieving revision 1.4
diff -u -r1.4 core.ops
--- core.ops 2001/10/15 21:18:42 1.4
+++ core.ops 2001/10/16 00:29:05
@@ -1678,6 +1678,35 @@
Parrot_push_p(interpreter);
}
+########################################
+
+=item B<clonei>()
+
+=item B<clonen>()
+
+=item B<clonep>()
+
+=item B<clones>()
+
+Save all the registers of the type indicated in the name of the operation.
+
+=cut
+
+AUTO_OP clonei() {
+ Parrot_clone_i(interpreter);
+}
+
+AUTO_OP clonen() {
+ Parrot_clone_n(interpreter);
+}
+
+AUTO_OP clones() {
+ Parrot_clone_s(interpreter);
+}
+
+AUTO_OP clonep() {
+ Parrot_clone_p(interpreter);
+}
=back
Index: register.c
===================================================================
RCS file: /home/perlcvs/parrot/register.c,v
retrieving revision 1.10
diff -u -r1.10 register.c
--- register.c 2001/10/02 14:01:30 1.10
+++ register.c 2001/10/16 00:29:06
@@ -38,6 +38,39 @@
}
}
+/*=for api register Parrot_clone_i
+ pushes a new integer register frame on the frame stack and
+ copies the last frame to the current frame
+*/
+void
+Parrot_clone_i(struct Parrot_Interp *interpreter) {
+ struct IRegChunk *chunk_base;
+
+ chunk_base = CHUNK_BASE(interpreter->int_reg);
+ /* Do we have any slots left in the current chunk? */
+ if (chunk_base->free) {
+ interpreter->int_reg = &chunk_base->IReg[chunk_base->used++];
+ chunk_base->free--;
+ mem_sys_memcopy(&chunk_base->IReg[chunk_base->used-1],
+ &chunk_base->IReg[chunk_base->used-2],
+ sizeof(struct IReg));
+ }
+ /* Nope, so plan B time. Allocate a new chunk of integer register frames */
+ else {
+ struct IRegChunk *new_chunk;
+ new_chunk = mem_allocate_aligned(sizeof(struct IRegChunk));
+ new_chunk->used = 1;
+ new_chunk->free = FRAMES_PER_INT_REG_CHUNK - 1;
+ new_chunk->next = NULL;
+ new_chunk->prev = chunk_base;
+ chunk_base->next = new_chunk;
+ mem_sys_memcopy(&new_chunk->IReg[0],
+ &chunk_base->IReg[chunk_base->used-1],
+ sizeof(struct IReg));
+ interpreter->int_reg = &new_chunk->IReg[0];
+ }
+}
+
/*=for api register Parrot_pop_i
pops an integer register frame off of the frame stack
*/
@@ -107,6 +140,42 @@
}
}
+/*=for api register Parrot_clone_s
+ pushes a new string register frame on the frame stack and
+ copies the last frame to the current frame
+*/
+void
+Parrot_clone_s(struct Parrot_Interp *interpreter) {
+ struct SRegChunk *chunk_base;
+
+ chunk_base = CHUNK_BASE(interpreter->string_reg);
+ /* Do we have any slots left in the current chunk? */
+ if (chunk_base->free) {
+ interpreter->string_reg = &chunk_base->SReg[chunk_base->used++];
+ chunk_base->free--;
+ mem_sys_memcopy(&chunk_base->SReg[chunk_base->used-1],
+ &chunk_base->SReg[chunk_base->used-2],
+ sizeof(struct SReg));
+ }
+ /* Nope, so plan B time. Allocate a new chunk of string register frames */
+ else {
+ struct SRegChunk *new_chunk;
+ new_chunk = mem_allocate_aligned(sizeof(struct SRegChunk));
+ new_chunk->used = 1;
+ new_chunk->free = FRAMES_PER_STR_REG_CHUNK - 1;
+ new_chunk->next = NULL;
+ new_chunk->prev = chunk_base;
+ chunk_base->next = new_chunk;
+ mem_sys_memcopy(&new_chunk->SReg[0],
+ &chunk_base->SReg[chunk_base->used-1],
+ sizeof(struct SReg));
+ interpreter->string_reg = &new_chunk->SReg[0];
+ /* Gotta NULL them out as some string
+ functions depend on NULL strings */
+ Parrot_clear_s(interpreter);
+ }
+}
+
/*=for api register Parrot_pop_s
pops a string register frame off of the frame stack
*/
@@ -173,6 +242,39 @@
}
}
+/*=for api register Parrot_clone_n
+ pushes a new numeric register frame on the frame stack and copy the
+ previous frame to the current frame
+*/
+void
+Parrot_clone_n(struct Parrot_Interp *interpreter) {
+ struct NRegChunk *chunk_base;
+
+ chunk_base = CHUNK_BASE(interpreter->num_reg);
+ /* Do we have any slots left in the current chunk? */
+ if (chunk_base->free) {
+ interpreter->num_reg = &chunk_base->NReg[chunk_base->used++];
+ chunk_base->free--;
+ mem_sys_memcopy(&chunk_base->NReg[chunk_base->used-1],
+ &chunk_base->NReg[chunk_base->used-2],
+ sizeof(struct NReg));
+ }
+ /* Nope, so plan B time. Allocate a new chunk of float register frames */
+ else {
+ struct NRegChunk *new_chunk;
+ new_chunk = mem_allocate_aligned(sizeof(struct NRegChunk));
+ new_chunk->used = 1;
+ new_chunk->free = FRAMES_PER_NUM_REG_CHUNK - 1;
+ new_chunk->next = NULL;
+ new_chunk->prev = chunk_base;
+ chunk_base->next = new_chunk;
+ mem_sys_memcopy(&new_chunk->NReg[0],
+ &chunk_base->NReg[chunk_base->used-1],
+ sizeof(struct NReg));
+ interpreter->num_reg = &new_chunk->NReg[0];
+ }
+}
+
/*=for api register Parrot_pop_n
pops a numeric register frame off of the frame stack
*/
@@ -235,6 +337,41 @@
new_chunk->next = NULL;
new_chunk->prev = chunk_base;
chunk_base->next = new_chunk;
+ interpreter->pmc_reg = &new_chunk->PReg[0];
+ /* Gotta NULL them out or we might GC Wrong things later */
+ Parrot_clear_p(interpreter);
+ }
+}
+
+/*=for api register Parrot_clone_p
+ pushes a new PMC register frame on the frame stack and copy the
+ previous frame to the current frame
+*/
+void
+Parrot_clone_p(struct Parrot_Interp *interpreter) {
+ struct PRegChunk *chunk_base;
+
+ chunk_base = CHUNK_BASE(interpreter->pmc_reg);
+ /* Do we have any slots left in the current chunk? */
+ if (chunk_base->free) {
+ interpreter->pmc_reg = &chunk_base->PReg[chunk_base->used++];
+ chunk_base->free--;
+ mem_sys_memcopy(&chunk_base->PReg[chunk_base->used-1],
+ &chunk_base->PReg[chunk_base->used-2],
+ sizeof(struct PReg));
+ }
+ /* Nope, so plan B time. Allocate a new chunk of float register frames */
+ else {
+ struct PRegChunk *new_chunk;
+ new_chunk = mem_allocate_aligned(sizeof(struct PRegChunk));
+ new_chunk->used = 1;
+ new_chunk->free = FRAMES_PER_PMC_REG_CHUNK - 1;
+ new_chunk->next = NULL;
+ new_chunk->prev = chunk_base;
+ chunk_base->next = new_chunk;
+ mem_sys_memcopy(&new_chunk->PReg[0],
+ &chunk_base->PReg[chunk_base->used-1],
+ sizeof(struct PReg));
interpreter->pmc_reg = &new_chunk->PReg[0];
/* Gotta NULL them out or we might GC Wrong things later */
Parrot_clear_p(interpreter);
Index: include/parrot/register.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/register.h,v
retrieving revision 1.6
diff -u -r1.6 register.h
--- include/parrot/register.h 2001/10/06 01:04:47 1.6
+++ include/parrot/register.h 2001/10/16 00:29:07
@@ -77,6 +77,11 @@
void Parrot_push_s(struct Parrot_Interp *);
void Parrot_push_p(struct Parrot_Interp *);
+void Parrot_clone_i(struct Parrot_Interp *);
+void Parrot_clone_n(struct Parrot_Interp *);
+void Parrot_clone_s(struct Parrot_Interp *);
+void Parrot_clone_p(struct Parrot_Interp *);
+
void Parrot_pop_i(struct Parrot_Interp *);
void Parrot_pop_n(struct Parrot_Interp *);
void Parrot_pop_s(struct Parrot_Interp *);