Skip to content

Commit

Permalink
target-tricore: Add instructions of RRR1 opcode format, which have 0x…
Browse files Browse the repository at this point in the history
…83 as first opcode

Add helpers:
    * add64_ssov: adds two 64 bit values and saturates the result.
    * addr_h/_ssov: adds two halfwords with two words in q-format with rounding
                    / and saturates each result independetly.

Add microcode generator:
    * gen_add64_d: adds two 64 bit values.
    * gen_addsub64_h: adds/subtracts one halfwords with a word and adds/
                      subtracts another halftword with another word.
    * gen_madd_h/s_h: multiply four halfwords, add each result left justfied
                      to two word values / and saturate each result.
    * gen_maddm_h/s_h: multiply four halfwords, add each result left justfied
                       to two words values in q-format / and saturate each
                       result.
    * gen_maddr32/64_h/s_h: multiply four halfwords, add each result left
                            justfied to two halftwords/words values in q-format
                            / and saturate each result.

Signed-off-by: Bastian Koppelmann <[email protected]>
Reviewed-by: Richard Henderson <[email protected]>
  • Loading branch information
bkoppelmann committed Mar 3, 2015
1 parent 2984cfb commit 2e430e1
Show file tree
Hide file tree
Showing 3 changed files with 534 additions and 0 deletions.
3 changes: 3 additions & 0 deletions target-tricore/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@

/* Arithmetic */
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
DEF_HELPER_3(add64_ssov, i64, env, i64, i64)
DEF_HELPER_3(add_suov, i32, env, i32, i32)
DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
DEF_HELPER_3(add_h_suov, i32, env, i32, i32)
DEF_HELPER_4(addr_h_ssov, i32, env, i64, i32, i32)
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
DEF_HELPER_3(sub_suov, i32, env, i32, i32)
DEF_HELPER_3(sub_h_ssov, i32, env, i32, i32)
Expand All @@ -44,6 +46,7 @@ DEF_HELPER_2(abs_b, i32, env, i32)
DEF_HELPER_2(abs_h, i32, env, i32)
DEF_HELPER_3(absdif_b, i32, env, i32, i32)
DEF_HELPER_3(absdif_h, i32, env, i32, i32)
DEF_HELPER_4(addr_h, i32, env, i64, i32, i32)
DEF_HELPER_3(add_b, i32, env, i32, i32)
DEF_HELPER_3(add_h, i32, env, i32, i32)
DEF_HELPER_3(sub_b, i32, env, i32, i32)
Expand Down
110 changes: 110 additions & 0 deletions target-tricore/op_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,31 @@ target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
return ssov32(env, result);
}

uint64_t helper_add64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2)
{
uint64_t result;
int64_t ovf;

result = r1 + r2;
ovf = (result ^ r1) & ~(r1 ^ r2);
env->PSW_USB_AV = (result ^ result * 2u) >> 32;
env->PSW_USB_SAV |= env->PSW_USB_AV;
if (ovf < 0) {
env->PSW_USB_V = (1 << 31);
env->PSW_USB_SV = (1 << 31);
/* ext_ret > MAX_INT */
if ((int64_t)r1 >= 0) {
result = INT64_MAX;
/* ext_ret < MIN_INT */
} else {
result = INT64_MIN;
}
} else {
env->PSW_USB_V = 0;
}
return result;
}

target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
Expand All @@ -194,6 +219,53 @@ target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
return ssov16(env, ret_hw0, ret_hw1);
}

uint32_t helper_addr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
uint32_t r2_h)
{
int64_t mul_res0 = sextract64(r1, 0, 32);
int64_t mul_res1 = sextract64(r1, 32, 32);
int64_t r2_low = sextract64(r2_l, 0, 32);
int64_t r2_high = sextract64(r2_h, 0, 32);
int64_t result0, result1;
uint32_t ovf0, ovf1;
uint32_t avf0, avf1;

ovf0 = ovf1 = 0;

result0 = r2_low + mul_res0 + 0x8000;
result1 = r2_high + mul_res1 + 0x8000;

avf0 = result0 * 2u;
avf0 = result0 ^ avf0;
avf1 = result1 * 2u;
avf1 = result1 ^ avf1;

if (result0 > INT32_MAX) {
ovf0 = (1 << 31);
result0 = INT32_MAX;
} else if (result0 < INT32_MIN) {
ovf0 = (1 << 31);
result0 = INT32_MIN;
}

if (result1 > INT32_MAX) {
ovf1 = (1 << 31);
result1 = INT32_MAX;
} else if (result1 < INT32_MIN) {
ovf1 = (1 << 31);
result1 = INT32_MIN;
}

env->PSW_USB_V = ovf0 | ovf1;
env->PSW_USB_SV |= env->PSW_USB_V;

env->PSW_USB_AV = avf0 | avf1;
env->PSW_USB_SAV |= env->PSW_USB_AV;

return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
}


target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
Expand Down Expand Up @@ -619,6 +691,44 @@ uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
return ret;
}

uint32_t helper_addr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
uint32_t r2_h)
{
int64_t mul_res0 = sextract64(r1, 0, 32);
int64_t mul_res1 = sextract64(r1, 32, 32);
int64_t r2_low = sextract64(r2_l, 0, 32);
int64_t r2_high = sextract64(r2_h, 0, 32);
int64_t result0, result1;
uint32_t ovf0, ovf1;
uint32_t avf0, avf1;

ovf0 = ovf1 = 0;

result0 = r2_low + mul_res0 + 0x8000;
result1 = r2_high + mul_res1 + 0x8000;

if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) {
ovf0 = (1 << 31);
}

if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) {
ovf1 = (1 << 31);
}

env->PSW_USB_V = ovf0 | ovf1;
env->PSW_USB_SV |= env->PSW_USB_V;

avf0 = result0 * 2u;
avf0 = result0 ^ avf0;
avf1 = result1 * 2u;
avf1 = result1 ^ avf1;

env->PSW_USB_AV = avf0 | avf1;
env->PSW_USB_SAV |= env->PSW_USB_AV;

return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
}

uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
{
int32_t b, i;
Expand Down
Loading

0 comments on commit 2e430e1

Please sign in to comment.