1 
2 #include "config.h"
3 
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 
9 #include <orc/orcprogram.h>
10 #include <orc/orcdebug.h>
11 #include <orc/orcinternal.h>
12 
13 /**
14  * SECTION:orcprogram
15  * @title: OrcProgram
16  * @short_description: Creating and manipulating Orc programs
17  */
18 
19 
20 /**
21  * orc_program_new:
22  *
23  * Create a new OrcProgram.  The program should be freed using
24  * @orc_program_free().
25  *
26  * Returns: a pointer to an OrcProgram structure
27  */
28 OrcProgram *
orc_program_new(void)29 orc_program_new (void)
30 {
31   OrcProgram *p;
32 
33   orc_init ();
34 
35   p = malloc(sizeof(OrcProgram));
36   memset (p, 0, sizeof(OrcProgram));
37 
38   p->name = malloc (40);
39   sprintf(p->name, "func_%p", p);
40 
41   return p;
42 }
43 
44 /**
45  * orc_program_new_dss:
46  * @size1: size of destination array members
47  * @size2: size of first source array members
48  * @size3: size of second source array members
49  *
50  * Create a new OrcProgram, with a destination named "d1" and
51  * two sources named "s1" and "s2".
52  *
53  * Returns: a pointer to an OrcProgram structure
54  */
55 OrcProgram *
orc_program_new_dss(int size1,int size2,int size3)56 orc_program_new_dss (int size1, int size2, int size3)
57 {
58   OrcProgram *p;
59 
60   p = orc_program_new ();
61 
62   orc_program_add_destination (p, size1, "d1");
63   orc_program_add_source (p, size2, "s1");
64   orc_program_add_source (p, size3, "s2");
65 
66   return p;
67 }
68 
69 /**
70  * orc_program_new_ds:
71  * @size1: size of destination array members
72  * @size2: size of source array members
73  *
74  * Create a new OrcProgram, with a destination named "d1" and
75  * one source named "s1".
76  *
77  * Returns: a pointer to an OrcProgram structure
78  */
79 OrcProgram *
orc_program_new_ds(int size1,int size2)80 orc_program_new_ds (int size1, int size2)
81 {
82   OrcProgram *p;
83 
84   p = orc_program_new ();
85 
86   orc_program_add_destination (p, size1, "d1");
87   orc_program_add_source (p, size2, "s1");
88 
89   return p;
90 }
91 
92 /**
93  * orc_program_new_ass:
94  * @size1: size of destination array members
95  * @size2: size of first source array members
96  * @size3: size of second source array members
97  *
98  * Create a new OrcProgram, with an accumulator named "a1" and
99  * two source named "s1" and "s2".
100  *
101  * Returns: a pointer to an OrcProgram structure
102  */
103 OrcProgram *
orc_program_new_ass(int size1,int size2,int size3)104 orc_program_new_ass (int size1, int size2, int size3)
105 {
106   OrcProgram *p;
107 
108   p = orc_program_new ();
109 
110   orc_program_add_accumulator (p, size1, "a1");
111   orc_program_add_source (p, size2, "s1");
112   orc_program_add_source (p, size3, "s2");
113 
114   return p;
115 }
116 
117 /**
118  * orc_program_new_as:
119  * @size1: size of destination array members
120  * @size2: size of source array members
121  *
122  * Create a new OrcProgram, with an accumulator named "a1" and
123  * one source named "s1".
124  *
125  * Returns: a pointer to an OrcProgram structure
126  */
127 OrcProgram *
orc_program_new_as(int size1,int size2)128 orc_program_new_as (int size1, int size2)
129 {
130   OrcProgram *p;
131 
132   p = orc_program_new ();
133 
134   orc_program_add_accumulator (p, size1, "a1");
135   orc_program_add_source (p, size2, "s1");
136 
137   return p;
138 }
139 
140 OrcProgram *
orc_program_new_from_static_bytecode(const orc_uint8 * bytecode)141 orc_program_new_from_static_bytecode (const orc_uint8 *bytecode)
142 {
143   OrcProgram *p;
144 
145   p = orc_program_new ();
146   orc_bytecode_parse_function (p, bytecode);
147 
148   return p;
149 }
150 
151 /**
152  * orc_program_free:
153  * @program: a pointer to an OrcProgram structure
154  *
155  * Frees an OrcProgram.
156  */
157 void
orc_program_free(OrcProgram * program)158 orc_program_free (OrcProgram *program)
159 {
160   int i;
161   for(i=0;i<ORC_N_VARIABLES;i++){
162     if (program->vars[i].name) {
163       free (program->vars[i].name);
164       program->vars[i].name = NULL;
165     }
166     if (program->vars[i].type_name) {
167       free (program->vars[i].type_name);
168       program->vars[i].type_name = NULL;
169     }
170   }
171   if (program->asm_code) {
172     free (program->asm_code);
173     program->asm_code = NULL;
174   }
175   if (program->orccode) {
176     orc_code_free (program->orccode);
177     program->orccode = NULL;
178   }
179   if (program->init_function) {
180     free (program->init_function);
181     program->init_function = NULL;
182   }
183   if (program->backup_name) {
184     free (program->backup_name);
185     program->backup_name = NULL;
186   }
187   if (program->name) {
188     free (program->name);
189     program->name = NULL;
190   }
191   if (program->error_msg) {
192     free (program->error_msg);
193     program->error_msg = NULL;
194   }
195   free (program);
196 }
197 
198 /**
199  * orc_program_set_name:
200  * @program: a pointer to an OrcProgram structure
201  * @name: string to set the name to
202  *
203  * Sets the name of the program.  The string is copied.
204  */
205 void
orc_program_set_name(OrcProgram * program,const char * name)206 orc_program_set_name (OrcProgram *program, const char *name)
207 {
208   if (program->name) {
209     free (program->name);
210   }
211   program->name = strdup (name);
212 }
213 
214 /**
215  * orc_program_set_line:
216  * @program: a pointer to an OrcProgram structure
217  * @name: define where we are in the source
218  *
219  * Sets the current line of the program.
220  */
221 void
orc_program_set_line(OrcProgram * program,unsigned int line)222 orc_program_set_line (OrcProgram *program, unsigned int line)
223 {
224   program->current_line = line;
225 }
226 
227 /**
228  * orc_program_set_2d:
229  * @program: a pointer to an OrcProgram structure
230  *
231  * Sets a flag on the program indicating that arrays are two
232  * dimensional.  This causes the compiler to generate code for
233  * an OrcExec2D executor.
234  */
235 void
orc_program_set_2d(OrcProgram * program)236 orc_program_set_2d (OrcProgram *program)
237 {
238   program->is_2d = TRUE;
239 }
240 
orc_program_set_constant_n(OrcProgram * program,int n)241 void orc_program_set_constant_n (OrcProgram *program, int n)
242 {
243   program->constant_n = n;
244 }
245 
orc_program_set_n_multiple(OrcProgram * program,int n)246 void orc_program_set_n_multiple (OrcProgram *program, int n)
247 {
248   program->n_multiple = n;
249 }
250 
orc_program_set_n_minimum(OrcProgram * program,int n)251 void orc_program_set_n_minimum (OrcProgram *program, int n)
252 {
253   program->n_minimum = n;
254 }
255 
orc_program_set_n_maximum(OrcProgram * program,int n)256 void orc_program_set_n_maximum (OrcProgram *program, int n)
257 {
258   program->n_maximum = n;
259 }
260 
orc_program_set_constant_m(OrcProgram * program,int m)261 void orc_program_set_constant_m (OrcProgram *program, int m)
262 {
263   program->constant_m = m;
264 }
265 
266 /**
267  * orc_program_set_backup_function:
268  * @program: a pointer to an OrcProgram structure
269  * @func: a function that performs the operations in the program
270  *
271  * Normally, if a program cannot be compiled for a particular CPU,
272  * Orc will emulate the function, which is typically very slow.  This
273  * function allows the developer to provide a function that is called
274  * instead of resorting to emulation.
275  */
276 void
orc_program_set_backup_function(OrcProgram * program,OrcExecutorFunc func)277 orc_program_set_backup_function (OrcProgram *program, OrcExecutorFunc func)
278 {
279   program->backup_func = func;
280   if (program->code_exec == NULL) {
281     program->code_exec = func;
282   }
283 }
284 
285 /**
286  * orc_program_set_backup_name:
287  * @program: a pointer to an OrcProgram structure
288  * @name: a function name that performs the operations in the program
289  */
290 void
orc_program_set_backup_name(OrcProgram * program,const char * name)291 orc_program_set_backup_name (OrcProgram *program, const char *name)
292 {
293   if (program->backup_name)
294     free (program->backup_name);
295   program->backup_name = strdup (name);
296 }
297 
298 /**
299  * orc_program_get_name:
300  * @program: a pointer to an OrcProgram structure
301  *
302  * Gets the name of the program.  The string is valid until the name
303  * is changed or the program is freed.
304  *
305  * Returns: a character string
306  */
307 const char *
orc_program_get_name(OrcProgram * program)308 orc_program_get_name (OrcProgram *program)
309 {
310   return program->name;
311 }
312 
313 /**
314  * orc_program_add_temporary:
315  * @program: a pointer to an OrcProgram structure
316  * @size: size of data values
317  * @name: name of variable
318  *
319  * Creates a new variable holding temporary values.
320  *
321  * Returns: the index of the new variable
322  */
323 int
orc_program_add_temporary(OrcProgram * program,int size,const char * name)324 orc_program_add_temporary (OrcProgram *program, int size, const char *name)
325 {
326   int i = ORC_VAR_T1 + program->n_temp_vars;
327 
328   if (program->n_temp_vars >= ORC_MAX_TEMP_VARS) {
329     orc_program_set_error (program, "too many temporary variables allocated");
330     return 0;
331   }
332 
333   program->vars[i].vartype = ORC_VAR_TYPE_TEMP;
334   program->vars[i].size = size;
335   program->vars[i].name = strdup(name);
336   program->n_temp_vars++;
337 
338   return i;
339 }
340 
341 /**
342  * orc_program_dup_temporary:
343  * @program: a pointer to an OrcProgram structure
344  * @var: variable to duplicate
345  * @j: index
346  *
347  * Internal function.
348  *
349  * Returns: the index of the new variable
350  */
351 int
orc_program_dup_temporary(OrcProgram * program,int var,int j)352 orc_program_dup_temporary (OrcProgram *program, int var, int j)
353 {
354   int i = ORC_VAR_T1 + program->n_temp_vars;
355 
356   if (program->n_temp_vars >= ORC_MAX_TEMP_VARS) {
357     orc_program_set_error (program, "too many temporary variables allocated");
358     return 0;
359   }
360 
361   program->vars[i].vartype = ORC_VAR_TYPE_TEMP;
362   program->vars[i].size = program->vars[var].size;
363   program->vars[i].name = malloc (strlen(program->vars[var].name) + 10);
364   sprintf(program->vars[i].name, "%s.dup%d", program->vars[var].name, j);
365   program->n_temp_vars++;
366 
367   return i;
368 }
369 
370 /**
371  * orc_program_add_source_full:
372  * @program: a pointer to an OrcProgram structure
373  * @size: size of data values
374  * @name: name of variable
375  * @type_name: name of type, or NULL
376  * @alignment: alignment in bytes, or 0
377  *
378  * Creates a new variable representing a source array.
379  *
380  * Returns: the index of the new variable
381  */
382 int
orc_program_add_source_full(OrcProgram * program,int size,const char * name,const char * type_name,int alignment)383 orc_program_add_source_full (OrcProgram *program, int size, const char *name,
384     const char *type_name, int alignment)
385 {
386   int i = ORC_VAR_S1 + program->n_src_vars;
387 
388   if (program->n_src_vars >= ORC_MAX_SRC_VARS) {
389     orc_program_set_error (program, "too many source variables allocated");
390     return 0;
391   }
392 
393   program->vars[i].vartype = ORC_VAR_TYPE_SRC;
394   program->vars[i].size = size;
395   if (alignment == 0) alignment = size;
396   program->vars[i].alignment = alignment;
397   program->vars[i].name = strdup(name);
398   if (type_name) {
399     program->vars[i].type_name = strdup(type_name);
400   }
401   program->n_src_vars++;
402 
403   return i;
404 }
405 
406 /**
407  * orc_program_add_source:
408  * @program: a pointer to an OrcProgram structure
409  * @size: size of data values
410  * @name: name of variable
411  *
412  * Creates a new variable representing a source array.
413  *
414  * Returns: the index of the new variable
415  */
416 int
orc_program_add_source(OrcProgram * program,int size,const char * name)417 orc_program_add_source (OrcProgram *program, int size, const char *name)
418 {
419   return orc_program_add_source_full (program, size, name, NULL, 0);
420 }
421 
422 /**
423  * orc_program_add_destination_full:
424  * @program: a pointer to an OrcProgram structure
425  * @size: size of data values
426  * @name: name of variable
427  *
428  * Creates a new variable representing a destination array.
429  *
430  * Returns: the index of the new variable
431  */
432 int
orc_program_add_destination_full(OrcProgram * program,int size,const char * name,const char * type_name,int alignment)433 orc_program_add_destination_full (OrcProgram *program, int size, const char *name,
434     const char *type_name, int alignment)
435 {
436   int i = ORC_VAR_D1 + program->n_dest_vars;
437 
438   if (program->n_dest_vars >= ORC_MAX_DEST_VARS) {
439     orc_program_set_error (program, "too many destination variables allocated");
440     return 0;
441   }
442 
443   program->vars[i].vartype = ORC_VAR_TYPE_DEST;
444   program->vars[i].size = size;
445   if (alignment == 0) alignment = size;
446   program->vars[i].alignment = alignment;
447   program->vars[i].name = strdup(name);
448   if (type_name) {
449     program->vars[i].type_name = strdup(type_name);
450   }
451   program->n_dest_vars++;
452 
453   return i;
454 }
455 
456 /**
457  * orc_program_add_destination:
458  * @program: a pointer to an OrcProgram structure
459  * @size: size of data values
460  * @name: name of variable
461  *
462  * Creates a new variable representing a destination array.
463  *
464  * Returns: the index of the new variable
465  */
466 int
orc_program_add_destination(OrcProgram * program,int size,const char * name)467 orc_program_add_destination (OrcProgram *program, int size, const char *name)
468 {
469   return orc_program_add_destination_full (program, size, name, NULL, 0);
470 }
471 
472 /**
473  * orc_program_add_constant:
474  * @program: a pointer to an OrcProgram structure
475  * @size: size of data value
476  * @value: the value
477  * @name: name of variable
478  *
479  * Creates a new variable representing a constant value.
480  *
481  * Returns: the index of the new variable
482  */
483 int
orc_program_add_constant(OrcProgram * program,int size,int value,const char * name)484 orc_program_add_constant (OrcProgram *program, int size, int value, const char *name)
485 {
486   int i;
487 
488   i = ORC_VAR_C1 + program->n_const_vars;
489 
490   if (program->n_const_vars >= ORC_MAX_CONST_VARS) {
491     orc_program_set_error (program, "too many constants allocated");
492     return 0;
493   }
494 
495   program->vars[i].vartype = ORC_VAR_TYPE_CONST;
496   program->vars[i].size = size;
497   program->vars[i].value.i = value;
498   program->vars[i].name = strdup(name);
499   program->n_const_vars++;
500 
501   return i;
502 }
503 
504 int
orc_program_add_constant_int64(OrcProgram * program,int size,orc_int64 value,const char * name)505 orc_program_add_constant_int64 (OrcProgram *program, int size,
506     orc_int64 value, const char *name)
507 {
508   int i;
509 
510   i = ORC_VAR_C1 + program->n_const_vars;
511 
512   if (program->n_const_vars >= ORC_MAX_CONST_VARS) {
513     orc_program_set_error (program, "too many constants allocated");
514     return 0;
515   }
516 
517   program->vars[i].vartype = ORC_VAR_TYPE_CONST;
518   program->vars[i].size = size;
519   program->vars[i].value.i = value;
520   program->vars[i].name = strdup(name);
521   program->n_const_vars++;
522 
523   return i;
524 }
525 
526 int
orc_program_add_constant_float(OrcProgram * program,int size,float value,const char * name)527 orc_program_add_constant_float (OrcProgram *program, int size,
528     float value, const char *name)
529 {
530   orc_union32 u;
531   u.f = value;
532   return orc_program_add_constant (program, size, u.i, name);
533 }
534 
535 int
orc_program_add_constant_double(OrcProgram * program,int size,double value,const char * name)536 orc_program_add_constant_double (OrcProgram *program, int size,
537     double value, const char *name)
538 {
539   orc_union64 u;
540   u.f = value;
541   return orc_program_add_constant_int64 (program, size, u.i, name);
542 }
543 
544 int
orc_program_add_constant_str(OrcProgram * program,int size,const char * value,const char * name)545 orc_program_add_constant_str (OrcProgram *program, int size,
546     const char *value, const char *name)
547 {
548   int i;
549   char *end;
550   orc_int64 val_i;
551   double val_d;
552   int j;
553 
554   i = ORC_VAR_C1 + program->n_const_vars;
555 
556   if (program->n_const_vars >= ORC_MAX_CONST_VARS) {
557     orc_program_set_error (program, "too many constants allocated");
558     return 0;
559   }
560 
561   val_i = _strtoll (value, &end, 0);
562   if (end[0] == 0) {
563     program->vars[i].value.i = val_i;
564     if (size == 0)
565       size = 4;
566   } else if ((end[0] == 'l' || end[0] == 'L') && end[1] == 0) {
567     program->vars[i].value.i = val_i;
568     if (size == 0)
569       size = 8;
570   } else {
571     val_d = strtod (value, &end);
572 
573     if (end[0] == 0) {
574       orc_union32 u;
575       u.f = val_d;
576       program->vars[i].value.i = u.i;
577       if (size == 0)
578         size = 4;
579     } else if ((end[0] == 'l' || end[0] == 'L') && end[1] == 0) {
580       program->vars[i].value.f = val_d;
581       if (size == 0)
582         size = 8;
583     } else {
584       return -1;
585     }
586   }
587 
588   for(j=0;j<program->n_const_vars;j++){
589     if (program->vars[ORC_VAR_C1 + j].value.i == program->vars[i].value.i &&
590         program->vars[ORC_VAR_C1 + j].size == size) {
591       return ORC_VAR_C1 + j;
592     }
593   }
594 
595   program->vars[i].vartype = ORC_VAR_TYPE_CONST;
596   program->vars[i].size = size;
597   program->vars[i].name = strdup(name);
598   program->n_const_vars++;
599 
600   return i;
601 }
602 
603 /**
604  * orc_program_add_parameter:
605  * @program: a pointer to an OrcProgram structure
606  * @size: size of data value
607  * @name: name of variable
608  *
609  * Creates a new variable representing a scalar parameter.
610  *
611  * Returns: the index of the new variable
612  */
613 int
orc_program_add_parameter(OrcProgram * program,int size,const char * name)614 orc_program_add_parameter (OrcProgram *program, int size, const char *name)
615 {
616   int i = ORC_VAR_P1 + program->n_param_vars;
617 
618   if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
619     orc_program_set_error (program, "too many parameter variables allocated");
620     return 0;
621   }
622 
623   program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
624   program->vars[i].param_type = ORC_PARAM_TYPE_INT;
625   program->vars[i].size = size;
626   program->vars[i].name = strdup(name);
627   program->n_param_vars++;
628 
629   return i;
630 }
631 
632 /**
633  * orc_program_add_parameter_float:
634  * @program: a pointer to an OrcProgram structure
635  * @size: size of data value
636  * @name: name of variable
637  *
638  * Creates a new variable representing a scalar parameter.
639  *
640  * Returns: the index of the new variable
641  */
642 int
orc_program_add_parameter_float(OrcProgram * program,int size,const char * name)643 orc_program_add_parameter_float (OrcProgram *program, int size, const char *name)
644 {
645   int i = ORC_VAR_P1 + program->n_param_vars;
646 
647   if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
648     orc_program_set_error (program, "too many parameter variables allocated");
649     return 0;
650   }
651 
652   program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
653   program->vars[i].param_type = ORC_PARAM_TYPE_FLOAT;
654   program->vars[i].size = size;
655   program->vars[i].name = strdup(name);
656   program->n_param_vars++;
657 
658   return i;
659 }
660 
661 int
orc_program_add_parameter_double(OrcProgram * program,int size,const char * name)662 orc_program_add_parameter_double (OrcProgram *program, int size,
663     const char *name)
664 {
665   int i = ORC_VAR_P1 + program->n_param_vars;
666 
667   if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
668     orc_program_set_error (program, "too many parameter variables allocated");
669     return 0;
670   }
671 
672   program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
673   program->vars[i].param_type = ORC_PARAM_TYPE_DOUBLE;
674   program->vars[i].size = size;
675   program->vars[i].name = strdup(name);
676   program->n_param_vars++;
677 
678   return i;
679 }
680 
681 int
orc_program_add_parameter_int64(OrcProgram * program,int size,const char * name)682 orc_program_add_parameter_int64 (OrcProgram *program, int size,
683     const char *name)
684 {
685   int i = ORC_VAR_P1 + program->n_param_vars;
686 
687   if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
688     orc_program_set_error (program, "too many parameter variables allocated");
689     return 0;
690   }
691 
692   program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
693   program->vars[i].param_type = ORC_PARAM_TYPE_INT64;
694   program->vars[i].size = size;
695   program->vars[i].name = strdup(name);
696   program->n_param_vars++;
697 
698   return i;
699 }
700 
701 /**
702  * orc_program_add_accumulator:
703  * @program: a pointer to an OrcProgram structure
704  * @size: size of data value
705  * @name: name of variable
706  *
707  * Creates a new variable representing an accumulator.
708  *
709  * Returns: the index of the new variable
710  */
711 int
orc_program_add_accumulator(OrcProgram * program,int size,const char * name)712 orc_program_add_accumulator (OrcProgram *program, int size, const char *name)
713 {
714   int i = ORC_VAR_A1 + program->n_accum_vars;
715 
716   if (program->n_accum_vars >= ORC_MAX_ACCUM_VARS) {
717     orc_program_set_error (program, "too many accumulator variables allocated");
718     return 0;
719   }
720 
721   program->vars[i].vartype = ORC_VAR_TYPE_ACCUMULATOR;
722   program->vars[i].size = size;
723   program->vars[i].name = strdup(name);
724   program->n_accum_vars++;
725 
726   return i;
727 }
728 
729 void
orc_program_set_type_name(OrcProgram * program,int var,const char * type_name)730 orc_program_set_type_name (OrcProgram *program, int var, const char *type_name)
731 {
732   program->vars[var].type_name = strdup(type_name);
733 }
734 
735 void
orc_program_set_var_alignment(OrcProgram * program,int var,int alignment)736 orc_program_set_var_alignment (OrcProgram *program, int var, int alignment)
737 {
738   program->vars[var].alignment = alignment;
739   if (alignment >= 16) {
740     program->vars[var].is_aligned = TRUE;
741   }
742 }
743 
744 void
orc_program_set_sampling_type(OrcProgram * program,int var,int sampling_type)745 orc_program_set_sampling_type (OrcProgram *program, int var,
746     int sampling_type)
747 {
748   /* This doesn't do anything yet */
749 }
750 
751 /**
752  * orc_program_append_ds:
753  * @program: a pointer to an OrcProgram structure
754  * @name: name of instruction
755  * @arg0: index of first variable
756  * @arg1: index of second variable
757  *
758  * Appends an instruction to the program, with arguments @arg0 and
759  * @arg1.  The instruction must take 2 operands.
760  */
761 void
orc_program_append_ds(OrcProgram * program,const char * name,int arg0,int arg1)762 orc_program_append_ds (OrcProgram *program, const char *name, int arg0,
763     int arg1)
764 {
765   OrcInstruction *insn;
766 
767   insn = program->insns + program->n_insns;
768 
769   insn->opcode = orc_opcode_find_by_name (name);
770   if (!insn->opcode) {
771     ORC_ERROR ("unknown opcode: %s", name);
772   }
773   insn->dest_args[0] = arg0;
774   insn->src_args[0] = arg1;
775 
776   program->n_insns++;
777 }
778 
779 /**
780  * orc_program_append_ds:
781  * @program: a pointer to an OrcProgram structure
782  * @name: name of instruction
783  * @arg0: index of first variable
784  * @arg1: index of second variable
785  * @arg2: index of second variable
786  *
787  * Appends an instruction to the program, with arguments @arg0,
788  * @arg1, and @arg2.  The instruction must take 3 operands.
789  */
790 void
orc_program_append(OrcProgram * program,const char * name,int arg0,int arg1,int arg2)791 orc_program_append (OrcProgram *program, const char *name, int arg0,
792     int arg1, int arg2)
793 {
794   OrcInstruction *insn;
795 
796   insn = program->insns + program->n_insns;
797 
798   insn->opcode = orc_opcode_find_by_name (name);
799   if (!insn->opcode) {
800     ORC_ERROR ("unknown opcode: %s", name);
801   }
802   insn->dest_args[0] = arg0;
803   insn->src_args[0] = arg1;
804   insn->src_args[1] = arg2;
805 
806   program->n_insns++;
807 }
808 
809 /**
810  * orc_program_append_ds_2:
811  * @program: a pointer to an OrcProgram structure
812  * @name: name of instruction
813  * @arg0: index of first variable
814  * @arg1: index of second variable
815  * @arg2: index of third variable
816  * @arg3: index of fourth variable
817  *
818  * Appends an instruction to the program, with arguments @arg0,
819  * @arg1, @arg2, and @arg3.
820  */
821 void
orc_program_append_2(OrcProgram * program,const char * name,unsigned int flags,int arg0,int arg1,int arg2,int arg3)822 orc_program_append_2 (OrcProgram *program, const char *name, unsigned int flags,
823     int arg0, int arg1, int arg2, int arg3)
824 {
825   OrcInstruction *insn;
826   int args[4];
827   int i;
828 
829   insn = program->insns + program->n_insns;
830 
831   insn->opcode = orc_opcode_find_by_name (name);
832   if (!insn->opcode) {
833     ORC_ERROR ("unknown opcode: %s", name);
834   }
835   insn->flags = flags;
836   args[0] = arg0;
837   args[1] = arg1;
838   args[2] = arg2;
839   args[3] = arg3;
840   insn->flags = flags;
841   i = 0;
842   insn->dest_args[0] = args[i++];
843   if (insn->opcode) {
844     if (insn->opcode->dest_size[1] != 0) {
845       insn->dest_args[1] = args[i++];
846     }
847     if (insn->opcode->src_size[0] != 0) {
848       insn->src_args[0] = args[i++];
849     }
850     if (insn->opcode->src_size[1] != 0) {
851       insn->src_args[1] = args[i++];
852     }
853     if (insn->opcode->src_size[2] != 0) {
854       insn->src_args[2] = args[i++];
855     }
856   }
857   program->n_insns++;
858 }
859 
860 /**
861  * orc_program_find_var_by_name:
862  * @program: a pointer to an OrcProgram structure
863  * @name: name of instruction
864  *
865  * Finds the variable with the name @name.  If no variable with the
866  * given name exists in the program, -1 is returned.
867  *
868  * Returns: the index of the variable
869  */
870 int
orc_program_find_var_by_name(OrcProgram * program,const char * name)871 orc_program_find_var_by_name (OrcProgram *program, const char *name)
872 {
873   int i;
874 
875   if (name == NULL) return -1;
876 
877   for(i=0;i<ORC_N_VARIABLES;i++){
878     if (program->vars[i].name && strcmp (program->vars[i].name, name) == 0) {
879       return i;
880     }
881   }
882 
883   return -1;
884 }
885 
886 /**
887  * orc_program_append_str:
888  * @program: a pointer to an OrcProgram structure
889  * @name: name of instruction
890  * @arg0: name of first variable
891  * @arg1: name of second variable
892  * @arg2: name of third variable
893  *
894  * Appends an instruction to the program, with arguments @arg0,
895  * @arg1, and @arg2.  The instruction must take 3 operands.
896  */
897 void
orc_program_append_str(OrcProgram * program,const char * name,const char * arg1,const char * arg2,const char * arg3)898 orc_program_append_str (OrcProgram *program, const char *name,
899     const char *arg1, const char *arg2, const char *arg3)
900 {
901   OrcInstruction *insn;
902 
903   insn = program->insns + program->n_insns;
904 
905   insn->opcode = orc_opcode_find_by_name (name);
906   if (!insn->opcode) {
907     ORC_ERROR ("unknown opcode: %s", name);
908     return;
909   }
910   insn->dest_args[0] = orc_program_find_var_by_name (program, arg1);
911   if (insn->opcode->dest_size[1] != 0) {
912     insn->dest_args[1] = orc_program_find_var_by_name (program, arg2);
913     insn->src_args[0] = orc_program_find_var_by_name (program, arg3);
914   } else {
915     insn->src_args[0] = orc_program_find_var_by_name (program, arg2);
916     insn->src_args[1] = orc_program_find_var_by_name (program, arg3);
917   }
918 
919   program->n_insns++;
920 }
921 
922 /**
923  * orc_program_append_str_2:
924  * @program: a pointer to an OrcProgram structure
925  * @name: name of instruction
926  * @flags: flags
927  * @arg0: name of first variable
928  * @arg1: name of second variable
929  * @arg2: name of third variable
930  * @arg3: name of fourth variable
931  *
932  * Appends an instruction to the program, with arguments @arg0,
933  * @arg1, @arg2, and @arg3.
934  */
935 void
orc_program_append_str_2(OrcProgram * program,const char * name,unsigned int flags,const char * arg1,const char * arg2,const char * arg3,const char * arg4)936 orc_program_append_str_2 (OrcProgram *program, const char *name,
937     unsigned int flags, const char *arg1, const char *arg2, const char *arg3,
938     const char *arg4)
939 {
940   OrcInstruction *insn;
941   int args[4];
942   int i;
943 
944   insn = program->insns + program->n_insns;
945 
946   insn->line = program->current_line;
947   insn->opcode = orc_opcode_find_by_name (name);
948   if (!insn->opcode) {
949     ORC_ERROR ("unknown opcode: %s at line %d", name, insn->line);
950   }
951   args[0] = orc_program_find_var_by_name (program, arg1);
952   args[1] = orc_program_find_var_by_name (program, arg2);
953   args[2] = orc_program_find_var_by_name (program, arg3);
954   args[3] = orc_program_find_var_by_name (program, arg4);
955   insn->flags = flags;
956   i = 0;
957   insn->dest_args[0] = args[i++];
958   if (insn->opcode) {
959     if (insn->opcode->dest_size[1] != 0) {
960       insn->dest_args[1] = args[i++];
961     }
962     if (insn->opcode->src_size[0] != 0) {
963       insn->src_args[0] = args[i++];
964     }
965     if (insn->opcode->src_size[1] != 0) {
966       insn->src_args[1] = args[i++];
967     }
968     if (insn->opcode->src_size[2] != 0) {
969       insn->src_args[2] = args[i++];
970     }
971   }
972   program->n_insns++;
973 }
974 
975 /**
976  * orc_program_append_ds_str:
977  * @program: a pointer to an OrcProgram structure
978  * @name: name of instruction
979  * @arg0: name of first variable
980  * @arg1: name of second variable
981  *
982  * Appends an instruction to the program, with arguments @arg0 and
983  * @arg2.  The instruction must take 2 operands.
984  */
985 void
orc_program_append_ds_str(OrcProgram * program,const char * name,const char * arg1,const char * arg2)986 orc_program_append_ds_str (OrcProgram *program, const char *name,
987     const char *arg1, const char *arg2)
988 {
989   OrcInstruction *insn;
990 
991   insn = program->insns + program->n_insns;
992 
993   insn->opcode = orc_opcode_find_by_name (name);
994   if (!insn->opcode) {
995     ORC_ERROR ("unknown opcode: %s", name);
996   }
997   insn->dest_args[0] = orc_program_find_var_by_name (program, arg1);
998   insn->src_args[0] = orc_program_find_var_by_name (program, arg2);
999 
1000   program->n_insns++;
1001 }
1002 
1003 void
orc_program_append_dds_str(OrcProgram * program,const char * name,const char * arg1,const char * arg2,const char * arg3)1004 orc_program_append_dds_str (OrcProgram *program, const char *name,
1005     const char *arg1, const char *arg2, const char *arg3)
1006 {
1007   OrcInstruction *insn;
1008 
1009   insn = program->insns + program->n_insns;
1010 
1011   insn->opcode = orc_opcode_find_by_name (name);
1012   if (!insn->opcode) {
1013     ORC_ERROR ("unknown opcode: %s", name);
1014   }
1015   insn->dest_args[0] = orc_program_find_var_by_name (program, arg1);
1016   insn->dest_args[1] = orc_program_find_var_by_name (program, arg2);
1017   insn->src_args[0] = orc_program_find_var_by_name (program, arg3);
1018 
1019   program->n_insns++;
1020 }
1021 
1022 /**
1023  * orc_program_get_asm_code:
1024  * @program: a pointer to an OrcProgram structure
1025  *
1026  * Returns a character string containing the assembly code created
1027  * by compiling the program.  This string is valid until the program
1028  * is compiled again or the program is freed.
1029  *
1030  * Returns: a character string
1031  */
1032 const char *
orc_program_get_asm_code(OrcProgram * program)1033 orc_program_get_asm_code (OrcProgram *program)
1034 {
1035   return program->asm_code;
1036 }
1037 
1038 /**
1039  * orc_program_get_error:
1040  * @program: a pointer to an OrcProgram structure
1041  *
1042  * Returns a character string containing the error message from
1043  * compilation.  This string is valid until the program
1044  * is compiled again, the program is freed, or another error
1045  * is set.
1046  *
1047  * Returns: a character string
1048  */
1049 const char *
orc_program_get_error(OrcProgram * program)1050 orc_program_get_error (OrcProgram *program)
1051 {
1052   if (program->error_msg) return program->error_msg;
1053   return "";
1054 }
1055 
1056 /**
1057  * orc_program_set_error:
1058  * @program: a pointer to an OrcProgram structure
1059  * @error: an error string
1060  *
1061  * Stores the error in the program. This string is duplicated.
1062  * If an error has already been set, this new error is ignored.
1063  * An error will stay till the next call to _reset, if any.
1064  */
1065 void
orc_program_set_error(OrcProgram * program,const char * error)1066 orc_program_set_error (OrcProgram *program, const char *error)
1067 {
1068   if (!program->error_msg && error) {
1069     program->error_msg = strdup (error);
1070   }
1071 }
1072 
1073 /**
1074  * orc_program_get_max_array_size:
1075  * @program: a pointer to an OrcProgram structure
1076  *
1077  * Returns the size of the largest array used in the program.
1078  *
1079  * Returns: the number of bytes
1080  */
1081 int
orc_program_get_max_array_size(OrcProgram * program)1082 orc_program_get_max_array_size (OrcProgram *program)
1083 {
1084   int i;
1085   int max;
1086 
1087   max = 0;
1088   for(i=0;i<ORC_N_VARIABLES;i++){
1089     if (program->vars[i].size) {
1090       if (program->vars[i].vartype == ORC_VAR_TYPE_SRC ||
1091           program->vars[i].vartype == ORC_VAR_TYPE_DEST) {
1092         max = MAX(max, program->vars[i].size);
1093       }
1094     }
1095   }
1096 
1097   return max;
1098 }
1099 
1100 /**
1101  * orc_program_get_max_accumulator_size:
1102  * @program: a pointer to an OrcProgram structure
1103  *
1104  * Returns the size of the largest array used in the program.
1105  *
1106  * Returns: the number of bytes
1107  */
1108 int
orc_program_get_max_accumulator_size(OrcProgram * program)1109 orc_program_get_max_accumulator_size (OrcProgram *program)
1110 {
1111   int i;
1112   int max;
1113 
1114   max = 0;
1115   for(i=0;i<ORC_N_VARIABLES;i++){
1116     if (program->vars[i].size) {
1117       if (program->vars[i].vartype == ORC_VAR_TYPE_ACCUMULATOR) {
1118         max = MAX(max, program->vars[i].size);
1119       }
1120     }
1121   }
1122 
1123   return max;
1124 }
1125 
1126 int _orc_data_cache_size_level1;
1127 int _orc_data_cache_size_level2;
1128 int _orc_data_cache_size_level3;
1129 int _orc_cpu_family;
1130 int _orc_cpu_model;
1131 int _orc_cpu_stepping;
1132 const char *_orc_cpu_name = "unknown";
1133 
1134 void
orc_get_data_cache_sizes(int * level1,int * level2,int * level3)1135 orc_get_data_cache_sizes (int *level1, int *level2, int *level3)
1136 {
1137   if (level1) {
1138     *level1 = _orc_data_cache_size_level1;
1139   }
1140   if (level2) {
1141     *level2 = _orc_data_cache_size_level2;
1142   }
1143   if (level3) {
1144     *level3 = _orc_data_cache_size_level3;
1145   }
1146 
1147 }
1148 
1149 void
orc_get_cpu_family_model_stepping(int * family,int * model,int * stepping)1150 orc_get_cpu_family_model_stepping (int *family, int *model, int *stepping)
1151 {
1152   if (family) {
1153     *family = _orc_cpu_family;
1154   }
1155   if (model) {
1156     *model = _orc_cpu_model;
1157   }
1158   if (stepping) {
1159     *stepping = _orc_cpu_stepping;
1160   }
1161 }
1162 
1163 const char *
orc_get_cpu_name(void)1164 orc_get_cpu_name (void)
1165 {
1166   return _orc_cpu_name;
1167 }
1168 
1169 void
orc_program_reset(OrcProgram * program)1170 orc_program_reset (OrcProgram *program)
1171 {
1172   if (program->orccode) {
1173     orc_code_free (program->orccode);
1174     program->orccode = NULL;
1175   }
1176   if (program->asm_code) {
1177     free(program->asm_code);
1178     program->asm_code = NULL;
1179   }
1180   if (program->error_msg) {
1181     free(program->error_msg);
1182     program->error_msg = NULL;
1183   }
1184 }
1185 
1186 OrcCode *
orc_program_take_code(OrcProgram * program)1187 orc_program_take_code (OrcProgram *program)
1188 {
1189   OrcCode *code = program->orccode;
1190   program->orccode = NULL;
1191   return code;
1192 }
1193 
1194 int
orc_program_has_float(OrcCompiler * compiler)1195 orc_program_has_float (OrcCompiler *compiler)
1196 {
1197   int j;
1198   for(j=0;j<compiler->n_insns;j++){
1199     OrcInstruction *insn = compiler->insns + j;
1200     OrcStaticOpcode *opcode = insn->opcode;
1201     if (opcode->flags & ORC_STATIC_OPCODE_FLOAT) return TRUE;
1202   }
1203   return FALSE;
1204 }
1205