1*5822Srrh /* 2*5822Srrh * Copyright (c) 1982 Regents of the University of California 3*5822Srrh */ 4*5822Srrh #ifndef lint 5*5822Srrh static char sccsid[] = "@(#)ascode.c 4.8 02/14/82"; 6*5822Srrh #endif not lint 7*5822Srrh 8592Sbill #include <stdio.h> 9592Sbill #include "as.h" 10592Sbill #include "assyms.h" 11592Sbill 12*5822Srrh insout(opcode, ap, nact) 13*5822Srrh struct Opcode opcode; 14*5822Srrh struct arg *ap; 15*5822Srrh int nact; 16*5822Srrh { 17*5822Srrh int jxxflg; 18*5822Srrh reg struct instab *ip; /* the instruction */ 19*5822Srrh reg struct arg *ap_walk; /* actual param walk */ 20*5822Srrh reg int i; 21*5822Srrh reg int ap_type; /* actual param type */ 22*5822Srrh reg int ap_type_mask; /* masked actual param */ 23673Shenry 24592Sbill jxxflg = nact; 25592Sbill if (nact < 0) 26592Sbill nact = -nact; 27592Sbill if (passno == 1) { 28*5822Srrh if (!(ITABCHECK(opcode))) 29*5822Srrh panic("Botched reference into itab"); 30*5822Srrh ip = ITABFETCH(opcode); 31*5822Srrh if (nact < ip->i_nargs) 32*5822Srrh yyerror("Too few arguments"); 33*5822Srrh if (nact > ip->i_nargs) { 34*5822Srrh yyerror("Too many arguments"); 35*5822Srrh nact = ip->i_nargs; 36*5822Srrh } 37667Shenry /* 38667Shenry * Check argument compatability with instruction template 39667Shenry */ 40667Shenry for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){ 41673Shenry ap_type = ap_walk->a_atype; 42667Shenry ap_type_mask = ap_type & AMASK; 431746Shenry /* 44*5822Srrh * The switch value is >> by TYPLG so that the switch 451746Shenry * code is dense, not implemented as a sequence 461746Shenry * of branches but implemented as a casel. 471746Shenry * In addition, cases ACCI and ACCR are added to force 481746Shenry * dense switch code. 49*5822Srrh * switch on the type of fp 501746Shenry */ 51*5822Srrh switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){ 52*5822Srrh case ACCI >> TYPLG: 53*5822Srrh case ACCR >> TYPLG: 541746Shenry break; 55*5822Srrh case ACCB >> TYPLG: 56667Shenry if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){ 57667Shenry yyerror("arg %d, branch displacement must be an expression",i); 58667Shenry return; 59667Shenry } 60667Shenry break; 61*5822Srrh case ACCA >> TYPLG: 62667Shenry switch(ap_type_mask){ 63667Shenry case AREG: yyerror("arg %d, addressing a register",i); 64667Shenry return; 65667Shenry case AIMM: if ( !(ap_type & ASTAR) ){ 66667Shenry yyerror("arg %d, addressing an immediate operand",i); 67667Shenry return; 68667Shenry } 69667Shenry } 70667Shenry break; 71*5822Srrh case ACCM >> TYPLG: 72*5822Srrh case ACCW >> TYPLG: 73667Shenry switch(ap_type_mask){ 74667Shenry case AIMM: if (!(ap_type&ASTAR)) { 75667Shenry yyerror("arg %d, modifying a constant",i); 76667Shenry return; 77667Shenry } 78667Shenry } 79667Shenry break; 80667Shenry } /* end of the switch on fp_type */ 81667Shenry if (ap_type & AINDX) { 82667Shenry if (ap_walk->a_areg2==0xF) { 83667Shenry yyerror("arg %d, PC used as index",i); 84667Shenry return; 85667Shenry } 86667Shenry switch(ap_type_mask){ 87667Shenry case AREG: yyerror("arg %d, indexing the register file",i); 88667Shenry return; 89667Shenry case AIMM: yyerror("arg %d, indexing a constant",i); 90667Shenry return; 91673Shenry case ADECR: 92673Shenry case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) { 93667Shenry yyerror("arg %d, indexing with modified register",i); 94667Shenry return; 95667Shenry } 96667Shenry break; 97667Shenry } /* end of switch on ap_type_mask */ 98667Shenry } /* end of AINDX */ 99667Shenry } 100667Shenry } /* both passes here */ 101592Sbill if (jxxflg < 0) 102*5822Srrh ijxout(opcode, ap, nact); 103*5822Srrh else 104*5822Srrh putins(opcode, ap, nact); 105592Sbill } 106592Sbill 107592Sbill extern int d124; 108592Sbill 109*5822Srrh putins(opcode, ap, n) 110*5822Srrh struct Opcode opcode; 111592Sbill register struct arg *ap; 112*5822Srrh int n; /* Must be positive */ 113592Sbill { 114*5822Srrh reg struct exp *xp; 115*5822Srrh reg int argtype; 116*5822Srrh int i; 117*5822Srrh int reloc_how; 118*5822Srrh int value; 119592Sbill 120592Sbill #ifdef DEBUG 121592Sbill fflush(stdout); 122592Sbill #endif 123592Sbill if (passno == 2) 124592Sbill goto PASS2; 125592Sbill 126*5822Srrh dotp->e_xvalue += n; /* at least one byte per arg */ 127*5822Srrh switch(opcode.Op_eopcode){ 128*5822Srrh case NEW: 129*5822Srrh case CORE: 130*5822Srrh dotp->e_xvalue += 1; /* 1 byte opcode */ 131*5822Srrh break; 132*5822Srrh case ESCD: 133*5822Srrh case ESCF: 134*5822Srrh dotp->e_xvalue += 2; /* 2 byte opcode */ 135*5822Srrh break; 136*5822Srrh default: 137*5822Srrh panic("Bad escape opcode"); 138*5822Srrh } 139*5822Srrh 140629Shenry for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */ 141853Shenry argtype = ap->a_atype; 142853Shenry if (argtype & AINDX) 143629Shenry dotp->e_xvalue++; 1441746Shenry /* 1451746Shenry * This switch has been fixed by enumerating the no action 1461746Shenry * alternatives (those that have 1 one byte of code) 1471746Shenry * so that a casel instruction is emitted. 1481746Shenry */ 149853Shenry switch (argtype&~(AINDX|ASTAR)) { 1501746Shenry case AREG: 1511746Shenry case ABASE: 1521746Shenry case ADECR: 1531746Shenry case AINCR: 1541746Shenry break; 155592Sbill case AEXP: 156*5822Srrh argtype = fetcharg(ITABFETCH(opcode), i); 157*5822Srrh if (argtype == A_BB) 158592Sbill break; 159*5822Srrh if (argtype == A_BW){ 160629Shenry dotp->e_xvalue++; 161592Sbill break; 162592Sbill } 163592Sbill /* 164592Sbill * Reduces to PC relative 165592Sbill */ 166629Shenry dotp->e_xvalue += ap->a_dispsize; 167592Sbill break; 168592Sbill 169592Sbill case ADISP: 170629Shenry xp=ap->a_xp; 171629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 172629Shenry dotp->e_xvalue += ap->a_dispsize; 173592Sbill break; 174592Sbill } 175853Shenry if (xp->e_xvalue==0 && !(argtype&ASTAR)) 176592Sbill break; 177*5822Srrh dotp->e_xvalue += 1; 178*5822Srrh if (ISBYTE(xp->e_xvalue)) 179*5822Srrh break; 180*5822Srrh dotp->e_xvalue += 1; 181*5822Srrh if (ISWORD(xp->e_xvalue)) 182*5822Srrh break; 183*5822Srrh dotp->e_xvalue += 2; 184592Sbill break; 185592Sbill 186592Sbill case AIMM: 187*5822Srrh if (ap->a_atype&ASTAR) { 188*5822Srrh argtype=TYPL; 189*5822Srrh } else { 190*5822Srrh argtype = fetcharg(ITABFETCH(opcode), i); 191853Shenry if (argtype&ACCA) 192853Shenry argtype = TYPL; 193592Sbill else 194853Shenry argtype &= TYPMASK; 195629Shenry xp = ap->a_xp; 196*5822Srrh if (immconstant(ap->a_xp, argtype, &value)) 197*5822Srrh break; 198592Sbill } 199*5822Srrh dotp->e_xvalue += ty_nbyte[argtype]; 200592Sbill } /*end of the switch on the type*/ 201592Sbill } /*end of looping for all arguments*/ 202592Sbill return; 203592Sbill 204592Sbill PASS2: 205*5822Srrh /* 206*5822Srrh * Output the opcode 207*5822Srrh */ 208*5822Srrh switch(opcode.Op_eopcode){ 209*5822Srrh case NEW: 210*5822Srrh nnewopcodes++; 211*5822Srrh break; 212*5822Srrh case ESCD: 213*5822Srrh case ESCF: 214*5822Srrh nGHopcodes++; 215*5822Srrh Outb(opcode.Op_eopcode); 216*5822Srrh break; 217*5822Srrh case CORE: 218*5822Srrh break; 219*5822Srrh default: 220*5822Srrh panic("Bad escape opcode"); 221*5822Srrh } 222*5822Srrh Outb(opcode.Op_popcode); 223592Sbill 224592Sbill for (i=0; i<n; i++,ap++) {/* now for the arguments */ 225853Shenry argtype=ap->a_atype; 226629Shenry xp=ap->a_xp; 227673Shenry reloc_how = TYPNONE; 228853Shenry if (argtype&AINDX) { 229*5822Srrh { Outb(0x40 | ap->a_areg2); } 230853Shenry argtype &= ~AINDX; 231592Sbill } 232853Shenry if (argtype&ASTAR) { 233629Shenry ap->a_areg1 |= 0x10; 234853Shenry argtype &= ~ASTAR; 235592Sbill } 236853Shenry switch (argtype) { 237592Sbill case AREG: /* %r */ 238629Shenry ap->a_areg1 |= 0x50; 239592Sbill break; 240592Sbill case ABASE: /* (%r) */ 241629Shenry ap->a_areg1 |= 0x60; 242592Sbill break; 243592Sbill case ADECR: /* -(%r) */ 244629Shenry ap->a_areg1 |= 0x70; 245592Sbill break; 246665Shenry case AINCR: /* (%r)+ */ 247629Shenry ap->a_areg1 |= 0x80; 248592Sbill break; 249592Sbill case AEXP: /* expr */ 250*5822Srrh argtype = fetcharg(ITABFETCH(opcode), i); 251*5822Srrh if (argtype == A_BB) { 252853Shenry ap->a_areg1 = argtype = 253629Shenry xp->e_xvalue - (dotp->e_xvalue + 1); 254*5822Srrh if (xp->e_xtype & XXTRN) 255*5822Srrh yywarning("%s: destination label is external", 256*5822Srrh ITABFETCH(opcode)->s_name); 257*5822Srrh if (!ISBYTE(argtype)) 258*5822Srrh yyerror("%s: Branch too far: %d", 259*5822Srrh ITABFETCH(opcode)->s_name, 260*5822Srrh argtype); 261*5822Srrh break; 262592Sbill } 263*5822Srrh if (argtype == A_BW) { 264853Shenry ap->a_areg1 = argtype = xp->e_xvalue 265629Shenry -= dotp->e_xvalue + 2; 266*5822Srrh if (xp->e_xtype & XXTRN) 267*5822Srrh yywarning("%s: destination label is external", 268*5822Srrh ITABFETCH(opcode)->s_name); 269629Shenry xp->e_xtype = XABS; 270*5822Srrh if (!ISWORD(argtype)) 271*5822Srrh yyerror("%s: Branch too far: %d", 272*5822Srrh ITABFETCH(opcode)->s_name, 273*5822Srrh argtype); 274853Shenry xp->e_xvalue = argtype>>8; 275673Shenry reloc_how = TYPB; 276592Sbill break; 277592Sbill } 278592Sbill /* reduces to expr(pc) mode */ 279629Shenry ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); 280673Shenry reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL; 281592Sbill break; 282592Sbill 283592Sbill case ADISP: /* expr(%r) */ 284629Shenry ap->a_areg1 |= 0xA0; 285629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 286629Shenry ap->a_areg1 += mod124[ap->a_dispsize]; 287673Shenry reloc_how = type_124[ap->a_dispsize]; 288592Sbill break; 289592Sbill } 290629Shenry if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { 291629Shenry ap->a_areg1 ^= 0xC0; 292592Sbill break; 293592Sbill } 294673Shenry reloc_how = TYPB; 295*5822Srrh if (ISBYTE(xp->e_xvalue)) 296*5822Srrh break; 297*5822Srrh ap->a_areg1 += 0x20; 298*5822Srrh reloc_how = TYPW; 299*5822Srrh if (ISWORD(xp->e_xvalue)) 300*5822Srrh break; 301*5822Srrh ap->a_areg1 += 0x20; 302*5822Srrh reloc_how = TYPL; 303592Sbill break; 304592Sbill 305592Sbill case AIMM: /* $expr */ 306*5822Srrh if (ap->a_atype&ASTAR) { 307853Shenry argtype=TYPL; 308*5822Srrh } else { 309*5822Srrh argtype = fetcharg(ITABFETCH(opcode), i); 310853Shenry if (argtype&ACCA) 311*5822Srrh argtype = TYPL; 312592Sbill else 313853Shenry argtype &= TYPMASK; 314*5822Srrh if (immconstant(xp, argtype, &value)){ 315*5822Srrh reloc_how = TYPNONE; 316*5822Srrh ap->a_areg1 = value; 317592Sbill break; 318592Sbill } 319592Sbill } 320629Shenry ap->a_areg1 |= 0x8F; 321853Shenry reloc_how = argtype; 322592Sbill break; 323592Sbill 324853Shenry } /*end of the switch on argtype*/ 325592Sbill /* 326592Sbill * use the first byte to describe the argument 327592Sbill */ 328*5822Srrh Outb(ap->a_areg1); 329592Sbill #ifdef VMS 330592Sbill if ((vms_obj_ptr-sobuf) > 400) { 331592Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 332592Sbill vms_obj_ptr=sobuf+1; 333592Sbill } 334592Sbill #endif VMS 335673Shenry if (reloc_how != TYPNONE) 336673Shenry outrel(xp, reloc_how); 337592Sbill } /*end of the for to pick up all arguments*/ 338592Sbill } 339*5822Srrh /* 340*5822Srrh * Is xp an immediate constant? 341*5822Srrh * argtype: how the instruction will interpret the bytes 342*5822Srrh * xp->e_number.num_tag ("numtype"): the kind of number given 343*5822Srrh * 344*5822Srrh * Use the following table: 345*5822Srrh * float: TYPF, TYPD, TYPG, TYPH 346*5822Srrh * quad: TYPQ, TYPO 347*5822Srrh * int: TYPG, TYPW, TYPL 348*5822Srrh * 349*5822Srrh * numtype 350*5822Srrh * argtype float quad int 351*5822Srrh * 352*5822Srrh * float slitflt slitflt slitflt 353*5822Srrh * quad 0 0 0 354*5822Srrh * int 0..63 0 0..63 355*5822Srrh * 356*5822Srrh * Where the table entry implies the predicate to return. 357*5822Srrh */ 358*5822Srrh #define IMMFLT 1 /* these flags are not used by anybody (yet) */ 359*5822Srrh #define IMMINT 2 360*5822Srrh 361*5822Srrh int immconstant(xp, argtype, valuep) 362*5822Srrh reg struct exp *xp; 363*5822Srrh int argtype; 364*5822Srrh int *valuep; 365*5822Srrh { 366*5822Srrh reg int back = 0; 367*5822Srrh int numtype; 368*5822Srrh reg int fits; 369*5822Srrh 370*5822Srrh if ((xp->e_xtype & XTYPE) != XABS) 371*5822Srrh return(0); 372*5822Srrh if ((xp->e_xtype & XFORW) != 0) 373*5822Srrh return(0); 374*5822Srrh numtype = xp->e_number.num_tag; 375*5822Srrh 376*5822Srrh fits = 1; 377*5822Srrh if (passno == 2) switch(argtype){ 378*5822Srrh case TYPB: 379*5822Srrh switch(numtype){ 380*5822Srrh default: fits = 0; break; 381*5822Srrh case TYPB: fits = 1; break; 382*5822Srrh case TYPW: 383*5822Srrh case TYPL: 384*5822Srrh fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue); 385*5822Srrh break; 386*5822Srrh } 387*5822Srrh break; 388*5822Srrh case TYPW: 389*5822Srrh switch(numtype){ 390*5822Srrh default: fits = 0; break; 391*5822Srrh case TYPB: 392*5822Srrh case TYPW: fits = 1; break; 393*5822Srrh case TYPL: 394*5822Srrh fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue); 395*5822Srrh break; 396*5822Srrh } 397*5822Srrh break; 398*5822Srrh case TYPF: 399*5822Srrh if (numtype == TYPD){ /* same format for first 32 bits */ 400*5822Srrh fits = 1; 401*5822Srrh break; 402*5822Srrh } 403*5822Srrh /*FALLTHROUGH*/ 404*5822Srrh default: 405*5822Srrh fits = ty_nbyte[argtype] >= ty_nbyte[numtype]; 406*5822Srrh } 407*5822Srrh if (!fits){ 408*5822Srrh yywarning("Immediate constant type %s mismatches instruction type %s", 409*5822Srrh ty_string[numtype], 410*5822Srrh ty_string[argtype]); 411*5822Srrh } 412*5822Srrh 413*5822Srrh switch(argtype){ 414*5822Srrh case TYPF: 415*5822Srrh case TYPG: 416*5822Srrh case TYPD: 417*5822Srrh case TYPH: 418*5822Srrh back = slitflt(xp->e_number, argtype, valuep); 419*5822Srrh break; 420*5822Srrh case TYPO: 421*5822Srrh case TYPQ: 422*5822Srrh back = 0; 423*5822Srrh break; 424*5822Srrh case TYPB: 425*5822Srrh case TYPW: 426*5822Srrh case TYPL: 427*5822Srrh switch(numtype){ 428*5822Srrh case TYPO: 429*5822Srrh case TYPQ: 430*5822Srrh back = 0; 431*5822Srrh break; 432*5822Srrh default: 433*5822Srrh *valuep = xp->e_xvalue; 434*5822Srrh back = ISLIT(xp->e_xvalue); 435*5822Srrh break; 436*5822Srrh } 437*5822Srrh break; 438*5822Srrh } 439*5822Srrh return(back); 440*5822Srrh } 441