scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

ins.c (4589B)


      1 #include <stdlib.h>
      2 
      3 #include <scc/scc.h>
      4 
      5 #include "../../as.h"
      6 #include "proc.h"
      7 
      8 /*
      9  * This code is derived from PowerISA_V2.06B_V2_PUBLIC document.
     10  * All the names used in the specification are preserved in
     11  * this code.
     12  */
     13 
     14 static int
     15 getclass(Node *np)
     16 {
     17 	if (np->addr != AREG)
     18 		return 0;
     19 
     20 	switch (np->sym->value) {
     21 	case AREG_R0:
     22 	case AREG_R1:
     23 	case AREG_R2:
     24 	case AREG_R3:
     25 	case AREG_R4:
     26 	case AREG_R5:
     27 	case AREG_R6:
     28 	case AREG_R7:
     29 	case AREG_R8:
     30 	case AREG_R9:
     31 	case AREG_R10:
     32 	case AREG_R11:
     33 	case AREG_R12:
     34 	case AREG_R13:
     35 	case AREG_R14:
     36 	case AREG_R15:
     37 	case AREG_R16:
     38 	case AREG_R17:
     39 	case AREG_R18:
     40 	case AREG_R19:
     41 	case AREG_R20:
     42 	case AREG_R21:
     43 	case AREG_R22:
     44 	case AREG_R23:
     45 	case AREG_R24:
     46 	case AREG_R25:
     47 	case AREG_R26:
     48 	case AREG_R27:
     49 	case AREG_R29:
     50 	case AREG_R30:
     51 	case AREG_R31:
     52 		return GPRSCLASS;
     53 	default:
     54 		abort();
     55 	}
     56 }
     57 
     58 int
     59 match(Op *op, Node **args)
     60 {
     61 	unsigned char *p;
     62 	int arg, class, rep, opt;
     63 	Node *np;
     64 
     65 	if (!op->args)
     66 		return args == NULL;
     67 
     68 	opt = rep = 0;
     69 	for (p = op->args; arg = *p; ++p) {
     70 		if (rep)
     71 			--p;
     72 		if ((np = *args++) == NULL)
     73 			return (rep|opt) != 0;
     74 
     75 		switch (arg) {
     76 		case AOPT:
     77 			opt = 1;
     78 			break;
     79 		case AREP:
     80 			rep = 1;
     81 			break;
     82 		case AREG_GPRSCLASS:
     83 			class = GPRSCLASS;
     84 		check_class:
     85 			if ((getclass(np) & class) == 0)
     86 				return 0;
     87 			break;
     88 		case AIMM2:
     89 		case AIMM5:
     90 		case AIMM8:
     91 		case AIMM16:
     92 		case AIMM32:
     93 		case AIMM64:
     94 			if (np->addr != AIMM)
     95 				return 0;
     96 			if (toobig(np, arg))
     97 				error("overflow in immediate operand");
     98 			break;
     99 		case ASYM:
    100 			if (np->addr != AIMM || np->op != IDEN)
    101 				return 0;
    102 			break;
    103 		case ADIRECT:
    104 		case ASTR:
    105 			if (np->addr != arg)
    106 				return 0;
    107 			break;
    108 		default:
    109 			abort();
    110 		}
    111 	}
    112 
    113 	return *args == NULL;
    114 }
    115 
    116 Node *
    117 moperand(void)
    118 {
    119 	abort();
    120 }
    121 
    122 static void
    123 emit_packed(unsigned long ins)
    124 {
    125 	char buff[4];
    126 
    127 	if (endian == BIG_ENDIAN) {
    128 		buff[0] = ins >> 24;
    129 		buff[1] = ins >> 16;
    130 		buff[2] = ins >> 8;
    131 		buff[3] = ins;
    132 	} else {
    133 		buff[0] = ins;
    134 		buff[1] = ins >> 8;
    135 		buff[2] = ins >> 16;
    136 		buff[3] = ins >> 24;
    137 	}
    138 
    139 	emit(buff, 4);
    140 }
    141 
    142 void
    143 i_form(Op *op, Node **args)
    144 {
    145 	unsigned long ins, opcd, li, aa, lk;
    146 	long long dst;
    147 	long long max = 1l << 23;
    148 	long long min = -(1l << 23);
    149 
    150 	opcd = op->bytes[0];
    151 	aa = op->bytes[1];
    152 	lk = op->bytes[2];
    153 
    154 	dst = args[0]->sym->value;
    155 	if (dst & 0x3)
    156 		error("unaligned branch");
    157 	if (aa)
    158 		dst -= cursec->curpc - 4;
    159 	if (dst < min || dst > max)
    160 		error("out of range branch");
    161 
    162 	li = dst;
    163 	li >>= 2;
    164 	ins = opcd<<26 | li<<2 | aa<<1 | lk;
    165 	emit_packed(ins);
    166 }
    167 
    168 void
    169 b_form(Op *op, Node **args)
    170 {
    171 	unsigned long ins, opcd, bo, bi, bd, aa, lk;
    172 	long long dst;
    173 	long long max = 1l << 13;
    174 	long long min = -(1l << 13);
    175 
    176 	opcd = op->bytes[0];
    177 	aa = op->bytes[1];
    178 	lk = op->bytes[2];
    179 
    180 	bo = args[0]->sym->value;
    181 	bi = args[1]->sym->value;
    182 
    183 	dst = args[2]->sym->value;
    184 	if (dst & 0x3)
    185 		error("unaligned branch");
    186 	if (aa)
    187 		dst -= cursec->curpc - 4;
    188 
    189 	if (dst < min || dst > max)
    190 		error("out of range branch");
    191 	bd = dst;
    192 	bd >>= 2;
    193 
    194 	ins = opcd<<26 | bo<<21 | bi<<16 | bd<<11 | aa<<1 | lk;
    195 	emit_packed(ins);
    196 }
    197 
    198 void
    199 sc_form(Op *op, Node **args)
    200 {
    201 	abort();
    202 }
    203 
    204 void
    205 d_form(Op *op, Node **args)
    206 {
    207 	abort();
    208 }
    209 
    210 void
    211 ds_form(Op *op, Node **args)
    212 {
    213 	abort();
    214 }
    215 
    216 void
    217 dq_form(Op *op, Node **args)
    218 {
    219 	abort();
    220 }
    221 
    222 void
    223 x_form(Op *op, Node **args)
    224 {
    225 	abort();
    226 }
    227 
    228 void
    229 xl_form(Op *op, Node **args)
    230 {
    231 	unsigned long ins, bo, bi, bh, lk;
    232 	unsigned long opcd1, opcd2;
    233 	long long dst;
    234 
    235 	opcd1 = op->bytes[0];
    236 	opcd2 = op->bytes[1]<<8 | op->bytes[2];
    237 	lk = op->bytes[3];
    238 
    239 	bo = args[0]->sym->value;
    240 	bi = args[1]->sym->value;
    241 	bh = args[2]->sym->value;
    242 
    243 	ins = opcd1<<26 | bo<<21 | bi<<16 | bh<<11 | opcd2<<1 | lk;
    244 	emit_packed(ins);
    245 }
    246 
    247 void
    248 xfx_form(Op *op, Node **args)
    249 {
    250 	abort();
    251 }
    252 
    253 void
    254 xlfdorm_form(Op *op, Node **args)
    255 {
    256 	abort();
    257 }
    258 
    259 void
    260 xx1_form(Op *op, Node **args)
    261 {
    262 	abort();
    263 }
    264 
    265 void
    266 xx2_form(Op *op, Node **args)
    267 {
    268 	abort();
    269 }
    270 
    271 void
    272 xx3_form(Op *op, Node **args)
    273 {
    274 	abort();
    275 }
    276 
    277 void
    278 xx4_form(Op *op, Node **args)
    279 {
    280 	abort();
    281 }
    282 
    283 void
    284 xs_form(Op *op, Node **args)
    285 {
    286 	abort();
    287 }
    288 
    289 void
    290 xo_form(Op *op, Node **args)
    291 {
    292 	abort();
    293 }
    294 
    295 void
    296 a_form(Op *op, Node **args)
    297 {
    298 	abort();
    299 }
    300 
    301 void
    302 m_form(Op *op, Node **args)
    303 {
    304 	abort();
    305 }
    306 
    307 void
    308 md_form(Op *op, Node **args)
    309 {
    310 	abort();
    311 }
    312 
    313 void
    314 mds_form(Op *op, Node **args)
    315 {
    316 	abort();
    317 }
    318 
    319 void
    320 va_form(Op *op, Node **args)
    321 {
    322 	abort();
    323 }
    324 
    325 void
    326 vc_form(Op *op, Node **args)
    327 {
    328 	abort();
    329 }
    330 
    331 void
    332 vx_form(Op *op, Node **args)
    333 {
    334 	abort();
    335 }
    336 
    337 void
    338 evs_form(Op *op, Node **args)
    339 {
    340 	abort();
    341 }
    342 
    343 void
    344 z22_form(Op *op, Node **args)
    345 {
    346 	abort();
    347 }
    348 
    349 void
    350 z23_form(Op *op, Node **args)
    351 {
    352 	abort();
    353 }