home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "formats.h"
- #include "arithmetic.h"
-
- /*
- * Decode integer arithmetic, logical, and shift instructions.
- * Assume pre-allocated buffer "buf" can be filled with text
- * describing the instruction.
- */
-
- void
- arithmetic(instr, buf)
- unsigned long instr;
- char *buf;
- {
- struct format3a instr3a;
- struct format3b instr3b;
-
- int op3_5_4, op3_3_0;
- int immediate;
- char *opcode_ptr;
-
- char *user_mode();
-
-
-
- bcopy((char *) &instr, (char *) &instr3a, 4);
-
- /* trim off op3 <5:4> */
- op3_5_4 = (instr3a.op3 & 0x30) >> 4;
- /* trim off op3 <3:0> */
- op3_3_0 = (instr3a.op3 & 0x0f);
-
- opcode_ptr = table_f_3[op3_3_0][op3_5_4];
-
- if (immediate = instr3a.i)
- bcopy((char *) &instr, (char *) &instr3b, 4);
-
- /* many different output formats: use switch */
- switch (instr3a.op3) {
- case 0x30:
- /* WRASR, WRY */
- if (instr3a.rd) {
- /* WRASR */
- if (immediate) {
- sprintf(buf, "wr %s, %d, %s ! WRASR", user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13),
- user_mode(instr3a.rd));
- } else {
- sprintf(buf, "wr %s, %s, %s ! WRASR", user_mode(instr3a.rs1),
- user_mode(instr3a.rs2), user_mode(instr3a.rd));
- }
- } else {
- /* WRY */
- if (immediate) {
- sprintf(buf, "wr %s, %d, %%y ! WRY", user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13));
-
- } else {
- sprintf(buf, "wr %s, %s, %%y ! WRY", user_mode(instr3a.rs1),
- user_mode(instr3a.rs2));
- }
- }
- break;
-
- case 0x31:
- /* WRPSR */
- if (immediate) {
- sprintf(buf, "wr %s, %d, %%psr ! WRPSR", user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13));
-
- } else {
- sprintf(buf, "wr %s, %s, %%psr ! WRPSR", user_mode(instr3a.rs1),
- user_mode(instr3a.rs2));
- }
- break;
-
- case 0x32:
- /* WRWIM */
- if (immediate) {
- sprintf(buf, "wr %s, %d, %%wim ! WRWIM", user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13));
-
- } else {
- sprintf(buf, "wr %s, %s, %%wim ! WRWIM", user_mode(instr3a.rs1),
- user_mode(instr3a.rs2));
- }
- break;
-
- case 0x33:
- /* WRTBR */
- if (immediate) {
- sprintf(buf, "wr %s, %d, %%tbr ! WRTBR", user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13));
-
- } else {
- sprintf(buf, "wr %s, %s, %%tbr ! WRTBR", user_mode(instr3a.rs1),
- user_mode(instr3a.rs2));
- }
- break;
-
- case 0x28:
- /* RDASR, RDY, STBAR */
- if (instr3a.rs1) {
- if (instr3a.rs1 == 15 && instr3a.rd == 0) {
- strcpy(buf, "stbar");
- } else {
- sprintf(buf, "rd %s, %s ! RDASR", user_mode(instr3a.rs1),
- user_mode(instr3a.rd));
- }
- } else {
- sprintf(buf, "rd %%y, %s ! RDY", user_mode(instr3a.rd));
- }
- break;
-
- case 0x29:
- /* RDPSR */
- sprintf(buf, "rd %%psr, %s ! RDPSR", user_mode(instr3a.rd));
- break;
-
- case 0x2a:
- /* RDWIM */
- sprintf(buf, "rd %%wim, %s ! RDWIM", user_mode(instr3a.rd));
- break;
-
- case 0x2b:
- /* RDTBR */
- sprintf(buf, "rd %%tbr, %s ! RDWIM", user_mode(instr3a.rd));
- break;
-
- case 0x38:
- /* JMPL */
- if (immediate) {
- if (instr3a.rs1 > 0) {
- sprintf(buf, "%s [%s + %d], %s",
- opcode_ptr, user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13),
- user_mode(instr3a.rd));
- } else {
- /* %g0 is rs1: ignore it for clarity */
- sprintf(buf, "%s [%d], %s", opcode_ptr,
- SIGN_EXT13(instr3b.simm13),
- user_mode(instr3a.rd));
- }
- } else {
- sprintf(buf, "%s [%s + %s], %s",
- opcode_ptr, user_mode(instr3a.rs1),
- user_mode(instr3a.rs2),
- user_mode(instr3a.rd));
- }
- break;
-
- case 0x39:
- /* RETT */
- if (immediate) {
- if (instr3a.rs1 > 0) {
- sprintf(buf, "%s [%s + %d]",
- opcode_ptr, user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13));
- } else {
- /* %g0 is rs1: ignore it for clarity */
- sprintf(buf, "%s [%d]", opcode_ptr,
- SIGN_EXT13(instr3b.simm13));
- }
- } else {
- sprintf(buf, "%s [%s + %s]",
- opcode_ptr, user_mode(instr3a.rs1),
- user_mode(instr3a.rs2));
- }
- break;
-
- case 0x3b:
- /* FLUSH */
- if (immediate) {
- if (instr3a.rs1 > 0) {
- sprintf(buf, "%s [%s + %d]",
- opcode_ptr, user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13));
- } else {
- /* %g0 is rs1: ignore it for clarity */
- sprintf(buf, "%s [%d]", opcode_ptr,
- SIGN_EXT13(instr3b.simm13));
- }
- } else {
- sprintf(buf, "%s [%s + %s]",
- opcode_ptr, user_mode(instr3a.rs1),
- user_mode(instr3a.rs2));
- }
- break;
-
- case 0x3a:
- /* Ticc */
- opcode_ptr = traps[instr3a.rd & 0x0f];
- if (immediate) {
- if (instr3a.rs1 > 0) {
- sprintf(buf, "%s %s + %d",
- opcode_ptr, user_mode(instr3b.rs1),
- SIGN_EXT13(instr3b.simm13));
- } else {
- sprintf(buf, "%s %d", opcode_ptr, SIGN_EXT13(instr3b.simm13));
- }
- } else {
- sprintf(buf, "%s %s + %s",
- opcode_ptr, user_mode(instr3a.rs1),
- user_mode(instr3a.rs2));
- }
- break;
-
- /* invalid ops or stuff I haven't covered
- * (floating point and co-processor) */
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x09:
- case 0x19:
- case 0x2c:
- case 0x0d:
- case 0x1d:
- case 0x2d:
- case 0x2e:
- case 0x2f:
- case 0x3e:
- case 0x3f:
- strcpy(buf, opcode_ptr);
- break;
-
- default:
- /* most of arithmetic, logical and shift instructions */
-
- /* I am really proud of the nifty use of the "?:" tertiary
- * operator in the next two or three sprintf()s, but lint
- * hates it. */
- #ifndef NOSYNTHETIC
- /* some "synthetic" instructions: special cases where %g0 is in it */
- if (instr3a.rd == 0 && instr3a.op3 == 0x14) {
- /* subcc becoming "cmp" */
- sprintf(buf, immediate?"cmp %s, %d":"cmp %s, %s",
- user_mode(instr3a.rs1),
- immediate?SIGN_EXT13(instr3b.simm13):user_mode(instr3a.rs2));
- break;
- }
- if (instr3a.rs1 == 0 && instr3a.op3 == 0x02) {
- if (!immediate && instr3a.rs2 == 0) {
- /* or %g0,%g0,rd becomes clr rd */
- sprintf(buf, "clr %s", user_mode(instr3a.rd));
- } else {
- /* or %g0,something,r[rd] turns into mov something, r[rd] */
- sprintf(buf, immediate?"mov %d, %s":"mov %s, %s",
- immediate?SIGN_EXT13(instr3b.simm13):user_mode(instr3a.rs2),
- user_mode(instr3a.rd));
- }
- break;
- }
- /* add rd,simm13,rd becomes inc something,rd */
- if (instr3a.op3 == 0x00
- && immediate
- && instr3a.rs1 == instr3a.rd) {
- if (instr3b.simm13 == 0x01) {
- sprintf(buf, "inc %s", user_mode(instr3a.rd));
- } else {
- sprintf(buf, "inc %d, %s", instr3b.simm13, user_mode(instr3a.rd));
- }
- break;
- }
-
- /* sub rd,simm13,rd becomes dec something,rd */
- if (instr3a.op3 == 0x04
- && immediate
- && instr3a.rs1 == instr3a.rd) {
- if (instr3b.simm13 == 0x01) {
- sprintf(buf, "dec %s", user_mode(instr3a.rd));
- } else {
- sprintf(buf, "dec %d, %s", instr3b.simm13, user_mode(instr3a.rd));
- }
- break;
- }
- /* orcc %g0,rs2,%g0 becomes tst rs2 */
- if (instr3a.op3 == 0x12 && instr3a.rs1 == 0 && instr3a.rd == 0) {
- sprintf(buf, "tst %s", user_mode(instr3a.rs2));
- break;
- }
- #endif
-
-
-
- if (immediate) {
- if (instr3a.rs1 > 0) {
- sprintf(buf, "%s %s, %d, %s",
- opcode_ptr, user_mode(instr3a.rs1),
- SIGN_EXT13(instr3b.simm13),
- user_mode(instr3a.rd));
- } else {
- /* %g0 is rs1: ignore it for clarity */
- sprintf(buf, "%s %d, %s", opcode_ptr,
- SIGN_EXT13(instr3b.simm13),
- user_mode(instr3a.rd));
- }
- } else {
- sprintf(buf, "%s %s, %s, %s",
- opcode_ptr, user_mode(instr3a.rs1),
- user_mode(instr3a.rs2),
- user_mode(instr3a.rd));
- }
- break;
- }
-
- return;
- }
-