ins.c (9695B)
1 #include <stdlib.h> 2 #include <string.h> 3 4 #include <scc/scc.h> 5 6 #include "../../as.h" 7 #include "proc.h" 8 9 /* 10 * This implementation is based in: 11 * - Zilog Z80 CPU Specifications by Sean Young 12 * - Decoding Z80 opcodes - of use to disassembler and emulator 13 * writers - by Cristian Dinu. 14 */ 15 16 static int 17 getclass(Node *np) 18 { 19 if (np->addr != AREG) 20 return 0; 21 22 switch (np->sym->value) { 23 case AREG_C: 24 return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS; 25 case AREG_A: 26 case AREG_B: 27 case AREG_D: 28 case AREG_E: 29 return RCLASS | PCLASS | QCLASS; 30 case AREG_H: 31 case AREG_L: 32 return RCLASS; 33 case AREG_IXL: 34 case AREG_IXH: 35 return PCLASS; 36 case AREG_IYL: 37 case AREG_IYH: 38 return QCLASS; 39 case AREG_HL: 40 return DDCLASS | QQCLASS; 41 case AREG_BC: 42 case AREG_DE: 43 return DDCLASS | QQCLASS | PPCLASS | RRCLASS; 44 case AREG_SP: 45 return DDCLASS | PPCLASS | RRCLASS; 46 case AREG_AF: 47 return QQCLASS; 48 case AREG_IX: 49 return PPCLASS; 50 case AREG_IY: 51 return RRCLASS; 52 case AREG_PO: 53 case AREG_PE: 54 case AREG_P: 55 case AREG_M: 56 return CCCLASS; 57 case AREG_NZ: 58 case AREG_Z: 59 case AREG_NC: 60 return CCCLASS | SSCLASS; 61 default: 62 return 0; 63 } 64 } 65 66 int 67 match(Op *op, Node **args) 68 { 69 unsigned char *p; 70 int arg, class, rep, opt; 71 Node *np; 72 73 if (!op->args) 74 return args == NULL; 75 76 opt = rep = 0; 77 for (p = op->args; arg = *p; ++p) { 78 if (rep) 79 --p; 80 if ((np = *args++) == NULL) 81 return (rep|opt) != 0; 82 83 switch (arg) { 84 case AOPT: 85 opt = 1; 86 break; 87 case AREP: 88 rep = 1; 89 break; 90 case AINDER_C: 91 arg = AREG_C; 92 goto indirect; 93 case AINDER_HL: 94 arg = AREG_HL; 95 goto indirect; 96 case AINDER_DE: 97 arg = AREG_DE; 98 goto indirect; 99 case AINDER_BC: 100 arg = AREG_BC; 101 goto indirect; 102 case AINDER_IX: 103 arg = AREG_IX; 104 goto indirect; 105 case AINDER_IY: 106 arg = AREG_IY; 107 goto indirect; 108 case AINDER_SP: 109 arg = AREG_SP; 110 indirect: 111 if (np->addr != AINDIR) 112 return 0; 113 np = np->left; 114 case AREG_A: 115 case AREG_I: 116 case AREG_R: 117 case AREG_F: 118 case AREG_HL: 119 case AREG_BC: 120 case AREG_DE: 121 case AREG_IY: 122 case AREG_IX: 123 case AREG_SP: 124 case AREG_AF: 125 case AREG_AF_: 126 if (np->addr != AREG || np->sym->value != arg) 127 return 0; 128 break; 129 case AREG_RCLASS: 130 class = RCLASS; 131 goto check_class; 132 case AREG_PCLASS: 133 class = PCLASS; 134 goto check_class; 135 case AREG_QCLASS: 136 class = QCLASS; 137 goto check_class; 138 case AREG_QQCLASS: 139 class = QQCLASS; 140 goto check_class; 141 case AREG_PPCLASS: 142 class = PPCLASS; 143 goto check_class; 144 case AREG_RRCLASS: 145 class = RRCLASS; 146 goto check_class; 147 case AREG_CCCLASS: 148 class = CCCLASS; 149 goto check_class; 150 case AREG_SSCLASS: 151 class = SSCLASS; 152 goto check_class; 153 case AREG_DDCLASS: 154 class = DDCLASS; 155 check_class: 156 if ((getclass(np) & class) == 0) 157 return 0; 158 break; 159 case AINDEX_IY: 160 arg = AREG_IY; 161 goto index_address; 162 case AINDEX_IX: 163 arg = AREG_IX; 164 index_address: 165 if (np->addr != AINDEX) 166 return 0; 167 np = np->left->left; 168 if (np->sym->value != arg) 169 return 0; 170 if (toobig(np, AIMM8)) 171 error("overflow in index"); 172 break; 173 case ARST: 174 if (np->addr != AIMM) 175 return 0; 176 if ((np->sym->value & ~0x38) != 0) 177 return 0; 178 break; 179 case AZERO: 180 if (np->addr != AIMM) 181 return 0; 182 break; 183 case AIMM3: 184 case AIMM8: 185 case AIMM16: 186 case AIMM32: 187 case AIMM64: 188 if (np->addr != AIMM) 189 return 0; 190 if (toobig(np, arg)) 191 error("overflow in immediate operand"); 192 break; 193 case ASYM: 194 if (np->addr != AIMM || np->op != IDEN) 195 return 0; 196 break; 197 case ADIRECT: 198 case ASTR: 199 if (np->addr != arg) 200 return 0; 201 break; 202 default: 203 abort(); 204 } 205 } 206 207 return *args == NULL; 208 } 209 210 /* 211 * (expr) -> ADIRECT 212 * (REG) -> AINDIR 213 * (REG + expr) -> AINDEX 214 * (REG - expr) -> AINDEX 215 * expr (REG) -> AINDEX 216 */ 217 Node * 218 moperand(void) 219 { 220 int op; 221 Node *np, *dir, *off, *reg; 222 223 dir = off = reg = NULL; 224 if (accept('(')) { 225 if (yytoken != REG) { 226 dir = expr(); 227 } else { 228 reg = getreg(); 229 switch (yytoken) { 230 case '+': 231 case '-': 232 off = expr(); 233 case ')': 234 break; 235 default: 236 unexpected(); 237 } 238 } 239 } else { 240 off = expr(); 241 expect('('); 242 reg = getreg(); 243 } 244 expect(')'); 245 246 if (dir) { 247 op = ADIRECT; 248 np = dir; 249 } else if (off) { 250 np = node(AREG_OFF, reg, off); 251 op = AINDEX; 252 } else { 253 np = reg; 254 op = AINDIR; 255 } 256 np = node(op, np, NULL); 257 np->addr = op; 258 return np; 259 } 260 261 static int 262 reg2int(Node *np) 263 { 264 switch (np->sym->value) { 265 case AREG_F: 266 case AREG_B: return 0; 267 case AREG_C: return 1; 268 case AREG_D: return 2; 269 case AREG_E: return 3; 270 case AREG_IXH: 271 case AREG_IYH: 272 case AREG_H: return 4; 273 case AREG_IXL: 274 case AREG_IYL: 275 case AREG_L: return 5; 276 case AREG_A: return 7; 277 case AREG_BC: return 0; 278 case AREG_DE: return 1; 279 case AREG_HL: 280 case AREG_IX: 281 case AREG_IY: return 2; 282 case AREG_AF: 283 case AREG_SP: return 3; 284 default: abort(); 285 } 286 } 287 288 static int 289 cc2int(Node *np) 290 { 291 switch (np->sym->value) { 292 case AREG_NZ: return 0; 293 case AREG_Z: return 1; 294 case AREG_NC: return 2; 295 case AREG_C: return 3; 296 case AREG_PO: return 4; 297 case AREG_PE: return 5; 298 case AREG_P: return 6; 299 case AREG_M: return 7; 300 default: abort(); 301 } 302 } 303 304 static int 305 ss2int(Node *np) 306 { 307 switch (np->sym->value) { 308 case AREG_NZ: return 4; 309 case AREG_Z: return 5; 310 case AREG_NC: return 6; 311 case AREG_C: return 7; 312 default: abort(); 313 } 314 } 315 316 void 317 dir(Op *op, Node **args) 318 { 319 Node *imm; 320 unsigned char buf[4]; 321 unsigned val; 322 int n = op->size; 323 324 imm = (args[1]->addr == ADIRECT) ? args[1] : args[0]; 325 imm = imm->left; 326 memcpy(buf, op->bytes, n); 327 val = imm->sym->value; 328 buf[n-1] = val >> 8; 329 buf[n-2] = val; 330 emit(buf, n); 331 } 332 333 void 334 ld8(Op *op, Node **args) 335 { 336 Node *par1 = args[0], *par2 = args[1]; 337 int n = op->size, i = n; 338 unsigned regval = 0; 339 unsigned char buf[4]; 340 341 memcpy(buf, op->bytes, n); 342 343 if (par1->addr == AREG) 344 regval |= reg2int(par1) << 3; 345 if (par2->addr == AREG) 346 regval |= reg2int(par2); 347 else if (par2->addr == AIMM) 348 buf[--i] = par2->sym->value; 349 350 buf[--i] |= regval; 351 emit(buf, n); 352 } 353 354 void 355 alu16(Op *op, Node **args) 356 { 357 Node *par; 358 int n = op->size; 359 unsigned val; 360 unsigned char buf[4]; 361 362 par = (args[1]) ? args[1] : args[0]; 363 val = reg2int(par); 364 memcpy(buf, op->bytes, n); 365 buf[n-1] |= val << 4; 366 emit(buf, n); 367 } 368 369 void 370 ld16(Op *op, Node **args) 371 { 372 Node *dst, *src, *tmp; 373 int n = op->size; 374 unsigned val; 375 unsigned char buf[4]; 376 377 dst = args[0]; 378 src = args[1]; 379 if (!src) { 380 alu16(op, args); 381 return; 382 } 383 384 if (dst->addr != AREG) { 385 tmp = src; 386 src = dst; 387 dst = tmp; 388 } 389 390 memcpy(buf, op->bytes, n); 391 if (src->addr == ADIRECT) 392 src = src->left; 393 val = src->sym->value; 394 buf[n-1] = val >> 8; 395 buf[n-2] = val; 396 buf[n-3] |= reg2int(dst) << 4; 397 emit(buf, n); 398 } 399 400 void 401 alu8(Op *op, Node **args) 402 { 403 Node *par = args[1]; 404 unsigned char buf[4]; 405 int n = op->size, shift; 406 unsigned val; 407 408 if (args[1]) { 409 shift = 0; 410 par = args[1]; 411 } else { 412 shift = 3; 413 par = args[0]; 414 } 415 416 switch (par->addr) { 417 case AIMM: 418 val = par->sym->value; 419 break; 420 case AREG: 421 val = reg2int(par) << shift; 422 break; 423 case AINDEX: 424 val = par->left->right->sym->value; 425 break; 426 case AINDIR: 427 val = 0; 428 break; 429 default: 430 abort(); 431 } 432 433 memcpy(buf, op->bytes, n); 434 buf[n-1] |= val; 435 emit(buf, n); 436 } 437 438 void 439 idx(Op *op, Node **args) 440 { 441 Node *tmp, *idx, *imm, *reg; 442 unsigned char buf[4]; 443 int n = op->size, i = n, shift = 0; 444 445 imm = reg = NULL; 446 if (args[0]->addr != AINDEX) { 447 shift = 3; 448 tmp = args[0]; 449 args[0] = args[1]; 450 args[1] = tmp; 451 } 452 idx = args[0]->left->right; 453 454 if (args[1]->addr == AREG) 455 reg = args[1]; 456 else 457 imm = args[1]; 458 459 memcpy(buf, op->bytes, n); 460 461 if (imm) 462 buf[--i] = imm->sym->value; 463 buf[--i] = idx->sym->value; 464 if (reg) 465 buf[--i] |= reg2int(reg) << shift; 466 467 emit(buf, n); 468 } 469 470 void 471 inout(Op *op, Node **args) 472 { 473 Node *port, *value; 474 unsigned val; 475 int n = op->size; 476 unsigned char buf[5]; 477 478 port = args[0]; 479 value = args[1]; 480 if (port->addr != ADIRECT && port->addr != AINDIR) { 481 value = port; 482 port = args[1]; 483 } 484 485 if (port->addr == ADIRECT) 486 val = port->left->sym->value; 487 else if (value->addr == AREG) 488 val = reg2int(value) << 3; 489 else 490 val = 0; 491 492 memcpy(buf, op->bytes, n); 493 buf[n-1] |= val; 494 emit(buf, n); 495 } 496 497 void 498 rot_bit(Op *op, Node **args) 499 { 500 Node *par = args[0]; 501 unsigned char buf[5]; 502 int n = op->size; 503 unsigned val, npar = 0; 504 505 memcpy(buf, op->bytes, n); 506 507 par = args[0]; 508 if (par->addr == AIMM) { 509 buf[n-1] |= par->sym->value << 3; 510 par = args[npar = 1]; 511 } 512 513 switch (par->addr) { 514 case AINDEX: 515 val = par->left->right->sym->value; 516 buf[n-2] = val; 517 par = args[npar+1]; 518 if (!par) 519 break; 520 case AREG: 521 val = reg2int(par); 522 buf[n-1] |= val; 523 case AINDIR: 524 break; 525 default: 526 abort(); 527 } 528 529 emit(buf, n); 530 } 531 532 void 533 im(Op *op, Node **args) 534 { 535 unsigned val = args[0]->sym->value; 536 unsigned char buf[4]; 537 int n = op->size; 538 539 if (val > 0) 540 ++val; 541 542 memcpy(buf, op->bytes, n); 543 buf[n-1] |= val << 3; 544 emit(buf, n); 545 } 546 547 void 548 branch(int relative, Op *op, Node **args) 549 { 550 unsigned char buf[4]; 551 Node *flag, *imm; 552 int n = op->size, i = n; 553 unsigned val; 554 int (*fun)(Node *); 555 556 flag = imm = NULL; 557 if (args[0]->addr == AREG) { 558 flag = args[0]; 559 imm = args[1]; 560 } else if (args[0]->addr == AIMM) { 561 imm = args[0]; 562 } 563 memcpy(buf, op->bytes, n); 564 565 if (imm) { 566 val = imm->sym->value; 567 if (!relative) 568 buf[--i] = val >> 8; 569 else 570 val -= cursec->curpc - 2; 571 buf[--i] = val; 572 573 } 574 if (flag) { 575 fun = (relative) ? ss2int : cc2int; 576 buf[--i] |= (*fun)(flag) << 3; 577 } 578 579 580 emit(buf, n); 581 } 582 583 void 584 jp(Op *op, Node **args) 585 { 586 branch(0, op, args); 587 } 588 589 void 590 jr(Op *op, Node **args) 591 { 592 branch(1, op, args); 593 } 594 595 void 596 rst(Op *op, Node **args) 597 { 598 unsigned char buf[1]; 599 600 buf[0] = op->bytes[0]; 601 buf[0] |= args[0]->sym->value; 602 emit(buf, 1); 603 }