dd6bca2001-07-20Henrik Grubbström (Grubba) /*
f1d1eb2001-07-20Henrik Grubbström (Grubba)  * $Id: sparc.c,v 1.4 2001/07/20 19:44:59 grubba Exp $
dd6bca2001-07-20Henrik Grubbström (Grubba)  * * Machine code generator for sparc. * * Henrik Grubbström 20010720 */
f1d1eb2001-07-20Henrik Grubbström (Grubba) #define ADD_CALL(X, DELAY_OK) do { \
dd6bca2001-07-20Henrik Grubbström (Grubba)  INT32 delta_; \ struct program *p_ = Pike_compiler->new_program; \ INT32 off_ = p_->num_program; \
f1d1eb2001-07-20Henrik Grubbström (Grubba)  /* noop */ \ INT32 delay_ = 0x01000000; \ \ if (DELAY_OK) { \ /* Move the previous opcode to the delay-slot. */ \ delay_ = p_->program[--off_]; \ } else { \ add_to_program(0); /* Placeholder... */ \ } \
dd6bca2001-07-20Henrik Grubbström (Grubba)  /* call X */ \ delta_ = ((PIKE_OPCODE_T *)(X)) - (p_->program + off_); \ p_->program[off_] = 0x40000000 | (delta_ & 0x3fffffff); \ add_to_relocations(off_); \
f1d1eb2001-07-20Henrik Grubbström (Grubba)  add_to_program(delay_); \
dd6bca2001-07-20Henrik Grubbström (Grubba)  } while(0)
f1d1eb2001-07-20Henrik Grubbström (Grubba) static void low_ins_f_byte(unsigned int b, int delay_ok)
dd6bca2001-07-20Henrik Grubbström (Grubba) { #ifdef PIKE_DEBUG if(store_linenumbers && b<F_MAX_OPCODE) ADD_COMPILED(b); #endif /* PIKE_DEBUG */ b-=F_OFFSET; #ifdef PIKE_DEBUG if(b>255) Pike_error("Instruction too big %d\n",b); #endif
f1d1eb2001-07-20Henrik Grubbström (Grubba)  {
dd6bca2001-07-20Henrik Grubbström (Grubba)  static int last_prog_id=-1; static int last_num_linenumbers=-1; if(last_prog_id != Pike_compiler->new_program->id || last_num_linenumbers != Pike_compiler->new_program->num_linenumbers) { last_prog_id=Pike_compiler->new_program->id; last_num_linenumbers = Pike_compiler->new_program->num_linenumbers; UPDATE_PC();
f1d1eb2001-07-20Henrik Grubbström (Grubba)  delay_ok = 1;
dd6bca2001-07-20Henrik Grubbström (Grubba)  }
f1d1eb2001-07-20Henrik Grubbström (Grubba)  }
dd6bca2001-07-20Henrik Grubbström (Grubba) 
f1d1eb2001-07-20Henrik Grubbström (Grubba)  ADD_CALL(instrs[b].address, delay_ok); } void ins_f_byte(unsigned int opcode) { low_ins_f_byte(opcode, 0);
dd6bca2001-07-20Henrik Grubbström (Grubba) } void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b) { SET_REG(REG_O0, b);
f1d1eb2001-07-20Henrik Grubbström (Grubba)  low_ins_f_byte(a, 1);
dd6bca2001-07-20Henrik Grubbström (Grubba)  return; } void ins_f_byte_with_2_args(unsigned int a, unsigned INT32 c, unsigned INT32 b) { SET_REG(REG_O0, c); SET_REG(REG_O1, b);
f1d1eb2001-07-20Henrik Grubbström (Grubba)  low_ins_f_byte(a, 1);
dd6bca2001-07-20Henrik Grubbström (Grubba)  return; }
697e0a2001-07-20Henrik Grubbström (Grubba)  #define addstr(s, l) low_my_binary_strcat((s), (l), buf) #define adddata2(s,l) addstr((char *)(s),(l) * sizeof((s)[0])); void sparc_encode_program(struct program *p, struct dynamic_buffer_s *buf) { size_t prev = 0, rel; /* De-relocate the program... */ for (rel = 0; rel < p->num_relocations; rel++) { size_t off = p->relocations[rel]; INT32 opcode; #ifdef PIKE_DEBUG if (off < prev) { fatal("Relocations in bad order!\n"); } #endif /* PIKE_DEBUG */ adddata2(p->program + prev, off - prev); #ifdef PIKE_DEBUG if ((p->program[off] & 0xc0000000) != 0x40000000) { fatal("Bad relocation!\n"); } #endif /* PIKE_DEBUG */ /* Relocate to being relative to NULL */ opcode = 0x40000000 | ((p->program[off] + (((INT32)(p->program)>>2))) & 0x3fffffff); adddata2(&opcode, 1); prev = off+1; } adddata2(p->program + prev, p->num_program - prev); } void sparc_decode_program(struct program *p) { /* Relocate the program... */ PIKE_OPCODE_T *prog = p->program; INT32 delta = ((INT32)p->program)>>2; size_t rel = p->num_relocations; while (rel--) { #ifdef PIKE_DEBUG if ((prog[p->relocations[rel]] & 0xc0000000) != 0x40000000) { Pike_error("Bad relocation: %d, off:%d, opcode: 0x%08x\n", rel, p->relocations[rel], prog[p->relocations[rel]]); } #endif /* PIKE_DEBUG */ prog[p->relocations[rel]] = 0x40000000 | (((prog[p->relocations[rel]] & 0x3fffffff) - delta) & 0x3fffffff); } }