interp.c revision 1.1.1.7
1/* Simulator for the moxie processor 2 Copyright (C) 2008-2017 Free Software Foundation, Inc. 3 Contributed by Anthony Green 4 5This file is part of GDB, the GNU debugger. 6 7This program is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3 of the License, or 10(at your option) any later version. 11 12This program is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "config.h" 21#include <fcntl.h> 22#include <signal.h> 23#include <stdlib.h> 24#include <string.h> 25#include <sys/times.h> 26#include <sys/param.h> 27#include <unistd.h> 28#include "bfd.h" 29#include "libiberty.h" 30#include "gdb/remote-sim.h" 31 32#include "sim-main.h" 33#include "sim-base.h" 34#include "sim-options.h" 35 36typedef int word; 37typedef unsigned int uword; 38 39/* Extract the signed 10-bit offset from a 16-bit branch 40 instruction. */ 41#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1) 42 43#define EXTRACT_WORD(addr) \ 44 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \ 45 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \ 46 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \ 47 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3))) 48 49#define EXTRACT_OFFSET(addr) \ 50 (unsigned int) \ 51 (((signed short) \ 52 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \ 53 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16) 54 55static unsigned long 56moxie_extract_unsigned_integer (unsigned char *addr, int len) 57{ 58 unsigned long retval; 59 unsigned char * p; 60 unsigned char * startaddr = (unsigned char *)addr; 61 unsigned char * endaddr = startaddr + len; 62 63 if (len > (int) sizeof (unsigned long)) 64 printf ("That operation is not available on integers of more than %zu bytes.", 65 sizeof (unsigned long)); 66 67 /* Start at the most significant end of the integer, and work towards 68 the least significant. */ 69 retval = 0; 70 71 for (p = endaddr; p > startaddr;) 72 retval = (retval << 8) | * -- p; 73 74 return retval; 75} 76 77static void 78moxie_store_unsigned_integer (unsigned char *addr, int len, unsigned long val) 79{ 80 unsigned char * p; 81 unsigned char * startaddr = (unsigned char *)addr; 82 unsigned char * endaddr = startaddr + len; 83 84 for (p = endaddr; p > startaddr;) 85 { 86 * -- p = val & 0xff; 87 val >>= 8; 88 } 89} 90 91/* moxie register names. */ 92static const char *reg_names[16] = 93 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", 94 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" }; 95 96/* The machine state. 97 98 This state is maintained in host byte order. The fetch/store 99 register functions must translate between host byte order and the 100 target processor byte order. Keeping this data in target byte 101 order simplifies the register read/write functions. Keeping this 102 data in native order improves the performance of the simulator. 103 Simulation speed is deemed more important. */ 104 105#define NUM_MOXIE_REGS 17 /* Including PC */ 106#define NUM_MOXIE_SREGS 256 /* The special registers */ 107#define PC_REGNO 16 108 109/* The ordering of the moxie_regset structure is matched in the 110 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */ 111/* TODO: This should be moved to sim-main.h:_sim_cpu. */ 112struct moxie_regset 113{ 114 word regs[NUM_MOXIE_REGS + 1]; /* primary registers */ 115 word sregs[256]; /* special registers */ 116 word cc; /* the condition code reg */ 117 unsigned long long insts; /* instruction counter */ 118}; 119 120#define CC_GT 1<<0 121#define CC_LT 1<<1 122#define CC_EQ 1<<2 123#define CC_GTU 1<<3 124#define CC_LTU 1<<4 125 126/* TODO: This should be moved to sim-main.h:_sim_cpu. */ 127union 128{ 129 struct moxie_regset asregs; 130 word asints [1]; /* but accessed larger... */ 131} cpu; 132 133static void 134set_initial_gprs (void) 135{ 136 int i; 137 long space; 138 139 /* Set up machine just out of reset. */ 140 cpu.asregs.regs[PC_REGNO] = 0; 141 142 /* Clean out the register contents. */ 143 for (i = 0; i < NUM_MOXIE_REGS; i++) 144 cpu.asregs.regs[i] = 0; 145 for (i = 0; i < NUM_MOXIE_SREGS; i++) 146 cpu.asregs.sregs[i] = 0; 147} 148 149/* Write a 1 byte value to memory. */ 150 151static INLINE void 152wbat (sim_cpu *scpu, word pc, word x, word v) 153{ 154 address_word cia = CPU_PC_GET (scpu); 155 156 sim_core_write_aligned_1 (scpu, cia, write_map, x, v); 157} 158 159/* Write a 2 byte value to memory. */ 160 161static INLINE void 162wsat (sim_cpu *scpu, word pc, word x, word v) 163{ 164 address_word cia = CPU_PC_GET (scpu); 165 166 sim_core_write_aligned_2 (scpu, cia, write_map, x, v); 167} 168 169/* Write a 4 byte value to memory. */ 170 171static INLINE void 172wlat (sim_cpu *scpu, word pc, word x, word v) 173{ 174 address_word cia = CPU_PC_GET (scpu); 175 176 sim_core_write_aligned_4 (scpu, cia, write_map, x, v); 177} 178 179/* Read 2 bytes from memory. */ 180 181static INLINE int 182rsat (sim_cpu *scpu, word pc, word x) 183{ 184 address_word cia = CPU_PC_GET (scpu); 185 186 return (sim_core_read_aligned_2 (scpu, cia, read_map, x)); 187} 188 189/* Read 1 byte from memory. */ 190 191static INLINE int 192rbat (sim_cpu *scpu, word pc, word x) 193{ 194 address_word cia = CPU_PC_GET (scpu); 195 196 return (sim_core_read_aligned_1 (scpu, cia, read_map, x)); 197} 198 199/* Read 4 bytes from memory. */ 200 201static INLINE int 202rlat (sim_cpu *scpu, word pc, word x) 203{ 204 address_word cia = CPU_PC_GET (scpu); 205 206 return (sim_core_read_aligned_4 (scpu, cia, read_map, x)); 207} 208 209#define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; } 210 211static unsigned int 212convert_target_flags (unsigned int tflags) 213{ 214 unsigned int hflags = 0x0; 215 216 CHECK_FLAG(0x0001, O_WRONLY); 217 CHECK_FLAG(0x0002, O_RDWR); 218 CHECK_FLAG(0x0008, O_APPEND); 219 CHECK_FLAG(0x0200, O_CREAT); 220 CHECK_FLAG(0x0400, O_TRUNC); 221 CHECK_FLAG(0x0800, O_EXCL); 222 CHECK_FLAG(0x2000, O_SYNC); 223 224 if (tflags != 0x0) 225 fprintf (stderr, 226 "Simulator Error: problem converting target open flags for host. 0x%x\n", 227 tflags); 228 229 return hflags; 230} 231 232/* TODO: Split this up into finger trace levels than just insn. */ 233#define MOXIE_TRACE_INSN(str) \ 234 TRACE_INSN (scpu, "0x%08x, %s, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", \ 235 opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \ 236 cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \ 237 cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \ 238 cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \ 239 cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \ 240 cpu.asregs.regs[14], cpu.asregs.regs[15]) 241 242void 243sim_engine_run (SIM_DESC sd, 244 int next_cpu_nr, /* ignore */ 245 int nr_cpus, /* ignore */ 246 int siggnal) /* ignore */ 247{ 248 word pc, opc; 249 unsigned short inst; 250 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */ 251 address_word cia = CPU_PC_GET (scpu); 252 253 pc = cpu.asregs.regs[PC_REGNO]; 254 255 /* Run instructions here. */ 256 do 257 { 258 opc = pc; 259 260 /* Fetch the instruction at pc. */ 261 inst = (sim_core_read_aligned_1 (scpu, cia, read_map, pc) << 8) 262 + sim_core_read_aligned_1 (scpu, cia, read_map, pc+1); 263 264 /* Decode instruction. */ 265 if (inst & (1 << 15)) 266 { 267 if (inst & (1 << 14)) 268 { 269 /* This is a Form 3 instruction. */ 270 int opcode = (inst >> 10 & 0xf); 271 272 switch (opcode) 273 { 274 case 0x00: /* beq */ 275 { 276 MOXIE_TRACE_INSN ("beq"); 277 if (cpu.asregs.cc & CC_EQ) 278 pc += INST2OFFSET(inst); 279 } 280 break; 281 case 0x01: /* bne */ 282 { 283 MOXIE_TRACE_INSN ("bne"); 284 if (! (cpu.asregs.cc & CC_EQ)) 285 pc += INST2OFFSET(inst); 286 } 287 break; 288 case 0x02: /* blt */ 289 { 290 MOXIE_TRACE_INSN ("blt"); 291 if (cpu.asregs.cc & CC_LT) 292 pc += INST2OFFSET(inst); 293 } break; 294 case 0x03: /* bgt */ 295 { 296 MOXIE_TRACE_INSN ("bgt"); 297 if (cpu.asregs.cc & CC_GT) 298 pc += INST2OFFSET(inst); 299 } 300 break; 301 case 0x04: /* bltu */ 302 { 303 MOXIE_TRACE_INSN ("bltu"); 304 if (cpu.asregs.cc & CC_LTU) 305 pc += INST2OFFSET(inst); 306 } 307 break; 308 case 0x05: /* bgtu */ 309 { 310 MOXIE_TRACE_INSN ("bgtu"); 311 if (cpu.asregs.cc & CC_GTU) 312 pc += INST2OFFSET(inst); 313 } 314 break; 315 case 0x06: /* bge */ 316 { 317 MOXIE_TRACE_INSN ("bge"); 318 if (cpu.asregs.cc & (CC_GT | CC_EQ)) 319 pc += INST2OFFSET(inst); 320 } 321 break; 322 case 0x07: /* ble */ 323 { 324 MOXIE_TRACE_INSN ("ble"); 325 if (cpu.asregs.cc & (CC_LT | CC_EQ)) 326 pc += INST2OFFSET(inst); 327 } 328 break; 329 case 0x08: /* bgeu */ 330 { 331 MOXIE_TRACE_INSN ("bgeu"); 332 if (cpu.asregs.cc & (CC_GTU | CC_EQ)) 333 pc += INST2OFFSET(inst); 334 } 335 break; 336 case 0x09: /* bleu */ 337 { 338 MOXIE_TRACE_INSN ("bleu"); 339 if (cpu.asregs.cc & (CC_LTU | CC_EQ)) 340 pc += INST2OFFSET(inst); 341 } 342 break; 343 default: 344 { 345 MOXIE_TRACE_INSN ("SIGILL3"); 346 sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL); 347 break; 348 } 349 } 350 } 351 else 352 { 353 /* This is a Form 2 instruction. */ 354 int opcode = (inst >> 12 & 0x3); 355 switch (opcode) 356 { 357 case 0x00: /* inc */ 358 { 359 int a = (inst >> 8) & 0xf; 360 unsigned av = cpu.asregs.regs[a]; 361 unsigned v = (inst & 0xff); 362 363 MOXIE_TRACE_INSN ("inc"); 364 cpu.asregs.regs[a] = av + v; 365 } 366 break; 367 case 0x01: /* dec */ 368 { 369 int a = (inst >> 8) & 0xf; 370 unsigned av = cpu.asregs.regs[a]; 371 unsigned v = (inst & 0xff); 372 373 MOXIE_TRACE_INSN ("dec"); 374 cpu.asregs.regs[a] = av - v; 375 } 376 break; 377 case 0x02: /* gsr */ 378 { 379 int a = (inst >> 8) & 0xf; 380 unsigned v = (inst & 0xff); 381 382 MOXIE_TRACE_INSN ("gsr"); 383 cpu.asregs.regs[a] = cpu.asregs.sregs[v]; 384 } 385 break; 386 case 0x03: /* ssr */ 387 { 388 int a = (inst >> 8) & 0xf; 389 unsigned v = (inst & 0xff); 390 391 MOXIE_TRACE_INSN ("ssr"); 392 cpu.asregs.sregs[v] = cpu.asregs.regs[a]; 393 } 394 break; 395 default: 396 MOXIE_TRACE_INSN ("SIGILL2"); 397 sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL); 398 break; 399 } 400 } 401 } 402 else 403 { 404 /* This is a Form 1 instruction. */ 405 int opcode = inst >> 8; 406 switch (opcode) 407 { 408 case 0x00: /* bad */ 409 opc = opcode; 410 MOXIE_TRACE_INSN ("SIGILL0"); 411 sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL); 412 break; 413 case 0x01: /* ldi.l (immediate) */ 414 { 415 int reg = (inst >> 4) & 0xf; 416 unsigned int val = EXTRACT_WORD(pc+2); 417 418 MOXIE_TRACE_INSN ("ldi.l"); 419 cpu.asregs.regs[reg] = val; 420 pc += 4; 421 } 422 break; 423 case 0x02: /* mov (register-to-register) */ 424 { 425 int dest = (inst >> 4) & 0xf; 426 int src = (inst ) & 0xf; 427 428 MOXIE_TRACE_INSN ("mov"); 429 cpu.asregs.regs[dest] = cpu.asregs.regs[src]; 430 } 431 break; 432 case 0x03: /* jsra */ 433 { 434 unsigned int fn = EXTRACT_WORD(pc+2); 435 unsigned int sp = cpu.asregs.regs[1]; 436 437 MOXIE_TRACE_INSN ("jsra"); 438 /* Save a slot for the static chain. */ 439 sp -= 4; 440 441 /* Push the return address. */ 442 sp -= 4; 443 wlat (scpu, opc, sp, pc + 6); 444 445 /* Push the current frame pointer. */ 446 sp -= 4; 447 wlat (scpu, opc, sp, cpu.asregs.regs[0]); 448 449 /* Uncache the stack pointer and set the pc and $fp. */ 450 cpu.asregs.regs[1] = sp; 451 cpu.asregs.regs[0] = sp; 452 pc = fn - 2; 453 } 454 break; 455 case 0x04: /* ret */ 456 { 457 unsigned int sp = cpu.asregs.regs[0]; 458 459 MOXIE_TRACE_INSN ("ret"); 460 461 /* Pop the frame pointer. */ 462 cpu.asregs.regs[0] = rlat (scpu, opc, sp); 463 sp += 4; 464 465 /* Pop the return address. */ 466 pc = rlat (scpu, opc, sp) - 2; 467 sp += 4; 468 469 /* Skip over the static chain slot. */ 470 sp += 4; 471 472 /* Uncache the stack pointer. */ 473 cpu.asregs.regs[1] = sp; 474 } 475 break; 476 case 0x05: /* add.l */ 477 { 478 int a = (inst >> 4) & 0xf; 479 int b = inst & 0xf; 480 unsigned av = cpu.asregs.regs[a]; 481 unsigned bv = cpu.asregs.regs[b]; 482 483 MOXIE_TRACE_INSN ("add.l"); 484 cpu.asregs.regs[a] = av + bv; 485 } 486 break; 487 case 0x06: /* push */ 488 { 489 int a = (inst >> 4) & 0xf; 490 int b = inst & 0xf; 491 int sp = cpu.asregs.regs[a] - 4; 492 493 MOXIE_TRACE_INSN ("push"); 494 wlat (scpu, opc, sp, cpu.asregs.regs[b]); 495 cpu.asregs.regs[a] = sp; 496 } 497 break; 498 case 0x07: /* pop */ 499 { 500 int a = (inst >> 4) & 0xf; 501 int b = inst & 0xf; 502 int sp = cpu.asregs.regs[a]; 503 504 MOXIE_TRACE_INSN ("pop"); 505 cpu.asregs.regs[b] = rlat (scpu, opc, sp); 506 cpu.asregs.regs[a] = sp + 4; 507 } 508 break; 509 case 0x08: /* lda.l */ 510 { 511 int reg = (inst >> 4) & 0xf; 512 unsigned int addr = EXTRACT_WORD(pc+2); 513 514 MOXIE_TRACE_INSN ("lda.l"); 515 cpu.asregs.regs[reg] = rlat (scpu, opc, addr); 516 pc += 4; 517 } 518 break; 519 case 0x09: /* sta.l */ 520 { 521 int reg = (inst >> 4) & 0xf; 522 unsigned int addr = EXTRACT_WORD(pc+2); 523 524 MOXIE_TRACE_INSN ("sta.l"); 525 wlat (scpu, opc, addr, cpu.asregs.regs[reg]); 526 pc += 4; 527 } 528 break; 529 case 0x0a: /* ld.l (register indirect) */ 530 { 531 int src = inst & 0xf; 532 int dest = (inst >> 4) & 0xf; 533 int xv; 534 535 MOXIE_TRACE_INSN ("ld.l"); 536 xv = cpu.asregs.regs[src]; 537 cpu.asregs.regs[dest] = rlat (scpu, opc, xv); 538 } 539 break; 540 case 0x0b: /* st.l */ 541 { 542 int dest = (inst >> 4) & 0xf; 543 int val = inst & 0xf; 544 545 MOXIE_TRACE_INSN ("st.l"); 546 wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]); 547 } 548 break; 549 case 0x0c: /* ldo.l */ 550 { 551 unsigned int addr = EXTRACT_OFFSET(pc+2); 552 int a = (inst >> 4) & 0xf; 553 int b = inst & 0xf; 554 555 MOXIE_TRACE_INSN ("ldo.l"); 556 addr += cpu.asregs.regs[b]; 557 cpu.asregs.regs[a] = rlat (scpu, opc, addr); 558 pc += 2; 559 } 560 break; 561 case 0x0d: /* sto.l */ 562 { 563 unsigned int addr = EXTRACT_OFFSET(pc+2); 564 int a = (inst >> 4) & 0xf; 565 int b = inst & 0xf; 566 567 MOXIE_TRACE_INSN ("sto.l"); 568 addr += cpu.asregs.regs[a]; 569 wlat (scpu, opc, addr, cpu.asregs.regs[b]); 570 pc += 2; 571 } 572 break; 573 case 0x0e: /* cmp */ 574 { 575 int a = (inst >> 4) & 0xf; 576 int b = inst & 0xf; 577 int cc = 0; 578 int va = cpu.asregs.regs[a]; 579 int vb = cpu.asregs.regs[b]; 580 581 MOXIE_TRACE_INSN ("cmp"); 582 if (va == vb) 583 cc = CC_EQ; 584 else 585 { 586 cc |= (va < vb ? CC_LT : 0); 587 cc |= (va > vb ? CC_GT : 0); 588 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0); 589 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0); 590 } 591 592 cpu.asregs.cc = cc; 593 } 594 break; 595 case 0x0f: /* nop */ 596 break; 597 case 0x10: /* sex.b */ 598 { 599 int a = (inst >> 4) & 0xf; 600 int b = inst & 0xf; 601 signed char bv = cpu.asregs.regs[b]; 602 603 MOXIE_TRACE_INSN ("sex.b"); 604 cpu.asregs.regs[a] = (int) bv; 605 } 606 break; 607 case 0x11: /* sex.s */ 608 { 609 int a = (inst >> 4) & 0xf; 610 int b = inst & 0xf; 611 signed short bv = cpu.asregs.regs[b]; 612 613 MOXIE_TRACE_INSN ("sex.s"); 614 cpu.asregs.regs[a] = (int) bv; 615 } 616 break; 617 case 0x12: /* zex.b */ 618 { 619 int a = (inst >> 4) & 0xf; 620 int b = inst & 0xf; 621 signed char bv = cpu.asregs.regs[b]; 622 623 MOXIE_TRACE_INSN ("zex.b"); 624 cpu.asregs.regs[a] = (int) bv & 0xff; 625 } 626 break; 627 case 0x13: /* zex.s */ 628 { 629 int a = (inst >> 4) & 0xf; 630 int b = inst & 0xf; 631 signed short bv = cpu.asregs.regs[b]; 632 633 MOXIE_TRACE_INSN ("zex.s"); 634 cpu.asregs.regs[a] = (int) bv & 0xffff; 635 } 636 break; 637 case 0x14: /* umul.x */ 638 { 639 int a = (inst >> 4) & 0xf; 640 int b = inst & 0xf; 641 unsigned av = cpu.asregs.regs[a]; 642 unsigned bv = cpu.asregs.regs[b]; 643 unsigned long long r = 644 (unsigned long long) av * (unsigned long long) bv; 645 646 MOXIE_TRACE_INSN ("umul.x"); 647 cpu.asregs.regs[a] = r >> 32; 648 } 649 break; 650 case 0x15: /* mul.x */ 651 { 652 int a = (inst >> 4) & 0xf; 653 int b = inst & 0xf; 654 unsigned av = cpu.asregs.regs[a]; 655 unsigned bv = cpu.asregs.regs[b]; 656 signed long long r = 657 (signed long long) av * (signed long long) bv; 658 659 MOXIE_TRACE_INSN ("mul.x"); 660 cpu.asregs.regs[a] = r >> 32; 661 } 662 break; 663 case 0x16: /* bad */ 664 case 0x17: /* bad */ 665 case 0x18: /* bad */ 666 { 667 opc = opcode; 668 MOXIE_TRACE_INSN ("SIGILL0"); 669 sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL); 670 break; 671 } 672 case 0x19: /* jsr */ 673 { 674 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf]; 675 unsigned int sp = cpu.asregs.regs[1]; 676 677 MOXIE_TRACE_INSN ("jsr"); 678 679 /* Save a slot for the static chain. */ 680 sp -= 4; 681 682 /* Push the return address. */ 683 sp -= 4; 684 wlat (scpu, opc, sp, pc + 2); 685 686 /* Push the current frame pointer. */ 687 sp -= 4; 688 wlat (scpu, opc, sp, cpu.asregs.regs[0]); 689 690 /* Uncache the stack pointer and set the fp & pc. */ 691 cpu.asregs.regs[1] = sp; 692 cpu.asregs.regs[0] = sp; 693 pc = fn - 2; 694 } 695 break; 696 case 0x1a: /* jmpa */ 697 { 698 unsigned int tgt = EXTRACT_WORD(pc+2); 699 700 MOXIE_TRACE_INSN ("jmpa"); 701 pc = tgt - 2; 702 } 703 break; 704 case 0x1b: /* ldi.b (immediate) */ 705 { 706 int reg = (inst >> 4) & 0xf; 707 unsigned int val = EXTRACT_WORD(pc+2); 708 709 MOXIE_TRACE_INSN ("ldi.b"); 710 cpu.asregs.regs[reg] = val; 711 pc += 4; 712 } 713 break; 714 case 0x1c: /* ld.b (register indirect) */ 715 { 716 int src = inst & 0xf; 717 int dest = (inst >> 4) & 0xf; 718 int xv; 719 720 MOXIE_TRACE_INSN ("ld.b"); 721 xv = cpu.asregs.regs[src]; 722 cpu.asregs.regs[dest] = rbat (scpu, opc, xv); 723 } 724 break; 725 case 0x1d: /* lda.b */ 726 { 727 int reg = (inst >> 4) & 0xf; 728 unsigned int addr = EXTRACT_WORD(pc+2); 729 730 MOXIE_TRACE_INSN ("lda.b"); 731 cpu.asregs.regs[reg] = rbat (scpu, opc, addr); 732 pc += 4; 733 } 734 break; 735 case 0x1e: /* st.b */ 736 { 737 int dest = (inst >> 4) & 0xf; 738 int val = inst & 0xf; 739 740 MOXIE_TRACE_INSN ("st.b"); 741 wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]); 742 } 743 break; 744 case 0x1f: /* sta.b */ 745 { 746 int reg = (inst >> 4) & 0xf; 747 unsigned int addr = EXTRACT_WORD(pc+2); 748 749 MOXIE_TRACE_INSN ("sta.b"); 750 wbat (scpu, opc, addr, cpu.asregs.regs[reg]); 751 pc += 4; 752 } 753 break; 754 case 0x20: /* ldi.s (immediate) */ 755 { 756 int reg = (inst >> 4) & 0xf; 757 758 unsigned int val = EXTRACT_WORD(pc+2); 759 760 MOXIE_TRACE_INSN ("ldi.s"); 761 cpu.asregs.regs[reg] = val; 762 pc += 4; 763 } 764 break; 765 case 0x21: /* ld.s (register indirect) */ 766 { 767 int src = inst & 0xf; 768 int dest = (inst >> 4) & 0xf; 769 int xv; 770 771 MOXIE_TRACE_INSN ("ld.s"); 772 xv = cpu.asregs.regs[src]; 773 cpu.asregs.regs[dest] = rsat (scpu, opc, xv); 774 } 775 break; 776 case 0x22: /* lda.s */ 777 { 778 int reg = (inst >> 4) & 0xf; 779 unsigned int addr = EXTRACT_WORD(pc+2); 780 781 MOXIE_TRACE_INSN ("lda.s"); 782 cpu.asregs.regs[reg] = rsat (scpu, opc, addr); 783 pc += 4; 784 } 785 break; 786 case 0x23: /* st.s */ 787 { 788 int dest = (inst >> 4) & 0xf; 789 int val = inst & 0xf; 790 791 MOXIE_TRACE_INSN ("st.s"); 792 wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]); 793 } 794 break; 795 case 0x24: /* sta.s */ 796 { 797 int reg = (inst >> 4) & 0xf; 798 unsigned int addr = EXTRACT_WORD(pc+2); 799 800 MOXIE_TRACE_INSN ("sta.s"); 801 wsat (scpu, opc, addr, cpu.asregs.regs[reg]); 802 pc += 4; 803 } 804 break; 805 case 0x25: /* jmp */ 806 { 807 int reg = (inst >> 4) & 0xf; 808 809 MOXIE_TRACE_INSN ("jmp"); 810 pc = cpu.asregs.regs[reg] - 2; 811 } 812 break; 813 case 0x26: /* and */ 814 { 815 int a = (inst >> 4) & 0xf; 816 int b = inst & 0xf; 817 int av, bv; 818 819 MOXIE_TRACE_INSN ("and"); 820 av = cpu.asregs.regs[a]; 821 bv = cpu.asregs.regs[b]; 822 cpu.asregs.regs[a] = av & bv; 823 } 824 break; 825 case 0x27: /* lshr */ 826 { 827 int a = (inst >> 4) & 0xf; 828 int b = inst & 0xf; 829 int av = cpu.asregs.regs[a]; 830 int bv = cpu.asregs.regs[b]; 831 832 MOXIE_TRACE_INSN ("lshr"); 833 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv); 834 } 835 break; 836 case 0x28: /* ashl */ 837 { 838 int a = (inst >> 4) & 0xf; 839 int b = inst & 0xf; 840 int av = cpu.asregs.regs[a]; 841 int bv = cpu.asregs.regs[b]; 842 843 MOXIE_TRACE_INSN ("ashl"); 844 cpu.asregs.regs[a] = av << bv; 845 } 846 break; 847 case 0x29: /* sub.l */ 848 { 849 int a = (inst >> 4) & 0xf; 850 int b = inst & 0xf; 851 unsigned av = cpu.asregs.regs[a]; 852 unsigned bv = cpu.asregs.regs[b]; 853 854 MOXIE_TRACE_INSN ("sub.l"); 855 cpu.asregs.regs[a] = av - bv; 856 } 857 break; 858 case 0x2a: /* neg */ 859 { 860 int a = (inst >> 4) & 0xf; 861 int b = inst & 0xf; 862 int bv = cpu.asregs.regs[b]; 863 864 MOXIE_TRACE_INSN ("neg"); 865 cpu.asregs.regs[a] = - bv; 866 } 867 break; 868 case 0x2b: /* or */ 869 { 870 int a = (inst >> 4) & 0xf; 871 int b = inst & 0xf; 872 int av, bv; 873 874 MOXIE_TRACE_INSN ("or"); 875 av = cpu.asregs.regs[a]; 876 bv = cpu.asregs.regs[b]; 877 cpu.asregs.regs[a] = av | bv; 878 } 879 break; 880 case 0x2c: /* not */ 881 { 882 int a = (inst >> 4) & 0xf; 883 int b = inst & 0xf; 884 int bv = cpu.asregs.regs[b]; 885 886 MOXIE_TRACE_INSN ("not"); 887 cpu.asregs.regs[a] = 0xffffffff ^ bv; 888 } 889 break; 890 case 0x2d: /* ashr */ 891 { 892 int a = (inst >> 4) & 0xf; 893 int b = inst & 0xf; 894 int av = cpu.asregs.regs[a]; 895 int bv = cpu.asregs.regs[b]; 896 897 MOXIE_TRACE_INSN ("ashr"); 898 cpu.asregs.regs[a] = av >> bv; 899 } 900 break; 901 case 0x2e: /* xor */ 902 { 903 int a = (inst >> 4) & 0xf; 904 int b = inst & 0xf; 905 int av, bv; 906 907 MOXIE_TRACE_INSN ("xor"); 908 av = cpu.asregs.regs[a]; 909 bv = cpu.asregs.regs[b]; 910 cpu.asregs.regs[a] = av ^ bv; 911 } 912 break; 913 case 0x2f: /* mul.l */ 914 { 915 int a = (inst >> 4) & 0xf; 916 int b = inst & 0xf; 917 unsigned av = cpu.asregs.regs[a]; 918 unsigned bv = cpu.asregs.regs[b]; 919 920 MOXIE_TRACE_INSN ("mul.l"); 921 cpu.asregs.regs[a] = av * bv; 922 } 923 break; 924 case 0x30: /* swi */ 925 { 926 unsigned int inum = EXTRACT_WORD(pc+2); 927 928 MOXIE_TRACE_INSN ("swi"); 929 /* Set the special registers appropriately. */ 930 cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */ 931 cpu.asregs.sregs[3] = inum; 932 switch (inum) 933 { 934 case 0x1: /* SYS_exit */ 935 { 936 sim_engine_halt (sd, NULL, NULL, pc, sim_exited, 937 cpu.asregs.regs[2]); 938 break; 939 } 940 case 0x2: /* SYS_open */ 941 { 942 char fname[1024]; 943 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]); 944 int perm = (int) cpu.asregs.regs[4]; 945 int fd = open (fname, mode, perm); 946 sim_core_read_buffer (sd, scpu, read_map, fname, 947 cpu.asregs.regs[2], 1024); 948 /* FIXME - set errno */ 949 cpu.asregs.regs[2] = fd; 950 break; 951 } 952 case 0x4: /* SYS_read */ 953 { 954 int fd = cpu.asregs.regs[2]; 955 unsigned len = (unsigned) cpu.asregs.regs[4]; 956 char *buf = malloc (len); 957 cpu.asregs.regs[2] = read (fd, buf, len); 958 sim_core_write_buffer (sd, scpu, write_map, buf, 959 cpu.asregs.regs[3], len); 960 free (buf); 961 break; 962 } 963 case 0x5: /* SYS_write */ 964 { 965 char *str; 966 /* String length is at 0x12($fp) */ 967 unsigned count, len = (unsigned) cpu.asregs.regs[4]; 968 str = malloc (len); 969 sim_core_read_buffer (sd, scpu, read_map, str, 970 cpu.asregs.regs[3], len); 971 count = write (cpu.asregs.regs[2], str, len); 972 free (str); 973 cpu.asregs.regs[2] = count; 974 break; 975 } 976 case 0xffffffff: /* Linux System Call */ 977 { 978 unsigned int handler = cpu.asregs.sregs[1]; 979 unsigned int sp = cpu.asregs.regs[1]; 980 981 /* Save a slot for the static chain. */ 982 sp -= 4; 983 984 /* Push the return address. */ 985 sp -= 4; 986 wlat (scpu, opc, sp, pc + 6); 987 988 /* Push the current frame pointer. */ 989 sp -= 4; 990 wlat (scpu, opc, sp, cpu.asregs.regs[0]); 991 992 /* Uncache the stack pointer and set the fp & pc. */ 993 cpu.asregs.regs[1] = sp; 994 cpu.asregs.regs[0] = sp; 995 pc = handler - 6; 996 } 997 default: 998 break; 999 } 1000 pc += 4; 1001 } 1002 break; 1003 case 0x31: /* div.l */ 1004 { 1005 int a = (inst >> 4) & 0xf; 1006 int b = inst & 0xf; 1007 int av = cpu.asregs.regs[a]; 1008 int bv = cpu.asregs.regs[b]; 1009 1010 MOXIE_TRACE_INSN ("div.l"); 1011 cpu.asregs.regs[a] = av / bv; 1012 } 1013 break; 1014 case 0x32: /* udiv.l */ 1015 { 1016 int a = (inst >> 4) & 0xf; 1017 int b = inst & 0xf; 1018 unsigned int av = cpu.asregs.regs[a]; 1019 unsigned int bv = cpu.asregs.regs[b]; 1020 1021 MOXIE_TRACE_INSN ("udiv.l"); 1022 cpu.asregs.regs[a] = (av / bv); 1023 } 1024 break; 1025 case 0x33: /* mod.l */ 1026 { 1027 int a = (inst >> 4) & 0xf; 1028 int b = inst & 0xf; 1029 int av = cpu.asregs.regs[a]; 1030 int bv = cpu.asregs.regs[b]; 1031 1032 MOXIE_TRACE_INSN ("mod.l"); 1033 cpu.asregs.regs[a] = av % bv; 1034 } 1035 break; 1036 case 0x34: /* umod.l */ 1037 { 1038 int a = (inst >> 4) & 0xf; 1039 int b = inst & 0xf; 1040 unsigned int av = cpu.asregs.regs[a]; 1041 unsigned int bv = cpu.asregs.regs[b]; 1042 1043 MOXIE_TRACE_INSN ("umod.l"); 1044 cpu.asregs.regs[a] = (av % bv); 1045 } 1046 break; 1047 case 0x35: /* brk */ 1048 MOXIE_TRACE_INSN ("brk"); 1049 sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGTRAP); 1050 pc -= 2; /* Adjust pc */ 1051 break; 1052 case 0x36: /* ldo.b */ 1053 { 1054 unsigned int addr = EXTRACT_OFFSET(pc+2); 1055 int a = (inst >> 4) & 0xf; 1056 int b = inst & 0xf; 1057 1058 MOXIE_TRACE_INSN ("ldo.b"); 1059 addr += cpu.asregs.regs[b]; 1060 cpu.asregs.regs[a] = rbat (scpu, opc, addr); 1061 pc += 2; 1062 } 1063 break; 1064 case 0x37: /* sto.b */ 1065 { 1066 unsigned int addr = EXTRACT_OFFSET(pc+2); 1067 int a = (inst >> 4) & 0xf; 1068 int b = inst & 0xf; 1069 1070 MOXIE_TRACE_INSN ("sto.b"); 1071 addr += cpu.asregs.regs[a]; 1072 wbat (scpu, opc, addr, cpu.asregs.regs[b]); 1073 pc += 2; 1074 } 1075 break; 1076 case 0x38: /* ldo.s */ 1077 { 1078 unsigned int addr = EXTRACT_OFFSET(pc+2); 1079 int a = (inst >> 4) & 0xf; 1080 int b = inst & 0xf; 1081 1082 MOXIE_TRACE_INSN ("ldo.s"); 1083 addr += cpu.asregs.regs[b]; 1084 cpu.asregs.regs[a] = rsat (scpu, opc, addr); 1085 pc += 2; 1086 } 1087 break; 1088 case 0x39: /* sto.s */ 1089 { 1090 unsigned int addr = EXTRACT_OFFSET(pc+2); 1091 int a = (inst >> 4) & 0xf; 1092 int b = inst & 0xf; 1093 1094 MOXIE_TRACE_INSN ("sto.s"); 1095 addr += cpu.asregs.regs[a]; 1096 wsat (scpu, opc, addr, cpu.asregs.regs[b]); 1097 pc += 2; 1098 } 1099 break; 1100 default: 1101 opc = opcode; 1102 MOXIE_TRACE_INSN ("SIGILL1"); 1103 sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL); 1104 break; 1105 } 1106 } 1107 1108 cpu.asregs.insts++; 1109 pc += 2; 1110 cpu.asregs.regs[PC_REGNO] = pc; 1111 } while (1); 1112} 1113 1114static int 1115moxie_reg_store (SIM_CPU *scpu, int rn, unsigned char *memory, int length) 1116{ 1117 if (rn < NUM_MOXIE_REGS && rn >= 0) 1118 { 1119 if (length == 4) 1120 { 1121 long ival; 1122 1123 /* misalignment safe */ 1124 ival = moxie_extract_unsigned_integer (memory, 4); 1125 cpu.asints[rn] = ival; 1126 } 1127 1128 return 4; 1129 } 1130 else 1131 return 0; 1132} 1133 1134static int 1135moxie_reg_fetch (SIM_CPU *scpu, int rn, unsigned char *memory, int length) 1136{ 1137 if (rn < NUM_MOXIE_REGS && rn >= 0) 1138 { 1139 if (length == 4) 1140 { 1141 long ival = cpu.asints[rn]; 1142 1143 /* misalignment-safe */ 1144 moxie_store_unsigned_integer (memory, 4, ival); 1145 } 1146 1147 return 4; 1148 } 1149 else 1150 return 0; 1151} 1152 1153static sim_cia 1154moxie_pc_get (sim_cpu *cpu) 1155{ 1156 return cpu->registers[PCIDX]; 1157} 1158 1159static void 1160moxie_pc_set (sim_cpu *cpu, sim_cia pc) 1161{ 1162 cpu->registers[PCIDX] = pc; 1163} 1164 1165static void 1166free_state (SIM_DESC sd) 1167{ 1168 if (STATE_MODULES (sd) != NULL) 1169 sim_module_uninstall (sd); 1170 sim_cpu_free_all (sd); 1171 sim_state_free (sd); 1172} 1173 1174SIM_DESC 1175sim_open (SIM_OPEN_KIND kind, host_callback *cb, 1176 struct bfd *abfd, char * const *argv) 1177{ 1178 int i; 1179 SIM_DESC sd = sim_state_alloc (kind, cb); 1180 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1181 1182 /* The cpu data is kept in a separately allocated chunk of memory. */ 1183 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK) 1184 { 1185 free_state (sd); 1186 return 0; 1187 } 1188 1189 STATE_WATCHPOINTS (sd)->pc = &cpu.asregs.regs[PC_REGNO]; 1190 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (word); 1191 1192 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 1193 { 1194 free_state (sd); 1195 return 0; 1196 } 1197 1198 /* The parser will print an error message for us, so we silently return. */ 1199 if (sim_parse_args (sd, argv) != SIM_RC_OK) 1200 { 1201 free_state (sd); 1202 return 0; 1203 } 1204 1205 sim_do_command(sd," memory region 0x00000000,0x4000000") ; 1206 sim_do_command(sd," memory region 0xE0000000,0x10000") ; 1207 1208 /* Check for/establish the a reference program image. */ 1209 if (sim_analyze_program (sd, 1210 (STATE_PROG_ARGV (sd) != NULL 1211 ? *STATE_PROG_ARGV (sd) 1212 : NULL), abfd) != SIM_RC_OK) 1213 { 1214 free_state (sd); 1215 return 0; 1216 } 1217 1218 /* Configure/verify the target byte order and other runtime 1219 configuration options. */ 1220 if (sim_config (sd) != SIM_RC_OK) 1221 { 1222 sim_module_uninstall (sd); 1223 return 0; 1224 } 1225 1226 if (sim_post_argv_init (sd) != SIM_RC_OK) 1227 { 1228 /* Uninstall the modules to avoid memory leaks, 1229 file descriptor leaks, etc. */ 1230 sim_module_uninstall (sd); 1231 return 0; 1232 } 1233 1234 /* CPU specific initialization. */ 1235 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 1236 { 1237 SIM_CPU *cpu = STATE_CPU (sd, i); 1238 1239 CPU_REG_FETCH (cpu) = moxie_reg_fetch; 1240 CPU_REG_STORE (cpu) = moxie_reg_store; 1241 CPU_PC_FETCH (cpu) = moxie_pc_get; 1242 CPU_PC_STORE (cpu) = moxie_pc_set; 1243 1244 set_initial_gprs (); /* Reset the GPR registers. */ 1245 } 1246 1247 return sd; 1248} 1249 1250/* Load the device tree blob. */ 1251 1252static void 1253load_dtb (SIM_DESC sd, const char *filename) 1254{ 1255 int size = 0; 1256 FILE *f = fopen (filename, "rb"); 1257 char *buf; 1258 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */ 1259 1260 /* Don't warn as the sim works fine w/out a device tree. */ 1261 if (f == NULL) 1262 return; 1263 fseek (f, 0, SEEK_END); 1264 size = ftell(f); 1265 fseek (f, 0, SEEK_SET); 1266 buf = alloca (size); 1267 if (size != fread (buf, 1, size, f)) 1268 { 1269 sim_io_eprintf (sd, "ERROR: error reading ``%s''.\n", filename); 1270 fclose (f); 1271 return; 1272 } 1273 sim_core_write_buffer (sd, scpu, write_map, buf, 0xE0000000, size); 1274 cpu.asregs.sregs[9] = 0xE0000000; 1275 fclose (f); 1276} 1277 1278SIM_RC 1279sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, 1280 char * const *argv, char * const *env) 1281{ 1282 char ** avp; 1283 int l, argc, i, tp; 1284 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */ 1285 1286 if (prog_bfd != NULL) 1287 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd); 1288 1289 /* Copy args into target memory. */ 1290 avp = argv; 1291 for (argc = 0; avp && *avp; avp++) 1292 argc++; 1293 1294 /* Target memory looks like this: 1295 0x00000000 zero word 1296 0x00000004 argc word 1297 0x00000008 start of argv 1298 . 1299 0x0000???? end of argv 1300 0x0000???? zero word 1301 0x0000???? start of data pointed to by argv */ 1302 1303 wlat (scpu, 0, 0, 0); 1304 wlat (scpu, 0, 4, argc); 1305 1306 /* tp is the offset of our first argv data. */ 1307 tp = 4 + 4 + argc * 4 + 4; 1308 1309 for (i = 0; i < argc; i++) 1310 { 1311 /* Set the argv value. */ 1312 wlat (scpu, 0, 4 + 4 + i * 4, tp); 1313 1314 /* Store the string. */ 1315 sim_core_write_buffer (sd, scpu, write_map, argv[i], 1316 tp, strlen(argv[i])+1); 1317 tp += strlen (argv[i]) + 1; 1318 } 1319 1320 wlat (scpu, 0, 4 + 4 + i * 4, 0); 1321 1322 load_dtb (sd, DTB); 1323 1324 return SIM_RC_OK; 1325} 1326