1206 lines
30 KiB
C
1206 lines
30 KiB
C
/* cpu.c example cpu-description file */
|
|
/* (c) in 2013 by Volker Barthelmann */
|
|
|
|
#include "vasm.h"
|
|
|
|
char *cpu_copyright="VideoCore IV cpu backend 0.1 (c) in 2013 Volker Barthelmann";
|
|
char *cpuname="vidcore";
|
|
|
|
mnemonic mnemonics[]={
|
|
#include "opcodes.h"
|
|
};
|
|
|
|
int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
|
|
|
|
int bitsperbyte=8;
|
|
int bytespertaddr=4;
|
|
|
|
static char *ccs[]={"eq","ne","cs","cc","mi","pl","vs","vc",
|
|
"hi","ls","ge","lt","gt","le","???","f"};
|
|
|
|
static char *vflags[]={"all","none","ifz","ifnz","ifn","ifnn","ifc","ifnc"};
|
|
|
|
static char *accs[]={
|
|
"???", "sub", "wba", "???", "clra", "???", "???", "???",
|
|
"sign", "???", "???", "???", "???", "???", "???", "???",
|
|
"high", "???", "???", "???", "???", "???", "???", "???",
|
|
"???", "???", "???", "???", "???", "???", "???", "???",
|
|
"uadd", "usub", "uacc", "udec", "???", "???", "???", "???",
|
|
"sadd", "ssub", "sacc", "sdec", "???", "???", "???", "???",
|
|
"uaddh", "usubh", "uacch", "udech", "???", "???", "???", "???",
|
|
"saddh", "ssubh", "sacch", "sdech", "???", "???", "???", "???"};
|
|
|
|
static char *sru[]={
|
|
"sumu", "sums", "???", "imin", "???", "imax", "???", "max"};
|
|
|
|
static size_t oplen(int op)
|
|
{
|
|
if(op<=EN_MEMDISP16)
|
|
return 2;
|
|
else if(op<=EN_ARITHI32)
|
|
return 4;
|
|
else if(op<=EN_VARITHI48)
|
|
return 6;
|
|
else if(op<=EN_ADDCMPB64)
|
|
return 8;
|
|
else if(op<=EN_VARITHI80)
|
|
return 10;
|
|
ierror(0);
|
|
}
|
|
|
|
static char *skip_reg(char *s,int *reg)
|
|
{
|
|
int r=-1;
|
|
char* orig=s;
|
|
if(s[0]=='p'&&s[1]=='c'){
|
|
*reg=31;
|
|
return s+2;
|
|
}
|
|
if(s[0]=='s'&&s[1]=='r'){
|
|
*reg=30;
|
|
return s+2;
|
|
}
|
|
if(s[0]=='l'&&s[1]=='r'){
|
|
*reg=26;
|
|
return s+2;
|
|
}
|
|
if(s[0]=='s'&&s[1]=='p'){
|
|
*reg=25;
|
|
return s+2;
|
|
}
|
|
if(*s!='r'){
|
|
return s;
|
|
}
|
|
s++;
|
|
if(*s<'0'||*s>'9'){
|
|
return orig;
|
|
}
|
|
r=*s++-'0';
|
|
if(*s>='0'&&*s<='9')
|
|
r=10*r+*s++-'0';
|
|
if(isalnum(*s)||*s=='_'){
|
|
return orig;
|
|
}
|
|
*reg=r;
|
|
return s;
|
|
}
|
|
|
|
int parse_operand(char *p,int len,operand *op,int req)
|
|
{
|
|
int r;
|
|
char *s,*start=p;
|
|
|
|
op->type=-1;
|
|
p=skip(p);
|
|
|
|
if(req>=OP_REG&&req<=OP_LR){
|
|
int reg;
|
|
s=skip_reg(p,&r);
|
|
if(s!=p){
|
|
if((req==OP_REG&&r<=31)||
|
|
(req==OP_SREG&&r<=15)||
|
|
(req==OP_PC&&r==31)||
|
|
(req==OP_LR&&r==26)||
|
|
(req==OP_MREG&&(r==0||r==6||r==16||r==24))){
|
|
op->type=OP_REG;
|
|
op->reg=r;
|
|
}else
|
|
return 0;
|
|
}else
|
|
return 0;
|
|
p=skip(s);
|
|
}else if(req==OP_MREG){
|
|
int first;
|
|
s=skip_reg(p,&r);
|
|
if(s==p)
|
|
return 0;
|
|
if(r==0)
|
|
op->dreg=0;
|
|
else if(r==6)
|
|
op->dreg=1;
|
|
else if(r==16)
|
|
op->dreg=2;
|
|
else if(r==24)
|
|
op->dreg=3;
|
|
else
|
|
return 0;
|
|
s=skip(s);
|
|
if(*s!='-')
|
|
return 0;
|
|
p=skip(s+1);
|
|
first=r;
|
|
s=skip_reg(p,&r);
|
|
if(s==p)
|
|
return 0;
|
|
p=skip(s);
|
|
op->reg=(r-first)&31;
|
|
}else if(req==OP_IND){
|
|
p=skip(p);
|
|
if(*p!='(') return 0;
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&r);
|
|
if(s==p) return 0;
|
|
if(r>15) return 0;
|
|
p=skip(s);
|
|
op->reg=r;
|
|
if(*p!=')') return 0;
|
|
p=skip(p+1);
|
|
op->type=OP_IND;
|
|
}else if(req==OP_VIND){
|
|
int nodisp=0;
|
|
p=skip(p);
|
|
if(*p=='('){
|
|
char *m;
|
|
m=s=skip(p+1);
|
|
s=skip_reg(s,&r);
|
|
if((m!=s)||(*s=='0')) nodisp=1;
|
|
}
|
|
if(!nodisp){
|
|
op->offset=parse_expr(&p);
|
|
if(!op->offset) return 0;
|
|
}else
|
|
op->offset=0;
|
|
if(*p!='(') return 0;
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&r);
|
|
if (s==p){
|
|
/* Special case: Allow '0' instead of a register */
|
|
if (*p=='0'){
|
|
p=skip(p+1);
|
|
op->reg=15;
|
|
}
|
|
else return 0;
|
|
}else{
|
|
if(r>14) return 0;
|
|
p=skip(s);
|
|
op->reg=r;
|
|
}
|
|
op->dreg=15;
|
|
if(*p=='+'&&p[1]=='='){
|
|
p=skip(p+2);
|
|
s=skip_reg(p,&r);
|
|
if(s==p) return 0;
|
|
if(r>14) return 0;
|
|
p=skip(s);
|
|
op->dreg=r;
|
|
}
|
|
if(*p!=')') return 0;
|
|
p=skip(p+1);
|
|
op->type=OP_IND;
|
|
}else if(req==OP_PREDEC){
|
|
p=skip(p);
|
|
if(p[0]!='-'||p[1]!='-') return 0;
|
|
p=skip(p+2);
|
|
if(*p!='(') return 0;
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&r);
|
|
if(s==p) return 0;
|
|
p=skip(s);
|
|
if(*p!=')') return 0;
|
|
p=skip(p+1);
|
|
op->reg=r;
|
|
op->type=OP_PREDEC;
|
|
}else if(req==OP_POSTINC){
|
|
p=skip(p);
|
|
if(*p!='(') return 0;
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&r);
|
|
if(s==p) return 0;
|
|
p=skip(s);
|
|
if(*p!=')') return 0;
|
|
p=skip(p+1);
|
|
if(*p++!='+') return 0;
|
|
if(*p!='+') return 0;
|
|
p=skip(p+1);
|
|
op->reg=r;
|
|
op->type=OP_POSTINC;
|
|
}else if(req==OP_REGIND){
|
|
p=skip(p);
|
|
if(*p!='(') return 0;
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&op->reg);
|
|
if(s==p) return 0;
|
|
p=skip(s);
|
|
if(*p!=',') return 0;
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&op->dreg);
|
|
if(s==p) return 0;
|
|
p=skip(s);
|
|
if(*p!=')') return 0;
|
|
op->type=OP_REGIND;
|
|
p=skip(p+1);
|
|
}else if(req==OP_IMMIND||
|
|
req==OP_IMMINDSP||
|
|
req==OP_IMMINDSD||
|
|
req==OP_IMMINDR0||
|
|
req==OP_IMMINDS||
|
|
req==OP_IMMINDPC){
|
|
op->offset=0;
|
|
if(*p=='('){
|
|
char *p2;
|
|
p2=skip(p+1);
|
|
s=skip_reg(p2,&r);
|
|
if(s!=p2){
|
|
p=skip(s);
|
|
if(*p==')'){
|
|
p=skip(p+1);
|
|
op->offset=number_expr(0);
|
|
}
|
|
}
|
|
}
|
|
if(!op->offset){
|
|
op->offset=parse_expr(&p);
|
|
if(!op->offset) return 0;
|
|
p=skip(p);
|
|
if(*p!='(') return 0;
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&r);
|
|
if(s==p) return 0;
|
|
p=skip(s);
|
|
if(*p!=')') return 0;
|
|
}
|
|
if(req==OP_IMMINDSP&&r!=25) return 0;
|
|
if(req==OP_IMMINDPC&&r!=31) return 0;
|
|
if(req==OP_IMMINDSD&&r!=24) return 0;
|
|
if(req==OP_IMMINDR0&&r!=0) return 0;
|
|
if(req==OP_IMMINDS&&r>15) return 0;
|
|
op->reg=r;
|
|
op->type=OP_IMMIND;
|
|
p=skip(p+1);
|
|
}else if(req>=OP_IMM4&&req<=OP_IMM32&&skip_reg(p,&r)==p){
|
|
op->type=OP_IMM32;
|
|
op->offset=parse_expr(&p);
|
|
simplify_expr(op->offset);
|
|
p=skip(p);
|
|
}else if((req==OP_ABS||req==OP_REL)&&skip_reg(p,&r)==p){
|
|
op->type=req;
|
|
op->offset=parse_expr(&p);
|
|
simplify_expr(op->offset);
|
|
p=skip(p);
|
|
}else if(req==OP_VREG||req==OP_VREGM||req==OP_VREGMM||req==OP_VREGA80){
|
|
s=skip_reg(p,&r);
|
|
op->offset=0;
|
|
if(s!=p){
|
|
if (*s=='+'||*s=='-'){
|
|
if(req==OP_VREG) return 0;
|
|
op->offset=parse_expr(&s);
|
|
}
|
|
p=skip(s);
|
|
op->type=OP_VREG;
|
|
if(req==OP_VREG){
|
|
op->reg=(0xE<<6)|r;
|
|
op->dreg=0x3c;
|
|
}else{
|
|
op->reg=(0xE<<6);
|
|
op->dreg=r<<2;
|
|
}
|
|
}else if(*p=='-'){
|
|
p=skip(p+1);
|
|
op->type=OP_VREG;
|
|
op->reg=(0xF<<6);
|
|
op->dreg=0x3c;
|
|
}else{
|
|
int size,vert,x,y,inc=15<<2;
|
|
expr *e;
|
|
if(*p=='H'||*p=='h')
|
|
vert=0;
|
|
// Disable vertical registers in 48-bit instructions for now
|
|
else if((req!=OP_VREG)&&(*p=='V'||*p=='v'))
|
|
vert=1;
|
|
else
|
|
return 0;
|
|
p=skip(p+1);
|
|
if(*p=='X'||*p=='x'){
|
|
size=2;
|
|
p=skip(p+1);
|
|
}else if(*p=='1'&&p[1]=='6'){
|
|
size=2;
|
|
p=skip(p+2);
|
|
}else if(*p=='Y'||*p=='y'){
|
|
size=4;
|
|
p=skip(p+1);
|
|
}else if(*p=='3'&&p[1]=='2'){
|
|
size=4;
|
|
p=skip(p+2);
|
|
}else if(*p=='8'){
|
|
size=1;
|
|
p=skip(p+1);
|
|
}else{
|
|
size=1;
|
|
p=skip(p);
|
|
}
|
|
if(*p!='(') return 0;
|
|
p=skip(p+1);
|
|
e=parse_expr(&p);
|
|
if(e->type!=NUM) return 0;
|
|
y=e->c.val;
|
|
p=skip(p);
|
|
#if 1
|
|
if(req!=OP_VREG&&*p=='+'){
|
|
p++;
|
|
if(*p!='+') return 0;
|
|
if(vert) {
|
|
cpu_error(4);
|
|
return 0;
|
|
}
|
|
p=skip(p+1);
|
|
inc|=2;
|
|
}
|
|
#endif
|
|
if(*p!=',') return 0;
|
|
p=skip(p+1);
|
|
if((*p=='c')||(*p=='C'))
|
|
{
|
|
p++;
|
|
if (*p!='b'&&*p!='B') return 0;
|
|
p++;
|
|
if (*p!='+') return 0;
|
|
inc|=1;
|
|
}
|
|
e=parse_expr(&p);
|
|
if(e->type!=NUM) return 0;
|
|
x=e->c.val;
|
|
p=skip(p);
|
|
#if 1
|
|
if(req!=OP_VREG&&*p=='+'){
|
|
p++;
|
|
if(*p!='+') return 0;
|
|
if(!vert) {
|
|
cpu_error(4);
|
|
return 0;
|
|
}
|
|
p=skip(p+1);
|
|
inc|=2;
|
|
}
|
|
#endif
|
|
if(*p!=')') return 0;
|
|
p=skip(p+1);
|
|
if(req!=OP_VREG&&*p=='*'){
|
|
p=skip(p+1);
|
|
inc|=1;
|
|
}
|
|
if(req!=OP_VREG&&*p=='+'){
|
|
p=skip(p+1);
|
|
s=skip_reg(p,&r);
|
|
if(s==p) return 0;
|
|
p=skip(s);
|
|
inc&=~0x3c;
|
|
inc|=(r<<2);
|
|
}
|
|
if(req==OP_VREGA80){
|
|
if(size==1){
|
|
op->reg=(vert<<6)|((x&48)<<3);
|
|
}else if(size==2){
|
|
if(x&16) return 0;
|
|
op->reg=(vert<<6)|(8<<6)|((x&32)<<2);
|
|
}else{
|
|
if(x&48) return 0;
|
|
op->reg=(vert<<6)|(12<<6);
|
|
}
|
|
if(y<0||y>63) return 0;
|
|
op->reg|=y&63;
|
|
inc|=(x&15)<<6;
|
|
}else{
|
|
if(vert){
|
|
if(size==1){
|
|
op->reg=(1<<6)|((x&48)<<3);
|
|
}else if(size==2){
|
|
if(x&16) return 0;
|
|
op->reg=(9<<6)|((x&32)<<2);
|
|
}else{
|
|
if(x&48) return 0;
|
|
op->reg=13<<6;
|
|
}
|
|
if(y<0||y>63||(y&15)) return 0;
|
|
op->reg|=(y&48)|(x&15);
|
|
}
|
|
else{
|
|
if(size==1){
|
|
if(x&15) return 0;
|
|
op->reg=(x&48)<<3;
|
|
}else if(size==2){
|
|
if(x&31) return 0;
|
|
op->reg=(8<<6)|((x&32)<<2);
|
|
}else{
|
|
if(x) return 0;
|
|
op->reg=12<<6;
|
|
}
|
|
if(y<0||y>63) return 0;
|
|
op->reg|=y&63;
|
|
}
|
|
}
|
|
op->dreg=inc;
|
|
op->type=OP_VREG;
|
|
}
|
|
}else
|
|
return 0;
|
|
|
|
if(req==OP_VREGMM||req==OP_IMM32M||req==OP_VIND){
|
|
int vecmod=0,i;
|
|
while(1){
|
|
if(!strncasecmp(p,"rep",3)&&isspace((unsigned char)p[3])){
|
|
expr *e;
|
|
taddr x;
|
|
p=skip(p+3);
|
|
if((*p=='r')&&(p[1]=='0')&&!isdigit(p[2])){
|
|
p=skip(p+2);
|
|
vecmod|=7<<16;
|
|
i=0;
|
|
}else{
|
|
e=parse_expr(&p);
|
|
if(e->type!=NUM) return 0;
|
|
x=e->c.val;
|
|
for(i=0;i<8;i++){
|
|
if((1<<i)==x){
|
|
vecmod|=i<<16;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(i>=8) return 0;
|
|
p=skip(p);
|
|
continue;
|
|
}
|
|
for(i=0;i<sizeof(vflags)/sizeof(vflags[0]);i++){
|
|
if((!strncasecmp(p,vflags[i],strlen(vflags[i])))&&
|
|
(!isalpha(p[strlen(vflags[i])]))){
|
|
if(vecmod&0x380) return 0;
|
|
vecmod|=i<<7;
|
|
p=skip(p+strlen(vflags[i]));
|
|
continue;
|
|
}
|
|
}
|
|
for (i=0;i<sizeof(sru)/sizeof(sru[0]);i++){
|
|
if(!strncasecmp(p,sru[i],strlen(sru[i]))){
|
|
p=skip(p+strlen(sru[i]));
|
|
p=skip_reg(p,&r);
|
|
if((r<0)||(r>7)) return 0;
|
|
vecmod|=(1<<6)|(i<<3)|r;
|
|
continue;
|
|
}
|
|
}
|
|
for (i=0;i<sizeof(accs)/sizeof(accs[0]);i++){
|
|
if((!strncasecmp(p,accs[i],strlen(accs[i])))&&
|
|
(!isalpha(p[strlen(accs[i])]))){
|
|
if(vecmod&0x40) return 0;
|
|
vecmod|=i;
|
|
p=skip(p+strlen(accs[i]));
|
|
continue;
|
|
}
|
|
}
|
|
if(!strncasecmp(p,"ena",3)){
|
|
if(vecmod&0x40) return 0;
|
|
p=skip(p+3);
|
|
vecmod|=32;
|
|
}
|
|
if(!strncasecmp(p,"setf",4)){
|
|
p=skip(p+4);
|
|
vecmod|=1<<20;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
op->vecmod=vecmod;
|
|
}
|
|
|
|
if(p>=start+len)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static taddr dooffset(int rel,expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
|
|
{
|
|
taddr val;
|
|
if(!eval_expr(tree,&val,sec,pc)){
|
|
taddr addend=val;
|
|
symbol *base;
|
|
if(find_base(tree,&base,sec,pc)!=BASE_OK){
|
|
general_error(38);
|
|
return val;
|
|
}
|
|
if(rel==REL_PC){
|
|
val-=pc;
|
|
addend+=roffset/8;
|
|
}
|
|
if(rel!=REL_PC||!LOCREF(base)||base->sec!=sec){
|
|
add_nreloc_masked(relocs,base,addend,rel,size,roffset,mask);
|
|
return 0;
|
|
}
|
|
}
|
|
#if 0
|
|
if(val<-(1<<(size-1))||val>((1<<(size-1))-1))
|
|
cpu_error(1,size);
|
|
#endif
|
|
return val&mask;
|
|
}
|
|
|
|
static taddr reloffset(expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
|
|
{
|
|
/* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
|
|
return dooffset(REL_PC,tree,sec,pc,relocs,roffset,size,mask);
|
|
}
|
|
|
|
static taddr absoffset(expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size)
|
|
{
|
|
/* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
|
|
return dooffset(REL_ABS,tree,sec,pc,relocs,roffset,size,0xffffffff);
|
|
}
|
|
|
|
static taddr absval(expr *tree,section *sec,taddr pc,int bits,int sgn)
|
|
{
|
|
taddr val;
|
|
if(!eval_expr(tree,&val,sec,pc))
|
|
cpu_error(0);
|
|
if(!sgn){
|
|
if(val<0||val>=(1<<bits))
|
|
cpu_error(1,bits);
|
|
}else{
|
|
if(val<-(1<<(bits-1))||val>=(1<<(bits-1)))
|
|
cpu_error(1,bits);
|
|
}
|
|
return val&((1<<bits)-1);
|
|
}
|
|
|
|
static int chkval(expr *tree,section *sec,taddr pc,int bits,int sgn)
|
|
{
|
|
taddr val;
|
|
if(!eval_expr(tree,&val,sec,pc))
|
|
cpu_error(0);
|
|
if(!sgn){
|
|
if(val<0||val>=(1<<bits))
|
|
return 0;
|
|
}else{
|
|
if(val<-(1<<(bits-1))||val>=(1<<(bits-1)))
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* replace instruction by one with encoding enc */
|
|
static int replace(int c,int enc)
|
|
{
|
|
int i=c+1;
|
|
while(!strcmp(mnemonics[c].name,mnemonics[i].name)){
|
|
if(mnemonics[i].ext.encoding==enc){
|
|
c=i;
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if(c!=i) ierror(0);
|
|
return c;
|
|
}
|
|
static int translate(instruction *p,section *sec,taddr pc)
|
|
{
|
|
int c=p->code,e=mnemonics[c].ext.encoding;
|
|
taddr val;
|
|
|
|
if(p->qualifiers[0]){
|
|
/* extend to larger variants if ccs are required */
|
|
if(e==EN_MEMDISP16)
|
|
c=replace(c,EN_MEMDISP32);
|
|
if(e==EN_ARITHR16)
|
|
c=replace(c,EN_ARITHR32);
|
|
if(e==EN_ARITHI16)
|
|
c=replace(c,EN_ARITHI32);
|
|
}
|
|
if(e==EN_ARITHI32){
|
|
if(p->op[2]){
|
|
if(!chkval(p->op[2]->offset,sec,pc,6,1)&&(!strcmp("add",mnemonics[c].name)||!strcmp("sub",mnemonics[c].name)))
|
|
c=replace(c,EN_ADD48);
|
|
}else{
|
|
if((mnemonics[c].ext.code<32)&&(!chkval(p->op[1]->offset,sec,pc,6,1)))
|
|
c=replace(c,EN_ARITHI48);
|
|
}
|
|
}
|
|
if(e==EN_ARITHI16){
|
|
if(!chkval(p->op[1]->offset,sec,pc,5,0))
|
|
c=replace(c,EN_ARITHI48);
|
|
}
|
|
if(e==EN_RBRANCH16){
|
|
symbol *base;
|
|
if(find_base(p->op[0]->offset,&base,sec,pc)!=BASE_OK||!LOCREF(base)||base->sec!=sec)
|
|
c=replace(c,EN_RBRANCH32);
|
|
else{
|
|
int i;
|
|
i=eval_expr(p->op[0]->offset,&val,sec,pc);
|
|
val-=pc;
|
|
if(val>126||val<-128)
|
|
c=replace(c,EN_RBRANCH32);
|
|
}
|
|
}
|
|
if(e==EN_ADDCMPB32){
|
|
int i;
|
|
i=eval_expr(p->op[3]->offset,&val,sec,pc);
|
|
val-=pc;
|
|
if(val>1022||val<-1024)
|
|
c+=4;
|
|
else if(p->op[2]->type!=OP_REG&&(val>254||val<-256))
|
|
c+=4;
|
|
}
|
|
if((e==EN_MEMDISP16||e==EN_MEMDISP32||e==EN_MEM12DISP32||e==EN_MEM16DISP32)){
|
|
if(!eval_expr(p->op[1]->offset,&val,sec,pc)){
|
|
c=replace(c,EN_MEM48);
|
|
}else{
|
|
if(e==EN_MEMDISP16&&(val<0||val>54||(val&3))){
|
|
if(val<=4095&&val>=-4096)
|
|
c=replace(c,EN_MEM12DISP32);
|
|
else
|
|
c=replace(c,EN_MEM48);
|
|
}
|
|
}
|
|
}
|
|
/* todo */
|
|
return c;
|
|
}
|
|
|
|
/* Convert an instruction into a DATA atom including relocations,
|
|
if necessary. */
|
|
dblock *eval_instruction(instruction *p,section *sec,taddr pc)
|
|
{
|
|
dblock *db=new_dblock();
|
|
int c,sz,enc,cc,ww,m=0;
|
|
unsigned long code,code2,code3;
|
|
rlist *relocs=0;
|
|
|
|
if(p->qualifiers[0]){
|
|
int i;
|
|
for(i=0;i<15;i++){
|
|
if(!strcmp(p->qualifiers[0],ccs[i])){
|
|
cc=i;
|
|
break;
|
|
}
|
|
}
|
|
if(i>15) ierror(0);
|
|
}else
|
|
cc=14;
|
|
|
|
c=translate(p,sec,pc);
|
|
enc=mnemonics[c].ext.encoding;
|
|
|
|
db->size=sz=oplen(enc);
|
|
db->data=mymalloc(db->size);
|
|
|
|
code=mnemonics[c].ext.code;
|
|
|
|
switch(enc){
|
|
case EN_ARITHR16:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0x40000000|(code<<24);
|
|
code|=(p->op[0]->reg<<16)|(p->op[1]->reg<<20);
|
|
break;
|
|
case EN_ARITHI16:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0x60000000|((code>>1)<<25);
|
|
code|=(p->op[0]->reg<<16)|(absval(p->op[1]->offset,sec,pc,5,0)<<20);
|
|
break;
|
|
case EN_FIX16:
|
|
if(cc!=14) cpu_error(3);
|
|
break;
|
|
case EN_IBRANCH16:
|
|
if(cc!=14) cpu_error(3);
|
|
code|=(p->op[0]->reg<<16);
|
|
break;
|
|
case EN_RBRANCH16:
|
|
code=0x18000000;
|
|
code|=cc<<23;
|
|
code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe)>>1)&127)<<16;
|
|
break;
|
|
case EN_MREG16:
|
|
if(cc!=14) cpu_error(3);
|
|
code|=(p->op[0]->dreg<<21)|(p->op[0]->reg<<16);
|
|
break;
|
|
case EN_RBRANCH32:
|
|
if(code==0x90000000)
|
|
code|=cc<<24;
|
|
else
|
|
code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,8,4,0xF000000)>>24)&0xf)<<24;
|
|
code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,16,16,0x1fffe)>>1)&0x7fffff);
|
|
code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe0000)>>17)&0x7f)<<16;
|
|
break;
|
|
case EN_FUNARY32:
|
|
code=0xC0000040|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
code|=p->op[1]->reg<<11;
|
|
code|=cc<<7;
|
|
break;
|
|
case EN_ARITHR32:
|
|
code=0xC0000000|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
if(p->op[2]){
|
|
code|=p->op[1]->reg<<11;
|
|
code|=p->op[2]->reg;
|
|
}else{
|
|
code|=p->op[0]->reg<<11;
|
|
code|=p->op[1]->reg;
|
|
}
|
|
code|=cc<<7;
|
|
break;
|
|
case EN_ARITHI32:
|
|
code=0xC0000040|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
if(p->op[2]){
|
|
code|=p->op[1]->reg<<11;
|
|
code|=absval(p->op[2]->offset,sec,pc,6,1);
|
|
}else{
|
|
code|=p->op[0]->reg<<11;
|
|
code|=absval(p->op[1]->offset,sec,pc,6,1);
|
|
}
|
|
code|=cc<<7;
|
|
break;
|
|
case EN_ADDCMPB64:
|
|
// Large offset: invert CC, place a long branch after
|
|
// so we really generate the following:
|
|
// addcmpb<~cc> d, a, b, skip
|
|
// b <destination>
|
|
// skip:
|
|
// <rest of code>
|
|
m=1;
|
|
if(cc&1) cc--; else cc++;
|
|
case EN_ADDCMPB32:
|
|
code=0x80000000|(code<<14);
|
|
code|=cc<<24;
|
|
code|=p->op[0]->reg<<16;
|
|
if(code&0x4000){
|
|
code|=absval(p->op[1]->offset,sec,pc,4,1)<<20;
|
|
}else{
|
|
code|=p->op[1]->reg<<20;
|
|
}
|
|
if(code&0x8000){
|
|
code|=absval(p->op[2]->offset,sec,pc,6,0)<<8;
|
|
if(m)
|
|
code|=4;
|
|
else
|
|
code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,9,0x1ff)>>1)&0xff);
|
|
}else{
|
|
code|=p->op[2]->reg<<10;
|
|
if(m)
|
|
code|=4;
|
|
else
|
|
code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,11,0x7ff)>>1)&0x3ff);
|
|
}
|
|
if(m){
|
|
code2=0x90000000|(14<<24);
|
|
code2|=((reloffset(p->op[3]->offset,sec,pc+4,&relocs,48,16,0x1fffe)>>1)&0x7fffff);
|
|
code2|=((reloffset(p->op[3]->offset,sec,pc+4,&relocs,32,7,0xfe0000)>>17)&0x7f)<<16;
|
|
}
|
|
break;
|
|
case EN_ARITHI48:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0xE8000000|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,32);
|
|
break;
|
|
case EN_ADD48:
|
|
if(cc!=14) cpu_error(3);
|
|
if(p->op[2])
|
|
code2=absoffset(p->op[2]->offset,sec,pc,&relocs,16,32);
|
|
else
|
|
code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,32);
|
|
/* pseudo sub */
|
|
if(code==6)
|
|
code2=-code2;
|
|
code=0xEC000000;
|
|
code|=p->op[0]->reg<<16;
|
|
if(p->op[2])
|
|
code|=p->op[1]->reg<<21;
|
|
else
|
|
code|=p->op[0]->reg<<21;
|
|
break;
|
|
case EN_MEMREG16:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0x08000000|(code<<24);
|
|
code|=p->op[0]->reg<<16;
|
|
code|=p->op[1]->reg<<20;
|
|
ww=0; /*FIXME*/
|
|
code|=ww<<25;
|
|
break;
|
|
case EN_MEMSTACK16:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0x04000000|(code<<25);
|
|
code|=p->op[0]->reg<<16;
|
|
code|=(absval(p->op[1]->offset,sec,pc,7,1)>>2)<<20;
|
|
break;
|
|
case EN_MEMDISP16:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0x20000000|(code<<28);
|
|
code|=p->op[0]->reg<<16;
|
|
code|=(absval(p->op[1]->offset,sec,pc,6,0)>>2)<<24;
|
|
code|=p->op[1]->reg<<20;
|
|
break;
|
|
case EN_LEA16:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0x10000000;
|
|
code|=p->op[0]->reg<<16;
|
|
code|=(absval(p->op[1]->offset,sec,pc,8,1)>>2)<<21;
|
|
break;
|
|
case EN_LEA48:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0xE5000000|(p->op[0]->reg<<16);
|
|
code2=reloffset(p->op[1]->offset,sec,pc,&relocs,16,32,0xffffffff);
|
|
break;
|
|
case EN_MEM48:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0xE6000000|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
if(p->op[1]->reg==31)
|
|
code2=reloffset(p->op[1]->offset,sec,pc,&relocs,16,27,0xffffffff)&0x7ffffff;
|
|
else
|
|
/* TODO: other relocs */
|
|
code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,27)&0x7ffffff;
|
|
code2|=p->op[1]->reg<<27;
|
|
break;
|
|
case EN_MEMREG32:
|
|
code=0xA0000000|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
code|=p->op[1]->reg<<11;
|
|
code|=p->op[1]->dreg;
|
|
code|=cc<<7;
|
|
break;
|
|
case EN_MEMDISP32:
|
|
code=0xA0000040|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
code|=p->op[1]->reg<<11;
|
|
code|=absval(p->op[1]->offset,sec,pc,5,1);
|
|
code|=cc<<7;
|
|
break;
|
|
case EN_MEMPREDEC:
|
|
case EN_MEMPOSTINC:
|
|
code<<=21;
|
|
if(p->op[1]->type==OP_POSTINC)
|
|
code|=0xA5000000;
|
|
else
|
|
code|=0xA4000000;
|
|
code|=p->op[0]->reg<<16;
|
|
code|=p->op[1]->reg<<11;
|
|
code|=cc<<7;
|
|
break;
|
|
case EN_MEM12DISP32:
|
|
if(cc!=14) cpu_error(3);
|
|
code=0xA2000000|(code<<21);
|
|
code|=p->op[0]->reg<<16;
|
|
code|=p->op[1]->reg<<11;
|
|
code|=absval(p->op[1]->offset,sec,pc,12,1)&0x7ff;
|
|
code|=(absval(p->op[1]->offset,sec,pc,12,1)&0x800)<<13;
|
|
break;
|
|
case EN_MEM16DISP32:
|
|
if(cc!=14) cpu_error(3);
|
|
code|=p->op[0]->reg<<16;
|
|
if((code&0xff000000)==0xaa000000)
|
|
code|=reloffset(p->op[1]->offset,sec,pc,&relocs,16,16,0xffff)&0xffff;
|
|
else
|
|
code|=absval(p->op[1]->offset,sec,pc,16,1);
|
|
break;
|
|
case EN_VLOAD48:
|
|
code=0xF0000000|(code<<19);
|
|
code2=(p->op[0]->reg<<22)|(7<<7)|p->op[1]->reg;
|
|
break;
|
|
case EN_VSTORE48:
|
|
code=0xF0000000|(code<<19);
|
|
code2=(p->op[0]->reg<<12)|(7<<7)|p->op[1]->reg;
|
|
break;
|
|
case EN_VREAD48:
|
|
code=0xF0000000|(code<<19);
|
|
code2=(p->op[0]->reg<<22)|p->op[1]->reg;
|
|
break;
|
|
case EN_VWRITE48:
|
|
code=0xF0000000|(code<<19);
|
|
code2=(p->op[0]->reg<<12)|p->op[1]->reg;
|
|
break;
|
|
case EN_VREADI48:
|
|
code=0xF0000000|(code<<19);
|
|
code2=(p->op[0]->reg<<22)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
|
|
break;
|
|
case EN_VWRITEI48:
|
|
code=0xF0000000|(code<<19);
|
|
code2=(p->op[0]->reg<<12)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
|
|
break;
|
|
case EN_VARITHR48:
|
|
if(code<48) code|=64;
|
|
code=0xF4000000|(code<<19);
|
|
if(p->op[2]){
|
|
code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|p->op[2]->reg;
|
|
}else{
|
|
code2=(p->op[0]->reg<<22)|p->op[1]->reg;
|
|
}
|
|
break;
|
|
case EN_VARITHI48:
|
|
if(code<48) code|=64;
|
|
code=0xF4000000|(code<<19);
|
|
if(p->op[2]){
|
|
code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|absval(p->op[2]->offset,sec,pc,6,0)|(1<<10);
|
|
}else{
|
|
code2=(p->op[0]->reg<<22)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
|
|
}
|
|
break;
|
|
// TODO: Check these!
|
|
case EN_VLOAD80:
|
|
code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
code2=(p->op[0]->reg<<22);
|
|
code3=(p->op[1]->reg<<2)|(p->op[0]->dreg<<26)|((p->op[1]->dreg)<<22);
|
|
if(p->op[1]->offset){
|
|
code2|=(absval(p->op[1]->offset,sec,pc,16,1)&0x7f);
|
|
code3|=(absval(p->op[1]->offset,sec,pc,16,1)>>7)&3;
|
|
code3|=((absval(p->op[1]->offset,sec,pc,16,1)>>9)&0x7f)<<6;
|
|
}
|
|
break;
|
|
case EN_VSTORE80:
|
|
code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
code2=(p->op[0]->reg<<12);
|
|
code3=(p->op[1]->reg<<2)|(p->op[0]->dreg<<20)|((p->op[1]->dreg)<<28);
|
|
if(p->op[1]->offset){
|
|
code2|=(absval(p->op[1]->offset,sec,pc,16,1)&0x7f);
|
|
code3|=(absval(p->op[1]->offset,sec,pc,16,1)>>7)&3;
|
|
code3|=((absval(p->op[1]->offset,sec,pc,16,1)>>9)&0x7f)<<6;
|
|
}
|
|
break;
|
|
case EN_VREAD80:
|
|
if(p->op[1]->offset){
|
|
p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
|
|
}
|
|
code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
code2=(p->op[0]->reg<<22)|(p->op[1]->reg);
|
|
if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code3=(p->op[0]->dreg<<26)|(p->op[1]->dreg);
|
|
code3|=(p->op[1]->vecmod&0x3fff)<<6;
|
|
break;
|
|
case EN_VWRITE80:
|
|
if(p->op[1]->offset){
|
|
p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
|
|
}
|
|
code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
code2=(p->op[0]->reg<<12)|(p->op[1]->reg);
|
|
if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code3=((p->op[0]->dreg&0x3f)<<20)|((p->op[0]->dreg&0x3c0)<<10)|(p->op[1]->dreg);
|
|
code3|=(p->op[1]->vecmod&0x3fff)<<6;
|
|
break;
|
|
case EN_VREADI80:
|
|
if(p->op[1]->offset){
|
|
p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
|
|
}
|
|
code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code2=(p->op[0]->reg<<22)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
|
|
code3=(p->op[0]->dreg<<26)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
|
|
code3|=(p->op[1]->vecmod&0x3fff)<<6;
|
|
break;
|
|
case EN_VWRITEI80:
|
|
if(p->op[1]->offset){
|
|
p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
|
|
}
|
|
code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code2=(p->op[0]->reg<<12)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
|
|
code3=((p->op[0]->dreg&0x3f)<<20)|((p->op[0]->dreg&0x3c0)<<10)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
|
|
code3|=(p->op[1]->vecmod&0x3fff)<<6;
|
|
break;
|
|
case EN_VARITHR80:
|
|
if(code<48) code|=64;
|
|
if(p->op[2]){
|
|
if(p->op[2]->offset){
|
|
p->op[2]->reg|=(absval(p->op[2]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[2]->dreg|=(absval(p->op[2]->offset,sec,pc,9,1)>>7)&3;
|
|
}
|
|
code=0xFC000000|(code<<19)|(p->op[2]->vecmod&0x70000);
|
|
code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|(p->op[2]->reg);
|
|
if(p->op[2]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code3=(p->op[0]->dreg<<26)|((p->op[1]->dreg&0x3f)<<20)|((p->op[1]->dreg&0x3c0)<<10)|(p->op[2]->dreg);
|
|
code3|=(p->op[2]->vecmod&0x3fff)<<6;
|
|
}else{
|
|
if(p->op[1]->offset){
|
|
p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
|
|
}
|
|
code=0xFC000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
code2=(p->op[0]->reg<<22)|(p->op[1]->reg);
|
|
if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code3=(p->op[0]->dreg<<26)|(p->op[1]->dreg);
|
|
code3|=(p->op[1]->vecmod&0x3fff)<<6;
|
|
}
|
|
break;
|
|
case EN_VARITHI80:
|
|
if(code<48) code|=64;
|
|
if(p->op[2]){
|
|
if(p->op[2]->offset){
|
|
p->op[2]->reg|=(absval(p->op[2]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[2]->dreg|=(absval(p->op[2]->offset,sec,pc,9,1)>>7);
|
|
}
|
|
code=0xFC000000|(code<<19)|(p->op[2]->vecmod&0x70000);
|
|
if(p->op[2]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|(1<<10)|(absval(p->op[2]->offset,sec,pc,16,0)&0x3ff);
|
|
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);
|
|
code3|=(p->op[2]->vecmod&0x3fff)<<6;
|
|
}else{
|
|
if(p->op[1]->offset){
|
|
p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
|
|
p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7);
|
|
}
|
|
code=0xFC000000|(code<<19)|(p->op[1]->vecmod&0x70000);
|
|
if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
|
|
code2=(p->op[0]->reg<<22)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
|
|
code3=(p->op[0]->dreg<<26)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
|
|
code3|=(p->op[1]->vecmod&0x3fff)<<6;
|
|
}
|
|
break;
|
|
default:
|
|
ierror(0);
|
|
}
|
|
|
|
if(enc>=EN_VLOAD48&&enc<=EN_VARITHI48){
|
|
db->data[0]=(code>>16)&0xff;
|
|
db->data[1]=(code>>24)&0xff;
|
|
db->data[3]=(code2>>24)&0xff;
|
|
db->data[2]=(code2>>16)&0xff;
|
|
db->data[5]=(code2>>8)&0xff;
|
|
db->data[4]=(code2>>0)&0xff;
|
|
}else if(sz==2){
|
|
db->data[0]=(code>>16)&0xff;
|
|
db->data[1]=(code>>24)&0xff;
|
|
}else if(sz==4){
|
|
db->data[1]=(code>>24)&0xff;
|
|
db->data[0]=(code>>16)&0xff;
|
|
db->data[3]=(code>>8)&0xff;
|
|
db->data[2]=(code)&0xff;
|
|
}else if(sz==6){
|
|
db->data[0]=(code>>16)&0xff;
|
|
db->data[1]=(code>>24)&0xff;
|
|
db->data[5]=(code2>>24)&0xff;
|
|
db->data[4]=(code2>>16)&0xff;
|
|
db->data[3]=(code2>>8)&0xff;
|
|
db->data[2]=(code2>>0)&0xff;
|
|
}
|
|
else if(sz==8){
|
|
db->data[1]=(code>>24)&0xff;
|
|
db->data[0]=(code>>16)&0xff;
|
|
db->data[3]=(code>>8)&0xff;
|
|
db->data[2]=(code)&0xff;
|
|
db->data[5]=(code2>>24)&0xff;
|
|
db->data[4]=(code2>>16)&0xff;
|
|
db->data[7]=(code2>>8)&0xff;
|
|
db->data[6]=(code2)&0xff;
|
|
}else if(sz==10){
|
|
db->data[0]=(code>>16)&0xff;
|
|
db->data[1]=(code>>24)&0xff;
|
|
db->data[3]=(code2>>24)&0xff;
|
|
db->data[2]=(code2>>16)&0xff;
|
|
db->data[5]=(code2>>8)&0xff;
|
|
db->data[4]=(code2>>0)&0xff;
|
|
db->data[7]=(code3>>24)&0xff;
|
|
db->data[6]=(code3>>16)&0xff;
|
|
db->data[9]=(code3>>8)&0xff;
|
|
db->data[8]=(code3>>0)&0xff;
|
|
}
|
|
db->relocs=relocs;
|
|
return db;
|
|
}
|
|
|
|
/* Create a dblock (with relocs, if necessary) for size bits of data. */
|
|
dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
|
|
{
|
|
dblock *new=new_dblock();
|
|
taddr val;
|
|
new->size=(bitsize+7)/8;
|
|
new->data=mymalloc(new->size);
|
|
if(op->type!=OP_ABS)
|
|
ierror(0);
|
|
if(bitsize!=8&&bitsize!=16&&bitsize!=32)
|
|
cpu_error(2);
|
|
val=absoffset(op->offset,sec,pc,&new->relocs,0,bitsize);
|
|
if(bitsize==32){
|
|
new->data[3]=val>>24;
|
|
new->data[2]=val>>16;
|
|
new->data[1]=val>>8;
|
|
new->data[0]=val;
|
|
}else if(bitsize==16){
|
|
new->data[1]=val>>8;
|
|
new->data[0]=val;
|
|
}else
|
|
new->data[0]=val;
|
|
return new;
|
|
}
|
|
|
|
|
|
/* Calculate the size of the current instruction; must be identical
|
|
to the data created by eval_instruction. */
|
|
size_t instruction_size(instruction *p,section *sec,taddr pc)
|
|
{
|
|
int c;
|
|
c=translate(p,sec,pc);
|
|
return oplen(mnemonics[c].ext.encoding);
|
|
}
|
|
|
|
operand *new_operand()
|
|
{
|
|
operand *new=mymalloc(sizeof(*new));
|
|
new->type=-1;
|
|
return new;
|
|
}
|
|
|
|
/* return true, if initialization was successfull */
|
|
int init_cpu()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
/* return true, if the passed argument is understood */
|
|
int cpu_args(char *p)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* parse cpu-specific directives; return pointer to end of
|
|
cpu-specific text */
|
|
char *parse_cpu_special(char *s)
|
|
{
|
|
char *name=s,*merk=s;
|
|
|
|
return merk;
|
|
}
|
|
|
|
int set_default_qualifiers(char **q,int *q_len)
|
|
/* fill in pointers to default qualifiers, return number of qualifiers */
|
|
{
|
|
q[0]="u32";
|
|
q_len[0]=3;
|
|
q[1]="";
|
|
q_len[1]=0;
|
|
return 2;
|
|
}
|
|
|
|
char *parse_instruction(char *s,int *inst_len,char **ext,int *ext_len,
|
|
int *ext_cnt)
|
|
/* parse instruction and save extension locations */
|
|
{
|
|
char *inst = s, l, i;
|
|
int cnt = 0;
|
|
|
|
while (*s && *s!='.' && !isspace((unsigned char)*s))
|
|
s++;
|
|
l = s - inst;
|
|
|
|
if(strncasecmp("divs",inst,l)&&strncmp("vreadacc",inst,l)&&
|
|
strncasecmp("vcmpge",inst,l)){
|
|
for(i=0;i<16;i++){
|
|
int cl=strlen(ccs[i]);
|
|
if(l>cl&&!strncasecmp(s-cl,ccs[i],cl)){
|
|
ext[0]=s-cl;
|
|
ext_len[0]=cl;
|
|
cnt=1;
|
|
l-=cl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ext_cnt = cnt;
|
|
|
|
*inst_len=l;
|
|
|
|
return s;
|
|
}
|