1 /* cpu.c example cpu-description file */
2 /* (c) in 2013 by Volker Barthelmann */
3 
4 #include "vasm.h"
5 
6 char *cpu_copyright="VideoCore IV cpu backend 0.1 (c) in 2013 Volker Barthelmann";
7 char *cpuname="vidcore";
8 
9 mnemonic mnemonics[]={
10 #include "opcodes.h"
11 };
12 
13 int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
14 
15 int bitsperbyte=8;
16 int bytespertaddr=4;
17 
18 static char *ccs[]={"eq","ne","cs","cc","mi","pl","vs","vc",
19 		    "hi","ls","ge","lt","gt","le","???","f"};
20 
21 static char *vflags[]={"all","none","ifz","ifnz","ifn","ifnn","ifc","ifnc"};
22 
23 static char *accs[]={
24   "???", "sub", "wba", "???", "clra", "???", "???", "???",
25   "sign", "???", "???", "???", "???", "???", "???", "???",
26   "high", "???", "???", "???", "???", "???", "???", "???",
27   "???", "???", "???", "???", "???", "???", "???", "???",
28   "uadd", "usub", "uacc", "udec", "???", "???", "???", "???",
29   "sadd", "ssub", "sacc", "sdec", "???", "???", "???", "???",
30   "uaddh", "usubh", "uacch", "udech", "???", "???", "???", "???",
31   "saddh", "ssubh", "sacch", "sdech", "???", "???", "???", "???"};
32 
33 static char *sru[]={
34   "sumu", "sums", "???", "imin", "???", "imax", "???", "max"};
35 
oplen(int op)36 static size_t oplen(int op)
37 {
38   if(op<=EN_MEMDISP16)
39     return 2;
40   else if(op<=EN_ARITHI32)
41     return 4;
42   else if(op<=EN_VARITHI48)
43     return 6;
44   else if(op<=EN_ADDCMPB64)
45     return 8;
46   else if(op<=EN_VARITHI80)
47     return 10;
48   ierror(0);
49 }
50 
skip_reg(char * s,int * reg)51 static char *skip_reg(char *s,int *reg)
52 {
53   int r=-1;
54   char* orig=s;
55   if(s[0]=='p'&&s[1]=='c'){
56     *reg=31;
57     return s+2;
58   }
59   if(s[0]=='s'&&s[1]=='r'){
60     *reg=30;
61     return s+2;
62   }
63   if(s[0]=='l'&&s[1]=='r'){
64     *reg=26;
65     return s+2;
66   }
67   if(s[0]=='s'&&s[1]=='p'){
68     *reg=25;
69     return s+2;
70   }
71   if(*s!='r'){
72     return s;
73   }
74   s++;
75   if(*s<'0'||*s>'9'){
76     return orig;
77   }
78   r=*s++-'0';
79   if(*s>='0'&&*s<='9')
80     r=10*r+*s++-'0';
81   if(isalnum(*s)||*s=='_'){
82     return orig;
83   }
84   *reg=r;
85   return s;
86 }
87 
parse_operand(char * p,int len,operand * op,int req)88 int parse_operand(char *p,int len,operand *op,int req)
89 {
90   int r;
91   char *s,*start=p;
92 
93   op->type=-1;
94   p=skip(p);
95 
96   if(req>=OP_REG&&req<=OP_LR){
97     int reg;
98     s=skip_reg(p,&r);
99     if(s!=p){
100       if((req==OP_REG&&r<=31)||
101 	 (req==OP_SREG&&r<=15)||
102 	 (req==OP_PC&&r==31)||
103 	 (req==OP_LR&&r==26)||
104 	 (req==OP_MREG&&(r==0||r==6||r==16||r==24))){
105 	op->type=OP_REG;
106 	op->reg=r;
107       }else
108 	return 0;
109     }else
110       return 0;
111     p=skip(s);
112   }else if(req==OP_MREG){
113     int first;
114     s=skip_reg(p,&r);
115     if(s==p)
116       return 0;
117     if(r==0)
118       op->dreg=0;
119     else if(r==6)
120       op->dreg=1;
121     else if(r==16)
122       op->dreg=2;
123     else if(r==24)
124       op->dreg=3;
125     else
126       return 0;
127     s=skip(s);
128     if(*s!='-')
129       return 0;
130     p=skip(s+1);
131     first=r;
132     s=skip_reg(p,&r);
133     if(s==p)
134       return 0;
135     p=skip(s);
136     op->reg=(r-first)&31;
137   }else if(req==OP_IND){
138     p=skip(p);
139     if(*p!='(') return 0;
140     p=skip(p+1);
141     s=skip_reg(p,&r);
142     if(s==p) return 0;
143     if(r>15) return 0;
144     p=skip(s);
145     op->reg=r;
146     if(*p!=')') return 0;
147     p=skip(p+1);
148     op->type=OP_IND;
149   }else if(req==OP_VIND){
150     int nodisp=0;
151     p=skip(p);
152     if(*p=='('){
153       char *m;
154       m=s=skip(p+1);
155       s=skip_reg(s,&r);
156       if((m!=s)||(*s=='0')) nodisp=1;
157     }
158     if(!nodisp){
159       op->offset=parse_expr(&p);
160       if(!op->offset) return 0;
161     }else
162       op->offset=0;
163     if(*p!='(') return 0;
164     p=skip(p+1);
165     s=skip_reg(p,&r);
166     if (s==p){
167       /* Special case: Allow '0' instead of a register */
168       if (*p=='0'){
169 	p=skip(p+1);
170 	op->reg=15;
171       }
172       else return 0;
173     }else{
174       if(r>14) return 0;
175       p=skip(s);
176       op->reg=r;
177     }
178     op->dreg=15;
179     if(*p=='+'&&p[1]=='='){
180       p=skip(p+2);
181       s=skip_reg(p,&r);
182       if(s==p) return 0;
183       if(r>14) return 0;
184       p=skip(s);
185       op->dreg=r;
186     }
187     if(*p!=')') return 0;
188     p=skip(p+1);
189     op->type=OP_IND;
190   }else if(req==OP_PREDEC){
191     p=skip(p);
192     if(p[0]!='-'||p[1]!='-') return 0;
193     p=skip(p+2);
194     if(*p!='(') return 0;
195     p=skip(p+1);
196     s=skip_reg(p,&r);
197     if(s==p) return 0;
198     p=skip(s);
199     if(*p!=')') return 0;
200     p=skip(p+1);
201     op->reg=r;
202     op->type=OP_PREDEC;
203   }else if(req==OP_POSTINC){
204     p=skip(p);
205     if(*p!='(') return 0;
206     p=skip(p+1);
207     s=skip_reg(p,&r);
208     if(s==p) return 0;
209     p=skip(s);
210     if(*p!=')') return 0;
211     p=skip(p+1);
212     if(*p++!='+') return 0;
213     if(*p!='+') return 0;
214     p=skip(p+1);
215     op->reg=r;
216     op->type=OP_POSTINC;
217   }else if(req==OP_REGIND){
218     p=skip(p);
219     if(*p!='(') return 0;
220     p=skip(p+1);
221     s=skip_reg(p,&op->reg);
222     if(s==p) return 0;
223     p=skip(s);
224     if(*p!=',') return 0;
225     p=skip(p+1);
226     s=skip_reg(p,&op->dreg);
227     if(s==p) return 0;
228     p=skip(s);
229     if(*p!=')') return 0;
230     op->type=OP_REGIND;
231     p=skip(p+1);
232   }else if(req==OP_IMMIND||
233 	   req==OP_IMMINDSP||
234 	   req==OP_IMMINDSD||
235 	   req==OP_IMMINDR0||
236 	   req==OP_IMMINDS||
237 	   req==OP_IMMINDPC){
238     op->offset=0;
239     if(*p=='('){
240       char *p2;
241       p2=skip(p+1);
242       s=skip_reg(p2,&r);
243       if(s!=p2){
244 	p=skip(s);
245 	if(*p==')'){
246 	  p=skip(p+1);
247 	  op->offset=number_expr(0);
248 	}
249       }
250     }
251     if(!op->offset){
252       op->offset=parse_expr(&p);
253       if(!op->offset) return 0;
254       p=skip(p);
255       if(*p!='(') return 0;
256       p=skip(p+1);
257       s=skip_reg(p,&r);
258       if(s==p) return 0;
259       p=skip(s);
260       if(*p!=')') return 0;
261     }
262     if(req==OP_IMMINDSP&&r!=25) return 0;
263     if(req==OP_IMMINDPC&&r!=31) return 0;
264     if(req==OP_IMMINDSD&&r!=24) return 0;
265     if(req==OP_IMMINDR0&&r!=0) return 0;
266     if(req==OP_IMMINDS&&r>15) return 0;
267     op->reg=r;
268     op->type=OP_IMMIND;
269     p=skip(p+1);
270   }else if(req>=OP_IMM4&&req<=OP_IMM32&&skip_reg(p,&r)==p){
271     op->type=OP_IMM32;
272     op->offset=parse_expr(&p);
273     simplify_expr(op->offset);
274     p=skip(p);
275   }else if((req==OP_ABS||req==OP_REL)&&skip_reg(p,&r)==p){
276     op->type=req;
277     op->offset=parse_expr(&p);
278     simplify_expr(op->offset);
279     p=skip(p);
280   }else if(req==OP_VREG||req==OP_VREGM||req==OP_VREGMM||req==OP_VREGA80){
281     s=skip_reg(p,&r);
282     op->offset=0;
283     if(s!=p){
284       if (*s=='+'||*s=='-'){
285         if(req==OP_VREG) return 0;
286         op->offset=parse_expr(&s);
287       }
288       p=skip(s);
289       op->type=OP_VREG;
290       if(req==OP_VREG){
291 	op->reg=(0xE<<6)|r;
292 	op->dreg=0x3c;
293       }else{
294 	op->reg=(0xE<<6);
295 	op->dreg=r<<2;
296       }
297     }else if(*p=='-'){
298       p=skip(p+1);
299       op->type=OP_VREG;
300       op->reg=(0xF<<6);
301       op->dreg=0x3c;
302     }else{
303       int size,vert,x,y,inc=15<<2;
304       expr *e;
305       if(*p=='H'||*p=='h')
306 	vert=0;
307       // Disable vertical registers in 48-bit instructions for now
308       else if((req!=OP_VREG)&&(*p=='V'||*p=='v'))
309 	vert=1;
310       else
311 	return 0;
312       p=skip(p+1);
313       if(*p=='X'||*p=='x'){
314 	size=2;
315 	p=skip(p+1);
316       }else if(*p=='1'&&p[1]=='6'){
317 	size=2;
318 	p=skip(p+2);
319       }else if(*p=='Y'||*p=='y'){
320 	size=4;
321 	p=skip(p+1);
322       }else if(*p=='3'&&p[1]=='2'){
323 	size=4;
324 	p=skip(p+2);
325       }else if(*p=='8'){
326 	size=1;
327 	p=skip(p+1);
328       }else{
329 	size=1;
330 	p=skip(p);
331       }
332       if(*p!='(') return 0;
333       p=skip(p+1);
334       e=parse_expr(&p);
335       if(e->type!=NUM) return 0;
336       y=e->c.val;
337       p=skip(p);
338 #if 1
339       if(req!=OP_VREG&&*p=='+'){
340 	p++;
341 	if(*p!='+') return 0;
342 	if(vert) {
343 	  cpu_error(4);
344 	  return 0;
345 	}
346 	p=skip(p+1);
347 	inc|=2;
348       }
349 #endif
350       if(*p!=',') return 0;
351       p=skip(p+1);
352       if((*p=='c')||(*p=='C'))
353       {
354 	p++;
355 	if (*p!='b'&&*p!='B') return 0;
356 	p++;
357 	if (*p!='+') return 0;
358 	inc|=1;
359       }
360       e=parse_expr(&p);
361       if(e->type!=NUM) return 0;
362       x=e->c.val;
363       p=skip(p);
364 #if 1
365       if(req!=OP_VREG&&*p=='+'){
366 	p++;
367 	if(*p!='+') return 0;
368 	if(!vert) {
369 	  cpu_error(4);
370 	  return 0;
371 	}
372 	p=skip(p+1);
373 	inc|=2;
374       }
375 #endif
376       if(*p!=')') return 0;
377       p=skip(p+1);
378       if(req!=OP_VREG&&*p=='*'){
379 	p=skip(p+1);
380 	inc|=1;
381       }
382       if(req!=OP_VREG&&*p=='+'){
383 	p=skip(p+1);
384 	s=skip_reg(p,&r);
385 	if(s==p) return 0;
386 	p=skip(s);
387 	inc&=~0x3c;
388 	inc|=(r<<2);
389       }
390       if(req==OP_VREGA80){
391 	if(size==1){
392 	  op->reg=(vert<<6)|((x&48)<<3);
393 	}else if(size==2){
394 	  if(x&16) return 0;
395 	  op->reg=(vert<<6)|(8<<6)|((x&32)<<2);
396 	}else{
397 	  if(x&48) return 0;
398 	  op->reg=(vert<<6)|(12<<6);
399 	}
400 	if(y<0||y>63) return 0;
401 	op->reg|=y&63;
402 	inc|=(x&15)<<6;
403       }else{
404 	if(vert){
405 	  if(size==1){
406 	    op->reg=(1<<6)|((x&48)<<3);
407 	  }else if(size==2){
408 	    if(x&16) return 0;
409 	    op->reg=(9<<6)|((x&32)<<2);
410 	  }else{
411 	    if(x&48) return 0;
412 	    op->reg=13<<6;
413 	  }
414 	  if(y<0||y>63||(y&15)) return 0;
415 	  op->reg|=(y&48)|(x&15);
416 	}
417 	else{
418 	  if(size==1){
419 	    if(x&15) return 0;
420 	    op->reg=(x&48)<<3;
421 	  }else if(size==2){
422 	    if(x&31) return 0;
423 	    op->reg=(8<<6)|((x&32)<<2);
424 	  }else{
425 	    if(x) return 0;
426 	    op->reg=12<<6;
427 	  }
428 	if(y<0||y>63) return 0;
429 	op->reg|=y&63;
430 	}
431       }
432       op->dreg=inc;
433       op->type=OP_VREG;
434     }
435   }else
436     return 0;
437 
438   if(req==OP_VREGMM||req==OP_IMM32M||req==OP_VIND){
439     int vecmod=0,i;
440     while(1){
441       if(!strncasecmp(p,"rep",3)&&isspace((unsigned char)p[3])){
442 	expr *e;
443 	taddr x;
444 	p=skip(p+3);
445 	if((*p=='r')&&(p[1]=='0')&&!isdigit(p[2])){
446 	  p=skip(p+2);
447 	  vecmod|=7<<16;
448 	  i=0;
449 	}else{
450 	  e=parse_expr(&p);
451 	  if(e->type!=NUM) return 0;
452 	  x=e->c.val;
453 	  for(i=0;i<8;i++){
454 	    if((1<<i)==x){
455 	      vecmod|=i<<16;
456 	      break;
457 	    }
458 	  }
459 	}
460 	if(i>=8) return 0;
461 	p=skip(p);
462 	continue;
463       }
464       for(i=0;i<sizeof(vflags)/sizeof(vflags[0]);i++){
465 	if((!strncasecmp(p,vflags[i],strlen(vflags[i])))&&
466 	   (!isalpha(p[strlen(vflags[i])]))){
467 	  if(vecmod&0x380) return 0;
468 	  vecmod|=i<<7;
469 	  p=skip(p+strlen(vflags[i]));
470 	  continue;
471 	}
472       }
473       for (i=0;i<sizeof(sru)/sizeof(sru[0]);i++){
474 	if(!strncasecmp(p,sru[i],strlen(sru[i]))){
475 	  p=skip(p+strlen(sru[i]));
476 	  p=skip_reg(p,&r);
477 	  if((r<0)||(r>7)) return 0;
478 	  vecmod|=(1<<6)|(i<<3)|r;
479 	  continue;
480 	}
481       }
482       for (i=0;i<sizeof(accs)/sizeof(accs[0]);i++){
483 	if((!strncasecmp(p,accs[i],strlen(accs[i])))&&
484 	   (!isalpha(p[strlen(accs[i])]))){
485 	  if(vecmod&0x40) return 0;
486 	  vecmod|=i;
487 	  p=skip(p+strlen(accs[i]));
488 	  continue;
489 	}
490       }
491       if(!strncasecmp(p,"ena",3)){
492 	if(vecmod&0x40) return 0;
493 	p=skip(p+3);
494 	vecmod|=32;
495       }
496       if(!strncasecmp(p,"setf",4)){
497 	p=skip(p+4);
498 	vecmod|=1<<20;
499 	continue;
500       }
501       break;
502     }
503 
504     op->vecmod=vecmod;
505   }
506 
507   if(p>=start+len)
508     return 1;
509   else
510     return 0;
511 }
512 
dooffset(int rel,expr * tree,section * sec,taddr pc,rlist ** relocs,int roffset,int size,taddr mask)513 static taddr dooffset(int rel,expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
514 {
515   taddr val;
516   if(!eval_expr(tree,&val,sec,pc)){
517     taddr addend=val;
518     symbol *base;
519     if(find_base(tree,&base,sec,pc)!=BASE_OK){
520       general_error(38);
521       return val;
522     }
523     if(rel==REL_PC){
524       val-=pc;
525       addend+=roffset/8;
526     }
527     if(rel!=REL_PC||!LOCREF(base)||base->sec!=sec){
528       add_nreloc_masked(relocs,base,addend,rel,size,roffset,mask);
529       return 0;
530     }
531   }
532 #if 0
533   if(val<-(1<<(size-1))||val>((1<<(size-1))-1))
534     cpu_error(1,size);
535 #endif
536   return val&mask;
537 }
538 
reloffset(expr * tree,section * sec,taddr pc,rlist ** relocs,int roffset,int size,taddr mask)539 static taddr reloffset(expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
540 {
541   /* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
542   return dooffset(REL_PC,tree,sec,pc,relocs,roffset,size,mask);
543 }
544 
absoffset(expr * tree,section * sec,taddr pc,rlist ** relocs,int roffset,int size)545 static taddr absoffset(expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size)
546 {
547   /* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
548   return dooffset(REL_ABS,tree,sec,pc,relocs,roffset,size,0xffffffff);
549 }
550 
absval(expr * tree,section * sec,taddr pc,int bits,int sgn)551 static taddr absval(expr *tree,section *sec,taddr pc,int bits,int sgn)
552 {
553   taddr val;
554   if(!eval_expr(tree,&val,sec,pc))
555     cpu_error(0);
556   if(!sgn){
557     if(val<0||val>=(1<<bits))
558       cpu_error(1,bits);
559   }else{
560     if(val<-(1<<(bits-1))||val>=(1<<(bits-1)))
561       cpu_error(1,bits);
562   }
563   return val&((1<<bits)-1);
564 }
565 
chkval(expr * tree,section * sec,taddr pc,int bits,int sgn)566 static int chkval(expr *tree,section *sec,taddr pc,int bits,int sgn)
567 {
568   taddr val;
569   if(!eval_expr(tree,&val,sec,pc))
570     cpu_error(0);
571   if(!sgn){
572     if(val<0||val>=(1<<bits))
573       return 0;
574   }else{
575     if(val<-(1<<(bits-1))||val>=(1<<(bits-1)))
576       return 0;
577   }
578   return 1;
579 }
580 
581 /* replace instruction by one with encoding enc */
replace(int c,int enc)582 static int replace(int c,int enc)
583 {
584   int i=c+1;
585   while(!strcmp(mnemonics[c].name,mnemonics[i].name)){
586     if(mnemonics[i].ext.encoding==enc){
587       c=i;
588       break;
589     }
590     i++;
591   }
592   if(c!=i) ierror(0);
593   return c;
594 }
translate(instruction * p,section * sec,taddr pc)595 static int translate(instruction *p,section *sec,taddr pc)
596 {
597   int c=p->code,e=mnemonics[c].ext.encoding;
598   taddr val;
599 
600   if(p->qualifiers[0]){
601     /* extend to larger variants if ccs are required */
602     if(e==EN_MEMDISP16)
603       c=replace(c,EN_MEMDISP32);
604     if(e==EN_ARITHR16)
605       c=replace(c,EN_ARITHR32);
606     if(e==EN_ARITHI16)
607       c=replace(c,EN_ARITHI32);
608   }
609   if(e==EN_ARITHI32){
610     if(p->op[2]){
611       if(!chkval(p->op[2]->offset,sec,pc,6,1)&&(!strcmp("add",mnemonics[c].name)||!strcmp("sub",mnemonics[c].name)))
612 	c=replace(c,EN_ADD48);
613     }else{
614       if((mnemonics[c].ext.code<32)&&(!chkval(p->op[1]->offset,sec,pc,6,1)))
615 	c=replace(c,EN_ARITHI48);
616     }
617   }
618   if(e==EN_ARITHI16){
619     if(!chkval(p->op[1]->offset,sec,pc,5,0))
620       c=replace(c,EN_ARITHI48);
621   }
622   if(e==EN_RBRANCH16){
623     symbol *base;
624     if(find_base(p->op[0]->offset,&base,sec,pc)!=BASE_OK||!LOCREF(base)||base->sec!=sec)
625       c=replace(c,EN_RBRANCH32);
626     else{
627       int i;
628       i=eval_expr(p->op[0]->offset,&val,sec,pc);
629       val-=pc;
630       if(val>126||val<-128)
631 	c=replace(c,EN_RBRANCH32);
632     }
633   }
634   if(e==EN_ADDCMPB32){
635     int i;
636     i=eval_expr(p->op[3]->offset,&val,sec,pc);
637     val-=pc;
638     if(val>1022||val<-1024)
639       c+=4;
640     else if(p->op[2]->type!=OP_REG&&(val>254||val<-256))
641       c+=4;
642   }
643   if((e==EN_MEMDISP16||e==EN_MEMDISP32||e==EN_MEM12DISP32||e==EN_MEM16DISP32)){
644     if(!eval_expr(p->op[1]->offset,&val,sec,pc)){
645       c=replace(c,EN_MEM48);
646     }else{
647       if(e==EN_MEMDISP16&&(val<0||val>54||(val&3))){
648 	if(val<=4095&&val>=-4096)
649 	  c=replace(c,EN_MEM12DISP32);
650 	else
651 	  c=replace(c,EN_MEM48);
652       }
653     }
654   }
655   /* todo */
656   return c;
657 }
658 
659 /* Convert an instruction into a DATA atom including relocations,
660    if necessary. */
eval_instruction(instruction * p,section * sec,taddr pc)661 dblock *eval_instruction(instruction *p,section *sec,taddr pc)
662 {
663   dblock *db=new_dblock();
664   int c,sz,enc,cc,ww,m=0;
665   unsigned long code,code2,code3;
666   rlist *relocs=0;
667 
668   if(p->qualifiers[0]){
669     int i;
670     for(i=0;i<15;i++){
671       if(!strcmp(p->qualifiers[0],ccs[i])){
672 	cc=i;
673 	break;
674       }
675     }
676     if(i>15) ierror(0);
677   }else
678     cc=14;
679 
680   c=translate(p,sec,pc);
681   enc=mnemonics[c].ext.encoding;
682 
683   db->size=sz=oplen(enc);
684   db->data=mymalloc(db->size);
685 
686   code=mnemonics[c].ext.code;
687 
688   switch(enc){
689   case EN_ARITHR16:
690     if(cc!=14) cpu_error(3);
691     code=0x40000000|(code<<24);
692     code|=(p->op[0]->reg<<16)|(p->op[1]->reg<<20);
693     break;
694   case EN_ARITHI16:
695     if(cc!=14) cpu_error(3);
696     code=0x60000000|((code>>1)<<25);
697     code|=(p->op[0]->reg<<16)|(absval(p->op[1]->offset,sec,pc,5,0)<<20);
698     break;
699   case EN_FIX16:
700     if(cc!=14) cpu_error(3);
701     break;
702   case EN_IBRANCH16:
703     if(cc!=14) cpu_error(3);
704     code|=(p->op[0]->reg<<16);
705     break;
706   case EN_RBRANCH16:
707     code=0x18000000;
708     code|=cc<<23;
709     code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe)>>1)&127)<<16;
710     break;
711   case EN_MREG16:
712     if(cc!=14) cpu_error(3);
713     code|=(p->op[0]->dreg<<21)|(p->op[0]->reg<<16);
714     break;
715   case EN_RBRANCH32:
716     if(code==0x90000000)
717       code|=cc<<24;
718     else
719       code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,8,4,0xF000000)>>24)&0xf)<<24;
720     code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,16,16,0x1fffe)>>1)&0x7fffff);
721     code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe0000)>>17)&0x7f)<<16;
722     break;
723   case EN_FUNARY32:
724     code=0xC0000040|(code<<21);
725     code|=p->op[0]->reg<<16;
726     code|=p->op[1]->reg<<11;
727     code|=cc<<7;
728     break;
729   case EN_ARITHR32:
730     code=0xC0000000|(code<<21);
731     code|=p->op[0]->reg<<16;
732     if(p->op[2]){
733       code|=p->op[1]->reg<<11;
734       code|=p->op[2]->reg;
735     }else{
736       code|=p->op[0]->reg<<11;
737       code|=p->op[1]->reg;
738     }
739     code|=cc<<7;
740     break;
741   case EN_ARITHI32:
742     code=0xC0000040|(code<<21);
743     code|=p->op[0]->reg<<16;
744     if(p->op[2]){
745       code|=p->op[1]->reg<<11;
746       code|=absval(p->op[2]->offset,sec,pc,6,1);
747     }else{
748       code|=p->op[0]->reg<<11;
749       code|=absval(p->op[1]->offset,sec,pc,6,1);
750     }
751     code|=cc<<7;
752     break;
753   case EN_ADDCMPB64:
754     // Large offset: invert CC, place a long branch after
755     // so we really generate the following:
756     //   addcmpb<~cc> d, a, b, skip
757     //   b <destination>
758     // skip:
759     //   <rest of code>
760     m=1;
761     if(cc&1) cc--; else cc++;
762   case EN_ADDCMPB32:
763     code=0x80000000|(code<<14);
764     code|=cc<<24;
765     code|=p->op[0]->reg<<16;
766     if(code&0x4000){
767       code|=absval(p->op[1]->offset,sec,pc,4,1)<<20;
768     }else{
769       code|=p->op[1]->reg<<20;
770     }
771     if(code&0x8000){
772       code|=absval(p->op[2]->offset,sec,pc,6,0)<<8;
773       if(m)
774 	code|=4;
775       else
776 	code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,9,0x1ff)>>1)&0xff);
777     }else{
778       code|=p->op[2]->reg<<10;
779       if(m)
780 	code|=4;
781       else
782 	code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,11,0x7ff)>>1)&0x3ff);
783     }
784     if(m){
785       code2=0x90000000|(14<<24);
786       code2|=((reloffset(p->op[3]->offset,sec,pc+4,&relocs,48,16,0x1fffe)>>1)&0x7fffff);
787       code2|=((reloffset(p->op[3]->offset,sec,pc+4,&relocs,32,7,0xfe0000)>>17)&0x7f)<<16;
788     }
789     break;
790   case EN_ARITHI48:
791     if(cc!=14) cpu_error(3);
792     code=0xE8000000|(code<<21);
793     code|=p->op[0]->reg<<16;
794     code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,32);
795     break;
796   case EN_ADD48:
797     if(cc!=14) cpu_error(3);
798     if(p->op[2])
799       code2=absoffset(p->op[2]->offset,sec,pc,&relocs,16,32);
800     else
801       code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,32);
802     /* pseudo sub */
803     if(code==6)
804       code2=-code2;
805     code=0xEC000000;
806     code|=p->op[0]->reg<<16;
807     if(p->op[2])
808       code|=p->op[1]->reg<<21;
809     else
810       code|=p->op[0]->reg<<21;
811     break;
812   case EN_MEMREG16:
813     if(cc!=14) cpu_error(3);
814     code=0x08000000|(code<<24);
815     code|=p->op[0]->reg<<16;
816     code|=p->op[1]->reg<<20;
817     ww=0; /*FIXME*/
818     code|=ww<<25;
819     break;
820   case EN_MEMSTACK16:
821     if(cc!=14) cpu_error(3);
822     code=0x04000000|(code<<25);
823     code|=p->op[0]->reg<<16;
824     code|=(absval(p->op[1]->offset,sec,pc,7,1)>>2)<<20;
825     break;
826   case EN_MEMDISP16:
827     if(cc!=14) cpu_error(3);
828     code=0x20000000|(code<<28);
829     code|=p->op[0]->reg<<16;
830     code|=(absval(p->op[1]->offset,sec,pc,6,0)>>2)<<24;
831     code|=p->op[1]->reg<<20;
832     break;
833   case EN_LEA16:
834     if(cc!=14) cpu_error(3);
835     code=0x10000000;
836     code|=p->op[0]->reg<<16;
837     code|=(absval(p->op[1]->offset,sec,pc,8,1)>>2)<<21;
838     break;
839   case EN_LEA48:
840     if(cc!=14) cpu_error(3);
841     code=0xE5000000|(p->op[0]->reg<<16);
842     code2=reloffset(p->op[1]->offset,sec,pc,&relocs,16,32,0xffffffff);
843     break;
844   case EN_MEM48:
845     if(cc!=14) cpu_error(3);
846     code=0xE6000000|(code<<21);
847     code|=p->op[0]->reg<<16;
848     if(p->op[1]->reg==31)
849       code2=reloffset(p->op[1]->offset,sec,pc,&relocs,16,27,0xffffffff)&0x7ffffff;
850     else
851       /* TODO: other relocs */
852       code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,27)&0x7ffffff;
853     code2|=p->op[1]->reg<<27;
854     break;
855   case EN_MEMREG32:
856     code=0xA0000000|(code<<21);
857     code|=p->op[0]->reg<<16;
858     code|=p->op[1]->reg<<11;
859     code|=p->op[1]->dreg;
860     code|=cc<<7;
861     break;
862   case EN_MEMDISP32:
863     code=0xA0000040|(code<<21);
864     code|=p->op[0]->reg<<16;
865     code|=p->op[1]->reg<<11;
866     code|=absval(p->op[1]->offset,sec,pc,5,1);
867     code|=cc<<7;
868     break;
869   case EN_MEMPREDEC:
870   case EN_MEMPOSTINC:
871     code<<=21;
872     if(p->op[1]->type==OP_POSTINC)
873       code|=0xA5000000;
874     else
875       code|=0xA4000000;
876     code|=p->op[0]->reg<<16;
877     code|=p->op[1]->reg<<11;
878     code|=cc<<7;
879     break;
880   case EN_MEM12DISP32:
881     if(cc!=14) cpu_error(3);
882     code=0xA2000000|(code<<21);
883     code|=p->op[0]->reg<<16;
884     code|=p->op[1]->reg<<11;
885     code|=absval(p->op[1]->offset,sec,pc,12,1)&0x7ff;
886     code|=(absval(p->op[1]->offset,sec,pc,12,1)&0x800)<<13;
887     break;
888   case EN_MEM16DISP32:
889     if(cc!=14) cpu_error(3);
890     code|=p->op[0]->reg<<16;
891     if((code&0xff000000)==0xaa000000)
892       code|=reloffset(p->op[1]->offset,sec,pc,&relocs,16,16,0xffff)&0xffff;
893     else
894       code|=absval(p->op[1]->offset,sec,pc,16,1);
895     break;
896   case EN_VLOAD48:
897     code=0xF0000000|(code<<19);
898     code2=(p->op[0]->reg<<22)|(7<<7)|p->op[1]->reg;
899     break;
900   case EN_VSTORE48:
901     code=0xF0000000|(code<<19);
902     code2=(p->op[0]->reg<<12)|(7<<7)|p->op[1]->reg;
903     break;
904   case EN_VREAD48:
905     code=0xF0000000|(code<<19);
906     code2=(p->op[0]->reg<<22)|p->op[1]->reg;
907     break;
908   case EN_VWRITE48:
909     code=0xF0000000|(code<<19);
910     code2=(p->op[0]->reg<<12)|p->op[1]->reg;
911     break;
912   case EN_VREADI48:
913     code=0xF0000000|(code<<19);
914     code2=(p->op[0]->reg<<22)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
915     break;
916   case EN_VWRITEI48:
917     code=0xF0000000|(code<<19);
918     code2=(p->op[0]->reg<<12)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
919     break;
920   case EN_VARITHR48:
921     if(code<48) code|=64;
922     code=0xF4000000|(code<<19);
923     if(p->op[2]){
924       code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|p->op[2]->reg;
925     }else{
926       code2=(p->op[0]->reg<<22)|p->op[1]->reg;
927     }
928     break;
929   case EN_VARITHI48:
930     if(code<48) code|=64;
931     code=0xF4000000|(code<<19);
932     if(p->op[2]){
933       code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|absval(p->op[2]->offset,sec,pc,6,0)|(1<<10);
934     }else{
935       code2=(p->op[0]->reg<<22)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
936     }
937     break;
938   // TODO: Check these!
939   case EN_VLOAD80:
940     code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
941     code2=(p->op[0]->reg<<22);
942     code3=(p->op[1]->reg<<2)|(p->op[0]->dreg<<26)|((p->op[1]->dreg)<<22);
943     if(p->op[1]->offset){
944       code2|=(absval(p->op[1]->offset,sec,pc,16,1)&0x7f);
945       code3|=(absval(p->op[1]->offset,sec,pc,16,1)>>7)&3;
946       code3|=((absval(p->op[1]->offset,sec,pc,16,1)>>9)&0x7f)<<6;
947     }
948     break;
949   case EN_VSTORE80:
950     code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
951     code2=(p->op[0]->reg<<12);
952     code3=(p->op[1]->reg<<2)|(p->op[0]->dreg<<20)|((p->op[1]->dreg)<<28);
953     if(p->op[1]->offset){
954       code2|=(absval(p->op[1]->offset,sec,pc,16,1)&0x7f);
955       code3|=(absval(p->op[1]->offset,sec,pc,16,1)>>7)&3;
956       code3|=((absval(p->op[1]->offset,sec,pc,16,1)>>9)&0x7f)<<6;
957     }
958     break;
959   case EN_VREAD80:
960     if(p->op[1]->offset){
961       p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
962       p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
963     }
964     code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
965     code2=(p->op[0]->reg<<22)|(p->op[1]->reg);
966     if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
967     code3=(p->op[0]->dreg<<26)|(p->op[1]->dreg);
968     code3|=(p->op[1]->vecmod&0x3fff)<<6;
969     break;
970   case EN_VWRITE80:
971     if(p->op[1]->offset){
972       p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
973       p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
974     }
975     code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
976     code2=(p->op[0]->reg<<12)|(p->op[1]->reg);
977     if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
978     code3=((p->op[0]->dreg&0x3f)<<20)|((p->op[0]->dreg&0x3c0)<<10)|(p->op[1]->dreg);
979     code3|=(p->op[1]->vecmod&0x3fff)<<6;
980     break;
981   case EN_VREADI80:
982     if(p->op[1]->offset){
983       p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
984       p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
985     }
986     code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
987     if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
988     code2=(p->op[0]->reg<<22)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
989     code3=(p->op[0]->dreg<<26)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
990     code3|=(p->op[1]->vecmod&0x3fff)<<6;
991     break;
992   case EN_VWRITEI80:
993     if(p->op[1]->offset){
994       p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
995       p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
996     }
997     code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
998     if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
999     code2=(p->op[0]->reg<<12)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
1000     code3=((p->op[0]->dreg&0x3f)<<20)|((p->op[0]->dreg&0x3c0)<<10)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
1001     code3|=(p->op[1]->vecmod&0x3fff)<<6;
1002     break;
1003   case EN_VARITHR80:
1004     if(code<48) code|=64;
1005     if(p->op[2]){
1006       if(p->op[2]->offset){
1007 	p->op[2]->reg|=(absval(p->op[2]->offset,sec,pc,9,1)&0x7f);
1008 	p->op[2]->dreg|=(absval(p->op[2]->offset,sec,pc,9,1)>>7)&3;
1009       }
1010       code=0xFC000000|(code<<19)|(p->op[2]->vecmod&0x70000);
1011       code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|(p->op[2]->reg);
1012       if(p->op[2]->vecmod&(1<<20)) code2|=(1<<11);
1013       code3=(p->op[0]->dreg<<26)|((p->op[1]->dreg&0x3f)<<20)|((p->op[1]->dreg&0x3c0)<<10)|(p->op[2]->dreg);
1014       code3|=(p->op[2]->vecmod&0x3fff)<<6;
1015     }else{
1016       if(p->op[1]->offset){
1017 	p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
1018 	p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
1019       }
1020       code=0xFC000000|(code<<19)|(p->op[1]->vecmod&0x70000);
1021       code2=(p->op[0]->reg<<22)|(p->op[1]->reg);
1022       if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
1023       code3=(p->op[0]->dreg<<26)|(p->op[1]->dreg);
1024       code3|=(p->op[1]->vecmod&0x3fff)<<6;
1025     }
1026     break;
1027   case EN_VARITHI80:
1028     if(code<48) code|=64;
1029     if(p->op[2]){
1030       if(p->op[2]->offset){
1031 	p->op[2]->reg|=(absval(p->op[2]->offset,sec,pc,9,1)&0x7f);
1032 	p->op[2]->dreg|=(absval(p->op[2]->offset,sec,pc,9,1)>>7);
1033       }
1034       code=0xFC000000|(code<<19)|(p->op[2]->vecmod&0x70000);
1035       if(p->op[2]->vecmod&(1<<20)) code2|=(1<<11);
1036       code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|(1<<10)|(absval(p->op[2]->offset,sec,pc,16,0)&0x3ff);
1037       code3=(p->op[0]->dreg<<26)|((p->op[1]->dreg&0x3f)<<20)|((p->op[1]->dreg&0x3c0)<<10)|((absval(p->op[2]->offset,sec,pc,16,0)>>10)&0x3f);
1038       code3|=(p->op[2]->vecmod&0x3fff)<<6;
1039     }else{
1040       if(p->op[1]->offset){
1041 	p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
1042 	p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7);
1043       }
1044       code=0xFC000000|(code<<19)|(p->op[1]->vecmod&0x70000);
1045       if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
1046       code2=(p->op[0]->reg<<22)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
1047       code3=(p->op[0]->dreg<<26)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
1048       code3|=(p->op[1]->vecmod&0x3fff)<<6;
1049     }
1050     break;
1051   default:
1052     ierror(0);
1053   }
1054 
1055   if(enc>=EN_VLOAD48&&enc<=EN_VARITHI48){
1056     db->data[0]=(code>>16)&0xff;
1057     db->data[1]=(code>>24)&0xff;
1058     db->data[3]=(code2>>24)&0xff;
1059     db->data[2]=(code2>>16)&0xff;
1060     db->data[5]=(code2>>8)&0xff;
1061     db->data[4]=(code2>>0)&0xff;
1062   }else if(sz==2){
1063     db->data[0]=(code>>16)&0xff;
1064     db->data[1]=(code>>24)&0xff;
1065   }else if(sz==4){
1066     db->data[1]=(code>>24)&0xff;
1067     db->data[0]=(code>>16)&0xff;
1068     db->data[3]=(code>>8)&0xff;
1069     db->data[2]=(code)&0xff;
1070   }else if(sz==6){
1071     db->data[0]=(code>>16)&0xff;
1072     db->data[1]=(code>>24)&0xff;
1073     db->data[5]=(code2>>24)&0xff;
1074     db->data[4]=(code2>>16)&0xff;
1075     db->data[3]=(code2>>8)&0xff;
1076     db->data[2]=(code2>>0)&0xff;
1077   }
1078   else if(sz==8){
1079     db->data[1]=(code>>24)&0xff;
1080     db->data[0]=(code>>16)&0xff;
1081     db->data[3]=(code>>8)&0xff;
1082     db->data[2]=(code)&0xff;
1083     db->data[5]=(code2>>24)&0xff;
1084     db->data[4]=(code2>>16)&0xff;
1085     db->data[7]=(code2>>8)&0xff;
1086     db->data[6]=(code2)&0xff;
1087   }else if(sz==10){
1088     db->data[0]=(code>>16)&0xff;
1089     db->data[1]=(code>>24)&0xff;
1090     db->data[3]=(code2>>24)&0xff;
1091     db->data[2]=(code2>>16)&0xff;
1092     db->data[5]=(code2>>8)&0xff;
1093     db->data[4]=(code2>>0)&0xff;
1094     db->data[7]=(code3>>24)&0xff;
1095     db->data[6]=(code3>>16)&0xff;
1096     db->data[9]=(code3>>8)&0xff;
1097     db->data[8]=(code3>>0)&0xff;
1098   }
1099   db->relocs=relocs;
1100   return db;
1101 }
1102 
1103 /* Create a dblock (with relocs, if necessary) for size bits of data. */
eval_data(operand * op,size_t bitsize,section * sec,taddr pc)1104 dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
1105 {
1106   dblock *new=new_dblock();
1107   taddr val;
1108   new->size=(bitsize+7)/8;
1109   new->data=mymalloc(new->size);
1110   if(op->type!=OP_ABS)
1111     ierror(0);
1112   if(bitsize!=8&&bitsize!=16&&bitsize!=32)
1113     cpu_error(2);
1114   val=absoffset(op->offset,sec,pc,&new->relocs,0,bitsize);
1115   if(bitsize==32){
1116     new->data[3]=val>>24;
1117     new->data[2]=val>>16;
1118     new->data[1]=val>>8;
1119     new->data[0]=val;
1120   }else if(bitsize==16){
1121     new->data[1]=val>>8;
1122     new->data[0]=val;
1123   }else
1124     new->data[0]=val;
1125   return new;
1126 }
1127 
1128 
1129 /* Calculate the size of the current instruction; must be identical
1130    to the data created by eval_instruction. */
instruction_size(instruction * p,section * sec,taddr pc)1131 size_t instruction_size(instruction *p,section *sec,taddr pc)
1132 {
1133   int c;
1134   c=translate(p,sec,pc);
1135   return oplen(mnemonics[c].ext.encoding);
1136 }
1137 
new_operand()1138 operand *new_operand()
1139 {
1140   operand *new=mymalloc(sizeof(*new));
1141   new->type=-1;
1142   return new;
1143 }
1144 
1145 /* return true, if initialization was successfull */
init_cpu()1146 int init_cpu()
1147 {
1148   return 1;
1149 }
1150 
1151 /* return true, if the passed argument is understood */
cpu_args(char * p)1152 int cpu_args(char *p)
1153 {
1154   return 0;
1155 }
1156 
1157 /* parse cpu-specific directives; return pointer to end of
1158    cpu-specific text */
parse_cpu_special(char * s)1159 char *parse_cpu_special(char *s)
1160 {
1161   char *name=s,*merk=s;
1162 
1163   return merk;
1164 }
1165 
set_default_qualifiers(char ** q,int * q_len)1166 int set_default_qualifiers(char **q,int *q_len)
1167 /* fill in pointers to default qualifiers, return number of qualifiers */
1168 {
1169   q[0]="u32";
1170   q_len[0]=3;
1171   q[1]="";
1172   q_len[1]=0;
1173   return 2;
1174 }
1175 
parse_instruction(char * s,int * inst_len,char ** ext,int * ext_len,int * ext_cnt)1176 char *parse_instruction(char *s,int *inst_len,char **ext,int *ext_len,
1177                         int *ext_cnt)
1178 /* parse instruction and save extension locations */
1179 {
1180   char *inst = s, l, i;
1181   int cnt = 0;
1182 
1183   while (*s && *s!='.' && !isspace((unsigned char)*s))
1184     s++;
1185   l = s - inst;
1186 
1187   if(strncasecmp("divs",inst,l)&&strncmp("vreadacc",inst,l)&&
1188      strncasecmp("vcmpge",inst,l)){
1189     for(i=0;i<16;i++){
1190       int cl=strlen(ccs[i]);
1191       if(l>cl&&!strncasecmp(s-cl,ccs[i],cl)){
1192 	ext[0]=s-cl;
1193 	ext_len[0]=cl;
1194 	cnt=1;
1195 	l-=cl;
1196 	break;
1197       }
1198     }
1199   }
1200 
1201   *ext_cnt = cnt;
1202 
1203   *inst_len=l;
1204 
1205   return s;
1206 }
1207