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