e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. || $Id: sparc.c,v 1.13 2002/10/11 01:39:39 nilsson Exp $ */
1b10db2002-10-08Martin Nilsson 
dd6bca2001-07-20Henrik Grubbström (Grubba) /* * Machine code generator for sparc. * * Henrik Grubbström 20010720 */
fc31002001-07-24Henrik Grubbström (Grubba) #include "operators.h"
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) {
11ed4b2001-07-24Henrik Grubbström (Grubba)  void *addr;
fc31002001-07-24Henrik Grubbström (Grubba) 
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)  }
fc31002001-07-24Henrik Grubbström (Grubba) 
11ed4b2001-07-24Henrik Grubbström (Grubba)  addr = instrs[b].address;
9a928d2002-05-10Martin Stjernholm #ifdef PIKE_DEBUG if (d_flag < 3) #endif
fc31002001-07-24Henrik Grubbström (Grubba)  /* This is not very pretty */ switch(b) { case F_MAKE_ITERATOR - F_OFFSET: { extern void f_Iterator(INT32); SET_REG(SPARC_REG_O0, 1); delay_ok = 1; addr = (void *)f_Iterator; } break; case F_ADD - F_OFFSET: SET_REG(SPARC_REG_O0, 2); delay_ok = 1; addr = (void *)f_add; break; }
9a928d2002-05-10Martin Stjernholm 
11ed4b2001-07-24Henrik Grubbström (Grubba)  ADD_CALL(addr, delay_ok);
f1d1eb2001-07-20Henrik Grubbström (Grubba) } 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) {
7df3482001-07-21Henrik Grubbström (Grubba)  SET_REG(SPARC_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) {
7df3482001-07-21Henrik Grubbström (Grubba)  SET_REG(SPARC_REG_O0, c); SET_REG(SPARC_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) {
5aad932002-08-15Marcus Comstedt  Pike_fatal("Relocations in bad order!\n");
697e0a2001-07-20Henrik Grubbström (Grubba)  } #endif /* PIKE_DEBUG */ adddata2(p->program + prev, off - prev); #ifdef PIKE_DEBUG if ((p->program[off] & 0xc0000000) != 0x40000000) {
5aad932002-08-15Marcus Comstedt  Pike_fatal("Bad relocation!\n");
697e0a2001-07-20Henrik Grubbström (Grubba)  } #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); } }
9d2e2d2001-07-21Henrik Grubbström (Grubba)  /* * Inline machine-code... */ const unsigned INT32 sparc_flush_instruction_cache[] = { /* * On entry: * %o0 : void *ptr * %o1 : size_t nbytes * * cmp %o1, #1 * .l0: * flush %o0+%o1 * bge,a .l0 * subcc %o1, 8, %o1 * retl * or %g0,%g0,%o0 */ /* 1000 0000 1010 0000 0010 0000 0000 0000 */ 0x80a02000|(SPARC_REG_O1<<14)|1, /* 1000 0001 1101 1000 0000 0000 0000 0000 */ 0x81d80000|(SPARC_REG_O0<<14)|(SPARC_REG_O1), /* 0011 0110 1000 0000 0000 0000 0000 0000 */ 0x36800000|((-1)&0x3fffff), /* 1000 0000 1010 0000 0010 0000 0000 0000 */ 0x80a02000|(SPARC_REG_O1<<25)|(SPARC_REG_O1<<14)|8, /* 1000 0001 1100 0000 0010 0000 0000 0000 */ 0x81c02000|(SPARC_REG_O7<<14)|8, /* 1000 0000 0001 0000 0000 0000 0000 0000 */ 0x80100000|(SPARC_REG_O0<<25), };