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