summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2008-10-08 20:44:32 -0600
committerBrian Paul <brian.paul@tungstengraphics.com>2008-10-08 20:44:32 -0600
commitd48a92e88040470f93e2186f8eb23e4797a09860 (patch)
tree7fbfd01dc04b42e42b4457eae507693ef8dc5f3b /src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
parenta4e477433f485a39b5de448d0a9cb6f4bf9bb90f (diff)
cell: implement function calls from shader code. fslight demo runs now.
Used for SIN, COS, EXP2, LOG2, POW instructions. TEX next. Fixed some bugs in MIN, MAX, DP3, DP4, DPH instructions. In rtasm code: Special-case spe_lqd(), spe_stqd() functions so they take byte offsets but low-order 4 bits are shifted out. This makes things consistant with SPU assembly language conventions. Added spe_get_registers_used() function.
Diffstat (limited to 'src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c')
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
index c442b1f6aa..9274bc5e3c 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
+++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
@@ -174,9 +174,12 @@ reg_name(int reg)
return "$lr";
default:
{
- static char buf[10];
- sprintf(buf, "$%d", reg);
- return buf;
+ /* cycle through four buffers to handle multiple calls per printf */
+ static char buf[4][10];
+ static int b = 0;
+ b = (b + 1) % 4;
+ sprintf(buf[b], "$%d", reg);
+ return buf[b];
}
}
}
@@ -269,15 +272,8 @@ static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT,
assert(p->num_inst <= p->max_inst);
if (p->print) {
indent(p);
- if (strcmp(name, "spe_lqd") == 0 ||
- strcmp(name, "spe_stqd") == 0) {
- printf("%s\t%s, %d(%s)\n",
- rem_prefix(name), reg_name(rT), imm, reg_name(rA));
- }
- else {
- printf("%s\t%s, %s, 0x%x\n",
- rem_prefix(name), reg_name(rT), reg_name(rA), imm);
- }
+ printf("%s\t%s, %s, 0x%x\n",
+ rem_prefix(name), reg_name(rT), reg_name(rA), imm);
}
}
@@ -379,6 +375,7 @@ void _name (struct spe_function *p, int imm) \
#include "rtasm_ppc_spe.h"
+
/**
* Initialize an spe_function.
* \param code_size size of instruction buffer to allocate, in bytes.
@@ -513,6 +510,20 @@ void spe_release_register_set(struct spe_function *p)
}
+unsigned
+spe_get_registers_used(const struct spe_function *p, ubyte used[])
+{
+ unsigned i, num = 0;
+ /* only count registers in the range available to callers */
+ for (i = 2; i < 80; i++) {
+ if (p->regs[i]) {
+ used[num++] = i;
+ }
+ }
+ return num;
+}
+
+
void
spe_print_code(struct spe_function *p, boolean enable)
{
@@ -540,6 +551,46 @@ spe_comment(struct spe_function *p, int rel_indent, const char *s)
/**
+ * Load quad word.
+ * NOTE: imm is in bytes and the least significant 4 bits must be zero!
+ */
+void spe_lqd(struct spe_function *p, unsigned rT, unsigned rA, int offset)
+{
+ const boolean pSave = p->print;
+
+ p->print = FALSE;
+ assert(offset % 4 == 0);
+ emit_RI10(p, 0x034, rT, rA, offset >> 4, "spe_lqd");
+ p->print = pSave;
+
+ if (p->print) {
+ indent(p);
+ printf("lqd\t%s, %d(%s)\n", reg_name(rT), offset, reg_name(rA));
+ }
+}
+
+
+/**
+ * Store quad word.
+ * NOTE: imm is in bytes and the least significant 4 bits must be zero!
+ */
+void spe_stqd(struct spe_function *p, unsigned rT, unsigned rA, int offset)
+{
+ const boolean pSave = p->print;
+
+ p->print = FALSE;
+ assert(offset % 4 == 0);
+ emit_RI10(p, 0x024, rT, rA, offset >> 4, "spe_stqd");
+ p->print = pSave;
+
+ if (p->print) {
+ indent(p);
+ printf("stqd\t%s, %d(%s)\n", reg_name(rT), offset, reg_name(rA));
+ }
+}
+
+
+/**
* For branch instructions:
* \param d if 1, disable interupts if branch is taken
* \param e if 1, enable interupts if branch is taken
@@ -764,6 +815,7 @@ spe_and_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui)
spe_release_register(p, tmp_reg);
}
+
/**
* This function is constructed identically to spe_and_uint() above.
* Changes to one should be made in the other.