1 /* cpu.c example cpu-description file */
2 /* (c) in 2002 by Volker Barthelmann */
3 
4 #include "vasm.h"
5 
6 char *cpu_copyright="vasm c16x/st10 cpu backend 0.2c (c) in 2002-2005 Volker Barthelmann";
7 char *cpuname="c16x";
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 int JMPA,JMPR,JMPS,JNB,JB,JBC,JNBS,JMP;
19 static int notrans,tojmpa;
20 
21 #define JMPCONV 256
22 #define INVCC(c) (((c)&1)?(c)-1:(c)+1)
23 
24 #define ISBIT 1
25 
26 typedef struct sfr {
27   struct sfr *next;
28   int flags;
29   unsigned int laddr,saddr,boffset;
30 } sfr;
31 
32 
33 sfr *first_sfr;
34 #define SFRHTSIZE 1024
35 hashtable *sfrhash;
36 
skip_reg(char * s,int * reg)37 static char *skip_reg(char *s,int *reg)
38 {
39   int r=-1;
40   if(*s!='r'&&*s!='R'){
41     cpu_error(1);
42     return s;
43   }
44   s++;
45   if(*s<'0'||*s>'9'){
46     cpu_error(1);
47     return s;
48   }
49   r=*s++-'0';
50   if(*s>='0'&&*s<='5')
51     r=10*r+*s++-'0';
52   *reg=r;
53   return s;
54 }
55 
parse_operand(char * p,int len,operand * op,int requires)56 int parse_operand(char *p,int len,operand *op,int requires)
57 {
58   op->type=-1;
59   op->mod=-1;
60   p=skip(p);
61   if(requires==OP_REL){
62     char *s=p;
63     op->type=OP_REL;
64     op->offset=parse_expr(&s);
65     simplify_expr(op->offset);
66     if(s==p)
67       return 0;
68     else
69       return 1;
70   }
71   if(requires==OP_CC){
72     op->type=OP_CC;
73     if(len<4||len>6||p[0]!='c'||p[1]!='c'||p[2]!='_')
74       return 0;
75     if(len==4){
76       if(p[3]=='z')
77 	op->cc=2;
78       else if(p[3]=='v')
79 	op->cc=4;
80       else if(p[3]=='n')
81 	op->cc=6;
82       else if(p[3]=='c')
83 	op->cc=8;
84       else
85 	return 0;
86     }else if(len==5){
87       if(p[3]=='u'&&p[4]=='c')
88 	op->cc=0;
89       else if(p[3]=='n'&&p[4]=='z')
90 	op->cc=3;
91       else if(p[3]=='n'&&p[4]=='v')
92 	op->cc=5;
93       else if(p[3]=='n'&&p[4]=='n')
94 	op->cc=7;
95       else if(p[3]=='n'&&p[4]=='c')
96 	op->cc=0;
97       else if(p[3]=='e'&&p[4]=='q')
98 	op->cc=2;
99       else if(p[3]=='n'&&p[4]=='e')
100 	op->cc=3;
101       else
102 	return 0;
103     }else if(len==6){
104       if(!strncmp(p+3,"ult",3))
105 	op->cc=8;
106       else if(!strncmp(p+3,"ule",3))
107 	op->cc=0xf;
108       else if(!strncmp(p+3,"uge",3))
109 	op->cc=0x9;
110       else if(!strncmp(p+3,"ugt",3))
111 	op->cc=0xe;
112       else if(!strncmp(p+3,"slt",3))
113 	op->cc=0xc;
114       else if(!strncmp(p+3,"sle",3))
115 	op->cc=0xb;
116       else if(!strncmp(p+3,"sge",3))
117 	op->cc=0xd;
118       else if(!strncmp(p+3,"sgt",3))
119 	op->cc=0xa;
120       else if(!strncmp(p+3,"net",3))
121 	op->cc=0x1;
122       else
123 	return 0;
124     }
125     return 1;
126   }
127   if((p[0]=='r'||p[0]=='R')&&p[1]>='0'&&p[1]<='9'&&(len==2||p[2]=='.')){
128     op->type=OP_GPR;
129     op->reg=p[1]-'0';
130     op->regsfr=op->reg+0xf0;
131     if(len>2){
132       op->type=OP_BADDR;
133       if(requires==OP_BADDR){
134 	p=skip(p+3);
135 	op->boffset=parse_expr(&p);
136 	op->offset=number_expr(op->regsfr);
137       }
138     }
139   }else if((p[0]=='r'||p[0]=='R')&&p[1]=='1'&&p[2]>='0'&&p[2]<='5'&&(len==3||p[3]=='.')){
140     op->type=OP_GPR;
141     op->reg=(p[1]-'0')*10+p[2]-'0';
142     op->regsfr=op->reg+0xf0;
143     if(len>3){
144       op->type=OP_BADDR;
145       if(requires==OP_BADDR){
146 	p=skip(p+4);
147 	op->boffset=parse_expr(&p);
148 	op->offset=number_expr(op->regsfr);
149       }
150     }
151   }else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='l'||p[1]=='L')&&p[2]>='0'&&p[2]<='7'){
152     op->type=OP_BGPR;
153     op->reg=(p[2]-'0')*2;
154     op->regsfr=op->reg+0xf0;
155   }else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='h'||p[1]=='H')&&p[2]>='0'&&p[2]<='7'){
156     op->type=OP_BGPR;
157     op->reg=(p[2]-'0')*2+1;
158     op->regsfr=op->reg+0xf0;
159   }else if(p[0]=='#'){
160     op->type=OP_IMM16;
161     p=skip(p+1);
162     if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);}
163     if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);}
164     if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);}
165     if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);}
166     if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);}
167     if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);}
168     if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);}
169     op->offset=parse_expr(&p);
170     simplify_expr(op->offset);
171 #if 0
172     if(op->offset->type==NUM){
173       taddr val=op->offset->c.val;
174       if(val>=0&&val<=7)
175 	op->type=OP_IMM3;
176       else if(val>=0&&val<=15)
177 	op->type=OP_IMM4;
178       else if(val>=0&&val<=127)
179 	op->type=OP_IMM7;
180       else if(val>=0&&val<=255)
181 	op->type=OP_IMM8;
182     }
183 #endif
184   }else if(*p=='['){
185     p=skip(p+1);
186     if(*p=='-'){
187       p=skip(p+1);
188       p=skip_reg(p,&op->reg);
189       p=skip(p);
190       if(*p!=']')
191 	cpu_error(0);
192       if(op->reg<=3)
193 	op->type=OP_PREDEC03;
194       else
195 	op->type=OP_PREDEC;
196     }else{
197       p=skip_reg(p,&op->reg);
198       p=skip(p);
199       if(*p=='+'){
200 	p=skip(p+1);
201 	if(*p==']'){
202 	  if(op->reg<=3)
203 	    op->type=OP_POSTINC03;
204 	  else
205 	    op->type=OP_POSTINC;
206 	}else{
207 	  if(*p!='#')
208 	    cpu_error(0);
209 	  p=skip(p+1);
210 	  op->offset=parse_expr(&p);
211 	  p=skip(p);
212 	  op->type=OP_REGDISP;
213 	}
214       }else{
215 	if(op->reg<=3)
216 	  op->type=OP_REG03IND;
217 	else
218 	  op->type=OP_REGIND;
219       }
220       if(*p!=']')
221 	cpu_error(0);
222     }
223   }else{
224     if(ISIDSTART(*p)){
225       char *name=p;
226       hashdata data;
227       while((p==name||ISIDCHAR(*p))&&*p!='.')
228 	p++;
229       if(find_namelen(sfrhash,name,p-name,&data)){
230 	sfr *sfr;
231 	sfr=data.ptr;
232 	if(sfr->flags&ISBIT){
233 	  op->offset=number_expr(sfr->saddr);
234 	  op->type=OP_BADDR;
235 	  op->boffset=number_expr(sfr->boffset);
236 	}else{
237 	  if(requires==OP_SFR||requires==OP_BSFR||requires==OP_BWORD){
238 	    op->offset=number_expr(sfr->saddr);
239 	    op->type=requires;
240 	  }else if(requires==OP_BADDR&&*p=='.'){
241 	    op->offset=number_expr(sfr->saddr);
242 	    p=skip(p+1);
243 	    op->boffset=parse_expr(&p);
244 	    op->type=OP_BADDR;
245 	  }else if(requires==OP_ABS||requires==OP_BABS){
246 	    op->type=requires;
247 	    op->offset=number_expr((2*sfr->saddr)+(sfr->laddr<<8));
248 	  }
249 	}
250       }
251       if(op->type==-1)
252 	p=name;
253     }
254     if(op->type==-1){
255       if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);}
256       if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);}
257       if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);}
258       if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);}
259       if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);}
260       if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);}
261       if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);}
262       op->offset=parse_expr(&p);
263       op->type=OP_ABS;
264     }
265   }
266   if(requires==op->type)
267     return 1;
268   if(requires==OP_BWORD&&op->type==OP_SFR)
269     return 1;
270   if(op->type==OP_IMM16&&(requires>=OP_IMM2&&requires<=OP_IMM16))
271     return 1;
272   if(op->type==OP_PREDEC03&&requires==OP_PREDEC)
273     return 1;
274   if(op->type==OP_POSTINC03&&requires==OP_POSTINC)
275     return 1;
276   if(op->type==OP_REG03IND&&requires==OP_REGIND)
277     return 1;
278   if((requires==OP_SFR&&op->type==OP_GPR)||
279      (requires==OP_BWORD&&op->type==OP_GPR)||
280      (requires==OP_BWORD&&op->type==OP_BGPR)||
281      (requires==OP_BSFR&&op->type==OP_BGPR)){
282     op->offset=number_expr(op->regsfr);
283     return 1;
284   }
285   if(requires==OP_BSFR&&op->type==OP_BGPR)
286     return 1;
287   if(requires==OP_JADDR&&op->type==OP_ABS)
288     return 1;
289   if(requires==OP_BABS&&op->type==OP_ABS)
290     return 1;
291   /*FIXME*/
292   return 0;
293 }
294 
reloffset(expr * tree,section * sec,taddr pc)295 static taddr reloffset(expr *tree,section *sec,taddr pc)
296 {
297   symbol *sym;
298   int btype;
299   taddr val;
300   simplify_expr(tree);
301   if(tree->type==NUM){
302     /* should we do it like this?? */
303     val=tree->c.val;
304   }else{
305     btype=find_base(tree,&sym,sec,pc);
306     if(btype!=BASE_OK||!LOCREF(sym)||sym->sec!=sec)
307       val=0xffff;
308     else{
309       eval_expr(tree,&val,sec,pc);
310       val=val-pc;
311     }
312   }
313   return val;
314 }
315 
absoffset2(expr * tree,int mod,section * sec,taddr pc,rlist ** relocs,int roffset,int size,taddr mask)316 static taddr absoffset2(expr *tree,int mod,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
317 {
318   taddr val;
319   if(mod==MOD_SOF){
320     if(mask!=0xffffffff&&mask!=0xffff) cpu_error(5);
321     mask=0xffff;
322   }
323   if(mod==MOD_SEG){
324     if(mask!=0xff&&mask!=0xffff&&mask!=0xffffffff) cpu_error(6);
325     mask<<=16;
326   }
327   if(mod==MOD_DPP0||mod==MOD_DPP1||mod==MOD_DPP2||mod==MOD_DPP3||mod==MOD_DPPX){
328     if(mask!=0xffffffff&&mask!=0xffff) cpu_error(7);
329     mask=0x3fff;
330   }
331   if(!eval_expr(tree,&val,sec,pc)){
332     taddr addend=val;
333     symbol *base;
334     if(find_base(tree,&base,sec,pc)!=BASE_OK){
335       general_error(38);
336       return val;
337     }
338     if(mod==MOD_DPP1) val|=0x4000;
339     if(mod==MOD_DPP2) val|=0x8000;
340     if(mod==MOD_DPP3) val|=0xc000;
341     if(mod==MOD_DPPX){
342       static int dpplen;
343       static char *dppname;
344       char *id=base->name;
345       symbol *dppsym;
346       size-=2;
347       if(strlen(id)+9>dpplen){
348         myfree(dppname);
349         dppname=mymalloc(dpplen=strlen(id)+9);
350       }
351       strcpy(dppname,"___DPP_");
352       strcat(dppname,id);
353       dppsym=new_import(dppname);
354       if(dppsym->type==EXPRESSION){
355         if(!eval_expr(dppsym->expr,&val,0,0))
356           ierror(0);
357         val<<=14;
358       }else{
359         add_nreloc_masked(relocs,dppsym,0,REL_ABS,2,roffset+14,0x3);
360       }
361     }
362     add_nreloc_masked(relocs,base,addend,REL_ABS,size,roffset,mask);
363     return val;
364   }
365   val&=mask;
366   if(mod==MOD_DPPX) cpu_error(7);
367   if(mod==MOD_DPP1) val|=0x4000;
368   if(mod==MOD_DPP2) val|=0x8000;
369   if(mod==MOD_DPP3) val|=0xc000;
370   if(mod==MOD_SEG) val>>=16;
371   /*FIXME: range check */
372 #if 1
373   if(size==16)
374     return val&0xffff;
375   else
376     return val&((1<<size)-1);
377 #else
378   return val;
379 #endif
380 }
381 
absoffset(expr * tree,int mod,section * sec,taddr pc,rlist ** relocs,int roffset,int size)382 static taddr absoffset(expr *tree,int mod,section *sec,taddr pc,rlist **relocs,int roffset,int size)
383 {
384   /* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
385   return absoffset2(tree,mod,sec,pc,relocs,roffset,size,0xffffffff);
386 }
387 
absval(expr * tree,section * sec,taddr pc,int bits)388 static taddr absval(expr *tree,section *sec,taddr pc,int bits)
389 {
390   taddr val;
391   if(!eval_expr(tree,&val,sec,pc))
392     cpu_error(0);
393   if(bits==2){
394     /* ext instructions */
395     if(val<1||val>4)
396       cpu_error(3,2);
397     return val;
398   }else if(val<0||val>=(1<<bits))
399     cpu_error(3,bits);
400   return val&((1<<bits)-1);
401 }
402 
translate(instruction * p,section * sec,taddr pc)403 static int translate(instruction *p,section *sec,taddr pc)
404 {
405   int c=p->code;
406   taddr val;
407   /* choose one of jmpr/jmpa */
408   if(c==JMP||(!notrans&&(c==JMPA||c==JMPR||c==JB||c==JNB))){
409     val=reloffset(p->op[1]->offset,sec,pc);
410     if(val<-256||val>254||val%2){
411       if(c==JB) return JNB|JMPCONV;
412       if(c==JNB) return JB|JMPCONV;
413       if(c==JMPA) return JMPA;
414       if(tojmpa) return JMPA;
415       if(p->op[0]->cc==0)
416 	return JMPS;
417       else
418 	return JMPR|JMPCONV;
419     }else{
420       if(c==JB||c==JNB)
421 	return c;
422       return JMPR;
423     }
424   }
425   /* choose between gpr,#imm3 and reg,#imm16 */
426   if(mnemonics[c].operand_type[1]==OP_IMM3){
427     if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){
428       if(!strcmp(mnemonics[c].name,mnemonics[c+1].name))
429 	return c+1;
430     }
431   }
432   /* choose between gpr,#imm4 and reg,#imm16 */
433   if(mnemonics[c].operand_type[1]==OP_IMM4){
434     if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){
435       if(!strcmp(mnemonics[c].name,mnemonics[c+1].name))
436 	return c+1;
437     }
438   }
439   return c;
440 }
441 
442 /* Convert an instruction into a DATA atom including relocations,
443    if necessary. */
eval_instruction(instruction * p,section * sec,taddr pc)444 dblock *eval_instruction(instruction *p,section *sec,taddr pc)
445 {
446   dblock *db=new_dblock();
447   int opcode,c,jmpconv=0,osize;
448   unsigned long code;
449   char *d;
450   taddr val;
451   rlist *relocs=0;
452   operand *jmpaddr;
453 
454   c=translate(p,sec,pc);
455   if(c&JMPCONV){ jmpconv=1;c&=~JMPCONV;}
456   if((mnemonics[p->code].operand_type[0]==OP_GPR&&mnemonics[c].operand_type[0]==OP_SFR)||
457      (mnemonics[p->code].operand_type[0]==OP_BGPR&&mnemonics[c].operand_type[0]==OP_BSFR))
458     p->op[0]->offset=number_expr(p->op[0]->regsfr);
459 
460 
461   db->size=osize=mnemonics[c].ext.len*2;
462   if(jmpconv) db->size+=4;
463   db->data=mymalloc(db->size);
464 
465   opcode=mnemonics[c].ext.opcode;
466   switch(mnemonics[c].ext.encoding){
467   case 0:
468     code=opcode<<16|(opcode>>8)<<8|opcode>>8;
469     break;
470   case 1:
471     code=opcode;
472     break;
473   case 2:
474     code=opcode|p->op[0]->reg<<4|p->op[1]->reg;
475     break;
476   case 3:
477     code=opcode|p->op[0]->reg|p->op[1]->reg<<4;
478     break;
479   case 4:
480     code=opcode|p->op[0]->reg<<4|p->op[1]->reg|8;
481     break;
482   case 5:
483     code=opcode|p->op[0]->reg<<4|p->op[1]->reg|12;
484     break;
485   case 6:
486     code=opcode|p->op[0]->reg<<4|absval(p->op[1]->offset,sec,pc,3);
487     break;
488   case 7:
489     /* fall through */
490   case 8:
491     code=opcode<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,20,8)<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
492     break;
493   case 9:
494     code=opcode|p->op[0]->reg|absval(p->op[1]->offset,sec,pc,4)<<4;
495     break;
496   case 10:
497 /* rfi: reorder bmov operands */
498     code=opcode<<16|
499       absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16|
500       absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8)<<0|
501       absoffset(p->op[1]->boffset,0,sec,pc,&relocs,24,4)<<12|
502       absoffset(p->op[0]->boffset,0,sec,pc,&relocs,28,4)<<8;
503     break;
504   case 11:
505     code=opcode|absoffset(p->op[0]->boffset,0,sec,pc,&relocs,0,4)<<12|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8);
506     break;
507   case 12:
508     code=opcode<<16|
509       absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
510       absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,16,8)<<8|
511       absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,24,8);
512     break;
513   case 13:
514     code=opcode<<16|
515       absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
516       absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,8)<<8|
517       absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,24,8);
518     break;
519   case 14:
520     code=opcode<<16|p->op[0]->cc<<20|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
521     break;
522   case 15:
523     code=opcode|p->op[0]->cc<<4|p->op[1]->reg;
524     break;
525   case 16:
526     val=((reloffset(p->op[0]->offset,sec,pc)-2)>>1)&255;
527     code=opcode|val;
528     break;
529   case 17:
530     if(p->op[0]->type==OP_CC){
531       /* jmp cc_uc was converted to jmps */
532       code=opcode<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,16,16,0xffff);
533     }else{
534       code=opcode<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,16,16,0xffff);
535     }
536     break;
537   case 18:
538     /* fall through */
539   case 19:
540     code=opcode<<16|0xf<<20|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
541     break;
542   case 20:
543     code=opcode|p->op[0]->reg<<4;
544     break;
545   case 21:
546     code=opcode|p->op[0]->reg<<4|p->op[0]->reg;
547     break;
548   case 22:
549     if(!jmpconv){
550       val=((reloffset(p->op[1]->offset,sec,pc)-4)>>1)&255;
551       code=opcode<<16|
552 	absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
553 	absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12|
554 	val;
555     }else{
556       code=opcode<<16|
557 	absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
558 	absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12|
559 	2;
560       jmpaddr=p->op[1];
561     }
562     break;
563   case 23:
564     if(!jmpconv){
565       val=((reloffset(p->op[1]->offset,sec,pc)-2)>>1)&255;
566       code=opcode|p->op[0]->cc<<12|val;
567     }else{
568       code=opcode|INVCC(p->op[0]->cc)<<12|2;
569       jmpaddr=p->op[1];
570     }
571     break;
572   case 24:
573     code=opcode<<16|p->op[0]->reg<<20|p->op[1]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
574     break;
575   case 25:
576     code=opcode<<16|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
577     break;
578   case 26:
579     code=opcode|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8);
580     break;
581   case 27:
582     code=opcode|absval(p->op[0]->offset,sec,pc,7)<<1;
583     break;
584   case 28:
585     code=opcode<<16|p->op[0]->reg<<16|p->op[1]->reg<<20|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
586     break;
587   case 29:
588     code=opcode<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
589     break;
590   case 30:
591     code=opcode<<16|p->op[1]->reg<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
592     break;
593   case 31:
594     code=opcode|((absval(p->op[0]->offset,sec,pc,2)-1)<<4);
595     break;
596   case 32:
597     code=opcode|p->op[0]->reg|((absval(p->op[1]->offset,sec,pc,2)-1)<<4);
598     break;
599   case 34:
600     code=opcode<<16|((absval(p->op[1]->offset,sec,pc,2)-1)<<20)|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8);
601     break;
602   case 33:
603   default:
604     ierror(mnemonics[c].ext.encoding);
605   }
606 
607   d=db->data;
608   if(osize==4){
609     *d++=code>>24;
610     *d++=code>>16;
611     *d++=code;
612     *d++=code>>8;
613   }else{
614     *d++=code>>8;
615     *d++=code;
616   }
617   if(jmpconv){
618     *d++=0xfa;
619     *d++=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,8+8*osize,8,0xffff0000);
620     val=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,16+8*osize,16,0xffff);
621     *d++=val>>8;
622     *d++=val;
623   }
624   db->relocs=relocs;
625   return db;
626 }
627 
628 /* Create a dblock (with relocs, if necessary) for size bits of data. */
eval_data(operand * op,size_t bitsize,section * sec,taddr pc)629 dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
630 {
631   dblock *new=new_dblock();
632   taddr val;
633   new->size=(bitsize+7)/8;
634   new->data=mymalloc(new->size);
635   if(op->type!=OP_ABS)
636     ierror(0);
637   if(bitsize!=8&&bitsize!=16&&bitsize!=32)
638     cpu_error(4);
639   val=absoffset(op->offset,op->mod,sec,pc,&new->relocs,0,bitsize);
640   if(bitsize==32){
641     new->data[3]=val>>24;
642     new->data[2]=val>>16;
643     new->data[1]=val>>8;
644     new->data[0]=val;
645   }else if(bitsize==16){
646     new->data[1]=val>>8;
647     new->data[0]=val;
648   }else
649     new->data[0]=val;
650   return new;
651 }
652 
653 
654 /* Calculate the size of the current instruction; must be identical
655    to the data created by eval_instruction. */
instruction_size(instruction * p,section * sec,taddr pc)656 size_t instruction_size(instruction *p,section *sec,taddr pc)
657 {
658   int c=translate(p,sec,pc),add=0;
659   if(c&JMPCONV){ add=4;c&=~JMPCONV;}
660   return mnemonics[c].ext.len*2+add;
661 }
662 
new_operand()663 operand *new_operand()
664 {
665   operand *new=mymalloc(sizeof(*new));
666   new->type=-1;
667   return new;
668 }
669 
670 /* return true, if initialization was successfull */
init_cpu()671 int init_cpu()
672 {
673   int i;
674   for(i=0;i<mnemonic_cnt;i++){
675     if(!strcmp(mnemonics[i].name,"jmp"))
676       JMP=i;
677     if(!strcmp(mnemonics[i].name,"jmpr"))
678       JMPR=i;
679     if(!strcmp(mnemonics[i].name,"jmpa"))
680       JMPA=i;
681     if(!strcmp(mnemonics[i].name,"jmps"))
682       JMPS=i;
683     if(!strcmp(mnemonics[i].name,"jb"))
684       JB=i;
685     if(!strcmp(mnemonics[i].name,"jbc"))
686       JBC=i;
687     if(!strcmp(mnemonics[i].name,"jnb"))
688       JNB=i;
689     if(!strcmp(mnemonics[i].name,"jnbs"))
690       JNBS=i;
691   }
692   sfrhash=new_hashtable(SFRHTSIZE);
693   return 1;
694 }
695 
696 /* return true, if the passed argument is understood */
cpu_args(char * p)697 int cpu_args(char *p)
698 {
699   if(!strcmp(p,"-no-translations")){
700     notrans=1;
701     return 1;
702   }
703   if(!strcmp(p,"-jmpa")){
704     tojmpa=1;
705     return 1;
706   }
707   return 0;
708 }
709 
710 /* parse cpu-specific directives; return pointer to end of
711    cpu-specific text */
parse_cpu_special(char * s)712 char *parse_cpu_special(char *s)
713 {
714   char *name=s,*merk=s;
715   if(ISIDSTART(*s)){
716     s++;
717     while(ISIDCHAR(*s))
718       s++;
719     if(s-name==4&&!strncmp(name,".sfr",4)){
720       sfr *new;
721       hashdata data;
722       expr *tree;
723       s=skip(s);
724       if(!ISIDSTART(*s))
725 	cpu_error(0);
726       name=s++;
727       while(ISIDCHAR(*s))
728 	s++;
729       if(find_namelen(sfrhash,name,s-name,&data))
730 	new=data.ptr;
731       else{
732 	data.ptr=new=mymalloc(sizeof(*new));
733 	add_hashentry(sfrhash,cnvstr(name,s-name),data);
734 	new->next=first_sfr;
735 	first_sfr=new;
736       }
737       new->flags=new->laddr=new->saddr=0;
738       new->boffset=0;
739       s=skip(s);
740       if(*s!=',')
741 	cpu_error(0);
742       else
743 	s=skip(s+1);
744       tree=parse_expr(&s);
745       simplify_expr(tree);
746       if(!tree||tree->type!=NUM)
747 	cpu_error(0);
748       else
749 	new->laddr=tree->c.val;
750       s=skip(s);
751       if(tree->c.val==0xfe||tree->c.val==0xf0){
752 	if(*s!=',')
753 	  cpu_error(0);
754 	else
755 	  s=skip(s+1);
756         free_expr(tree);
757 	tree=parse_expr(&s);
758 	simplify_expr(tree);
759 	if(!tree||tree->type!=NUM)
760 	  cpu_error(0);
761 	else
762 	  new->saddr=tree->c.val;
763 	free_expr(tree);
764 	s=skip(s);
765       }else{
766 	if(tree->c.val>=0xfe00)
767 	  new->laddr=0xfe;
768 	else
769 	  new->laddr=0xf0;
770 	new->saddr=(tree->c.val-(new->laddr<<8))/2;
771 	if((new->laddr<<8)+2*new->saddr!=tree->c.val) ierror(0);
772         free_expr(tree);
773       }
774       if(*s==','){
775 	s=skip(s+1);
776 	tree=parse_expr(&s);
777 	simplify_expr(tree);
778 	new->boffset=tree->c.val;
779 	new->flags|=ISBIT;
780         free_expr(tree);
781       }
782       return skip(s);
783     }
784   }
785   return merk;
786 }
787