1 //
2 //  gravity_ircode.c
3 //  gravity
4 //
5 //  Created by Marco Bambini on 06/11/14.
6 //  Copyright (c) 2014 CreoLabs. All rights reserved.
7 //
8 
9 #include "gravity_ircode.h"
10 #include "gravity_value.h"
11 #include "gravity_debug.h"
12 #include <inttypes.h>
13 
14 typedef marray_t(inst_t *)      code_r;
15 typedef marray_t(bool *)        context_r;
16 
17 struct ircode_t {
18     code_r      *list;                      // array of ircode instructions
19 
20     uint32_r    label_true;                 // labels used in loops
21     uint32_r    label_false;
22     uint32_r    label_check;
23     uint32_t    label_counter;
24 
25     uint32_t    maxtemp;                    // maximum number of temp registers used in this ircode
26     uint32_t    ntemps;                     // current number of temp registers in use
27     uint16_t    nlocals;                    // number of local registers (params + local variables)
28     bool        error;                      // error flag set when no more registers are availables
29 
30     bool        state[MAX_REGISTERS];       // registers mask
31     bool        skipclear[MAX_REGISTERS];   // registers protection for temps used in for loop
32     uint32_r    registers;                  // registers stack
33     context_r   context;                    // context array
34 };
35 
ircode_create(uint16_t nlocals)36 ircode_t *ircode_create (uint16_t nlocals) {
37     ircode_t *code = (ircode_t *)mem_alloc(NULL, sizeof(ircode_t));
38     if (!code) return NULL;
39     code->label_counter = 0;
40     code->nlocals = nlocals;
41     code->ntemps = 0;
42     code->maxtemp = 0;
43     code->error = false;
44 
45     code->list = mem_alloc(NULL, sizeof(code_r));
46     if (!code->list) return NULL;
47     marray_init(*code->list);
48     marray_init(code->label_true);
49     marray_init(code->label_false);
50     marray_init(code->label_check);
51     marray_init(code->registers);
52     marray_init(code->context);
53 
54     // init state array (register 0 is reserved)
55     bzero(code->state, MAX_REGISTERS * sizeof(bool));
56     code->state[0] = true;
57     for (uint32_t i=0; i<nlocals; ++i) {
58         code->state[i] = true;
59     }
60     return code;
61 }
62 
ircode_free(ircode_t * code)63 void ircode_free (ircode_t *code) {
64     uint32_t count = ircode_count(code);
65     for (uint32_t i=0; i<count; ++i) {
66         inst_t *inst = marray_get(*code->list, i);
67         mem_free(inst);
68     }
69 
70     marray_destroy(*code->list);
71     marray_destroy(code->context);
72     marray_destroy(code->registers);
73     marray_destroy(code->label_true);
74     marray_destroy(code->label_false);
75     marray_destroy(code->label_check);
76     mem_free(code->list);
77     mem_free(code);
78 }
79 
ircode_ntemps(ircode_t * code)80 uint32_t ircode_ntemps (ircode_t *code) {
81     return code->ntemps;
82 }
83 
ircode_count(ircode_t * code)84 uint32_t ircode_count (ircode_t *code) {
85     return (uint32_t)marray_size(*code->list);
86 }
87 
ircode_get(ircode_t * code,uint32_t index)88 inst_t *ircode_get (ircode_t *code, uint32_t index) {
89     uint32_t n = (uint32_t)marray_size(*code->list);
90     return (index >= n) ? NULL : marray_get(*code->list, index);
91 }
92 
ircode_iserror(ircode_t * code)93 bool ircode_iserror (ircode_t *code) {
94     return code->error;
95 }
96 // MARK: -
97 
inst_new(opcode_t op,uint32_t p1,uint32_t p2,uint32_t p3,optag_t tag,int64_t n,double d,uint32_t lineno)98 static inst_t *inst_new (opcode_t op, uint32_t p1, uint32_t p2, uint32_t p3, optag_t tag, int64_t n, double d, uint32_t lineno) {
99 
100     // debug code
101     #if GRAVITY_OPCODE_DEBUG
102     if (tag == LABEL_TAG) {
103         DEBUG_OPCODE("LABEL %d", p1);
104     } else if (tag != PRAGMA_MOVE_OPTIMIZATION){
105         const char *op_name = opcode_name(op);
106 
107         if (op == LOADI) {
108             if (tag == DOUBLE_TAG)
109                 printf("%s %d %.2f\n", op_name, p1, d);
110             else
111                 printf("%s %d %lld\n", op_name, p1, n);
112         } else {
113             int nop = opcode_numop(op);
114             if (nop == 0) {
115                 DEBUG_OPCODE("%s", op_name);
116             } else if (nop == 1) {
117                 DEBUG_OPCODE("%s %d", op_name, p1);
118             } else if (nop == 2) {
119                 DEBUG_OPCODE("%s %d %d", op_name, p1, p2);
120             } else if (nop == 3) {
121                 DEBUG_OPCODE("%s %d %d %d", opcode_name(op), p1, p2, p3);
122             }
123         }
124     }
125     #endif
126 
127     inst_t *inst = (inst_t *)mem_alloc(NULL, sizeof(inst_t));
128     inst->op = op;
129     inst->tag = tag;
130     inst->p1 = p1;
131     inst->p2 = p2;
132     inst->p3 = p3;
133     inst->lineno = lineno;
134 
135     if (tag == DOUBLE_TAG) inst->d = d;
136     else if (tag == INT_TAG) inst->n = n;
137 
138     assert(inst);
139     return inst;
140 }
141 
inst_setskip(inst_t * inst)142 void inst_setskip (inst_t *inst) {
143     inst->tag = SKIP_TAG;
144 }
145 
ircode_patch_init(ircode_t * code,uint16_t index)146 void ircode_patch_init (ircode_t *code, uint16_t index) {
147     // prepend call instructions to code
148     // LOADK temp index
149     // LOAD  temp 0 temp
150     // MOVE  temp+1 0
151     // CALL  temp temp 1
152 
153     // load constant
154     uint32_t dest = ircode_register_push_temp(code);
155 	inst_t *inst1 = inst_new(LOADK, dest, index, 0, NO_TAG, 0, 0.0, 0);
156 
157     // load from lookup
158 	inst_t *inst2 = inst_new(LOAD, dest, 0, dest, NO_TAG, 0, 0.0, 0);
159 
160     // prepare parameter
161     uint32_t dest2 = ircode_register_push_temp(code);
162 	inst_t *inst3 = inst_new(MOVE, dest2, 0, 0, NO_TAG, 0, 0.0, 0);
163     ircode_register_pop(code);
164 
165     // execute call
166 	inst_t *inst4 = inst_new(CALL, dest, dest, 1, NO_TAG, 0, 0.0, 0);
167 
168     // pop temps used
169     ircode_register_pop(code);
170 
171     // create new instruction list
172     code_r        *list = mem_alloc(NULL, sizeof(code_r));
173     marray_init(*list);
174 
175     // add newly create instructions
176     marray_push(inst_t*, *list, inst1);
177     marray_push(inst_t*, *list, inst2);
178     marray_push(inst_t*, *list, inst3);
179     marray_push(inst_t*, *list, inst4);
180 
181     // then copy original instructions
182     code_r *orig_list = code->list;
183     uint32_t count = ircode_count(code);
184     for (uint32_t i=0; i<count; ++i) {
185         inst_t *inst = marray_get(*orig_list, i);
186         marray_push(inst_t*, *list, inst);
187     }
188 
189     // free dest list
190     marray_destroy(*orig_list);
191     mem_free(code->list);
192 
193     // replace dest list with the newly created list
194     code->list = list;
195 }
196 
opcode_numop(opcode_t op)197 uint8_t opcode_numop (opcode_t op) {
198     switch (op) {
199         case HALT: return 0;
200         case NOP: return 0;
201         case RET0: return 0;
202         case RET: return 1;
203         case CALL: return 3;
204         case SETLIST: return 3;
205         case LOADK: return 2;
206         case LOADG: return 2;
207         case LOADI: return 2;
208         case LOADAT: return 3;
209         case LOADS: return 3;
210         case LOAD: return 3;
211         case LOADU: return 2;
212         case MOVE: return 2;
213         case STOREG: return 2;
214         case STOREAT: return 3;
215         case STORE: return 3;
216         case STOREU: return 2;
217         case JUMP: return 1;
218         case JUMPF: return 2;
219         case SWITCH: return 1;
220         case ADD: return 3;
221         case SUB: return 3;
222         case DIV: return 3;
223         case MUL: return 3;
224         case REM: return 3;
225         case AND: return 3;
226         case OR: return 3;
227         case LT: return 3;
228         case GT: return 3;
229         case EQ: return 3;
230         case ISA: return 3;
231         case MATCH: return 3;
232         case EQQ: return 3;
233         case LEQ: return 3;
234         case GEQ: return 3;
235         case NEQ: return 3;
236         case NEQQ: return 3;
237         case NEG: return 2;
238         case NOT: return 2;
239         case LSHIFT: return 3;
240         case RSHIFT: return 3;
241         case BAND: return 3;
242         case BOR: return 3;
243         case BXOR: return 3;
244         case BNOT: return 2;
245         case MAPNEW: return 2;
246         case LISTNEW: return 2;
247         case RANGENEW: return 3;
248         case CLOSURE: return 2;
249         case CLOSE: return 1;
250         case CHECK: return 1;
251         case RESERVED2:
252         case RESERVED3:
253         case RESERVED4:
254         case RESERVED5:
255         case RESERVED6: return 0;
256     }
257 
258     assert(0);
259     return 0;
260 }
261 
ircode_dump(void * _code)262 void ircode_dump (void *_code) {
263     ircode_t    *code = (ircode_t *)_code;
264     code_r      *list = code->list;
265     uint32_t    count = ircode_count(code);
266 
267     if (count == 0) {
268         printf("NONE\n");
269         return;
270     }
271 
272     for (uint32_t i=0, line=0; i<count; ++i) {
273         inst_t      *inst = marray_get(*list, i);
274         opcode_t    op = inst->op;
275         int32_t     p1 = inst->p1;
276         int32_t     p2 = inst->p2;
277         int32_t     p3 = inst->p3;
278         if (inst->tag == SKIP_TAG) continue;
279         if (inst->tag == PRAGMA_MOVE_OPTIMIZATION) continue;
280         if (inst->tag == LABEL_TAG) {printf("LABEL %d:\n", p1); continue;}
281 
282         uint8_t n = opcode_numop(op);
283         if ((op == SETLIST) && (p2 == 0)) n = 2;
284 
285         // set to 1 to debug line number for each instruction
286         #if 0
287         printf("(%d)\t\t", inst->lineno);
288         #endif
289 
290         switch (n) {
291             case 0: {
292                 printf("%05d\t%s\n", line, opcode_name(op));
293             }
294 
295             case 1: {
296                 printf("%05d\t%s %d\n", line, opcode_name(op), p1);
297             } break;
298 
299             case 2: {
300                 if (op == LOADI) {
301                     if (inst->tag == DOUBLE_TAG) printf("%05d\t%s %d %.2f\n", line, opcode_name(op), p1, inst->d);
302                     #if defined(_WIN32)
303                     else printf("%05d\t%s %d %I64d\n", line, opcode_name(op), p1, inst->n);
304                     #else
305                     else printf("%05d\t%s %d %"PRId64"\n", line, opcode_name(op), p1, inst->n);
306                     #endif
307                 } else if (op == LOADK) {
308                     if (p2 < CPOOL_INDEX_MAX) printf("%05d\t%s %d %d\n", line, opcode_name(op), p1, p2);
309                     else printf("%05d\t%s %d %s\n", line, opcode_name(op), p1, opcode_constname(p2));
310                 } else {
311                     printf("%05d\t%s %d %d\n", line, opcode_name(op), p1, p2);
312                 }
313             } break;
314 
315             case 3: {
316                 printf("%05d\t%s %d %d %d\n", line, opcode_name(op), p1, p2, p3);
317             } break;
318 
319             default: assert(0);
320         }
321         ++line;
322     }
323 }
324 
325 // MARK: -
326 
ircode_newlabel(ircode_t * code)327 uint32_t ircode_newlabel (ircode_t *code) {
328     return ++code->label_counter;
329 }
330 
ircode_setlabel_true(ircode_t * code,uint32_t nlabel)331 void ircode_setlabel_true (ircode_t *code, uint32_t nlabel) {
332     marray_push(uint32_t, code->label_true, nlabel);
333 }
334 
ircode_setlabel_false(ircode_t * code,uint32_t nlabel)335 void ircode_setlabel_false (ircode_t *code, uint32_t nlabel) {
336     marray_push(uint32_t, code->label_false, nlabel);
337 }
338 
ircode_setlabel_check(ircode_t * code,uint32_t nlabel)339 void ircode_setlabel_check (ircode_t *code, uint32_t nlabel) {
340     marray_push(uint32_t, code->label_check, nlabel);
341 }
342 
ircode_unsetlabel_true(ircode_t * code)343 void ircode_unsetlabel_true (ircode_t *code) {
344     marray_pop(code->label_true);
345 }
346 
ircode_unsetlabel_false(ircode_t * code)347 void ircode_unsetlabel_false (ircode_t *code) {
348     marray_pop(code->label_false);
349 }
350 
ircode_unsetlabel_check(ircode_t * code)351 void ircode_unsetlabel_check (ircode_t *code) {
352     marray_pop(code->label_check);
353 }
354 
ircode_getlabel_true(ircode_t * code)355 uint32_t ircode_getlabel_true (ircode_t *code) {
356     size_t n = marray_size(code->label_true);
357     uint32_t v = marray_get(code->label_true, n-1);
358     return v;
359 }
360 
ircode_getlabel_false(ircode_t * code)361 uint32_t ircode_getlabel_false (ircode_t *code) {
362     size_t n = marray_size(code->label_false);
363     uint32_t v = marray_get(code->label_false, n-1);
364     return v;
365 }
366 
ircode_getlabel_check(ircode_t * code)367 uint32_t ircode_getlabel_check (ircode_t *code) {
368     size_t n = marray_size(code->label_check);
369     uint32_t v = marray_get(code->label_check, n-1);
370     return v;
371 }
372 
ircode_marklabel(ircode_t * code,uint32_t nlabel,uint32_t lineno)373 void ircode_marklabel (ircode_t *code, uint32_t nlabel, uint32_t lineno) {
374 	inst_t *inst = inst_new(0, nlabel, 0, 0, LABEL_TAG, 0, 0.0, lineno);
375     marray_push(inst_t*, *code->list, inst);
376 }
377 
378 // MARK: -
ircode_pragma(ircode_t * code,optag_t tag,uint32_t value,uint32_t lineno)379 void ircode_pragma (ircode_t *code, optag_t tag, uint32_t value, uint32_t lineno) {
380 	ircode_add_tag(code, 0, value, 0, 0, tag, lineno);
381 }
382 
383 // MARK: -
384 
ircode_set_index(uint32_t index,ircode_t * code,opcode_t op,uint32_t p1,uint32_t p2,uint32_t p3)385 void ircode_set_index (uint32_t index, ircode_t *code, opcode_t op, uint32_t p1, uint32_t p2, uint32_t p3) {
386     inst_t *inst = marray_get(*code->list, index);
387     inst->op = op;
388     inst->p1 = p1;
389     inst->p2 = p2;
390     inst->p3 = p3;
391     inst->tag = NO_TAG;
392 }
393 
ircode_add(ircode_t * code,opcode_t op,uint32_t p1,uint32_t p2,uint32_t p3,uint32_t lineno)394 void ircode_add (ircode_t *code, opcode_t op, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t lineno) {
395 	ircode_add_tag(code, op, p1, p2, p3, 0, lineno);
396 }
397 
ircode_add_tag(ircode_t * code,opcode_t op,uint32_t p1,uint32_t p2,uint32_t p3,optag_t tag,uint32_t lineno)398 void ircode_add_tag (ircode_t *code, opcode_t op, uint32_t p1, uint32_t p2, uint32_t p3, optag_t tag, uint32_t lineno) {
399 	inst_t *inst = inst_new(op, p1, p2, p3, tag, 0, 0.0, lineno);
400     marray_push(inst_t*, *code->list, inst);
401 }
402 
ircode_add_double(ircode_t * code,double d,uint32_t lineno)403 void ircode_add_double (ircode_t *code, double d, uint32_t lineno) {
404     uint32_t regnum = ircode_register_push_temp(code);
405 	inst_t *inst = inst_new(LOADI, regnum, 0, 0, DOUBLE_TAG, 0, d, lineno);
406     marray_push(inst_t*, *code->list, inst);
407 }
408 
ircode_add_constant(ircode_t * code,uint32_t index,uint32_t lineno)409 void ircode_add_constant (ircode_t *code, uint32_t index, uint32_t lineno) {
410     uint32_t regnum = ircode_register_push_temp(code);
411 	inst_t *inst = inst_new(LOADK, regnum, index, 0, NO_TAG, 0, 0, lineno);
412     marray_push(inst_t*, *code->list, inst);
413 }
414 
ircode_add_int(ircode_t * code,int64_t n,uint32_t lineno)415 void ircode_add_int (ircode_t *code, int64_t n, uint32_t lineno) {
416     uint32_t regnum = ircode_register_push_temp(code);
417 	inst_t *inst = inst_new(LOADI, regnum, 0, 0, INT_TAG, n, 0, lineno);
418     marray_push(inst_t*, *code->list, inst);
419 }
420 
ircode_add_skip(ircode_t * code,uint32_t lineno)421 void ircode_add_skip (ircode_t *code, uint32_t lineno) {
422 	inst_t *inst = inst_new(0, 0, 0, 0, NO_TAG, 0, 0, lineno);
423     inst_setskip(inst);
424     marray_push(inst_t*, *code->list, inst);
425 }
426 
ircode_add_check(ircode_t * code)427 void ircode_add_check (ircode_t *code) {
428     inst_t *inst = marray_last(*code->list);
429     if ((inst) && (inst->op == MOVE)) {
430         inst_t *newinst = inst_new(CHECK, inst->p1, 0, 0, NO_TAG, 0, 0, inst->lineno);
431         marray_push(inst_t*, *code->list, newinst);
432     }
433 }
434 
435 // MARK: - Context based functions -
436 
437 #if 0
438 static void dump_context(bool *context) {
439     for (uint32_t i=0; i<MAX_REGISTERS; ++i) {
440         printf("%d ", context[i]);
441     }
442     printf("\n");
443 }
444 #endif
445 
ircode_push_context(ircode_t * code)446 void ircode_push_context (ircode_t *code) {
447     bool *context = mem_alloc(NULL, sizeof(bool) * MAX_REGISTERS);
448     marray_push(bool *, code->context, context);
449 }
450 
ircode_pop_context(ircode_t * code)451 void ircode_pop_context (ircode_t *code) {
452     bool *context = marray_pop(code->context);
453     // apply context mask
454     for (uint32_t i=0; i<MAX_REGISTERS; ++i) {
455         if (context[i]) code->state[i] = false;
456     }
457     mem_free(context);
458 }
459 
ircode_register_pop_context_protect(ircode_t * code,bool protect)460 uint32_t ircode_register_pop_context_protect (ircode_t *code, bool protect) {
461     if (marray_size(code->registers) == 0) return REGISTER_ERROR;
462     uint32_t value = (uint32_t)marray_pop(code->registers);
463 
464     if (protect) code->state[value] = true;
465     else if (value >= code->nlocals) code->state[value] = false;
466 
467     if (protect && value >= code->nlocals) {
468         bool *context = marray_last(code->context);
469         context[value] = true;
470     }
471 
472     DEBUG_REGISTER("POP REGISTER %d", value);
473     return value;
474 }
475 
ircode_register_protect_outside_context(ircode_t * code,uint32_t nreg)476 bool ircode_register_protect_outside_context (ircode_t *code, uint32_t nreg) {
477     if (nreg < code->nlocals) return true;
478     if (!code->state[nreg]) return false;
479     bool *context = marray_last(code->context);
480     context[nreg] = false;
481     return true;
482 }
483 
ircode_register_protect_in_context(ircode_t * code,uint32_t nreg)484 void ircode_register_protect_in_context (ircode_t *code, uint32_t nreg) {
485     assert(code->state[nreg]);
486     bool *context = marray_last(code->context);
487     context[nreg] = true;
488 }
489 
490 // MARK: -
491 
ircode_register_new(ircode_t * code)492 static uint32_t ircode_register_new (ircode_t *code) {
493     for (uint32_t i=0; i<MAX_REGISTERS; ++i) {
494         if (code->state[i] == false) {
495             code->state[i] = true;
496             return i;
497         }
498     }
499     // 0 means no registers available
500     code->error = true;
501     return 0;
502 }
503 
ircode_register_push(ircode_t * code,uint32_t nreg)504 uint32_t ircode_register_push (ircode_t *code, uint32_t nreg) {
505     marray_push(uint32_t, code->registers, nreg);
506     if (ircode_register_istemp(code, nreg)) ++code->ntemps;
507 
508     DEBUG_REGISTER("PUSH REGISTER %d", nreg);
509     return nreg;
510 }
511 
ircode_register_first_temp_available(ircode_t * code)512 uint32_t ircode_register_first_temp_available (ircode_t *code) {
513     for (uint32_t i=0; i<MAX_REGISTERS; ++i) {
514         if (code->state[i] == false) {
515             return i;
516         }
517     }
518     // 0 means no registers available
519     code->error = true;
520     return 0;
521 }
522 
ircode_register_push_temp_protected(ircode_t * code)523 uint32_t ircode_register_push_temp_protected (ircode_t *code) {
524     uint32_t value = ircode_register_push_temp(code);
525     ircode_register_temp_protect(code, value);
526     return value;
527 }
528 
ircode_register_push_temp(ircode_t * code)529 uint32_t ircode_register_push_temp (ircode_t *code) {
530     uint32_t value = ircode_register_new(code);
531     marray_push(uint32_t, code->registers, value);
532     if (value > code->maxtemp) {code->maxtemp = value; ++code->ntemps;}
533 
534     DEBUG_REGISTER("PUSH TEMP REGISTER %d", value);
535     return value;
536 }
537 
ircode_register_pop(ircode_t * code)538 uint32_t ircode_register_pop (ircode_t *code) {
539     return ircode_register_pop_context_protect(code, false);
540 }
541 
ircode_register_clear(ircode_t * code,uint32_t nreg)542 void ircode_register_clear (ircode_t *code, uint32_t nreg) {
543     if (nreg == REGISTER_ERROR) return;
544     // cleanup busy mask only if it is a temp register
545     if (nreg >= code->nlocals) code->state[nreg] = false;
546 }
547 
ircode_register_set(ircode_t * code,uint32_t nreg)548 void ircode_register_set (ircode_t *code, uint32_t nreg) {
549     if (nreg == REGISTER_ERROR) return;
550     // set busy mask only if it is a temp register
551     if (nreg >= code->nlocals) code->state[nreg] = true;
552 }
553 
ircode_register_last(ircode_t * code)554 uint32_t ircode_register_last (ircode_t *code) {
555     if (marray_size(code->registers) == 0) return REGISTER_ERROR;
556     return (uint32_t)marray_last(code->registers);
557 }
558 
ircode_register_istemp(ircode_t * code,uint32_t nreg)559 bool ircode_register_istemp (ircode_t *code, uint32_t nreg) {
560     return (nreg >= (uint32_t)code->nlocals);
561 }
562 
ircode_register_dump(ircode_t * code)563 void ircode_register_dump (ircode_t *code) {
564     uint32_t n = (uint32_t)marray_size(code->registers);
565     if (n == 0) printf("EMPTY\n");
566     for (uint32_t i=0; i<n; ++i) {
567         uint32_t value = marray_get(code->registers, i);
568         printf("[%d]\t%d\n", i, value);
569     }
570 }
571 
ircode_register_count(ircode_t * code)572 uint32_t ircode_register_count (ircode_t *code) {
573     return (uint32_t)marray_size(code->registers);
574 }
575 
576 // MARK: -
577 
ircode_register_temp_protect(ircode_t * code,uint32_t nreg)578 void ircode_register_temp_protect (ircode_t *code, uint32_t nreg) {
579     code->skipclear[nreg] = true;
580     DEBUG_REGISTER("SET SKIP REGISTER %d", nreg);
581 }
582 
ircode_register_temp_unprotect(ircode_t * code,uint32_t nreg)583 void ircode_register_temp_unprotect (ircode_t *code, uint32_t nreg) {
584     code->skipclear[nreg] = false;
585     DEBUG_REGISTER("UNSET SKIP REGISTER %d", nreg);
586 }
587 
ircode_register_temps_clear(ircode_t * code)588 void ircode_register_temps_clear (ircode_t *code) {
589     // clear all temporary registers (if not protected)
590     for (uint32_t i=code->nlocals; i<=code->maxtemp; ++i) {
591         if (!code->skipclear[i]) {
592             code->state[i] = false;
593             DEBUG_REGISTER("CLEAR TEMP REGISTER %d", i);
594         }
595     }
596 }
597