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